1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-02-14 23:19:37 +00:00

Tighten list_users() to trust Core's auth/list contract

Core's config/auth/list WS command always returns a list, never None.
Replace the silent `if not raw: return []` (which also swallowed empty
lists) with an assert, remove the dead AuthListUsersNoneResponseError
exception class, and document the HomeAssistantWSError contract in the
docstring.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Stefan Agner
2026-02-12 11:05:46 +01:00
parent 33b0d4b256
commit 2a9ef0565c
4 changed files with 8 additions and 29 deletions

View File

@@ -620,18 +620,6 @@ class AuthListUsersError(AuthError, APIUnknownSupervisorError):
message_template = "Can't request listing users on Home Assistant"
class AuthListUsersNoneResponseError(AuthError, APIInternalServerError):
"""Auth error if listing users returned invalid None response."""
error_key = "auth_list_users_none_response_error"
message_template = "Home Assistant returned invalid response of `{none}` instead of a list of users. Check Home Assistant logs for details (check with `{logs_command}`)"
extra_fields = {"none": "None", "logs_command": "ha core logs"}
def __init__(self, logger: Callable[..., None] | None = None) -> None:
"""Initialize exception."""
super().__init__(None, logger)
class AuthInvalidNonStringValueError(AuthError, APIUnauthorized):
"""Auth error if something besides a string provided as username or password."""

View File

@@ -568,10 +568,12 @@ class HomeAssistant(FileConfiguration, CoreSysAttributes):
self._data[attr] = data[attr]
async def list_users(self) -> list[HomeAssistantUser]:
"""Fetch list of all users from Home Assistant Core via WebSocket."""
"""Fetch list of all users from Home Assistant Core via WebSocket.
Raises HomeAssistantWSError on WebSocket connection/communication failure.
"""
raw: list[dict[str, Any]] | None = await self.websocket.async_send_command(
{ATTR_TYPE: "config/auth/list"}
)
if not raw:
return []
assert raw is not None
return [HomeAssistantUser.from_dict(data) for data in raw]

View File

@@ -189,18 +189,6 @@ async def test_list_users_ws_error(
assert "Can't request listing users on Home Assistant: fail" in caplog.text
async def test_list_users_none_response(
api_client: TestClient,
ha_ws_client: AsyncMock,
):
"""Test None response from WS returns empty user list."""
ha_ws_client.async_send_command.return_value = None
resp = await api_client.get("/auth/list")
assert resp.status == 200
result = await resp.json()
assert result["data"]["users"] == []
@pytest.mark.parametrize(
("field", "api_client"),
[("username", TEST_ADDON_SLUG), ("user", TEST_ADDON_SLUG)],

View File

@@ -59,9 +59,10 @@ async def test_load(
async def test_list_users_none(coresys: CoreSys, ha_ws_client: AsyncMock):
"""Test list users returning none does not fail."""
"""Test list users asserts on unexpected None response from Core."""
ha_ws_client.async_send_command.return_value = None
assert await coresys.homeassistant.list_users() == []
with pytest.raises(AssertionError):
await coresys.homeassistant.list_users()
async def test_write_pulse_error(coresys: CoreSys, caplog: pytest.LogCaptureFixture):