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 user module
"""
"""

View file

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

View file

@ -6,6 +6,7 @@ Exports:
- user_model_query_dependency: user_model: Gets user model from db, if it exists. Uses user_id from query param
- user_model_body_dependency: user_model: Gets user model from db, if it exists. Uses user_id from request body.
"""
from typing import Annotated
from fastapi import Depends, Query
@ -28,6 +29,7 @@ async def get_user_model_claims(claims: claims_dependency, db: db_dependency):
return user_model
user_model_claims_dependency = Annotated[type[User], Depends(get_user_model_claims)]
@ -38,6 +40,7 @@ async def get_user_model_query(db: db_dependency, user_id: Annotated[int, Query(
return user_model
user_model_query_dependency = Annotated[type[User], Depends(get_user_model_query)]
@ -48,4 +51,5 @@ async def get_user_model_body(db: db_dependency, request_model: UserIDMixin):
return user_model
user_model_body_dependency = Annotated[type[User], Depends(get_user_model_body)]

View file

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

View file

@ -9,6 +9,7 @@ Models:
- organisations: Calc property list of organisation_rel.name
- groups: Calc property dict of {group_rel.org_rel.name: group_rel.name}
"""
from collections import defaultdict
from sqlalchemy import Column, Integer, String
@ -18,29 +19,29 @@ from src.database import Base
class User(Base):
__tablename__ = "user"
__tablename__ = "user"
id = Column(Integer, primary_key=True)
email = Column(String)
first_name = Column(String)
last_name = Column(String)
oidc_id = Column(String, index=True, unique=True)
id = Column(Integer, primary_key=True)
email = Column(String)
first_name = Column(String)
last_name = Column(String)
oidc_id = Column(String, index=True, unique=True)
organisation_rel = relationship(
"Organisation", secondary="orgusers", back_populates="user_rel"
)
organisation_rel = relationship(
"Organisation", secondary="orgusers", back_populates="user_rel"
)
@property
def organisations(self):
return [{"name": org.name, "id": org.id} for org in self.organisation_rel]
@property
def organisations(self):
return [{"name": org.name, "id": org.id} for org in self.organisation_rel]
group_rel = relationship(
"Group", secondary="user_groups", back_populates="user_rel"
)
group_rel = relationship(
"Group", secondary="user_groups", back_populates="user_rel"
)
@property
def groups(self):
result = defaultdict(list)
for group in self.group_rel:
result[group.org_rel.name].append({"name": group.name, "id": group.id})
return dict(result)
@property
def groups(self):
result = defaultdict(list)
for group in self.group_rel:
result[group.org_rel.name].append({"name": group.name, "id": group.id})
return dict(result)

View file

