# auth/routes_misc.py
from __future__ import annotations
from datetime import datetime
from fastapi import Depends, Query, Request, Response
from jose import JWTError, jwt
from .config import ALGORITHM, SECRET_KEY, oauth2_scheme, router
from .models import User
from .roles import ROLE_LEVELS, canonical_role
from .tokens import _extract_token, get_current_user
from .users import USERS
[docs]
@router.post("/logout")
async def logout(response: Response):
response.delete_cookie("taranta_jwt", path="/")
return {"ok": True}
[docs]
@router.get("/me", response_model=User)
async def read_me(current: User = Depends(get_current_user)):
return current
[docs]
@router.get("/validate")
async def validate_token(
request: Request,
token: str | None = Depends(oauth2_scheme),
query_token: str | None = Query(default=None, alias="token"),
):
"""
Quick session check - handy from tools like `curl` or the browser:
GET /auth/validate?token=<access_token>
or GET with Authorization: Bearer …
or GET with the cookie already set
"""
token_val = _extract_token(request, token, query_token)
if not token_val:
return {"valid": False, "expires_at": None, "seconds_left": None}
try:
payload = jwt.decode(token_val, SECRET_KEY, algorithms=[ALGORITHM])
exp_ts = payload.get("exp")
if not exp_ts:
return {"valid": False, "expires_at": None, "seconds_left": None}
now_ts = int(datetime.utcnow().timestamp())
seconds_left = exp_ts - now_ts
return {
"valid": seconds_left > 0,
"expires_at": datetime.utcfromtimestamp(exp_ts).isoformat() + "Z",
"seconds_left": max(seconds_left, 0),
}
except JWTError:
return {"valid": False, "expires_at": None, "seconds_left": None}
[docs]
@router.get("/roles")
async def list_roles_and_groups():
"""
Return roles and groups from the in-memory user store for UI dropdowns.
"""
roles: set[str] = set()
groups: set[str] = set()
for user in USERS.values():
if user.role:
roles.add(canonical_role(user.role))
for g in user.groups or []:
groups.add(g)
# Always publish the canonical defaults
roles.update(set(ROLE_LEVELS))
sorted_roles = sorted(roles, key=lambda r: ROLE_LEVELS.get(r, 0))
role_levels = {name: ROLE_LEVELS[name] for name in sorted_roles}
return {
"roles": sorted_roles,
"role_levels": role_levels,
"groups": sorted(groups),
}