aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Vakulenko <avakulenko@google.com>2016-02-23 16:03:43 -0800
committerAlex Vakulenko <avakulenko@google.com>2016-03-01 16:00:54 +0000
commit0d3062e00517217a9be7d68d979116c558a0fef6 (patch)
tree3877e6b2bc0a302daf9d7d5c96429e719406e667 /src
parentc7fab1816836c8b3f4f2bd4f04065fae1b9c0d50 (diff)
downloadlibweave-0d3062e00517217a9be7d68d979116c558a0fef6.tar.gz
Implement minimalRole for state definitions
State definition may now specify the user's minimal role needed to see the value of the state. When a user with lower access rights is requesting the component tree, state properties unavailable to that user will be removed from the resulting JSON object. BUG: 24622262 Change-Id: I3b75c60e868d14fe9a9eaec373fcb148bfac1188 Reviewed-on: https://weave-review.googlesource.com/2721 Reviewed-by: Alex Vakulenko <avakulenko@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/component_manager.h16
-rw-r--r--src/component_manager_impl.cc112
-rw-r--r--src/component_manager_impl.h21
-rw-r--r--src/component_manager_unittest.cc268
-rw-r--r--src/privet/cloud_delegate.cc8
-rw-r--r--src/privet/cloud_delegate.h6
-rw-r--r--src/privet/mock_delegates.h13
-rw-r--r--src/privet/privet_handler.cc3
-rw-r--r--src/privet/privet_handler_unittest.cc37
-rw-r--r--src/privet/privet_types.h8
-rw-r--r--src/test/mock_component_manager.h13
11 files changed, 480 insertions, 25 deletions
diff --git a/src/component_manager.h b/src/component_manager.h
index cea5569..1a3d05f 100644
--- a/src/component_manager.h
+++ b/src/component_manager.h
@@ -154,9 +154,14 @@ class ComponentManager {
const std::string& command_name) const = 0;
// Checks the minimum required user role for a given command.
- virtual bool GetMinimalRole(const std::string& command_name,
- UserRole* minimal_role,
- ErrorPtr* error) const = 0;
+ virtual bool GetCommandMinimalRole(const std::string& command_name,
+ UserRole* minimal_role,
+ ErrorPtr* error) const = 0;
+
+ // Checks the minimum required user role for a given state property.
+ virtual bool GetStateMinimalRole(const std::string& state_property_name,
+ UserRole* minimal_role,
+ ErrorPtr* error) const = 0;
// Returns the full JSON dictionary containing trait definitions.
virtual const base::DictionaryValue& GetTraits() const = 0;
@@ -164,6 +169,11 @@ class ComponentManager {
// Returns the full JSON dictionary containing component instances.
virtual const base::DictionaryValue& GetComponents() const = 0;
+ // Returns a JSON dictionary containing component instances with state
+ // properties visible to a user of the given |role|.
+ virtual std::unique_ptr<base::DictionaryValue> GetComponentsForUserRole(
+ UserRole role) const = 0;
+
// Component state manipulation methods.
virtual bool SetStateProperties(const std::string& component_path,
const base::DictionaryValue& dict,
diff --git a/src/component_manager_impl.cc b/src/component_manager_impl.cc
index 3ea1f46..9712a3c 100644
--- a/src/component_manager_impl.cc
+++ b/src/component_manager_impl.cc
@@ -27,6 +27,60 @@ const EnumToStringMap<UserRole>::Map kMap[] = {
{UserRole::kOwner, "owner"},
{UserRole::kManager, "manager"},
};
+
+void RemoveInaccessibleState(const ComponentManagerImpl* manager,
+ base::DictionaryValue* component,
+ UserRole role) {
+ std::vector<std::string> state_props_to_remove;
+ base::DictionaryValue* state = nullptr;
+ if (component->GetDictionary("state", &state)) {
+ for (base::DictionaryValue::Iterator it_trait(*state);
+ !it_trait.IsAtEnd(); it_trait.Advance()) {
+ const base::DictionaryValue* trait = nullptr;
+ CHECK(it_trait.value().GetAsDictionary(&trait));
+ for (base::DictionaryValue::Iterator it_prop(*trait);
+ !it_prop.IsAtEnd(); it_prop.Advance()) {
+ std::string prop_name = base::StringPrintf("%s.%s",
+ it_trait.key().c_str(),
+ it_prop.key().c_str());
+ UserRole minimal_role;
+ if (manager->GetStateMinimalRole(prop_name, &minimal_role, nullptr) &&
+ minimal_role > role) {
+ state_props_to_remove.push_back(prop_name);
+ }
+ }
+ }
+ }
+ // Now remove any inaccessible properties from the state collection.
+ for (const std::string& path : state_props_to_remove) {
+ // Remove starting from component level in order for "state" to be removed
+ // if no sub-properties remain.
+ CHECK(component->RemovePath(base::StringPrintf("state.%s", path.c_str()),
+ nullptr));
+ }
+
+ // If this component has any sub-components, filter them too.
+ base::DictionaryValue* sub_components = nullptr;
+ if (component->GetDictionary("components", &sub_components)) {
+ for (base::DictionaryValue::Iterator it_component(*sub_components);
+ !it_component.IsAtEnd(); it_component.Advance()) {
+ base::Value* sub_component = nullptr;
+ CHECK(sub_components->Get(it_component.key(), &sub_component));
+ if (sub_component->GetType() == base::Value::TYPE_LIST) {
+ base::ListValue* component_array = nullptr;
+ CHECK(sub_component->GetAsList(&component_array));
+ for (base::Value* item : *component_array) {
+ CHECK(item->GetAsDictionary(&component));
+ RemoveInaccessibleState(manager, component, role);
+ }
+ } else if (sub_component->GetType() == base::Value::TYPE_DICTIONARY) {
+ CHECK(sub_component->GetAsDictionary(&component));
+ RemoveInaccessibleState(manager, component, role);
+ }
+ }
+ }
+}
+
} // anonymous namespace
template <>
@@ -230,7 +284,7 @@ std::unique_ptr<CommandInstance> ComponentManagerImpl::ParseCommandInstance(
return nullptr;
UserRole minimal_role;
- if (!GetMinimalRole(command_instance->GetName(), &minimal_role, error))
+ if (!GetCommandMinimalRole(command_instance->GetName(), &minimal_role, error))
return nullptr;
if (role < minimal_role) {
@@ -346,9 +400,24 @@ const base::DictionaryValue* ComponentManagerImpl::FindCommandDefinition(
return definition;
}
-bool ComponentManagerImpl::GetMinimalRole(const std::string& command_name,
- UserRole* minimal_role,
- ErrorPtr* error) const {
+const base::DictionaryValue* ComponentManagerImpl::FindStateDefinition(
+ const std::string& state_property_name) const {
+ const base::DictionaryValue* definition = nullptr;
+ std::vector<std::string> components =
+ Split(state_property_name, ".", true, false);
+ // Make sure the |state_property_name| came in form of trait_name.state_name.
+ if (components.size() != 2)
+ return definition;
+ std::string key = base::StringPrintf("%s.state.%s", components[0].c_str(),
+ components[1].c_str());
+ traits_.GetDictionary(key, &definition);
+ return definition;
+}
+
+bool ComponentManagerImpl::GetCommandMinimalRole(
+ const std::string& command_name,
+ UserRole* minimal_role,
+ ErrorPtr* error) const {
const base::DictionaryValue* command = FindCommandDefinition(command_name);
if (!command) {
return Error::AddToPrintf(
@@ -363,12 +432,47 @@ bool ComponentManagerImpl::GetMinimalRole(const std::string& command_name,
return true;
}
+bool ComponentManagerImpl::GetStateMinimalRole(
+ const std::string& state_property_name,
+ UserRole* minimal_role,
+ ErrorPtr* error) const {
+ const base::DictionaryValue* state = FindStateDefinition(state_property_name);
+ if (!state) {
+ return Error::AddToPrintf(
+ error, FROM_HERE, errors::commands::kInvalidState,
+ "State definition for '%s' not found", state_property_name.c_str());
+ }
+ std::string value;
+ if (state->GetString(kMinimalRole, &value)) {
+ CHECK(StringToEnum(value, minimal_role));
+ } else {
+ *minimal_role = UserRole::kUser;
+ }
+ return true;
+}
+
void ComponentManagerImpl::AddStateChangedCallback(
const base::Closure& callback) {
on_state_changed_.push_back(callback);
callback.Run(); // Force to read current state.
}
+std::unique_ptr<base::DictionaryValue>
+ComponentManagerImpl::GetComponentsForUserRole(UserRole role) const {
+ std::unique_ptr<base::DictionaryValue> components{components_.DeepCopy()};
+ // Build a list of all state properties that are inaccessible to the given
+ // user. These properties will be removed from the components collection
+ // returned from this method.
+ for (base::DictionaryValue::Iterator it_component(components_);
+ !it_component.IsAtEnd(); it_component.Advance()) {
+ base::DictionaryValue* component = nullptr;
+ CHECK(components->GetDictionary(it_component.key(), &component));
+ RemoveInaccessibleState(this, component, role);
+ }
+
+ return components;
+}
+
bool ComponentManagerImpl::SetStateProperties(const std::string& component_path,
const base::DictionaryValue& dict,
ErrorPtr* error) {
diff --git a/src/component_manager_impl.h b/src/component_manager_impl.h
index 5b8201a..5550d99 100644
--- a/src/component_manager_impl.h
+++ b/src/component_manager_impl.h
@@ -115,10 +115,20 @@ class ComponentManagerImpl final : public ComponentManager {
const base::DictionaryValue* FindCommandDefinition(
const std::string& command_name) const override;
+ // Finds a state definition, where |state_property_name| is in the form of
+ // "trait.state".
+ const base::DictionaryValue* FindStateDefinition(
+ const std::string& state_property_name) const;
+
// Checks the minimum required user role for a given command.
- bool GetMinimalRole(const std::string& command_name,
- UserRole* minimal_role,
- ErrorPtr* error) const override;
+ bool GetCommandMinimalRole(const std::string& command_name,
+ UserRole* minimal_role,
+ ErrorPtr* error) const override;
+
+ // Checks the minimum required user role for a given state.
+ bool GetStateMinimalRole(const std::string& state_property_name,
+ UserRole* minimal_role,
+ ErrorPtr* error) const override;
// Returns the full JSON dictionary containing trait definitions.
const base::DictionaryValue& GetTraits() const override { return traits_; }
@@ -128,6 +138,11 @@ class ComponentManagerImpl final : public ComponentManager {
return components_;
}
+ // Returns a JSON dictionary containing component instances with state
+ // properties visible to a user of the given |role|.
+ std::unique_ptr<base::DictionaryValue> GetComponentsForUserRole(
+ UserRole role) const override;
+
// Component state manipulation methods.
bool SetStateProperties(const std::string& component_path,
const base::DictionaryValue& dict,
diff --git a/src/component_manager_unittest.cc b/src/component_manager_unittest.cc
index 291ace8..f0db3ef 100644
--- a/src/component_manager_unittest.cc
+++ b/src/component_manager_unittest.cc
@@ -404,7 +404,7 @@ TEST_F(ComponentManagerTest, FindCommandDefinition) {
manager_.FindTraitDefinition("trait1.command1.parameters"));
}
-TEST_F(ComponentManagerTest, GetMinimalRole) {
+TEST_F(ComponentManagerTest, GetCommandMinimalRole) {
const char kTraits[] = R"({
"trait1": {
"commands": {
@@ -423,19 +423,63 @@ TEST_F(ComponentManagerTest, GetMinimalRole) {
ASSERT_TRUE(manager_.LoadTraits(*json, nullptr));
UserRole role;
- ASSERT_TRUE(manager_.GetMinimalRole("trait1.command1", &role, nullptr));
+ ASSERT_TRUE(manager_.GetCommandMinimalRole("trait1.command1", &role,
+ nullptr));
EXPECT_EQ(UserRole::kUser, role);
- ASSERT_TRUE(manager_.GetMinimalRole("trait1.command2", &role, nullptr));
+ ASSERT_TRUE(manager_.GetCommandMinimalRole("trait1.command2", &role,
+ nullptr));
EXPECT_EQ(UserRole::kViewer, role);
- ASSERT_TRUE(manager_.GetMinimalRole("trait2.command1", &role, nullptr));
+ ASSERT_TRUE(manager_.GetCommandMinimalRole("trait2.command1", &role,
+ nullptr));
EXPECT_EQ(UserRole::kManager, role);
- ASSERT_TRUE(manager_.GetMinimalRole("trait2.command2", &role, nullptr));
+ ASSERT_TRUE(manager_.GetCommandMinimalRole("trait2.command2", &role,
+ nullptr));
EXPECT_EQ(UserRole::kOwner, role);
- EXPECT_FALSE(manager_.GetMinimalRole("trait1.command3", &role, nullptr));
+ EXPECT_FALSE(manager_.GetCommandMinimalRole("trait1.command3", &role,
+ nullptr));
+}
+
+TEST_F(ComponentManagerTest, GetStateMinimalRole) {
+ const char kTraits[] = R"({
+ "trait1": {
+ "state": {
+ "property1": {"type": "integer"},
+ "property2": {"type": "boolean", "minimalRole": "viewer"},
+ "property3": {"type": "integer", "minimalRole": "user"}
+ }
+ },
+ "trait2": {
+ "state": {
+ "property1": {"type": "string", "minimalRole": "manager"},
+ "property2": {"type": "integer", "minimalRole": "owner"}
+ }
+ }
+ })";
+ auto json = CreateDictionaryValue(kTraits);
+ ASSERT_TRUE(manager_.LoadTraits(*json, nullptr));
+
+ UserRole role;
+ ASSERT_TRUE(manager_.GetStateMinimalRole("trait1.property1", &role, nullptr));
+ EXPECT_EQ(UserRole::kUser, role);
+
+ ASSERT_TRUE(manager_.GetStateMinimalRole("trait1.property2", &role, nullptr));
+ EXPECT_EQ(UserRole::kViewer, role);
+
+ ASSERT_TRUE(manager_.GetStateMinimalRole("trait1.property3", &role, nullptr));
+ EXPECT_EQ(UserRole::kUser, role);
+
+ ASSERT_TRUE(manager_.GetStateMinimalRole("trait2.property1", &role, nullptr));
+ EXPECT_EQ(UserRole::kManager, role);
+
+ ASSERT_TRUE(manager_.GetStateMinimalRole("trait2.property2", &role, nullptr));
+ EXPECT_EQ(UserRole::kOwner, role);
+
+ ASSERT_FALSE(manager_.GetStateMinimalRole("trait2.property3", &role,
+ nullptr));
}
TEST_F(ComponentManagerTest, AddComponent) {
@@ -1267,4 +1311,216 @@ TEST_F(ComponentManagerTest, TestMockComponentManager) {
test::MockComponentManager mock;
}
+TEST_F(ComponentManagerTest, GetComponentsForUserRole) {
+ const char kTraits[] = R"({
+ "trait1": {
+ "state": {
+ "prop1": { "type": "string", "minimalRole": "viewer" },
+ "prop2": { "type": "string", "minimalRole": "user" }
+ }
+ },
+ "trait2": {
+ "state": {
+ "prop3": { "type": "string", "minimalRole": "manager" },
+ "prop4": { "type": "string", "minimalRole": "owner" }
+ }
+ },
+ "trait3": {
+ "state": {
+ "prop5": { "type": "string" }
+ }
+ }
+ })";
+ auto json = CreateDictionaryValue(kTraits);
+ ASSERT_TRUE(manager_.LoadTraits(*json, nullptr));
+ ASSERT_TRUE(manager_.AddComponent("", "comp1", {"trait1", "trait2"},
+ nullptr));
+ ASSERT_TRUE(manager_.AddComponent("", "comp2", {"trait2"}, nullptr));
+ ASSERT_TRUE(manager_.AddComponentArrayItem("comp2", "comp3", {"trait3"},
+ nullptr));
+ ASSERT_TRUE(manager_.AddComponent("comp2", "comp4", {"trait3"}, nullptr));
+
+ const char kComp1Properties[] = R"({
+ "trait1": { "prop1": "foo", "prop2": "bar" },
+ "trait2": { "prop3": "baz", "prop4": "quux" }
+ })";
+ ASSERT_TRUE(manager_.SetStatePropertiesFromJson("comp1", kComp1Properties,
+ nullptr));
+
+ const char kComp2Properties[] = R"({
+ "trait2": { "prop3": "foo", "prop4": "bar" }
+ })";
+ ASSERT_TRUE(manager_.SetStatePropertiesFromJson("comp2", kComp2Properties,
+ nullptr));
+
+ const char kComp3Properties[] = R"({
+ "trait3": { "prop5": "foo" }
+ })";
+ ASSERT_TRUE(manager_.SetStatePropertiesFromJson("comp2.comp3[0]",
+ kComp3Properties, nullptr));
+
+ const char kComp4Properties[] = R"({
+ "trait3": { "prop5": "bar" }
+ })";
+ ASSERT_TRUE(manager_.SetStatePropertiesFromJson("comp2.comp4",
+ kComp4Properties, nullptr));
+
+ const char kExpected1[] = R"({
+ "comp1": {
+ "traits": [ "trait1", "trait2" ],
+ "state": {
+ "trait1": {
+ "prop1": "foo",
+ "prop2": "bar"
+ },
+ "trait2": {
+ "prop3": "baz",
+ "prop4": "quux"
+ }
+ }
+ },
+ "comp2": {
+ "traits": [ "trait2" ],
+ "state": {
+ "trait2": {
+ "prop3": "foo",
+ "prop4": "bar"
+ }
+ },
+ "components": {
+ "comp3": [
+ {
+ "traits": [ "trait3" ],
+ "state": {
+ "trait3": {
+ "prop5": "foo"
+ }
+ }
+ }
+ ],
+ "comp4": {
+ "traits": [ "trait3" ],
+ "state": {
+ "trait3": {
+ "prop5": "bar"
+ }
+ }
+ }
+ }
+ }
+ })";
+ EXPECT_JSON_EQ(kExpected1, manager_.GetComponents());
+
+ EXPECT_JSON_EQ(kExpected1,
+ *manager_.GetComponentsForUserRole(UserRole::kOwner));
+
+ const char kExpected2[] = R"({
+ "comp1": {
+ "traits": [ "trait1", "trait2" ],
+ "state": {
+ "trait1": {
+ "prop1": "foo",
+ "prop2": "bar"
+ },
+ "trait2": {
+ "prop3": "baz"
+ }
+ }
+ },
+ "comp2": {
+ "traits": [ "trait2" ],
+ "state": {
+ "trait2": {
+ "prop3": "foo"
+ }
+ },
+ "components": {
+ "comp3": [
+ {
+ "traits": [ "trait3" ],
+ "state": {
+ "trait3": {
+ "prop5": "foo"
+ }
+ }
+ }
+ ],
+ "comp4": {
+ "traits": [ "trait3" ],
+ "state": {
+ "trait3": {
+ "prop5": "bar"
+ }
+ }
+ }
+ }
+ }
+ })";
+ EXPECT_JSON_EQ(kExpected2,
+ *manager_.GetComponentsForUserRole(UserRole::kManager));
+
+ const char kExpected3[] = R"({
+ "comp1": {
+ "traits": [ "trait1", "trait2" ],
+ "state": {
+ "trait1": {
+ "prop1": "foo",
+ "prop2": "bar"
+ }
+ }
+ },
+ "comp2": {
+ "traits": [ "trait2" ],
+ "components": {
+ "comp3": [
+ {
+ "traits": [ "trait3" ],
+ "state": {
+ "trait3": {
+ "prop5": "foo"
+ }
+ }
+ }
+ ],
+ "comp4": {
+ "traits": [ "trait3" ],
+ "state": {
+ "trait3": {
+ "prop5": "bar"
+ }
+ }
+ }
+ }
+ }
+ })";
+ EXPECT_JSON_EQ(kExpected3,
+ *manager_.GetComponentsForUserRole(UserRole::kUser));
+
+ const char kExpected4[] = R"({
+ "comp1": {
+ "traits": [ "trait1", "trait2" ],
+ "state": {
+ "trait1": {
+ "prop1": "foo"
+ }
+ }
+ },
+ "comp2": {
+ "traits": [ "trait2" ],
+ "components": {
+ "comp3": [
+ {
+ "traits": [ "trait3" ]
+ }
+ ],
+ "comp4": {
+ "traits": [ "trait3" ]
+ }
+ }
+ }
+ })";
+ EXPECT_JSON_EQ(kExpected4,
+ *manager_.GetComponentsForUserRole(UserRole::kViewer));
+}
+
} // namespace weave
diff --git a/src/privet/cloud_delegate.cc b/src/privet/cloud_delegate.cc
index f565687..0833780 100644
--- a/src/privet/cloud_delegate.cc
+++ b/src/privet/cloud_delegate.cc
@@ -151,8 +151,12 @@ class CloudDelegateImpl : public CloudDelegate {
return device_->GetSettings().xmpp_endpoint;
}
- const base::DictionaryValue& GetComponents() const override {
- return component_manager_->GetComponents();
+ std::unique_ptr<base::DictionaryValue> GetComponentsForUser(
+ const UserInfo& user_info) const override {
+ UserRole role;
+ std::string str_scope = EnumToString(user_info.scope());
+ CHECK(StringToEnum(str_scope, &role));
+ return component_manager_->GetComponentsForUserRole(role);
}
const base::DictionaryValue* FindComponent(const std::string& path,
diff --git a/src/privet/cloud_delegate.h b/src/privet/cloud_delegate.h
index 43b8904..5ae54cf 100644
--- a/src/privet/cloud_delegate.h
+++ b/src/privet/cloud_delegate.h
@@ -100,8 +100,10 @@ class CloudDelegate {
virtual std::string GetServiceUrl() const = 0;
virtual std::string GetXmppEndpoint() const = 0;
- // Returns dictionary with component tree.
- virtual const base::DictionaryValue& GetComponents() const = 0;
+ // Returns dictionary with component tree. The components contain only the
+ // state visible to the given user.
+ virtual std::unique_ptr<base::DictionaryValue> GetComponentsForUser(
+ const UserInfo& user_info) const = 0;
// Finds a component at the given path. Return nullptr in case of an error.
virtual const base::DictionaryValue* FindComponent(const std::string& path,
diff --git a/src/privet/mock_delegates.h b/src/privet/mock_delegates.h
index f04fb37..3fab9d0 100644
--- a/src/privet/mock_delegates.h
+++ b/src/privet/mock_delegates.h
@@ -188,7 +188,8 @@ class MockCloudDelegate : public CloudDelegate {
MOCK_CONST_METHOD0(GetOAuthUrl, std::string());
MOCK_CONST_METHOD0(GetServiceUrl, std::string());
MOCK_CONST_METHOD0(GetXmppEndpoint, std::string());
- MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&());
+ MOCK_CONST_METHOD1(MockGetComponentsForUser,
+ const base::DictionaryValue&(const UserInfo&));
MOCK_CONST_METHOD2(FindComponent,
const base::DictionaryValue*(const std::string& path,
ErrorPtr* error));
@@ -228,13 +229,21 @@ class MockCloudDelegate : public CloudDelegate {
EXPECT_CALL(*this, GetCloudId()).WillRepeatedly(Return("TestCloudId"));
test_dict_.Set("test", new base::DictionaryValue);
EXPECT_CALL(*this, GetTraits()).WillRepeatedly(ReturnRef(test_dict_));
- EXPECT_CALL(*this, GetComponents()).WillRepeatedly(ReturnRef(test_dict_));
+ EXPECT_CALL(*this, MockGetComponentsForUser(_))
+ .WillRepeatedly(ReturnRef(test_dict_));
EXPECT_CALL(*this, FindComponent(_, _)).Times(0);
}
ConnectionState connection_state_{ConnectionState::kOnline};
SetupState setup_state_{SetupState::kNone};
base::DictionaryValue test_dict_;
+
+ private:
+ std::unique_ptr<base::DictionaryValue> GetComponentsForUser(
+ const UserInfo& user_info) const override {
+ return std::unique_ptr<base::DictionaryValue>{
+ MockGetComponentsForUser(user_info).DeepCopy()};
+ }
};
} // namespace privet
diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc
index 83d5ef3..813812b 100644
--- a/src/privet/privet_handler.cc
+++ b/src/privet/privet_handler.cc
@@ -906,7 +906,8 @@ void PrivetHandler::HandleComponents(const base::DictionaryValue& input,
auto parts = Split(path, ".", true, false);
components->Set(parts.back(), CloneComponent(*component, filter).release());
} else {
- components = CloneComponentTree(cloud_->GetComponents(), filter);
+ components = CloneComponentTree(*cloud_->GetComponentsForUser(user_info),
+ filter);
}
base::DictionaryValue output;
output.Set(kComponentsKey, components.release());
diff --git a/src/privet/privet_handler_unittest.cc b/src/privet/privet_handler_unittest.cc
index ecf4797..b7fb758 100644
--- a/src/privet/privet_handler_unittest.cc
+++ b/src/privet/privet_handler_unittest.cc
@@ -484,6 +484,40 @@ TEST_F(PrivetHandlerTest, AuthLocalHighScope) {
HandleRequest("/privet/v3/auth", kInput));
}
+TEST_F(PrivetHandlerTest, ComponentsForUser) {
+ auth_header_ = "Privet 123";
+ const UserInfo kOwner{AuthScope::kOwner, TestUserId{"1"}};
+ const UserInfo kManager{AuthScope::kManager, TestUserId{"2"}};
+ const UserInfo kUser{AuthScope::kUser, TestUserId{"3"}};
+ const UserInfo kViewer{AuthScope::kViewer, TestUserId{"4"}};
+ const base::DictionaryValue components;
+ const std::string expected = R"({"components": {}, "fingerprint": "1"})";
+
+ EXPECT_CALL(security_, ParseAccessToken(_, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(kOwner), Return(true)));
+ EXPECT_CALL(cloud_, MockGetComponentsForUser(kOwner))
+ .WillOnce(ReturnRef(components));
+ EXPECT_JSON_EQ(expected, HandleRequest("/privet/v3/components", "{}"));
+
+ EXPECT_CALL(security_, ParseAccessToken(_, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(kManager), Return(true)));
+ EXPECT_CALL(cloud_, MockGetComponentsForUser(kManager))
+ .WillOnce(ReturnRef(components));
+ EXPECT_JSON_EQ(expected, HandleRequest("/privet/v3/components", "{}"));
+
+ EXPECT_CALL(security_, ParseAccessToken(_, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(kUser), Return(true)));
+ EXPECT_CALL(cloud_, MockGetComponentsForUser(kUser))
+ .WillOnce(ReturnRef(components));
+ EXPECT_JSON_EQ(expected, HandleRequest("/privet/v3/components", "{}"));
+
+ EXPECT_CALL(security_, ParseAccessToken(_, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(kViewer), Return(true)));
+ EXPECT_CALL(cloud_, MockGetComponentsForUser(kViewer))
+ .WillOnce(ReturnRef(components));
+ EXPECT_JSON_EQ(expected, HandleRequest("/privet/v3/components", "{}"));
+}
+
class PrivetHandlerTestWithAuth : public PrivetHandlerTest {
public:
void SetUp() override {
@@ -780,7 +814,8 @@ TEST_F(PrivetHandlerTestWithAuth, ComponentsWithFiltersAndPaths) {
base::DictionaryValue components;
LoadTestJson(kComponents, &components);
EXPECT_CALL(cloud_, FindComponent(_, _)).WillRepeatedly(Return(nullptr));
- EXPECT_CALL(cloud_, GetComponents()).WillRepeatedly(ReturnRef(components));
+ EXPECT_CALL(cloud_, MockGetComponentsForUser(_))
+ .WillRepeatedly(ReturnRef(components));
const char kExpected1[] = R"({
"components": {
"comp1": {
diff --git a/src/privet/privet_types.h b/src/privet/privet_types.h
index 0f51862..44be96f 100644
--- a/src/privet/privet_types.h
+++ b/src/privet/privet_types.h
@@ -62,6 +62,14 @@ class UserInfo {
AuthScope scope() const { return scope_; }
const UserAppId& id() const { return id_; }
+ bool operator==(const UserInfo& rhs) const {
+ return scope_ == rhs.scope_ && id_ == rhs.id_;
+ }
+
+ bool operator!=(const UserInfo& rhs) const {
+ return scope_ != rhs.scope_ || id_ != rhs.id_;
+ }
+
private:
AuthScope scope_;
UserAppId id_;
diff --git a/src/test/mock_component_manager.h b/src/test/mock_component_manager.h
index 2c1d695..de6ffee 100644
--- a/src/test/mock_component_manager.h
+++ b/src/test/mock_component_manager.h
@@ -65,12 +65,18 @@ class MockComponentManager : public ComponentManager {
MOCK_CONST_METHOD1(
FindCommandDefinition,
const base::DictionaryValue*(const std::string& command_name));
- MOCK_CONST_METHOD3(GetMinimalRole,
+ MOCK_CONST_METHOD3(GetCommandMinimalRole,
bool(const std::string& command_name,
UserRole* minimal_role,
ErrorPtr* error));
+ MOCK_CONST_METHOD3(GetStateMinimalRole,
+ bool(const std::string& state_property_name,
+ UserRole* minimal_role,
+ ErrorPtr* error));
MOCK_CONST_METHOD0(GetTraits, const base::DictionaryValue&());
MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&());
+ MOCK_CONST_METHOD1(MockGetComponentsForUserRole,
+ base::DictionaryValue*(UserRole));
MOCK_METHOD3(SetStateProperties,
bool(const std::string& component_path,
const base::DictionaryValue& dict,
@@ -118,6 +124,11 @@ class MockComponentManager : public ComponentManager {
const base::Callback<void(UpdateID)>& callback) override {
return Token{MockAddServerStateUpdatedCallback(callback)};
}
+ std::unique_ptr<base::DictionaryValue> GetComponentsForUserRole(
+ UserRole role) const override {
+ return std::unique_ptr<base::DictionaryValue>{
+ MockGetComponentsForUserRole(role)};
+ }
};
} // namespace test