File size: 2,820 Bytes
0d04b76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
"""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]