"""End-to-end integration tests for the deployed-environment E2E test-auth path (`POST /auth/test/login`). This endpoint is a **deliberately gated auth shortcut** for running the Playwright E2E suite against a *deployed* environment (PPE) that has no Mailpit OTC sink and no direct SQLite access to inject an owner row — the two scaffolds the Tier-1 stack relies on. It mints an authenticated **owner** session for a single, pre-configured test identity, but ONLY when the deployment has explicitly opted in by setting BOTH `E2E_TEST_AUTH_SECRET` and `E2E_TEST_AUTH_EMAIL`. It is fail-closed: * Off by default — with neither (or only one) env var set, the route is invisible (404), so a production deployment that never sets them cannot be coaxed into minting a session. * Even when enabled, it requires the caller to present the shared secret in the `X-Test-Auth-Secret` header (constant-time compare), and it will only mint a session for the one configured email — any other address is refused (403). So the blast radius of an enabled PPE is a single throwaway owner identity, and the secret is the trust boundary. The tests below pin every branch of that gate. """ from __future__ import annotations from test_propose_vertical import ( # noqa: F401 FakeGitea, app_with_fake_gitea, tmp_env, ) SECRET = "ppe-e2e-shared-secret-value" EMAIL = "e2e-owner@example.test" def test_test_login_is_404_when_disabled(app_with_fake_gitea): """Neither env var set (the default, incl. production) → the route does not exist.""" from fastapi.testclient import TestClient app, _fake = app_with_fake_gitea with TestClient(app) as client: r = client.post( "/auth/test/login", json={"email": EMAIL}, headers={"X-Test-Auth-Secret": SECRET}, ) assert r.status_code == 404, r.text def test_test_login_is_404_when_only_email_is_set(app_with_fake_gitea, monkeypatch): """Half-configured (email but no secret) must NOT open the route — a framework auth shortcut gated only by a known email would be far too weak.""" from fastapi.testclient import TestClient monkeypatch.setenv("E2E_TEST_AUTH_EMAIL", EMAIL) monkeypatch.delenv("E2E_TEST_AUTH_SECRET", raising=False) app, _fake = app_with_fake_gitea with TestClient(app) as client: r = client.post( "/auth/test/login", json={"email": EMAIL}, headers={"X-Test-Auth-Secret": SECRET}, ) assert r.status_code == 404, r.text def test_test_login_refuses_wrong_secret(app_with_fake_gitea, monkeypatch): """Enabled, but a bad/absent secret → 404 (don't advertise the route's existence to an unauthenticated caller).""" from fastapi.testclient import TestClient monkeypatch.setenv("E2E_TEST_AUTH_SECRET", SECRET) monkeypatch.setenv("E2E_TEST_AUTH_EMAIL", EMAIL) app, _fake = app_with_fake_gitea with TestClient(app) as client: # Wrong secret. r = client.post( "/auth/test/login", json={"email": EMAIL}, headers={"X-Test-Auth-Secret": "not-the-secret"}, ) assert r.status_code == 404, r.text # Absent secret. r = client.post("/auth/test/login", json={"email": EMAIL}) assert r.status_code == 404, r.text def test_test_login_refuses_unconfigured_email(app_with_fake_gitea, monkeypatch): """Right secret but an email other than the single configured identity → 403. Even a secret-bearer can only mint the one test owner.""" from fastapi.testclient import TestClient monkeypatch.setenv("E2E_TEST_AUTH_SECRET", SECRET) monkeypatch.setenv("E2E_TEST_AUTH_EMAIL", EMAIL) app, _fake = app_with_fake_gitea with TestClient(app) as client: r = client.post( "/auth/test/login", json={"email": "someone-else@example.test"}, headers={"X-Test-Auth-Secret": SECRET}, ) assert r.status_code == 403, r.text def test_test_login_mints_owner_session(app_with_fake_gitea, monkeypatch): """The happy path: right secret + configured email → an authenticated session whose user is a GRANTED OWNER (so the metadata write paths — SLICE-4 edit, SLICE-5 bulk — accept it), persisted on a fresh `users` row.""" from fastapi.testclient import TestClient monkeypatch.setenv("E2E_TEST_AUTH_SECRET", SECRET) monkeypatch.setenv("E2E_TEST_AUTH_EMAIL", EMAIL) app, _fake = app_with_fake_gitea with TestClient(app) as client: r = client.post( "/auth/test/login", json={"email": EMAIL}, headers={"X-Test-Auth-Secret": SECRET}, ) assert r.status_code == 200, r.text # The session cookie now surfaces an authenticated owner. me = client.get("/api/auth/me").json() assert me["authenticated"] is True assert me["user"]["email"] == EMAIL assert me["user"]["role"] == "owner" assert me["user"]["permission_state"] == "granted" # Idempotent: a second login reuses the same row (still owner). r = client.post( "/auth/test/login", json={"email": EMAIL}, headers={"X-Test-Auth-Secret": SECRET}, ) assert r.status_code == 200, r.text from app import db rows = db.conn().execute( "SELECT role, permission_state FROM users WHERE email = ? COLLATE NOCASE", (EMAIL,), ).fetchall() assert len(rows) == 1 assert rows[0]["role"] == "owner" assert rows[0]["permission_state"] == "granted" def test_test_login_is_case_insensitive_on_email(app_with_fake_gitea, monkeypatch): """The configured-email check matches case-insensitively, mirroring how the rest of the auth stack treats email.""" from fastapi.testclient import TestClient monkeypatch.setenv("E2E_TEST_AUTH_SECRET", SECRET) monkeypatch.setenv("E2E_TEST_AUTH_EMAIL", EMAIL) app, _fake = app_with_fake_gitea with TestClient(app) as client: r = client.post( "/auth/test/login", json={"email": EMAIL.upper()}, headers={"X-Test-Auth-Secret": SECRET}, ) assert r.status_code == 200, r.text