minor: ruff formatter

All changes are either:
- Correcting tabs
- Adding/removing line breaks
- Adding trailing commas
This commit is contained in:
Chris Milne 2026-06-08 15:31:37 +01:00
parent b2e5dd2ebb
commit c689ac1e10
91 changed files with 1710 additions and 689 deletions

View file

@ -1,3 +1,3 @@
"""
Configurations for the services module
"""
"""

View file

@ -1,3 +1,3 @@
"""
Constants for the services module
"""
"""

View file

@ -5,6 +5,7 @@ Exports:
- service_model_query_dependency: service_model: Gets service model from db, if it exists. Uses service_id from query param.
- service_model_body_dependency: service_model: Gets service model from db, if it exists. Uses service_id from request body.
"""
from typing import Annotated
from fastapi import Depends, Query
@ -15,14 +16,19 @@ from src.service.models import Service
from src.service.schemas import ServiceIDMixin
async def get_service_model_query(db: db_dependency, service_id: Annotated[int, Query(gt=0)]):
async def get_service_model_query(
db: db_dependency, service_id: Annotated[int, Query(gt=0)]
):
service_model = db.get(Service, service_id)
if service_model is None:
raise ServiceNotFoundException(service_id=service_id)
return service_model
service_model_query_dependency = Annotated[type[Service], Depends(get_service_model_query)]
service_model_query_dependency = Annotated[
type[Service], Depends(get_service_model_query)
]
async def get_service_model_body(db: db_dependency, request_model: ServiceIDMixin):
@ -32,4 +38,7 @@ async def get_service_model_body(db: db_dependency, request_model: ServiceIDMixi
return service_model
service_model_body_dependency = Annotated[type[Service], Depends(get_service_model_body)]
service_model_body_dependency = Annotated[
type[Service], Depends(get_service_model_body)
]

View file

@ -4,6 +4,7 @@ Exceptions related to the services module
Exceptions:
- ServiceNotFoundException: Takes an optional service_id int
"""
from typing import Optional
from fastapi import HTTPException, status
@ -11,7 +12,11 @@ from fastapi import HTTPException, status
class ServiceNotFoundException(HTTPException):
def __init__(self, service_id: Optional[int] = None) -> None:
detail = "Service not found" if service_id is None else f"Service with ID '{service_id}' was not found."
detail = (
"Service not found"
if service_id is None
else f"Service with ID '{service_id}' was not found."
)
super().__init__(
status_code=status.HTTP_404_NOT_FOUND,
detail=detail,

View file

@ -5,6 +5,7 @@ Models:
- Service:
- id[PK], name[U], api_key[U]
"""
from sqlalchemy import Column, Integer, String
from src.database import Base

View file

@ -7,19 +7,30 @@ Endpoints:
- [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.
"""
from fastapi import APIRouter, status
from psycopg.errors import UniqueViolation
from sqlalchemy.exc import IntegrityError
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.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
from src.service.dependencies import service_model_body_dependency
from src.service.schemas import ServiceGetServiceResponse, ServicePostServiceRequest, ServicePostServiceResponse, \
ServiceWithKeySchema, ServicePatchKeyResponse, ServicePatchKeyRequest, ServiceDeleteServiceRequest
from src.service.schemas import (
ServiceGetServiceResponse,
ServicePostServiceRequest,
ServicePostServiceResponse,
ServiceWithKeySchema,
ServicePatchKeyResponse,
ServicePatchKeyRequest,
ServiceDeleteServiceRequest,
)
router = APIRouter(
tags=["Service"],
@ -27,15 +38,19 @@ router = APIRouter(
)
@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):
@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
):
"""
Returns the ID and name of all services registered to the hub.
"""
@ -44,16 +59,24 @@ async def get_all_services(db: db_dependency, org_model: org_model_root_claim_qu
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):
@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,
):
"""
Registers a new service to the hub, generating and returning an API key for it.
"""
@ -71,16 +94,22 @@ async def register_service(db: db_dependency, su: super_admin_dependency, reques
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):
@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,
):
"""
Generates and returns a new API key for the service to access the hub.
"""
@ -93,15 +122,23 @@ async def regenerate_api_key(db: db_dependency, su: super_admin_dependency,
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):
@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,
):
"""
Removes a service from the hub.
"""

View file

@ -6,36 +6,46 @@ Models follow the nomenclature of:
- Mixins: "<Attribute>Mixin"
- Models: "<Module><Method><Resource><Opt:Resource><Direction>" ie "ServiceGetServiceResponse"
"""
from pydantic import ConfigDict, Field
from src.schemas import CustomBaseModel
class ServiceIDMixin(CustomBaseModel):
service_id: int = Field(gt=0)
class ServiceSchema(CustomBaseModel):
model_config = ConfigDict(from_attributes=True, extra="ignore")
id: int
name: str
class ServiceWithKeySchema(ServiceSchema):
api_key: str
class ServiceGetServiceResponse(CustomBaseModel):
services: list[ServiceSchema]
class ServicePostServiceRequest(CustomBaseModel):
name: str
class ServicePostServiceResponse(CustomBaseModel):
service: ServiceWithKeySchema
class ServicePatchKeyRequest(ServiceIDMixin):
pass
class ServicePatchKeyResponse(CustomBaseModel):
service: ServiceWithKeySchema
class ServiceDeleteServiceRequest(ServiceIDMixin):
pass

View file

@ -1,3 +1,3 @@
"""
Business logic for the services module
"""
"""

View file

@ -4,6 +4,7 @@ Non-business logic reusable functions and classes for the services module
Exports:
- generate_api_key(): returns a new UUID
"""
import uuid