arbret/backend/routes/auth.py
counterweight 280c1e5687
Move slot expansion logic to ExchangeService
- Add get_available_slots() and _expand_availability_to_slots() to ExchangeService
- Update routes/exchange.py to use ExchangeService.get_available_slots()
- Remove all business logic from get_available_slots endpoint
- Add AvailabilityRepository to ExchangeService dependencies
- Add Availability and BookableSlot imports to ExchangeService
- Fix import path for validate_date_in_range (use date_validation module)
- Remove unused user_repo variable and import from routes/invites.py
- Fix mypy error in ValidationError by adding proper type annotation
2025-12-25 18:42:46 +01:00

80 lines
2.3 KiB
Python

"""Authentication routes for register, login, logout, and current user."""
from fastapi import APIRouter, Depends, Response
from sqlalchemy.ext.asyncio import AsyncSession
from auth import (
ACCESS_TOKEN_EXPIRE_MINUTES,
COOKIE_NAME,
COOKIE_SECURE,
build_user_response,
get_current_user,
)
from database import get_db
from models import User
from schemas import RegisterWithInvite, UserLogin, UserResponse
from services.auth import AuthService
router = APIRouter(prefix="/api/auth", tags=["auth"])
def set_auth_cookie(response: Response, token: str) -> None:
"""Set the authentication cookie on the response."""
response.set_cookie(
key=COOKIE_NAME,
value=token,
httponly=True,
secure=COOKIE_SECURE,
samesite="lax",
max_age=ACCESS_TOKEN_EXPIRE_MINUTES * 60,
)
@router.post("/register", response_model=UserResponse)
async def register(
user_data: RegisterWithInvite,
response: Response,
db: AsyncSession = Depends(get_db),
) -> UserResponse:
"""Register a new user using an invite code."""
service = AuthService(db)
user, access_token = await service.register_user(
email=user_data.email,
password=user_data.password,
invite_identifier=user_data.invite_identifier,
)
set_auth_cookie(response, access_token)
return await build_user_response(user, db)
@router.post("/login", response_model=UserResponse)
async def login(
user_data: UserLogin,
response: Response,
db: AsyncSession = Depends(get_db),
) -> UserResponse:
"""Authenticate a user and return their info with an auth cookie."""
service = AuthService(db)
user, access_token = await service.login_user(
email=user_data.email, password=user_data.password
)
set_auth_cookie(response, access_token)
return await build_user_response(user, db)
@router.post("/logout")
async def logout(response: Response) -> dict[str, bool]:
"""Log out the current user by clearing their auth cookie."""
response.delete_cookie(key=COOKIE_NAME)
return {"ok": True}
@router.get("/me", response_model=UserResponse)
async def get_me(
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> UserResponse:
"""Get the current authenticated user's info."""
return await build_user_response(current_user, db)