campus-placement-engine / backend /app /api /auth /dependencies.py
deeep-sec's picture
feat: institutional campus placement eligibility & interview scheduling engine
788eab4 verified
Raw History Blame Contribute Delete
2.59 kB
"""
FastAPI Authentication, RBAC, and UnitOfWork Dependencies.
"""
from __future__ import annotations
from collections.abc import Callable, Generator
from fastapi import Depends, HTTPException, Request, status
from sqlalchemy.orm import Session
from backend.app.api.auth.session_manager import SESSION_COOKIE_NAME, get_session
from backend.app.storage.database import SessionLocal, get_db
from backend.app.storage.models.entities import UserModel
from backend.app.storage.repositories.sqlalchemy_repo import SqlAlchemyUnitOfWork
def get_uow() -> Generator[SqlAlchemyUnitOfWork, None, None]:
"""Dependency supplying a Unit of Work context."""
uow = SqlAlchemyUnitOfWork(SessionLocal)
yield uow
def get_current_user(
request: Request,
db: Session = Depends(get_db),
) -> UserModel:
"""
Extracts and authenticates the current user from the session cookie
or Bearer authorization header.
"""
token = request.cookies.get(SESSION_COOKIE_NAME)
# Fallback to Authorization header for programmatic / testing access
if not token:
auth_header = request.headers.get("Authorization")
if auth_header and auth_header.startswith("Bearer "):
token = auth_header.split(" ", 1)[1]
if not token:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Authentication required. No active session token found.",
)
session = get_session(db, token)
if not session or not session.user or not session.user.is_active:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Session has expired or is invalid. Please log in again.",
)
return session.user
def require_role(allowed_roles: list[str]) -> Callable[[UserModel], UserModel]:
"""Factory creating an RBAC role verification dependency."""
def role_checker(user: UserModel = Depends(get_current_user)) -> UserModel:
if user.role not in allowed_roles:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Access denied. User role '{user.role}' is not authorized for this operation.",
)
return user
return role_checker
# Canonical Role Dependencies
require_officer = require_role(["officer"])
require_officer_or_coordinator = require_role(["officer", "coordinator"])
require_student = require_role(["student"])
require_recruiter = require_role(["recruiter_readonly"])