From 0d3062e00517217a9be7d68d979116c558a0fef6 Mon Sep 17 00:00:00 2001 From: Alex Vakulenko Date: Tue, 23 Feb 2016 16:03:43 -0800 Subject: 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 --- src/component_manager.h | 16 +- src/component_manager_impl.cc | 112 +++++++++++++- src/component_manager_impl.h | 21 ++- src/component_manager_unittest.cc | 268 +++++++++++++++++++++++++++++++++- src/privet/cloud_delegate.cc | 8 +- src/privet/cloud_delegate.h | 6 +- src/privet/mock_delegates.h | 13 +- src/privet/privet_handler.cc | 3 +- src/privet/privet_handler_unittest.cc | 37 ++++- src/privet/privet_types.h | 8 + src/test/mock_component_manager.h | 13 +- 11 files changed, 480 insertions(+), 25 deletions(-) (limited to 'src') 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 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::Map kMap[] = { {UserRole::kOwner, "owner"}, {UserRole::kManager, "manager"}, }; + +void RemoveInaccessibleState(const ComponentManagerImpl* manager, + base::DictionaryValue* component, + UserRole role) { + std::vector 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 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 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 +ComponentManagerImpl::GetComponentsForUserRole(UserRole role) const { + std::unique_ptr 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 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 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 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 GetComponentsForUser( + const UserInfo& user_info) const override { + return std::unique_ptr{ + 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& callback) override { return Token{MockAddServerStateUpdatedCallback(callback)}; } + std::unique_ptr GetComponentsForUserRole( + UserRole role) const override { + return std::unique_ptr{ + MockGetComponentsForUserRole(role)}; + } }; } // namespace test -- cgit v1.2.3