from __future__ import annotations import secrets from typing import Any from fastapi import Depends, HTTPException, Request from Groups import AdminGroupName, GetGroupsForUser, IsUserInGroup from Users import GetUser # In-memory only for now: sessions don't survive a container restart, so # everyone just logs in again. Fine for a handful of trusted tailnet users; # worth revisiting if that stops being true. ActiveSessions: dict[str, str] = {} SessionCookieName = "SaraViewSession" def CreateSession(Username: str) -> str: Token = secrets.token_urlsafe(32) ActiveSessions[Token] = Username return Token def DeleteSession(Token: str) -> None: ActiveSessions.pop(Token, None) def GetCurrentUser(request: Request) -> dict[str, Any]: Token = request.cookies.get(SessionCookieName) Username = ActiveSessions.get(Token) if Token else None if Username is None: raise HTTPException(status_code=401, detail="Not logged in.") User = GetUser(Username) if User is None: raise HTTPException(status_code=401, detail="Session user no longer exists.") # Admin isn't a stored flag — it's membership in the built-in Admin # group, computed live, so it behaves exactly like any other group. UserGroups = GetGroupsForUser(Username) return { "Username": Username, "IsAdmin": AdminGroupName in UserGroups, "Groups": UserGroups, "Colour": User.get("Colour", "Purple"), } def RequireAdmin(CurrentUser: dict = Depends(GetCurrentUser)) -> dict: if not CurrentUser.get("IsAdmin"): raise HTTPException(status_code=403, detail="Admin access required.") return CurrentUser