from typing import Annotated from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from sqlmodel import Session, select from app.core.security import decode_access_token from app.db import SessionDep from app.models.participant import Participant from app.models.route import Route from app.models.user import User oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login") def get_current_user(session: SessionDep, token: Annotated[str, Depends(oauth2_scheme)]) -> User: credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) payload = decode_access_token(token) if payload is None or payload.get("sub") is None: raise credentials_exception user = session.get(User, int(payload["sub"])) if user is None or not user.is_active: raise credentials_exception return user CurrentUser = Annotated[User, Depends(get_current_user)] def get_current_active_superuser( current_user: CurrentUser, token: Annotated[str, Depends(oauth2_scheme)], ) -> User: if not current_user.is_superadmin: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Not enough privileges") payload = decode_access_token(token) if not payload or not payload.get("elevated"): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="This action requires an elevated session — call POST /auth/elevate first", ) return current_user CurrentSuperuser = Annotated[User, Depends(get_current_active_superuser)] def get_route_in_organization(session: Session, route_id: int, organization_id: int) -> Route: route = session.get(Route, route_id) if route is None or route.organization_id != organization_id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Route not found") return route def get_participant_in_organization(session: Session, participant_id: int, organization_id: int) -> Participant: participant = session.exec( select(Participant) .join(Route) .where(Participant.id == participant_id, Route.organization_id == organization_id) ).first() if participant is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Participant not found") return participant