urmi-ai/backend/app/voice_auth.py
2026-10-02 11:22:40 +05:30

52 lines
2.1 KiB
Python

import uuid
from fastapi import Cookie, Depends, Header, HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import Session
from .api_key_auth import _extract_api_key, parse_api_token, verify_api_token
from .api_keys_service import KEY_PREFIX
from .auth import COOKIE_NAME, decode_token
from .database import get_db
from .models import ApiKey, UserAccount
def current_voice_user(
urmi_session: str | None = Cookie(default=None, alias=COOKIE_NAME),
authorization: str | None = Header(default=None),
x_api_key: str | None = Header(default=None, alias="X-Api-Key"),
db: Session = Depends(get_db),
) -> UserAccount:
if urmi_session:
payload = decode_token(urmi_session)
try:
user_id = uuid.UUID(payload["sub"])
except (KeyError, ValueError) as exc:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid session") from exc
user = db.scalar(select(UserAccount).where(UserAccount.id == user_id))
if user and user.status == "active":
return user
token = _extract_api_key(authorization, x_api_key)
if not token or not token.startswith(KEY_PREFIX):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Authentication required")
parsed = parse_api_token(token)
if parsed:
key_id, _ = parsed
api_key = db.scalar(
select(ApiKey).where(ApiKey.id == key_id, ApiKey.revoked_at.is_(None))
)
if api_key and verify_api_token(token, api_key.key_hash):
user = db.scalar(select(UserAccount).where(UserAccount.id == api_key.user_id))
if user and user.status == "active":
return user
active_keys = db.scalars(select(ApiKey).where(ApiKey.revoked_at.is_(None))).all()
for api_key in active_keys:
if verify_api_token(token, api_key.key_hash):
user = db.scalar(select(UserAccount).where(UserAccount.id == api_key.user_id))
if user and user.status == "active":
return user
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")