mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Ensure entry_id is set on reauth/reconfigure flows (#129319)
* Ensure entry_id is set on reauth/reconfigure flows * Improve * Improve * Use report helper * Adjust deprecation date * Update config_entries.py * Improve message and adjust tests * Apply suggestions from code review Co-authored-by: G Johansson <goran.johansson@shiftit.se> --------- Co-authored-by: G Johansson <goran.johansson@shiftit.se>
This commit is contained in:
parent
5430eca93e
commit
b626c9b450
@ -1260,13 +1260,24 @@ class ConfigEntriesFlowManager(
|
|||||||
if not context or "source" not in context:
|
if not context or "source" not in context:
|
||||||
raise KeyError("Context not set or doesn't have a source set")
|
raise KeyError("Context not set or doesn't have a source set")
|
||||||
|
|
||||||
|
# reauth/reconfigure flows should be linked to a config entry
|
||||||
|
if (source := context["source"]) in {
|
||||||
|
SOURCE_REAUTH,
|
||||||
|
SOURCE_RECONFIGURE,
|
||||||
|
} and "entry_id" not in context:
|
||||||
|
# Deprecated in 2024.12, should fail in 2025.12
|
||||||
|
report(
|
||||||
|
f"initialises a {source} flow without a link to the config entry",
|
||||||
|
error_if_integration=False,
|
||||||
|
error_if_core=True,
|
||||||
|
)
|
||||||
|
|
||||||
flow_id = ulid_util.ulid_now()
|
flow_id = ulid_util.ulid_now()
|
||||||
|
|
||||||
# Avoid starting a config flow on an integration that only supports
|
# Avoid starting a config flow on an integration that only supports
|
||||||
# a single config entry, but which already has an entry
|
# a single config entry, but which already has an entry
|
||||||
if (
|
if (
|
||||||
context.get("source")
|
source not in {SOURCE_IGNORE, SOURCE_REAUTH, SOURCE_RECONFIGURE}
|
||||||
not in {SOURCE_IGNORE, SOURCE_REAUTH, SOURCE_RECONFIGURE}
|
|
||||||
and self.config_entries.async_has_entries(handler, include_ignore=False)
|
and self.config_entries.async_has_entries(handler, include_ignore=False)
|
||||||
and await _support_single_config_entry_only(self.hass, handler)
|
and await _support_single_config_entry_only(self.hass, handler)
|
||||||
):
|
):
|
||||||
@ -1280,7 +1291,7 @@ class ConfigEntriesFlowManager(
|
|||||||
|
|
||||||
loop = self.hass.loop
|
loop = self.hass.loop
|
||||||
|
|
||||||
if context["source"] == SOURCE_IMPORT:
|
if source == SOURCE_IMPORT:
|
||||||
self._pending_import_flows[handler][flow_id] = loop.create_future()
|
self._pending_import_flows[handler][flow_id] = loop.create_future()
|
||||||
|
|
||||||
cancel_init_future = loop.create_future()
|
cancel_init_future = loop.create_future()
|
||||||
|
@ -37,7 +37,7 @@ from homeassistant.exceptions import (
|
|||||||
ConfigEntryNotReady,
|
ConfigEntryNotReady,
|
||||||
HomeAssistantError,
|
HomeAssistantError,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
from homeassistant.helpers import entity_registry as er, frame, issue_registry as ir
|
||||||
from homeassistant.helpers.discovery_flow import DiscoveryKey
|
from homeassistant.helpers.discovery_flow import DiscoveryKey
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.json import json_dumps
|
from homeassistant.helpers.json import json_dumps
|
||||||
@ -4779,6 +4779,74 @@ async def test_reauth(
|
|||||||
assert len(hass.config_entries.flow.async_progress()) == 1
|
assert len(hass.config_entries.flow.async_progress()) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"source", [config_entries.SOURCE_REAUTH, config_entries.SOURCE_RECONFIGURE]
|
||||||
|
)
|
||||||
|
async def test_reauth_reconfigure_missing_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
manager: config_entries.ConfigEntries,
|
||||||
|
source: str,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test the async_reauth_helper."""
|
||||||
|
entry = MockConfigEntry(title="test_title", domain="test")
|
||||||
|
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)
|
||||||
|
|
||||||
|
await manager.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
with pytest.raises(
|
||||||
|
RuntimeError,
|
||||||
|
match=f"Detected code that initialises a {source} flow without a link "
|
||||||
|
"to the config entry. Please report this issue.",
|
||||||
|
):
|
||||||
|
await manager.flow.async_init("test", context={"source": source})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
flows = hass.config_entries.flow.async_progress()
|
||||||
|
assert len(flows) == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("mock_integration_frame")
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"source", [config_entries.SOURCE_REAUTH, config_entries.SOURCE_RECONFIGURE]
|
||||||
|
)
|
||||||
|
async def test_reauth_reconfigure_missing_entry_component(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
manager: config_entries.ConfigEntries,
|
||||||
|
source: str,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test the async_reauth_helper."""
|
||||||
|
entry = MockConfigEntry(title="test_title", domain="test")
|
||||||
|
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)
|
||||||
|
|
||||||
|
await manager.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
with patch.object(frame, "_REPORTED_INTEGRATIONS", set()):
|
||||||
|
await manager.flow.async_init("test", context={"source": source})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Flow still created, but deprecation logged
|
||||||
|
flows = hass.config_entries.flow.async_progress()
|
||||||
|
assert len(flows) == 1
|
||||||
|
assert flows[0]["context"]["source"] == source
|
||||||
|
|
||||||
|
assert (
|
||||||
|
f"Detected that integration 'hue' initialises a {source} flow"
|
||||||
|
" without a link to the config entry at homeassistant/components" in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_reconfigure(
|
async def test_reconfigure(
|
||||||
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -5012,7 +5080,9 @@ async def test_initializing_flows_canceled_on_shutdown(
|
|||||||
config_entries.HANDLERS, {"comp": MockFlowHandler, "test": MockFlowHandler}
|
config_entries.HANDLERS, {"comp": MockFlowHandler, "test": MockFlowHandler}
|
||||||
):
|
):
|
||||||
task = asyncio.create_task(
|
task = asyncio.create_task(
|
||||||
manager.flow.async_init("test", context={"source": "reauth"})
|
manager.flow.async_init(
|
||||||
|
"test", context={"source": "reauth", "entry_id": "abc"}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
manager.flow.async_shutdown()
|
manager.flow.async_shutdown()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user