@ -7,11 +7,16 @@ Endpoints:
- [GET](/user/): [super admin]: Returns user(id) details.
- [DELETE](/user/): [super admin]: Removes a User(id) from the hub database.
"""
from fastapi import APIRouter
from starlette import status
from src.user.schemas import UserResponse, OIDCClaims, UserDeleteUserRequest
from src.user.dependencies import user_model_claims_dependency, user_model_query_dependency, user_model_body_dependency
from src.user.dependencies import (
user_model_claims_dependency,
user_model_query_dependency,
user_model_body_dependency,
)
from src.auth.dependencies import super_admin_dependency
from src.auth.service import claims_dependency
@ -23,13 +28,15 @@ router = APIRouter(
)
@router.get("/self/claims",
summary="Get current user OIDC claims.",
response_model=OIDCClaims,
status_code=status.HTTP_200_OK,
responses={
status.HTTP_200_OK: {"description": "Successful retrieval from database"},
})
@router.get(
"/self/claims",
summary="Get current user OIDC claims.",
response_model=OIDCClaims,
status_code=status.HTTP_200_OK,
responses={
status.HTTP_200_OK: {"description": "Successful retrieval from database"},
},
)
async def current_user_claims(user: claims_dependency):
"""
Returns the full OIDC claims associated with the currently logged-in user.
@ -38,14 +45,16 @@ async def current_user_claims(user: claims_dependency):
return user
@router.get("/self/db",
summary="Get current user hub details.",
response_model=UserResponse,
status_code=status.HTTP_200_OK,
responses={
status.HTTP_404_NOT_FOUND: {"description": "User not found"},
status.HTTP_200_OK: {"description": "Successful retrieval from database"},
})
@router.get(
"/self/db",
summary="Get current user hub details.",
response_model=UserResponse,
status_code=status.HTTP_200_OK,
responses={
status.HTTP_404_NOT_FOUND: {"description": "User not found"},
status.HTTP_200_OK: {"description": "Successful retrieval from database"},
},
)
async def current_user(user_model: user_model_claims_dependency):
"""
Returns the database details associated with the currently logged-in user.
@ -53,30 +62,40 @@ async def current_user(user_model: user_model_claims_dependency):
return user_model
@router.get("/",
summary="Get user hub details by ID.",
response_model=UserResponse,
status_code=status.HTTP_200_OK,
responses={
status.HTTP_404_NOT_FOUND: {"description": "User not found"},
status.HTTP_200_OK: {"description": "Successful retrieval from database"},
})
async def get_user_by_id(user_model: user_model_query_dependency, su: super_admin_dependency):
@router.get(
"/",
summary="Get user hub details by ID.",
response_model=UserResponse,
status_code=status.HTTP_200_OK,
responses={
status.HTTP_404_NOT_FOUND: {"description": "User not found"},
status.HTTP_200_OK: {"description": "Successful retrieval from database"},
},
)
async def get_user_by_id(
user_model: user_model_query_dependency, su: super_admin_dependency
):
"""
Returns the database details associated with the provided user ID.
"""
return user_model
@router.delete("/",
summary="Delete user from hub by ID.",
status_code=status.HTTP_204_NO_CONTENT,
responses={
status.HTTP_204_NO_CONTENT: {"description": "User deleted"},
status.HTTP_404_NOT_FOUND: {"description": "User not found"},
})
async def delete_user_by_id(db: db_dependency, user_model: user_model_body_dependency, su: super_admin_dependency,
request_model: UserDeleteUserRequest):
@router.delete(
"/",
summary="Delete user from hub by ID.",
status_code=status.HTTP_204_NO_CONTENT,
responses={
status.HTTP_204_NO_CONTENT: {"description": "User deleted"},
status.HTTP_404_NOT_FOUND: {"description": "User not found"},
},
)
async def delete_user_by_id(
db: db_dependency,
user_model: user_model_body_dependency,
su: super_admin_dependency,
request_model: UserDeleteUserRequest,
):
"""
Deletes the user with the provided ID from the database. This will not remove them from OIDC, and they will be automatically readded on next login.
"""

View file

@ -1,6 +1,7 @@
"""
Pydantic models for the user module
"""
from typing import Optional
from pydantic import Field
@ -47,8 +48,8 @@ class UserResponse(CustomBaseModel):
first_name: str
last_name: str
email: str
organisations: list[Optional[dict[str, str|int]]]
groups: Optional[dict[str, list[dict[str, str|int]]]] = None
organisations: list[Optional[dict[str, str | int]]]
groups: Optional[dict[str, list[dict[str, str | int]]]] = None
class OrgResponse(CustomBaseModel):
@ -57,4 +58,4 @@ class OrgResponse(CustomBaseModel):
class UserDeleteUserRequest(UserIDMixin):
pass
pass

View file

@ -4,6 +4,7 @@ Module specific business logic for user module
Exports:
- add_user_to_db: Creates a User record from OIDC claims, or updates user details
"""
from typing import Any
from sqlalchemy.orm import Session
@ -16,7 +17,12 @@ from src.user.models import User
async def add_user_to_db(db: Session, user_claims: dict[str, Any]) -> int:
try:
valid_user = OIDCUser(first_name=user_claims["given_name"], last_name=user_claims["family_name"], email=user_claims["email"], oidc_id=user_claims["sub"])
valid_user = OIDCUser(
first_name=user_claims["given_name"],
last_name=user_claims["family_name"],
email=user_claims["email"],
oidc_id=user_claims["sub"],
)
except Exception as e:
print(e)
raise UnprocessableContentException("Invalid or missing OIDC data")

View file

@ -1,3 +1,3 @@
"""
Non-business logic reusable functions and classes for the user module
"""
"""