"""Auth routes: login (admin/provider), logout, me.""" import os from fastapi import APIRouter, HTTPException, Response, Cookie from pydantic import BaseModel from utils import auth as auth_utils from api.deps import SESSION_COOKIE router = APIRouter(prefix="/api/auth", tags=["auth"]) # HuggingFace Spaces serves the app inside a cross-site iframe, so the session # cookie needs SameSite=None; Secure to be sent. Locally over http://localhost, # `secure=True` would prevent the cookie from being set at all — so we detect # the environment and pick the right pair. HF sets SPACE_ID automatically. _IN_HF_SPACE = bool(os.environ.get("SPACE_ID")) _COOKIE_KW = ( {"samesite": "none", "secure": True} if _IN_HF_SPACE else {"samesite": "lax"} ) class LoginRequest(BaseModel): username: str password: str class ProviderLoginRequest(BaseModel): name: str password: str @router.post("/login") def login(req: LoginRequest, response: Response): if not auth_utils.check_credentials(req.username, req.password): raise HTTPException(status_code=401, detail="Invalid username or password") token = auth_utils.create_session(user_role="admin", current_user=req.username) response.set_cookie(key=SESSION_COOKIE, value=token, httponly=True, max_age=60 * 60 * 24 * 7, **_COOKIE_KW) return {"user_role": "admin", "current_user": req.username} @router.post("/provider-login") def provider_login(req: ProviderLoginRequest, response: Response): provider = auth_utils.check_provider_credentials(req.name, req.password) if not provider: raise HTTPException(status_code=401, detail="Invalid provider name or password") token = auth_utils.create_session( user_role="provider", current_user=provider["name"], provider_id=provider["id"], ) response.set_cookie(key=SESSION_COOKIE, value=token, httponly=True, max_age=60 * 60 * 24 * 7, **_COOKIE_KW) return {"user_role": "provider", "current_user": provider["name"], "provider_id": provider["id"]} @router.post("/logout") def logout(response: Response, session_token: str | None = Cookie(default=None, alias=SESSION_COOKIE)): auth_utils.destroy_session(session_token) response.delete_cookie(SESSION_COOKIE) return {"ok": True} @router.get("/me") def me(session_token: str | None = Cookie(default=None, alias=SESSION_COOKIE)): session = auth_utils.get_session(session_token) if not session: return {"authenticated": False} return {"authenticated": True, **session} @router.get("/provider-names") def provider_names(): """Public list of provider names for the login dropdown.""" from core import data_manager providers = data_manager.get_all_providers(active_only=False) return [{"id": p["id"], "name": p["name"]} for p in providers]