mirror of
https://github.com/home-assistant/core.git
synced 2026-09-26 09:23:17 -04:00
Reuse an existing Supervisor system user instead of creating a duplicate (#182304)
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
7af5bcc88a
commit
0527dcd495
@@ -186,15 +186,28 @@ async def _async_get_or_create_supervisor_user(
|
||||
if user is None and legacy_user_id is not None:
|
||||
user = await hass.auth.async_get_user(legacy_user_id)
|
||||
|
||||
if user is None:
|
||||
# The storage naming the Supervisor user may have been lost. Reuse an
|
||||
# existing Supervisor system user instead of creating a duplicate.
|
||||
user = next(
|
||||
(
|
||||
existing
|
||||
for existing in await hass.auth.async_get_users()
|
||||
if existing.system_generated and existing.name == HASSIO_USER_NAME
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
if user is None:
|
||||
user = await hass.auth.async_create_system_user(
|
||||
HASSIO_USER_NAME, group_ids=[GROUP_ID_ADMIN]
|
||||
)
|
||||
if entry is not None:
|
||||
hass.config_entries.async_update_entry(
|
||||
entry,
|
||||
data={**entry.data, ENTRY_DATA_USER: user.id},
|
||||
)
|
||||
|
||||
if entry is not None and entry.data.get(ENTRY_DATA_USER) != user.id:
|
||||
hass.config_entries.async_update_entry(
|
||||
entry,
|
||||
data={**entry.data, ENTRY_DATA_USER: user.id},
|
||||
)
|
||||
|
||||
# Migrate old Hass.io users to be admin.
|
||||
if not user.is_admin:
|
||||
|
||||
@@ -33,6 +33,7 @@ from probatio import Invalid
|
||||
import pytest
|
||||
|
||||
from homeassistant.auth.const import GROUP_ID_ADMIN
|
||||
from homeassistant.auth.models import User
|
||||
from homeassistant.components import frontend, hassio
|
||||
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
||||
from homeassistant.components.hassio import (
|
||||
@@ -69,6 +70,7 @@ from homeassistant.components.homeassistant import (
|
||||
)
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import HASSIO_USER_NAME
|
||||
from homeassistant.core import CoreState, HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.helpers import device_registry as dr, issue_registry as ir
|
||||
@@ -444,6 +446,60 @@ async def test_setup_api_existing_hassio_user(
|
||||
assert hass.auth.async_validate_access_token(access_token) is None
|
||||
|
||||
|
||||
async def _async_assert_supervisor_user_adopted(
|
||||
hass: HomeAssistant, user: User, human: User
|
||||
) -> None:
|
||||
"""Assert setup adopted the existing Supervisor system user."""
|
||||
entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||
assert entry.data[ENTRY_DATA_USER] == user.id
|
||||
assert entry.data[ENTRY_DATA_USER] != human.id
|
||||
assert [
|
||||
existing
|
||||
for existing in await hass.auth.async_get_users()
|
||||
if existing.system_generated and existing.name == HASSIO_USER_NAME
|
||||
] == [user]
|
||||
|
||||
|
||||
async def test_setup_adopts_existing_supervisor_user(hass: HomeAssistant) -> None:
|
||||
"""Test setup reuses an existing Supervisor system user.
|
||||
|
||||
When the config entry data (and legacy store) naming the Supervisor user
|
||||
is lost, an existing Supervisor system user must be adopted instead of
|
||||
creating a duplicate. A regular user named alike must not be picked up.
|
||||
"""
|
||||
human = await hass.auth.async_create_user(HASSIO_USER_NAME)
|
||||
user = await hass.auth.async_create_system_user(
|
||||
HASSIO_USER_NAME, group_ids=[GROUP_ID_ADMIN]
|
||||
)
|
||||
MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN).add_to_hass(hass)
|
||||
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
assert await async_setup_component(hass, DOMAIN, {"hassio": {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await _async_assert_supervisor_user_adopted(hass, user, human)
|
||||
|
||||
|
||||
async def test_setup_adopts_existing_supervisor_user_without_entry(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test setup reuses an existing Supervisor system user without config entry.
|
||||
|
||||
Same as above, but with the config entry itself gone: the entry created by
|
||||
the system flow must name the adopted user.
|
||||
"""
|
||||
human = await hass.auth.async_create_user(HASSIO_USER_NAME)
|
||||
user = await hass.auth.async_create_system_user(
|
||||
HASSIO_USER_NAME, group_ids=[GROUP_ID_ADMIN]
|
||||
)
|
||||
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
assert await async_setup_component(hass, DOMAIN, {"hassio": {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await _async_assert_supervisor_user_adopted(hass, user, human)
|
||||
|
||||
|
||||
async def test_setup_migrates_legacy_hassio_store_to_config_entry(
|
||||
hass: HomeAssistant,
|
||||
hass_storage: dict[str, Any],
|
||||
|
||||
Reference in New Issue
Block a user