Public Access
feat(auth): harden sessions + HA Ingress support
- backend: settings SESSION_COOKIE_SECURE + TRUSTED_NETWORK_AUTO_AUTH, require_session uses secrets.compare_digest and respects trusted-network opt-in, main.py adds require_family_session middleware gating all /api/ routes except auth/admin/email-vote-token paths - docker-compose: pass SESSION_COOKIE_SECURE + TRUSTED_NETWORK_AUTO_AUTH through to backend + scheduler (fixes env-file changes not reaching runtime) - frontend: Ingress path-prefix support (APP_BASE_PATH, BrowserRouter basename, vite base './'), Login redirect honors APP_BASE_PATH - nginx: no-cache headers on root + /assets/ - docs: Home Assistant Ingress install/troubleshooting + plan file - tests: test_auth expects 401 on no-session GET Defaults: SESSION_COOKIE_SECURE=false, TRUSTED_NETWORK_AUTO_AUTH=true (HA is the auth boundary; MealPlanner must not be port-forwarded directly).
This commit is contained in:
@@ -19,6 +19,7 @@ import pytest
|
||||
os.environ.setdefault("ADMIN_TOKEN", "test-admin-token")
|
||||
os.environ.setdefault("SESSION_PASSWORD", "test-family-password")
|
||||
os.environ.setdefault("SECRET_KEY", "test-secret-key-do-not-use-in-prod")
|
||||
os.environ.setdefault("SESSION_COOKIE_SECURE", "false")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@@ -27,6 +28,7 @@ def _reload_settings(monkeypatch):
|
||||
monkeypatch.setenv("ADMIN_TOKEN", "test-admin-token")
|
||||
monkeypatch.setenv("SESSION_PASSWORD", "test-family-password")
|
||||
monkeypatch.setenv("SECRET_KEY", "test-secret-key-do-not-use-in-prod")
|
||||
monkeypatch.setenv("SESSION_COOKIE_SECURE", "false")
|
||||
# Re-instantiate the singleton so dependents pick up env.
|
||||
from app import config as app_config
|
||||
|
||||
@@ -76,11 +78,10 @@ def test_session_required_for_mutation(client):
|
||||
|
||||
|
||||
@pytest.mark.requires_postgres
|
||||
def test_session_open_for_reads(client):
|
||||
"""GET /api/profile is NOT auth-gated (reads stay open)."""
|
||||
def test_session_required_for_reads(client):
|
||||
"""GET /api/profile requires a session for non-LAN exposure."""
|
||||
r = client.get("/api/profile")
|
||||
# Either 200 (profile exists) or 404 (no profile yet) — never 401.
|
||||
assert r.status_code in (200, 404), r.text
|
||||
assert r.status_code == 401, r.text
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user