1
0
Fork 0
forked from sr2/cloud-api
cloud-api/src/service/router.py

149 lines
3.9 KiB
Python
Raw Normal View History

"""
2026-05-28 14:41:11 +01:00
Router endpoints for the services module
Endpoints:
2026-05-28 14:41:11 +01:00
- [GET](/): [root user]: Get a list of all services(id, name)
- [POST](/): [super admin]: Register a new service(name) on the hub, returns the API key for the service to access the hub.
- [PATCH](/key): [super_admin]: Refreshes the API key for a service(id), returning a new one.
- [DELETE](/): [super_admin]: Removes a service(id) from the hub.
"""
2026-05-27 13:43:06 +01:00
from fastapi import APIRouter, status
from sqlalchemy.exc import IntegrityError
2026-05-29 09:50:09 +01:00
from src.exceptions import ConflictException
from src.database import db_dependency
from src.auth.dependencies import (
super_admin_dependency,
org_model_root_claim_query_dependency,
)
from src.service.models import Service
from src.service.utils import generate_api_key
2026-05-27 13:43:06 +01:00
from src.service.dependencies import service_model_body_dependency
from src.service.schemas import (
ServiceGetServiceResponse,
ServicePostServiceRequest,
ServicePostServiceResponse,
ServiceWithKeySchema,
ServicePatchKeyResponse,
ServicePatchKeyRequest,
ServiceDeleteServiceRequest,
)
router = APIRouter(
tags=["Service"],
prefix="/service",
)
@router.get(
"/",
summary="Get all services",
status_code=status.HTTP_200_OK,
response_model=ServiceGetServiceResponse,
responses={
status.HTTP_200_OK: {"description": "Successful retrieval from database"},
status.HTTP_401_UNAUTHORIZED: {"description": "Unauthorized"},
},
)
async def get_all_services(
db: db_dependency, org_model: org_model_root_claim_query_dependency
):
2026-05-28 15:25:29 +01:00
"""
Returns the ID and name of all services registered to the hub.
"""
permission_models = db.query(Service).all()
2026-05-26 10:16:59 +01:00
return {"services": permission_models}
@router.post(
"/",
summary="Register a new service.",
status_code=status.HTTP_200_OK,
response_model=ServicePostServiceResponse,
responses={
status.HTTP_200_OK: {"description": "Successfully registered a new service"},
status.HTTP_401_UNAUTHORIZED: {"description": "Unauthorized"},
status.HTTP_409_CONFLICT: {
"description": "Service with this name already exists"
},
},
)
async def register_service(
db: db_dependency,
su: super_admin_dependency,
request_model: ServicePostServiceRequest,
):
2026-05-28 15:25:29 +01:00
"""
Registers a new service to the hub, generating and returning an API key for it.
"""
key = generate_api_key()
2026-05-28 15:25:29 +01:00
service_model = Service(name=request_model.name, api_key=key)
db.add(service_model)
try:
db.flush()
except IntegrityError as e:
2026-06-08 16:05:20 +01:00
if (
getattr(e.orig, "pgcode", None) == "23505" # Postgres unique violation
or "UNIQUE constraint failed" in str(e.orig) # SQLite unique violation
):
2026-05-29 09:50:09 +01:00
raise ConflictException(message="Service with this name already exists")
2026-05-28 14:27:14 +01:00
response = ServiceWithKeySchema(**service_model.__dict__)
db.commit()
2026-05-26 10:16:59 +01:00
return {"service": response}
@router.patch(
"/key",
summary="Regenerate service API key.",
status_code=status.HTTP_200_OK,
response_model=ServicePatchKeyResponse,
responses={
status.HTTP_200_OK: {"description": "Successful update of API key"},
status.HTTP_401_UNAUTHORIZED: {"description": "Unauthorized"},
},
)
async def regenerate_api_key(
db: db_dependency,
su: super_admin_dependency,
service_model: service_model_body_dependency,
request_model: ServicePatchKeyRequest,
):
2026-05-28 15:25:29 +01:00
"""
Generates and returns a new API key for the service to access the hub.
"""
key = generate_api_key()
service_model.api_key = key
2026-05-27 13:43:06 +01:00
2026-05-26 10:16:59 +01:00
db.flush()
2026-05-28 14:27:14 +01:00
response = ServiceWithKeySchema(**service_model.__dict__)
db.commit()
2026-05-26 10:16:59 +01:00
return {"service": response}
@router.delete(
"/",
summary="Remove a service.",
status_code=status.HTTP_204_NO_CONTENT,
responses={
status.HTTP_204_NO_CONTENT: {
"description": "Successfully removed service from db"
},
status.HTTP_401_UNAUTHORIZED: {"description": "Unauthorized"},
},
)
async def remove_service(
db: db_dependency,
service_model: service_model_body_dependency,
su: super_admin_dependency,
request_model: ServiceDeleteServiceRequest,
):
2026-05-28 15:25:29 +01:00
"""
Removes a service from the hub.
"""
db.delete(service_model)
db.commit()