Files
Hotel-Booking/Backend/src/integrations/routes/api_key_routes.py
Iliyan Angelov 1a103a769f updates
2025-12-01 01:08:39 +02:00

166 lines
5.8 KiB
Python

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