Spaces:
Runtime error
Runtime error
| from urllib.parse import urlparse | |
| from fastapi import Depends, HTTPException, Request | |
| from sqlalchemy.orm import Session | |
| from app.auth.jwt import TokenError, decode_token | |
| from app.config import Settings | |
| from app.db import get_db | |
| from app.models import Role, User | |
| COOKIE_NAME = "claimflow_session" | |
| def get_settings_dep(request: Request) -> Settings: | |
| return request.app.state.settings | |
| def get_current_user( | |
| request: Request, | |
| session: Session = Depends(get_db), | |
| settings: Settings = Depends(get_settings_dep), | |
| ) -> User: | |
| token = request.cookies.get(COOKIE_NAME) | |
| if not token: | |
| raise HTTPException(status_code=401, detail="Not authenticated") | |
| try: | |
| payload = decode_token(token, settings) | |
| except TokenError as exc: | |
| raise HTTPException(status_code=401, detail="Invalid or expired session") from exc | |
| user = session.get(User, int(payload["sub"])) | |
| if user is None: | |
| raise HTTPException(status_code=401, detail="Unknown user") | |
| return user | |
| def require_role(*roles: Role): | |
| allowed = set(roles) | |
| def dependency(user: User = Depends(get_current_user)) -> User: | |
| if user.role not in allowed: | |
| raise HTTPException(status_code=403, detail="Insufficient role") | |
| return user | |
| return dependency | |
| def enforce_origin(request: Request, settings: Settings = Depends(get_settings_dep)) -> None: | |
| """CSRF belt-and-braces for mutating routes. | |
| Primary defenses are the same-origin rewrite proxy and SameSite=Lax cookies; | |
| this rejects cross-origin browser requests that carry an Origin/Referer header. | |
| Requests with neither header (curl, server-to-server, tests) are allowed. | |
| """ | |
| origin = request.headers.get("origin") or request.headers.get("referer") | |
| if not origin: | |
| return | |
| expected = urlparse(settings.app_origin).netloc | |
| actual = urlparse(origin).netloc | |
| if expected and actual and actual != expected: | |
| raise HTTPException(status_code=403, detail="Cross-origin request rejected") | |