diff --git a/homeassistant/components/cloud/alexa_config.py b/homeassistant/components/cloud/alexa_config.py index 7394936f355..43ef0ee62da 100644 --- a/homeassistant/components/cloud/alexa_config.py +++ b/homeassistant/components/cloud/alexa_config.py @@ -56,12 +56,6 @@ class AlexaConfig(alexa_config.AbstractConfig): self._alexa_sync_unsub = None self._endpoint = None - prefs.async_listen_updates(self._async_prefs_updated) - hass.bus.async_listen( - entity_registry.EVENT_ENTITY_REGISTRY_UPDATED, - self._handle_entity_registry_updated, - ) - @property def enabled(self): """Return if Alexa is enabled.""" @@ -114,6 +108,12 @@ class AlexaConfig(alexa_config.AbstractConfig): start.async_at_start(self.hass, hass_started) + self._prefs.async_listen_updates(self._async_prefs_updated) + self.hass.bus.async_listen( + entity_registry.EVENT_ENTITY_REGISTRY_UPDATED, + self._handle_entity_registry_updated, + ) + def should_expose(self, entity_id): """If an entity should be exposed.""" if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES: @@ -171,6 +171,15 @@ class AlexaConfig(alexa_config.AbstractConfig): async def _async_prefs_updated(self, prefs): """Handle updated preferences.""" + if not self._cloud.is_logged_in: + if self.is_reporting_states: + await self.async_disable_proactive_mode() + + if self._alexa_sync_unsub: + self._alexa_sync_unsub() + self._alexa_sync_unsub = None + return + if ALEXA_DOMAIN not in self.hass.config.components and self.enabled: await async_setup_component(self.hass, ALEXA_DOMAIN, {}) diff --git a/homeassistant/components/cloud/google_config.py b/homeassistant/components/cloud/google_config.py index aed66ae179d..f1783771f2f 100644 --- a/homeassistant/components/cloud/google_config.py +++ b/homeassistant/components/cloud/google_config.py @@ -172,6 +172,13 @@ class CloudGoogleConfig(AbstractConfig): async def _async_prefs_updated(self, prefs): """Handle updated preferences.""" + if not self._cloud.is_logged_in: + if self.is_reporting_state: + self.async_disable_report_state() + if self.is_local_sdk_active: + self.async_disable_local_sdk() + return + if self.enabled and GOOGLE_DOMAIN not in self.hass.config.components: await async_setup_component(self.hass, GOOGLE_DOMAIN, {}) diff --git a/tests/components/cloud/test_alexa_config.py b/tests/components/cloud/test_alexa_config.py index 83c2a5aa2d1..60ef992dafb 100644 --- a/tests/components/cloud/test_alexa_config.py +++ b/tests/components/cloud/test_alexa_config.py @@ -28,6 +28,7 @@ async def test_alexa_config_expose_entity_prefs(hass, cloud_prefs, cloud_stub): conf = alexa_config.AlexaConfig( hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub ) + await conf.async_initialize() assert not conf.should_expose("light.kitchen") entity_conf["should_expose"] = True @@ -50,6 +51,7 @@ async def test_alexa_config_report_state(hass, cloud_prefs, cloud_stub): conf = alexa_config.AlexaConfig( hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub ) + await conf.async_initialize() assert cloud_prefs.alexa_report_state is False assert conf.should_report_state is False @@ -131,9 +133,9 @@ def patch_sync_helper(): async def test_alexa_update_expose_trigger_sync(hass, cloud_prefs, cloud_stub): """Test Alexa config responds to updating exposed entities.""" - alexa_config.AlexaConfig( + await alexa_config.AlexaConfig( hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub - ) + ).async_initialize() with patch_sync_helper() as (to_update, to_remove): await cloud_prefs.async_update_alexa_entity_config( @@ -166,9 +168,9 @@ async def test_alexa_update_expose_trigger_sync(hass, cloud_prefs, cloud_stub): async def test_alexa_entity_registry_sync(hass, mock_cloud_login, cloud_prefs): """Test Alexa config responds to entity registry.""" - alexa_config.AlexaConfig( + await alexa_config.AlexaConfig( hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"] - ) + ).async_initialize() with patch_sync_helper() as (to_update, to_remove): hass.bus.async_fire( @@ -218,9 +220,9 @@ async def test_alexa_entity_registry_sync(hass, mock_cloud_login, cloud_prefs): async def test_alexa_update_report_state(hass, cloud_prefs, cloud_stub): """Test Alexa config responds to reporting state.""" - alexa_config.AlexaConfig( + await alexa_config.AlexaConfig( hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub - ) + ).async_initialize() with patch( "homeassistant.components.cloud.alexa_config.AlexaConfig.async_sync_entities", @@ -244,3 +246,32 @@ def test_enabled_requires_valid_sub(hass, mock_expired_cloud_login, cloud_prefs) ) assert not config.enabled + + +async def test_alexa_handle_logout(hass, cloud_prefs, cloud_stub): + """Test Alexa config responds to logging out.""" + aconf = alexa_config.AlexaConfig( + hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub + ) + + await aconf.async_initialize() + + with patch( + "homeassistant.components.alexa.config.async_enable_proactive_mode", + return_value=Mock(), + ) as mock_enable: + await aconf.async_enable_proactive_mode() + + # This will trigger a prefs update when we logout. + await cloud_prefs.get_cloud_user() + + cloud_stub.is_logged_in = False + with patch.object( + cloud_stub.auth, + "async_check_token", + side_effect=AssertionError("Should not be called"), + ): + await cloud_prefs.async_set_username(None) + await hass.async_block_till_done() + + assert len(mock_enable.return_value.mock_calls) == 1 diff --git a/tests/components/cloud/test_google_config.py b/tests/components/cloud/test_google_config.py index 1f513dbf53e..f2528de221d 100644 --- a/tests/components/cloud/test_google_config.py +++ b/tests/components/cloud/test_google_config.py @@ -264,3 +264,32 @@ async def test_setup_integration(hass, mock_conf, cloud_prefs): await cloud_prefs.async_update() await hass.async_block_till_done() assert "google_assistant" in hass.config.components + + +async def test_google_handle_logout(hass, cloud_prefs, mock_cloud_login): + """Test Google config responds to logging out.""" + gconf = CloudGoogleConfig( + hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, Mock(is_logged_in=False) + ) + + await gconf.async_initialize() + + with patch( + "homeassistant.components.google_assistant.report_state.async_enable_report_state", + ) as mock_enable: + gconf.async_enable_report_state() + + assert len(mock_enable.mock_calls) == 1 + + # This will trigger a prefs update when we logout. + await cloud_prefs.get_cloud_user() + + with patch.object( + hass.data["cloud"].auth, + "async_check_token", + side_effect=AssertionError("Should not be called"), + ): + await cloud_prefs.async_set_username(None) + await hass.async_block_till_done() + + assert len(mock_enable.return_value.mock_calls) == 1