mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Auto recover mqtt config entry secret if Mosquitto add-on was re-installed (#124514)
Auto recover mqtt config entry secret if Mosquitto add-on is re-installed
This commit is contained in:
parent
76ebb0df08
commit
65216df3a5
@ -401,6 +401,36 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle re-authentication with MQTT broker."""
|
||||
self.entry = self.hass.config_entries.async_get_entry(self.context["entry_id"])
|
||||
if is_hassio(self.hass):
|
||||
# Check if entry setup matches the add-on discovery config
|
||||
addon_manager = get_addon_manager(self.hass)
|
||||
try:
|
||||
addon_discovery_config = (
|
||||
await addon_manager.async_get_addon_discovery_info()
|
||||
)
|
||||
except AddonError:
|
||||
# Follow manual flow if we have an error
|
||||
pass
|
||||
else:
|
||||
# Check if the addon secrets need to be renewed.
|
||||
# This will repair the config entry,
|
||||
# in case the official Mosquitto Broker addon was re-installed.
|
||||
if (
|
||||
entry_data[CONF_BROKER] == addon_discovery_config[CONF_HOST]
|
||||
and entry_data[CONF_PORT] == addon_discovery_config[CONF_PORT]
|
||||
and entry_data.get(CONF_USERNAME)
|
||||
== (username := addon_discovery_config.get(CONF_USERNAME))
|
||||
and entry_data.get(CONF_PASSWORD)
|
||||
!= (password := addon_discovery_config.get(CONF_PASSWORD))
|
||||
):
|
||||
_LOGGER.info(
|
||||
"Executing autorecovery %s add-on secrets",
|
||||
addon_manager.addon_name,
|
||||
)
|
||||
return await self.async_step_reauth_confirm(
|
||||
user_input={CONF_USERNAME: username, CONF_PASSWORD: password}
|
||||
)
|
||||
|
||||
return await self.async_step_reauth_confirm()
|
||||
|
||||
async def async_step_reauth_confirm(
|
||||
|
@ -1587,6 +1587,108 @@ async def test_step_reauth(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("discovery_info", [{"config": ADD_ON_DISCOVERY_INFO.copy()}])
|
||||
@pytest.mark.usefixtures(
|
||||
"mqtt_client_mock", "mock_reload_after_entry_update", "supervisor", "addon_running"
|
||||
)
|
||||
async def test_step_hassio_reauth(
|
||||
hass: HomeAssistant, mock_try_connection: MagicMock, addon_info: AsyncMock
|
||||
) -> None:
|
||||
"""Test that the reauth step works in case the Mosquitto broker add-on was re-installed."""
|
||||
|
||||
# Set up entry data based on the discovery data, but with a stale password
|
||||
entry_data = {
|
||||
mqtt.CONF_BROKER: "core-mosquitto",
|
||||
CONF_PORT: 1883,
|
||||
CONF_USERNAME: "mock-user",
|
||||
CONF_PASSWORD: "stale-secret",
|
||||
}
|
||||
|
||||
addon_info["hostname"] = "core-mosquitto"
|
||||
|
||||
# Prepare the config entry
|
||||
config_entry = MockConfigEntry(domain=mqtt.DOMAIN, data=entry_data)
|
||||
config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
assert config_entry.data.get(CONF_PASSWORD) == "stale-secret"
|
||||
|
||||
# Start reauth flow
|
||||
mock_try_connection.reset_mock()
|
||||
mock_try_connection.return_value = True
|
||||
config_entry.async_start_reauth(hass)
|
||||
await hass.async_block_till_done()
|
||||
flows = hass.config_entries.flow.async_progress()
|
||||
assert len(flows) == 0
|
||||
|
||||
# Assert the entry is updated automatically
|
||||
assert config_entry.data.get(CONF_PASSWORD) == "mock-pass"
|
||||
mock_try_connection.assert_called_once_with(
|
||||
{
|
||||
"broker": "core-mosquitto",
|
||||
"port": 1883,
|
||||
"username": "mock-user",
|
||||
"password": "mock-pass",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("discovery_info", "discovery_info_side_effect", "broker"),
|
||||
[
|
||||
({"config": ADD_ON_DISCOVERY_INFO.copy()}, AddonError, "core-mosquitto"),
|
||||
({"config": ADD_ON_DISCOVERY_INFO.copy()}, None, "broker-not-addon"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures(
|
||||
"mqtt_client_mock", "mock_reload_after_entry_update", "supervisor", "addon_running"
|
||||
)
|
||||
async def test_step_hassio_reauth_no_discovery_info(
|
||||
hass: HomeAssistant,
|
||||
mock_try_connection: MagicMock,
|
||||
addon_info: AsyncMock,
|
||||
broker: str,
|
||||
) -> None:
|
||||
"""Test hassio reauth flow defaults to manual flow.
|
||||
|
||||
Test that the reauth step defaults to
|
||||
normal reauth flow if fetching add-on discovery info failed,
|
||||
or the broker is not the add-on.
|
||||
"""
|
||||
|
||||
# Set up entry data based on the discovery data, but with a stale password
|
||||
entry_data = {
|
||||
mqtt.CONF_BROKER: broker,
|
||||
CONF_PORT: 1883,
|
||||
CONF_USERNAME: "mock-user",
|
||||
CONF_PASSWORD: "wrong-pass",
|
||||
}
|
||||
|
||||
addon_info["hostname"] = "core-mosquitto"
|
||||
|
||||
# Prepare the config entry
|
||||
config_entry = MockConfigEntry(domain=mqtt.DOMAIN, data=entry_data)
|
||||
config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
assert config_entry.data.get(CONF_PASSWORD) == "wrong-pass"
|
||||
|
||||
# Start reauth flow
|
||||
mock_try_connection.reset_mock()
|
||||
mock_try_connection.return_value = True
|
||||
config_entry.async_start_reauth(hass)
|
||||
await hass.async_block_till_done()
|
||||
flows = hass.config_entries.flow.async_progress()
|
||||
assert len(flows) == 1
|
||||
result = flows[0]
|
||||
assert result["step_id"] == "reauth_confirm"
|
||||
assert result["context"]["source"] == "reauth"
|
||||
|
||||
# Assert the entry is not updated
|
||||
assert config_entry.data.get(CONF_PASSWORD) == "wrong-pass"
|
||||
mock_try_connection.assert_not_called()
|
||||
|
||||
|
||||
async def test_options_user_connection_fails(
|
||||
hass: HomeAssistant, mock_try_connection_time_out: MagicMock
|
||||
) -> None:
|
||||
|
Loading…
x
Reference in New Issue
Block a user