feat: add local admin authentication

This commit is contained in:
Bastian Wagner
2026-08-15 09:33:27 +02:00
parent 93232a809e
commit da6b94ca2f
10 changed files with 173 additions and 0 deletions

View File

@@ -1,10 +1,16 @@
from pathlib import Path
import pytest
from cryptography.fernet import Fernet
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.pool import StaticPool
from app.config import Settings
from app.db.models import Base
from app.db.repositories import ActivityRepository, UserRepository
from app.main import create_app
@pytest.fixture
@@ -28,3 +34,16 @@ def user_repository(db_session: Session) -> UserRepository:
@pytest.fixture
def activity_repository(db_session: Session) -> ActivityRepository:
return ActivityRepository(db_session)
@pytest.fixture
def client(tmp_path: Path) -> TestClient:
settings = Settings(
ADMIN_PASSWORD="admin-secret",
SECRET_KEY="0123456789abcdef0123456789abcdef",
CREDENTIAL_ENCRYPTION_KEY=Fernet.generate_key().decode("ascii"),
DATA_DIR=str(tmp_path),
DATABASE_URL=f"sqlite:///{tmp_path / 'app.db'}",
SYNC_INTERVAL_MINUTES=5,
)
return TestClient(create_app(settings))

36
tests/web/test_auth.py Normal file
View File

@@ -0,0 +1,36 @@
from fastapi.testclient import TestClient
def test_dashboard_redirects_when_not_logged_in(client: TestClient) -> None:
response = client.get("/", follow_redirects=False)
assert response.status_code == 303
assert response.headers["location"] == "/login"
def extract_csrf(html: str) -> str:
marker = 'name="csrf_token" value="'
start = html.index(marker) + len(marker)
return html[start:html.index('"', start)]
def test_login_rejects_wrong_password(client: TestClient) -> None:
login_page = client.get("/login")
csrf = extract_csrf(login_page.text)
response = client.post(
"/login",
data={"password": "wrong", "csrf_token": csrf},
follow_redirects=False,
)
assert response.status_code == 401
def test_login_accepts_configured_password(client: TestClient) -> None:
login_page = client.get("/login")
csrf = extract_csrf(login_page.text)
response = client.post(
"/login",
data={"password": "admin-secret", "csrf_token": csrf},
follow_redirects=False,
)
assert response.status_code == 303
assert response.headers["location"] == "/"