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")