feat(auth): single-admin password login (signed cookie) — gate tuning + Sources catalog, keep chat and document viewer public
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
"""Shared Playwright auth helper (phase 16).
|
||||
|
||||
``login`` drives the REAL form login on /login.html (fill → submit →
|
||||
redirect) so every story that needs the admin does exactly what a human
|
||||
would — no cookie surgery. ``password=None`` uses the shared E2E admin
|
||||
password (success path); pass a wrong value to drive the error state
|
||||
(no redirect, ``#login-error`` role=alert visible, still anonymous).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from playwright.sync_api import Page, expect
|
||||
|
||||
from e2e.conftest import ADMIN_PASSWORD # noqa: F401 (re-exported for tests)
|
||||
|
||||
DEFAULT_NEXT = "/sources.html"
|
||||
|
||||
|
||||
def login(page: Page, app_url: str, password: str | None = None, next: str | None = None) -> None:
|
||||
"""Perform the real form login and wait for its outcome.
|
||||
|
||||
* correct password (or ``password=None`` → the shared admin password)
|
||||
→ redirects to ``next`` (default ``/sources.html``);
|
||||
* wrong password → ``#login-error`` (role=alert) is visible, the URL
|
||||
never changes, and the visitor is still anonymous.
|
||||
"""
|
||||
attempt = ADMIN_PASSWORD if password is None else password
|
||||
url = f"{app_url}/login.html"
|
||||
if next is not None:
|
||||
url += f"?next={next}"
|
||||
page.goto(url)
|
||||
expect(page.locator("#login-password")).to_be_visible()
|
||||
page.fill("#login-password", attempt)
|
||||
page.click("#login-form button[type=submit]")
|
||||
if attempt != ADMIN_PASSWORD:
|
||||
expect(page.locator("#login-error")).to_be_visible(timeout=15_000)
|
||||
expect(page).to_have_url(url) # no redirect on failure
|
||||
return
|
||||
expect(page).to_have_url(app_url + (next or DEFAULT_NEXT), timeout=30_000)
|
||||
Reference in New Issue
Block a user