diff --git a/homeassistant/components/cloud/http_api.py b/homeassistant/components/cloud/http_api.py index 03fd8400dfa..c3809f76b8c 100644 --- a/homeassistant/components/cloud/http_api.py +++ b/homeassistant/components/cloud/http_api.py @@ -492,7 +492,7 @@ async def google_assistant_list(hass, connection, msg): { "entity_id": entity.entity_id, "traits": [trait.name for trait in entity.traits()], - "might_2fa": entity.might_2fa(), + "might_2fa": entity.might_2fa_traits(), } ) diff --git a/homeassistant/components/google_assistant/helpers.py b/homeassistant/components/google_assistant/helpers.py index 6ba301c01e8..bbdb8a82183 100644 --- a/homeassistant/components/google_assistant/helpers.py +++ b/homeassistant/components/google_assistant/helpers.py @@ -372,14 +372,19 @@ class GoogleEntity: @callback def might_2fa(self) -> bool: """Return if the entity might encounter 2FA.""" + if not self.config.should_2fa(self.state): + return False + + return self.might_2fa_traits() + + @callback + def might_2fa_traits(self) -> bool: + """Return if the entity might encounter 2FA based on just traits.""" state = self.state domain = state.domain features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) device_class = state.attributes.get(ATTR_DEVICE_CLASS) - if not self.config.should_2fa(state): - return False - return any( trait.might_2fa(domain, features, device_class) for trait in self.traits() ) diff --git a/tests/components/cloud/test_http_api.py b/tests/components/cloud/test_http_api.py index 8cb4a0b9636..2cfca8e6b92 100644 --- a/tests/components/cloud/test_http_api.py +++ b/tests/components/cloud/test_http_api.py @@ -688,20 +688,30 @@ async def test_list_google_entities(hass, hass_ws_client, setup_api, mock_cloud_ entity = GoogleEntity( hass, MockConfig(should_expose=lambda *_: False), State("light.kitchen", "on") ) + entity2 = GoogleEntity( + hass, + MockConfig(should_expose=lambda *_: True, should_2fa=lambda *_: False), + State("cover.garage", "open", {"device_class": "garage"}), + ) with patch( "homeassistant.components.google_assistant.helpers.async_get_entities", - return_value=[entity], + return_value=[entity, entity2], ): await client.send_json({"id": 5, "type": "cloud/google_assistant/entities"}) response = await client.receive_json() assert response["success"] - assert len(response["result"]) == 1 + assert len(response["result"]) == 2 assert response["result"][0] == { "entity_id": "light.kitchen", "might_2fa": False, "traits": ["action.devices.traits.OnOff"], } + assert response["result"][1] == { + "entity_id": "cover.garage", + "might_2fa": True, + "traits": ["action.devices.traits.OpenClose"], + } async def test_update_google_entity(hass, hass_ws_client, setup_api, mock_cloud_login): diff --git a/tests/components/google_assistant/__init__.py b/tests/components/google_assistant/__init__.py index 802b7968ee6..79684bdeb44 100644 --- a/tests/components/google_assistant/__init__.py +++ b/tests/components/google_assistant/__init__.py @@ -33,6 +33,7 @@ class MockConfig(helpers.AbstractConfig): """Initialize config.""" super().__init__(hass) self._should_expose = should_expose + self._should_2fa = should_2fa self._secure_devices_pin = secure_devices_pin self._entity_config = entity_config or {} self._local_sdk_webhook_id = local_sdk_webhook_id @@ -73,6 +74,10 @@ class MockConfig(helpers.AbstractConfig): """Expose it all.""" return self._should_expose is None or self._should_expose(state) + def should_2fa(self, state): + """Expose it all.""" + return self._should_2fa is None or self._should_2fa(state) + BASIC_CONFIG = MockConfig() diff --git a/tests/components/google_assistant/test_trait.py b/tests/components/google_assistant/test_trait.py index d0ed9a9d33c..a2b8f2e9ea7 100644 --- a/tests/components/google_assistant/test_trait.py +++ b/tests/components/google_assistant/test_trait.py @@ -845,10 +845,8 @@ async def test_lock_unlock_unlock(hass): assert err.value.code == const.ERR_CHALLENGE_NOT_SETUP # Test with 2FA override - with patch( - "homeassistant.components.google_assistant.helpers" - ".AbstractConfig.should_2fa", - return_value=False, + with patch.object( + BASIC_CONFIG, "should_2fa", return_value=False, ): await trt.execute(trait.COMMAND_LOCKUNLOCK, BASIC_DATA, {"lock": False}, {}) assert len(calls) == 2