74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Response
|
|
from sqlalchemy.orm import Session
|
|
|
|
from .. import models
|
|
from ..auth import (
|
|
clear_session_cookie,
|
|
create_local_session,
|
|
get_optional_local_session,
|
|
set_session_cookie,
|
|
)
|
|
from ..db import get_session
|
|
from ..schemas import AuthSessionRead, HouseholdRead, LocalLoginRequest, LocalSessionRead, UserRead
|
|
|
|
router = APIRouter(tags=["auth"])
|
|
|
|
|
|
def _auth_session_read(
|
|
session: Session,
|
|
local_session: models.LocalSession,
|
|
) -> AuthSessionRead:
|
|
user = session.get(models.User, local_session.user_id)
|
|
household = session.get(models.Household, local_session.household_id)
|
|
if not user or not household:
|
|
raise HTTPException(status_code=404, detail="Session user or household not found")
|
|
return AuthSessionRead(
|
|
session=LocalSessionRead.model_validate(local_session),
|
|
user=UserRead.model_validate(user),
|
|
household=HouseholdRead.model_validate(household),
|
|
)
|
|
|
|
|
|
@router.post("/auth/login", response_model=AuthSessionRead)
|
|
def local_login(
|
|
payload: LocalLoginRequest,
|
|
response: Response,
|
|
session: Session = Depends(get_session),
|
|
) -> AuthSessionRead:
|
|
user = session.get(models.User, payload.user_id)
|
|
if not user:
|
|
raise HTTPException(status_code=404, detail="User not found")
|
|
local_session, token = create_local_session(session, user)
|
|
session.commit()
|
|
session.refresh(local_session)
|
|
set_session_cookie(response, token)
|
|
return _auth_session_read(session, local_session)
|
|
|
|
|
|
@router.get("/auth/me", response_model=AuthSessionRead | None)
|
|
def current_local_session(
|
|
local_session: models.LocalSession | None = Depends(get_optional_local_session),
|
|
session: Session = Depends(get_session),
|
|
) -> AuthSessionRead | None:
|
|
if not local_session:
|
|
return None
|
|
return _auth_session_read(session, local_session)
|
|
|
|
|
|
@router.post("/auth/logout")
|
|
def logout(
|
|
response: Response,
|
|
local_session: models.LocalSession | None = Depends(get_optional_local_session),
|
|
session: Session = Depends(get_session),
|
|
) -> dict[str, bool]:
|
|
if local_session:
|
|
local_session.revoked_at = datetime.now(UTC)
|
|
session.add(local_session)
|
|
session.commit()
|
|
clear_session_cookie(response)
|
|
return {"logged_out": True}
|