feat: Implement session management with middleware and update authentication flow
This commit is contained in:
@@ -9,7 +9,13 @@ from fastapi.templating import Jinja2Templates
|
||||
from pydantic import ValidationError
|
||||
from starlette.datastructures import FormData
|
||||
|
||||
from dependencies import get_jwt_settings, get_unit_of_work
|
||||
from dependencies import (
|
||||
get_auth_session,
|
||||
get_jwt_settings,
|
||||
get_session_strategy,
|
||||
get_unit_of_work,
|
||||
require_current_user,
|
||||
)
|
||||
from models import Role, User
|
||||
from schemas.auth import (
|
||||
LoginForm,
|
||||
@@ -29,6 +35,12 @@ from services.security import (
|
||||
hash_password,
|
||||
verify_password,
|
||||
)
|
||||
from services.session import (
|
||||
AuthSession,
|
||||
SessionStrategy,
|
||||
clear_session_cookies,
|
||||
set_session_cookies,
|
||||
)
|
||||
from services.repositories import RoleRepository, UserRepository
|
||||
from services.unit_of_work import UnitOfWork
|
||||
|
||||
@@ -103,6 +115,7 @@ async def login_submit(
|
||||
request: Request,
|
||||
uow: UnitOfWork = Depends(get_unit_of_work),
|
||||
jwt_settings: JWTSettings = Depends(get_jwt_settings),
|
||||
session_strategy: SessionStrategy = Depends(get_session_strategy),
|
||||
):
|
||||
form_data = _normalise_form_data(await request.form())
|
||||
try:
|
||||
@@ -158,7 +171,31 @@ async def login_submit(
|
||||
request.url_for("dashboard.home"),
|
||||
status_code=status.HTTP_303_SEE_OTHER,
|
||||
)
|
||||
_set_auth_cookies(response, access_token, refresh_token, jwt_settings)
|
||||
set_session_cookies(
|
||||
response,
|
||||
access_token=access_token,
|
||||
refresh_token=refresh_token,
|
||||
strategy=session_strategy,
|
||||
jwt_settings=jwt_settings,
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
@router.get("/logout", include_in_schema=False, name="auth.logout")
|
||||
async def logout(
|
||||
request: Request,
|
||||
_: User = Depends(require_current_user),
|
||||
session: AuthSession = Depends(get_auth_session),
|
||||
session_strategy: SessionStrategy = Depends(get_session_strategy),
|
||||
) -> RedirectResponse:
|
||||
session.mark_cleared()
|
||||
redirect_url = request.url_for(
|
||||
"auth.login_form").include_query_params(logout="1")
|
||||
response = RedirectResponse(
|
||||
redirect_url,
|
||||
status_code=status.HTTP_303_SEE_OTHER,
|
||||
)
|
||||
clear_session_cookies(response, session_strategy)
|
||||
return response
|
||||
|
||||
|
||||
@@ -168,32 +205,6 @@ def _lookup_user(users_repo: UserRepository, identifier: str) -> User | None:
|
||||
return users_repo.get_by_username(identifier, with_roles=True)
|
||||
|
||||
|
||||
def _set_auth_cookies(
|
||||
response: RedirectResponse,
|
||||
access_token: str,
|
||||
refresh_token: str,
|
||||
jwt_settings: JWTSettings,
|
||||
) -> None:
|
||||
access_ttl = int(jwt_settings.access_token_ttl.total_seconds())
|
||||
refresh_ttl = int(jwt_settings.refresh_token_ttl.total_seconds())
|
||||
response.set_cookie(
|
||||
"calminer_access_token",
|
||||
access_token,
|
||||
httponly=True,
|
||||
secure=False,
|
||||
samesite="lax",
|
||||
max_age=max(access_ttl, 0) or None,
|
||||
)
|
||||
response.set_cookie(
|
||||
"calminer_refresh_token",
|
||||
refresh_token,
|
||||
httponly=True,
|
||||
secure=False,
|
||||
samesite="lax",
|
||||
max_age=max(refresh_ttl, 0) or None,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/register", response_class=HTMLResponse, include_in_schema=False, name="auth.register_form")
|
||||
def register_form(request: Request) -> HTMLResponse:
|
||||
return _template(
|
||||
|
||||
Reference in New Issue
Block a user