From b91b553ce52b76c7b2b129c055e27842e72c9911 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 2 Jul 2021 20:56:51 +0200 Subject: [PATCH] Abort existing reauth flow on entry removal (#52407) --- homeassistant/config_entries.py | 13 +++++++++++++ tests/test_config_entries.py | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index 49892937217..2bb8c4f3e29 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -819,6 +819,19 @@ class ConfigEntries: dev_reg.async_clear_config_entry(entry_id) ent_reg.async_clear_config_entry(entry_id) + # If the configuration entry is removed during reauth, it should + # abort any reauth flow that is active for the removed entry. + for progress_flow in self.hass.config_entries.flow.async_progress(): + context = progress_flow.get("context") + if ( + context + and context["source"] == SOURCE_REAUTH + and "entry_id" in context + and context["entry_id"] == entry_id + and "flow_id" in progress_flow + ): + self.hass.config_entries.flow.async_abort(progress_flow["flow_id"]) + # After we have fully removed an "ignore" config entry we can try and rediscover it so that a # user is able to immediately start configuring it. We do this by starting a new flow with # the 'unignore' step. If the integration doesn't implement async_step_unignore then diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index 615b97fb990..7bcc83048a4 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -337,6 +337,30 @@ async def test_remove_entry(hass, manager): assert not entity_entry_list +async def test_remove_entry_cancels_reauth(hass, manager): + """Tests that removing a config entry, also aborts existing reauth flows.""" + entry = MockConfigEntry(title="test_title", domain="test") + + mock_setup_entry = AsyncMock(side_effect=ConfigEntryAuthFailed()) + mock_integration(hass, MockModule("test", async_setup_entry=mock_setup_entry)) + mock_entity_platform(hass, "config_flow.test", None) + + entry.add_to_hass(hass) + await entry.async_setup(hass) + await hass.async_block_till_done() + + flows = hass.config_entries.flow.async_progress() + assert len(flows) == 1 + assert flows[0]["context"]["entry_id"] == entry.entry_id + assert flows[0]["context"]["source"] == config_entries.SOURCE_REAUTH + assert entry.state is config_entries.ConfigEntryState.SETUP_ERROR + + await manager.async_remove(entry.entry_id) + + flows = hass.config_entries.flow.async_progress() + assert len(flows) == 0 + + async def test_remove_entry_handles_callback_error(hass, manager): """Test that exceptions in the remove callback are handled.""" mock_setup_entry = AsyncMock(return_value=True)