Prevent `async_create_entry` from reauth/reconfigure flows (#127527)

* Prevent `async_create_entry` from reauth/reconfigure flows

* Adjust message

* Don't raise just yet

* Adjust message

* Fix string

* Remove invalid comment

* Add parameter

* Use count parameter

* Remove another branching
pull/127942/head
epenet 2024-10-08 15:19:58 +02:00 committed by GitHub
parent 4e15556eeb
commit 5836a85340
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 95 additions and 0 deletions

View File

@ -2726,6 +2726,20 @@ class ConfigFlow(ConfigEntryBaseFlow):
options: Mapping[str, Any] | None = None,
) -> ConfigFlowResult:
"""Finish config flow and create a config entry."""
if self.source in {SOURCE_REAUTH, SOURCE_RECONFIGURE}:
report_issue = async_suggest_report_issue(
self.hass, integration_domain=self.handler
)
_LOGGER.warning(
(
"Detected %s config flow creating a new entry, "
"when it is expected to update an existing entry and abort. "
"This will stop working in %s, please %s"
),
self.source,
"2025.11",
report_issue,
)
result = super().async_create_entry(
title=title,
data=data,

View File

@ -6789,6 +6789,87 @@ async def test_state_cache_is_cleared_on_entry_disable(hass: HomeAssistant) -> N
assert loaded["disabled_by"] == "user"
@pytest.mark.parametrize(
("original_unique_id", "new_unique_id", "count"),
[
("unique", "unique", 1),
("unique", "new", 2),
("unique", None, 2),
(None, "unique", 2),
],
)
@pytest.mark.parametrize(
"source",
[config_entries.SOURCE_REAUTH, config_entries.SOURCE_RECONFIGURE],
)
async def test_create_entry_reauth_reconfigure(
hass: HomeAssistant,
source: str,
original_unique_id: str | None,
new_unique_id: str | None,
count: int,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test to highlight unexpected behavior on create_entry."""
entry = MockConfigEntry(
title="From config flow",
domain="test",
entry_id="01J915Q6T9F6G5V0QJX6HBC94T",
data={"host": "any", "port": 123},
unique_id=original_unique_id,
)
entry.add_to_hass(hass)
mock_setup_entry = AsyncMock(return_value=True)
mock_integration(hass, MockModule("test", async_setup_entry=mock_setup_entry))
mock_platform(hass, "test.config_flow", None)
class TestFlow(config_entries.ConfigFlow):
VERSION = 1
async def async_step_user(self, user_input=None):
"""Test user step."""
return await self._async_step_confirm()
async def async_step_reauth(self, entry_data):
"""Test reauth step."""
return await self._async_step_confirm()
async def async_step_reconfigure(self, user_input=None):
"""Test reauth step."""
return await self._async_step_confirm()
async def _async_step_confirm(self):
"""Confirm input."""
await self.async_set_unique_id(new_unique_id)
return self.async_create_entry(
title="From config flow",
data={"token": "supersecret"},
)
assert len(hass.config_entries.async_entries("test")) == 1
with mock_config_flow("test", TestFlow):
result = await getattr(entry, f"start_{source}_flow")(hass)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
entries = hass.config_entries.async_entries("test")
assert len(entries) == count
if count == 1:
# Show that the previous entry got binned and recreated
assert entries[0].entry_id != entry.entry_id
assert (
f"Detected {source} config flow creating a new entry, when it is expected "
"to update an existing entry and abort. This will stop working in "
"2025.11, please create a bug report at https://github.com/home"
"-assistant/core/issues?q=is%3Aopen+is%3Aissue+"
"label%3A%22integration%3A+test%22"
) in caplog.text
async def test_async_update_entry_unique_id_collision(
hass: HomeAssistant,
manager: config_entries.ConfigEntries,