"""Phase 14: API Key management router.""" from typing import List, Optional from uuid import UUID from fastapi import APIRouter, Depends, Query from sqlalchemy.orm import Session from app.database import get_db from app.dependencies.auth import get_current_user, require_any_role from app.models.user import User from app.schemas.api_key_schema import ( ApiKeyCreate, ApiKeyCreated, ApiKeyOut, ApiKeyUpdate, ) import app.services.api_key_service as svc router = APIRouter(prefix="/api-keys", tags=["API Keys"]) @router.post("", response_model=ApiKeyCreated, status_code=201) def create_key( body: ApiKeyCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """ Create a scoped API key. The ``raw_key`` field in the response is shown **exactly once** and cannot be retrieved later. Store it securely. """ key, raw_key = svc.create_api_key( db, user_id = current_user.id, name = body.name, scopes = body.scopes, description = body.description, expires_at = body.expires_at, ) out = ApiKeyOut.model_validate(key) return ApiKeyCreated(**out.model_dump(), raw_key=raw_key) @router.get("", response_model=List[ApiKeyOut]) def list_keys( include_inactive: bool = Query(False), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """List API keys owned by the current user.""" # Admins can see all keys; others only see their own user_id = None if current_user.role == "admin" else current_user.id return svc.list_api_keys(db, user_id=user_id, include_inactive=include_inactive) @router.get("/{key_id}", response_model=ApiKeyOut) def get_key( key_id: UUID, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Get a single API key (owner or admin).""" user_id = None if current_user.role == "admin" else current_user.id return svc.get_api_key(db, key_id, user_id=user_id) @router.patch("/{key_id}", response_model=ApiKeyOut) def update_key( key_id: UUID, body: ApiKeyUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Update name, description, scopes, expiry, or active status.""" user_id = None if current_user.role == "admin" else current_user.id return svc.update_api_key( db, key_id, user_id, name = body.name, description = body.description, scopes = body.scopes, expires_at = body.expires_at, is_active = body.is_active, ) @router.post("/{key_id}/revoke", response_model=ApiKeyOut) def revoke_key( key_id: UUID, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Revoke an API key (soft-delete — sets is_active=False).""" user_id = None if current_user.role == "admin" else current_user.id return svc.revoke_api_key(db, key_id, user_id=user_id) @router.delete("/{key_id}", status_code=204) def delete_key( key_id: UUID, db: Session = Depends(get_db), current_user: User = Depends(require_any_role("admin")), ): """Permanently delete an API key (admin only).""" svc.delete_api_key(db, key_id)