Files
wled-screen-controller-mixed/server/tests/e2e/test_auth_flow.py
alexei.dolgolyov 7380b33b9b
Some checks failed
Lint & Test / test (push) Failing after 9s
fix: resolve all 153 ruff lint errors for CI
Auto-fixed 138 unused imports and f-string issues. Manually fixed:
ambiguous variable names (l→layer), availability-check imports using
importlib.util.find_spec, unused Color import, ImagePool forward ref
via TYPE_CHECKING, multi-statement semicolons, and E402 suppression.
2026-03-22 01:29:26 +03:00

124 lines
4.4 KiB
Python

"""E2E: Authentication enforcement.
Tests that protected endpoints require valid auth, and public endpoints work
without auth.
Uses the `client` fixture (which has the correct auth header set), and
helpers to make unauthenticated requests by temporarily removing the header.
"""
def _unauth_get(client, url):
"""Make a GET request without the Authorization header."""
saved = client.headers.pop("Authorization", None)
try:
return client.get(url)
finally:
if saved is not None:
client.headers["Authorization"] = saved
def _unauth_request(client, method, url, **kwargs):
"""Make a request without the Authorization header."""
saved = client.headers.pop("Authorization", None)
try:
return client.request(method, url, **kwargs)
finally:
if saved is not None:
client.headers["Authorization"] = saved
def _with_header(client, method, url, auth_value, **kwargs):
"""Make a request with a custom Authorization header."""
saved = client.headers.get("Authorization")
client.headers["Authorization"] = auth_value
try:
return client.request(method, url, **kwargs)
finally:
if saved is not None:
client.headers["Authorization"] = saved
else:
client.headers.pop("Authorization", None)
class TestAuthEnforcement:
"""Verify API key authentication is enforced correctly."""
def test_request_without_auth_returns_401(self, client):
"""Protected endpoint without Authorization header returns 401."""
resp = _unauth_get(client, "/api/v1/devices")
assert resp.status_code == 401
def test_request_with_wrong_key_returns_401(self, client):
"""Protected endpoint with an incorrect API key returns 401."""
resp = _with_header(
client, "GET", "/api/v1/devices",
auth_value="Bearer wrong-key-12345",
)
assert resp.status_code == 401
def test_request_with_correct_key_returns_200(self, client):
"""Protected endpoint with valid API key succeeds."""
resp = client.get("/api/v1/devices")
assert resp.status_code == 200
def test_health_endpoint_is_public(self, client):
"""Health check does not require authentication."""
resp = _unauth_get(client, "/health")
assert resp.status_code == 200
data = resp.json()
assert data["status"] == "healthy"
def test_version_endpoint_is_public(self, client):
"""Version endpoint does not require authentication."""
resp = _unauth_get(client, "/api/v1/version")
assert resp.status_code == 200
data = resp.json()
assert "version" in data
assert "api_version" in data
def test_post_without_auth_returns_401(self, client):
"""Creating a device without auth fails."""
resp = _unauth_request(
client, "POST", "/api/v1/devices",
json={
"name": "Unauthorized Device",
"url": "mock://test",
"device_type": "mock",
"led_count": 10,
},
)
assert resp.status_code == 401
def test_delete_without_auth_returns_401(self, client):
"""Deleting a device without auth fails."""
resp = _unauth_request(client, "DELETE", "/api/v1/devices/some_id")
assert resp.status_code == 401
def test_backup_without_auth_returns_401(self, client):
"""Backup endpoint requires authentication."""
resp = _unauth_get(client, "/api/v1/system/backup")
assert resp.status_code == 401
def test_color_strip_sources_without_auth_returns_401(self, client):
"""Color strip source listing requires authentication."""
resp = _unauth_get(client, "/api/v1/color-strip-sources")
assert resp.status_code == 401
def test_output_targets_without_auth_returns_401(self, client):
"""Output target listing requires authentication."""
resp = _unauth_get(client, "/api/v1/output-targets")
assert resp.status_code == 401
def test_malformed_bearer_token_returns_401_or_403(self, client):
"""A malformed Authorization header is rejected."""
resp = _with_header(
client, "GET", "/api/v1/devices",
auth_value="just-a-key",
)
# FastAPI's HTTPBearer returns 403 for malformed format,
# or 401 depending on auto_error setting. Accept either.
assert resp.status_code in (401, 403)