""" API key management routes. """ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from typing import List, Optional from datetime import datetime from ...shared.config.database import get_db from ...shared.config.logging_config import get_logger from ...security.middleware.auth import get_current_user, authorize_roles from ...auth.models.user import User from ..services.api_key_service import api_key_service from ..models.api_key import APIKey from ...shared.utils.response_helpers import success_response from pydantic import BaseModel logger = get_logger(__name__) router = APIRouter(prefix='/api-keys', tags=['api-keys']) class CreateAPIKeyRequest(BaseModel): name: str scopes: List[str] description: Optional[str] = None rate_limit: int = 100 expires_at: Optional[str] = None class UpdateAPIKeyRequest(BaseModel): name: Optional[str] = None scopes: Optional[List[str]] = None description: Optional[str] = None rate_limit: Optional[int] = None expires_at: Optional[str] = None @router.post('/') async def create_api_key( key_data: CreateAPIKeyRequest, current_user: User = Depends(authorize_roles('admin')), db: Session = Depends(get_db) ): """Create a new API key.""" try: expires_at = None if key_data.expires_at: expires_at = datetime.fromisoformat(key_data.expires_at.replace('Z', '+00:00')) api_key, plain_key = api_key_service.create_api_key( db=db, name=key_data.name, scopes=key_data.scopes, created_by=current_user.id, description=key_data.description, rate_limit=key_data.rate_limit, expires_at=expires_at ) return success_response( data={ 'api_key': { 'id': api_key.id, 'name': api_key.name, 'key_prefix': api_key.key_prefix, 'scopes': api_key.scopes, 'rate_limit': api_key.rate_limit, 'expires_at': api_key.expires_at.isoformat() if api_key.expires_at else None }, 'key': plain_key # Return plain key only on creation }, message='API key created successfully. Save this key securely - it will not be shown again.' ) except Exception as e: logger.error(f'Error creating API key: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.get('/') async def get_api_keys( current_user: User = Depends(authorize_roles('admin')), db: Session = Depends(get_db) ): """Get all API keys.""" try: api_keys = db.query(APIKey).order_by(APIKey.created_at.desc()).all() return success_response(data={ 'api_keys': [{ 'id': k.id, 'name': k.name, 'key_prefix': k.key_prefix, 'scopes': k.scopes, 'rate_limit': k.rate_limit, 'is_active': k.is_active, 'last_used_at': k.last_used_at.isoformat() if k.last_used_at else None, 'expires_at': k.expires_at.isoformat() if k.expires_at else None, 'created_at': k.created_at.isoformat() if k.created_at else None } for k in api_keys] }) except Exception as e: logger.error(f'Error getting API keys: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.put('/{key_id}') async def update_api_key( key_id: int, key_data: UpdateAPIKeyRequest, current_user: User = Depends(authorize_roles('admin')), db: Session = Depends(get_db) ): """Update an API key.""" try: expires_at = None if key_data.expires_at: expires_at = datetime.fromisoformat(key_data.expires_at.replace('Z', '+00:00')) api_key = api_key_service.update_api_key( db=db, key_id=key_id, name=key_data.name, scopes=key_data.scopes, description=key_data.description, rate_limit=key_data.rate_limit, expires_at=expires_at ) if not api_key: raise HTTPException(status_code=404, detail='API key not found') return success_response( data={ 'api_key': { 'id': api_key.id, 'name': api_key.name, 'key_prefix': api_key.key_prefix, 'scopes': api_key.scopes, 'rate_limit': api_key.rate_limit, 'is_active': api_key.is_active, 'expires_at': api_key.expires_at.isoformat() if api_key.expires_at else None, 'created_at': api_key.created_at.isoformat() if api_key.created_at else None } }, message='API key updated successfully' ) except HTTPException: raise except Exception as e: logger.error(f'Error updating API key: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.delete('/{key_id}') async def revoke_api_key( key_id: int, current_user: User = Depends(authorize_roles('admin')), db: Session = Depends(get_db) ): """Revoke an API key.""" try: success = api_key_service.revoke_api_key(db=db, key_id=key_id) if not success: raise HTTPException(status_code=404, detail='API key not found') return success_response(message='API key revoked successfully') except HTTPException: raise except Exception as e: logger.error(f'Error revoking API key: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e))