feat: Implement session management with middleware and update authentication flow

This commit is contained in:
2025-11-09 23:14:41 +01:00
parent 3601c2e422
commit 27262bdfa3
9 changed files with 804 additions and 83 deletions

View File

@@ -1,15 +1,19 @@
from __future__ import annotations
from collections.abc import Iterator
from typing import cast
from urllib.parse import parse_qs, urlparse
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from sqlalchemy import select
from sqlalchemy.orm import Session, sessionmaker
from models import Role, User, UserRole
from dependencies import get_auth_session, require_current_user
from services.security import hash_password
from services.session import AuthSession, SessionTokens
@pytest.fixture()
@@ -223,7 +227,8 @@ class TestPasswordResetFlow:
data={"email": "mismatch@example.com"},
follow_redirects=False,
)
token = parse_qs(urlparse(request_response.headers["location"]).query)["token"][0]
token = parse_qs(urlparse(request_response.headers["location"]).query)[
"token"][0]
submit_response = client.post(
"/reset-password",
@@ -236,4 +241,46 @@ class TestPasswordResetFlow:
)
assert submit_response.status_code == 400
assert "Passwords do not match" in submit_response.text
assert "Passwords do not match" in submit_response.text
class TestLogoutFlow:
def test_logout_clears_cookies_and_redirects(
self,
client: TestClient,
db_session: Session,
) -> None:
user = User(
email="logout@example.com",
username="logoutuser",
password_hash=hash_password("SecureP@ss1"),
is_active=True,
)
db_session.add(user)
db_session.commit()
session = AuthSession(
tokens=SessionTokens(
access_token="access-token",
refresh_token="refresh-token",
access_token_source="cookie",
),
user=user,
)
app = cast(FastAPI, client.app)
app.dependency_overrides[require_current_user] = lambda: user
app.dependency_overrides[get_auth_session] = lambda: session
try:
response = client.get("/logout", follow_redirects=False)
finally:
app.dependency_overrides.pop(require_current_user, None)
app.dependency_overrides.pop(get_auth_session, None)
assert response.status_code == 303
location = response.headers.get("location")
assert location and location.startswith("http://testserver/login")
set_cookie_header = response.headers.get("set-cookie") or ""
assert "calminer_access_token=" in set_cookie_header
assert "Max-Age=0" in set_cookie_header or "expires=" in set_cookie_header.lower()