mirror of
https://github.com/home-assistant/core.git
synced 2026-05-28 03:06:30 +01:00
a19c2ee9ef
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
217 lines
7.3 KiB
Python
217 lines
7.3 KiB
Python
"""The tests for the hassio component."""
|
|
|
|
from contextlib import AbstractContextManager, ExitStack as DefaultContext
|
|
from http import HTTPStatus
|
|
from unittest.mock import MagicMock, Mock, patch
|
|
|
|
from aiohttp.test_utils import TestClient
|
|
from aiohttp.web_exceptions import HTTPUnauthorized
|
|
import pytest
|
|
|
|
from homeassistant.auth.providers.homeassistant import InvalidAuth
|
|
from homeassistant.components.hassio.auth import HassIOBaseAuth
|
|
from homeassistant.components.hassio.const import DATA_HASSIO_SUPERVISOR_USER
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
|
|
async def test_auth_success(hassio_client_supervisor: TestClient) -> None:
|
|
"""Test no auth needed for ."""
|
|
with patch(
|
|
"homeassistant.auth.providers.homeassistant."
|
|
"HassAuthProvider.async_validate_login",
|
|
) as mock_login:
|
|
resp = await hassio_client_supervisor.post(
|
|
"/api/hassio_auth",
|
|
json={"username": "test", "password": "123456", "addon": "samba"},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.OK
|
|
mock_login.assert_called_with("test", "123456")
|
|
|
|
|
|
async def test_auth_fails_no_supervisor(hassio_client: TestClient) -> None:
|
|
"""Test if only supervisor can access."""
|
|
with patch(
|
|
"homeassistant.auth.providers.homeassistant."
|
|
"HassAuthProvider.async_validate_login",
|
|
) as mock_login:
|
|
resp = await hassio_client.post(
|
|
"/api/hassio_auth",
|
|
json={"username": "test", "password": "123456", "addon": "samba"},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.UNAUTHORIZED
|
|
assert not mock_login.called
|
|
|
|
|
|
async def test_auth_fails_no_auth(hassio_noauth_client: TestClient) -> None:
|
|
"""Test if only supervisor can access."""
|
|
with patch(
|
|
"homeassistant.auth.providers.homeassistant."
|
|
"HassAuthProvider.async_validate_login",
|
|
) as mock_login:
|
|
resp = await hassio_noauth_client.post(
|
|
"/api/hassio_auth",
|
|
json={"username": "test", "password": "123456", "addon": "samba"},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.UNAUTHORIZED
|
|
assert not mock_login.called
|
|
|
|
|
|
async def test_login_error(hassio_client_supervisor: TestClient) -> None:
|
|
"""Test no auth needed for error."""
|
|
with patch(
|
|
"homeassistant.auth.providers.homeassistant."
|
|
"HassAuthProvider.async_validate_login",
|
|
Mock(side_effect=InvalidAuth()),
|
|
) as mock_login:
|
|
resp = await hassio_client_supervisor.post(
|
|
"/api/hassio_auth",
|
|
json={"username": "test", "password": "123456", "addon": "samba"},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.NOT_FOUND
|
|
mock_login.assert_called_with("test", "123456")
|
|
|
|
|
|
async def test_login_no_data(hassio_client_supervisor: TestClient) -> None:
|
|
"""Test auth with no data -> error."""
|
|
with patch(
|
|
"homeassistant.auth.providers.homeassistant."
|
|
"HassAuthProvider.async_validate_login",
|
|
Mock(side_effect=InvalidAuth()),
|
|
) as mock_login:
|
|
resp = await hassio_client_supervisor.post("/api/hassio_auth")
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.BAD_REQUEST
|
|
assert not mock_login.called
|
|
|
|
|
|
async def test_login_no_username(hassio_client_supervisor: TestClient) -> None:
|
|
"""Test auth with no username in data -> error."""
|
|
with patch(
|
|
"homeassistant.auth.providers.homeassistant."
|
|
"HassAuthProvider.async_validate_login",
|
|
Mock(side_effect=InvalidAuth()),
|
|
) as mock_login:
|
|
resp = await hassio_client_supervisor.post(
|
|
"/api/hassio_auth", json={"password": "123456", "addon": "samba"}
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.BAD_REQUEST
|
|
assert not mock_login.called
|
|
|
|
|
|
async def test_login_success_extra(hassio_client_supervisor: TestClient) -> None:
|
|
"""Test auth with extra data."""
|
|
with patch(
|
|
"homeassistant.auth.providers.homeassistant."
|
|
"HassAuthProvider.async_validate_login",
|
|
) as mock_login:
|
|
resp = await hassio_client_supervisor.post(
|
|
"/api/hassio_auth",
|
|
json={
|
|
"username": "test",
|
|
"password": "123456",
|
|
"addon": "samba",
|
|
"path": "/share",
|
|
},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.OK
|
|
mock_login.assert_called_with("test", "123456")
|
|
|
|
|
|
async def test_password_success(hassio_client_supervisor: TestClient) -> None:
|
|
"""Test no auth needed for ."""
|
|
with patch(
|
|
"homeassistant.auth.providers.homeassistant."
|
|
"HassAuthProvider.async_change_password",
|
|
) as mock_change:
|
|
resp = await hassio_client_supervisor.post(
|
|
"/api/hassio_auth/password_reset",
|
|
json={"username": "test", "password": "123456"},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.OK
|
|
mock_change.assert_called_with("test", "123456")
|
|
|
|
|
|
async def test_password_fails_no_supervisor(hassio_client: TestClient) -> None:
|
|
"""Test if only supervisor can access."""
|
|
resp = await hassio_client.post(
|
|
"/api/hassio_auth/password_reset",
|
|
json={"username": "test", "password": "123456"},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.UNAUTHORIZED
|
|
|
|
|
|
async def test_password_fails_no_auth(hassio_noauth_client: TestClient) -> None:
|
|
"""Test if only supervisor can access."""
|
|
resp = await hassio_noauth_client.post(
|
|
"/api/hassio_auth/password_reset",
|
|
json={"username": "test", "password": "123456"},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.UNAUTHORIZED
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("peername", "unix_socket", "expectation"),
|
|
[
|
|
# Unix socket transports report an empty string for peername. Before
|
|
# the fix this raised IndexError on `peername[0]`.
|
|
("", True, DefaultContext()),
|
|
# Defensive: a TCP transport with no peername at all should be
|
|
# rejected, not crash.
|
|
(None, False, pytest.raises(HTTPUnauthorized)),
|
|
],
|
|
)
|
|
@pytest.mark.usefixtures("hassio_stubs")
|
|
async def test_check_access_unix_socket_or_missing_peername(
|
|
hass: HomeAssistant,
|
|
peername: str | None,
|
|
unix_socket: bool,
|
|
expectation: AbstractContextManager,
|
|
) -> None:
|
|
"""Test _check_access handles Unix socket requests and missing peername."""
|
|
user = hass.data.get(DATA_HASSIO_SUPERVISOR_USER)
|
|
assert user is not None
|
|
|
|
auth_view = HassIOBaseAuth(hass)
|
|
request = MagicMock()
|
|
request.transport.get_extra_info.return_value = peername
|
|
request.__getitem__.return_value = user
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.components.hassio.auth.is_supervisor_unix_socket_request",
|
|
return_value=unix_socket,
|
|
),
|
|
expectation,
|
|
):
|
|
auth_view._check_access(request)
|
|
|
|
|
|
async def test_password_no_user(hassio_client_supervisor: TestClient) -> None:
|
|
"""Test changing password for invalid user."""
|
|
resp = await hassio_client_supervisor.post(
|
|
"/api/hassio_auth/password_reset",
|
|
json={"username": "test", "password": "123456"},
|
|
)
|
|
|
|
# Check we got right response
|
|
assert resp.status == HTTPStatus.NOT_FOUND
|