Compare commits

..

No commits in common. "6a90e03d4056c1b1b2a1531e91b9209b178f5625" and "f7efbfcfc58dce8695475b3533e03f5ab32c5ec1" have entirely different histories.

3 changed files with 29 additions and 147 deletions

View file

@ -36,10 +36,6 @@ tags_metadata = [
"name": "Service", "name": "Service",
"description": "Services related operations, includes registering services and reissuing API keys", "description": "Services related operations, includes registering services and reissuing API keys",
}, },
{
"name": "Organisation",
"description": "Organisation related operations, includes getting lists of users etc associated with orgs",
},
] ]

View file

@ -43,20 +43,11 @@ from src.organisation.schemas import OrgPostOrgRequest, OrgPatchQuestionnaireReq
router = APIRouter( router = APIRouter(
prefix="/org", prefix="/org",
tags=["Organisation"], tags=["org"],
) )
@router.get("/id", @router.get("/id", response_model=OrgGetOrgResponse)
summary="Get org details by ID.",
response_model=OrgGetOrgResponse,
status_code=status.HTTP_200_OK,
responses={
status.HTTP_200_OK: {"description": "Successful retrieval from database"},
status.HTTP_404_NOT_FOUND: {"description": "Organisation not found"},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Missing or invalid org_id query parameter"},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
})
async def get_org_by_id(org_model: org_model_root_claim_query_dependency): async def get_org_by_id(org_model: org_model_root_claim_query_dependency):
response = { response = {
"name": org_model.name, "name": org_model.name,
@ -70,17 +61,8 @@ async def get_org_by_id(org_model: org_model_root_claim_query_dependency):
return response return response
@router.post("/", @router.post("/")
summary="Create new organisation.",
status_code=status.HTTP_201_CREATED,
responses={
status.HTTP_201_CREATED: {"description": "Successfully created organisation."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "User must be logged in with OIDC to create organisation."},
status.HTTP_409_CONFLICT: {"description": "Organisation with this name already exists."},
})
async def create_org(db: db_dependency, user_model: user_model_claims_dependency, request_model: OrgPostOrgRequest): async def create_org(db: db_dependency, user_model: user_model_claims_dependency, request_model: OrgPostOrgRequest):
# TODO: Response model
if request_model.intake_questionnaire: if request_model.intake_questionnaire:
intake_questionnaire = request_model.intake_questionnaire.model_dump() intake_questionnaire = request_model.intake_questionnaire.model_dump()
else: else:
@ -106,21 +88,13 @@ async def create_org(db: db_dependency, user_model: user_model_claims_dependency
db.commit() db.commit()
@router.patch("/questionnaire", @router.patch("/questionnaire")
summary="Update questionnaire.",
status_code=status.HTTP_200_OK,
responses={
status.HTTP_200_OK: {"description": "Successfully updated questionnaire."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
})
async def update_questionnaire(db: db_dependency, org_model: org_model_root_claim_query_dependency, request_model: OrgPatchQuestionnaireRequest): async def update_questionnaire(db: db_dependency, org_model: org_model_root_claim_query_dependency, request_model: OrgPatchQuestionnaireRequest):
""" """
Route for updating questionnaire. Route for updating questionnaire.
The partial bool allows for submission of partially completed questionnaire and/or The partial bool allows for submission of partially completed questionnaire and/or
final "are you sure" check before setting the org to be in "submitted" status, awaiting admin approval. final "are you sure" check before setting the org to be in "submitted" status, awaiting admin approval.
""" """
# TODO: Response model
org_model.intake_questionnaire = request_model.intake_questionnaire.model_dump() org_model.intake_questionnaire = request_model.intake_questionnaire.model_dump()
# Allows for partially completed questionnaires to be saved without being submitted for review # Allows for partially completed questionnaires to be saved without being submitted for review
@ -130,101 +104,45 @@ async def update_questionnaire(db: db_dependency, org_model: org_model_root_clai
db.commit() db.commit()
@router.patch("/status", @router.patch("/status")
summary="Update status of organisation.",
status_code=status.HTTP_200_OK,
responses={
status.HTTP_200_OK: {"description": "Successfully updated organisation status."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be super admin."},
})
async def update_status(db: db_dependency, org_model: org_model_body_dependency, su: super_admin_dependency, request_model: OrgPatchStatusRequest): async def update_status(db: db_dependency, org_model: org_model_body_dependency, su: super_admin_dependency, request_model: OrgPatchStatusRequest):
# TODO: Response model
org_model.status = request_model.status org_model.status = request_model.status
db.commit() db.commit()
@router.get("/users", @router.get("/users", response_model=OrgGetUserResponse)
summary="Get email addresses of users of the organisation.",
status_code=status.HTTP_200_OK,
response_model=OrgGetUserResponse,
responses={
status.HTTP_200_OK: {"description": "Successful retrieval of users."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Org ID missing or invalid."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
})
async def get_users(org_model: org_model_root_claim_query_dependency): async def get_users(org_model: org_model_root_claim_query_dependency):
return {"users": [user.email for user in org_model.user_rel]} return {"users": [user.email for user in org_model.user_rel]}
@router.post("/users", @router.post("/users")
summary="All user to the organisation.",
status_code=status.HTTP_200_OK,
responses={
status.HTTP_200_OK: {"description": "Successfully added user to the organisation."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_409_CONFLICT: {"description": "User is already a member of the organisation."},
})
async def add_user_to_org(db: db_dependency, org_model: org_model_root_claim_body_dependency, user_model: user_model_body_dependency, request_model: OrgPostUserRequest): async def add_user_to_org(db: db_dependency, org_model: org_model_root_claim_body_dependency, user_model: user_model_body_dependency, request_model: OrgPostUserRequest):
# TODO: response model
if user_model in org_model.user_rel: if user_model in org_model.user_rel:
raise Conflict(message="User already a part of this organisation") raise Conflict(message="User already a part of this organisation")
org_model.user_rel.append(user_model) org_model.user_rel.append(user_model)
db.commit() db.commit()
@router.delete("/", @router.delete("/", status_code=status.HTTP_204_NO_CONTENT)
summary="Delete organisation from the hub.",
status_code=status.HTTP_204_NO_CONTENT,
responses={
status.HTTP_204_NO_CONTENT: {"description": "Successfully deleted organisation."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be super admin."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Org ID missing or invalid."},
})
async def delete_organisation_by_id(db: db_dependency, org_model: org_model_body_dependency, su: super_admin_dependency, request_model: OrgDeleteOrgRequest): async def delete_organisation_by_id(db: db_dependency, org_model: org_model_body_dependency, su: super_admin_dependency, request_model: OrgDeleteOrgRequest):
db.delete(org_model) db.delete(org_model)
db.commit() db.commit()
@router.patch("/root_user", @router.patch("/root_user", status_code=status.HTTP_204_NO_CONTENT)
summary="Update the root user of the organisation.",
status_code=status.HTTP_200_OK,
responses={
status.HTTP_200_OK: {"description": "Successfully updated root user."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be super admin."},
})
async def update_root_user(db: db_dependency, org_model: org_model_body_dependency, user_model: user_model_body_dependency, su: super_admin_dependency, request_model: OrgPatchRootRequest): async def update_root_user(db: db_dependency, org_model: org_model_body_dependency, user_model: user_model_body_dependency, su: super_admin_dependency, request_model: OrgPatchRootRequest):
# TODO: response model
org_model.root_user_rel = user_model org_model.root_user_rel = user_model
db.commit() db.commit()
@router.get("/groups", @router.get("/groups", response_model=OrgGetGroupResponse)
summary="Get all organisation IAM groups.",
status_code=status.HTTP_200_OK,
response_model=OrgGetGroupResponse,
responses={
status.HTTP_200_OK: {"description": "Successful retrieval of IAM groups."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Org ID missing or invalid."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
})
async def get_org_groups(org_model: org_model_root_claim_query_dependency): async def get_org_groups(org_model: org_model_root_claim_query_dependency):
return {"groups": [group.name for group in org_model.group_rel]} return {"groups": [group.name for group in org_model.group_rel]}
@router.delete("/user", @router.delete("/user", status_code=status.HTTP_204_NO_CONTENT)
summary="Remove user from organisation.",
status_code=status.HTTP_204_NO_CONTENT,
responses={
status.HTTP_204_NO_CONTENT: {"description": "Successfully removed user."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
})
async def remove_user_from_org(db: db_dependency, org_model: org_model_root_claim_body_dependency, user_model: user_model_body_dependency, request_model: OrgDeleteUserRequest): async def remove_user_from_org(db: db_dependency, org_model: org_model_root_claim_body_dependency, user_model: user_model_body_dependency, request_model: OrgDeleteUserRequest):
# TODO: response model
if user_model not in org_model.user_rel: if user_model not in org_model.user_rel:
return return
@ -232,15 +150,7 @@ async def remove_user_from_org(db: db_dependency, org_model: org_model_root_clai
db.commit() db.commit()
@router.get("/contact", @router.get("/contact", response_model=OrgGetContactResponse)
summary="Get contact for organisation.",
status_code=status.HTTP_200_OK,
response_model=OrgGetContactResponse,
responses={
status.HTTP_200_OK: {"description": "Successful retrieval of contact."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
})
async def get_contact(org_model: org_model_root_claim_query_dependency, contact_type: Annotated[ContactType, Query()]): async def get_contact(org_model: org_model_root_claim_query_dependency, contact_type: Annotated[ContactType, Query()]):
match contact_type: match contact_type:
case "billing": case "billing":
@ -261,15 +171,7 @@ async def get_contact(org_model: org_model_root_claim_query_dependency, contact_
return {"contact": contact_response} return {"contact": contact_response}
@router.patch("/contact", @router.patch("/contact", response_model=OrgGetContactResponse)
summary="Update contact for organisation.",
status_code=status.HTTP_200_OK,
response_model=OrgGetContactResponse,
responses={
status.HTTP_200_OK: {"description": "Successfully updated contact."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
})
async def update_contact(db: db_dependency, org_model: org_model_root_claim_body_dependency, request_model: OrgPatchContactRequest): async def update_contact(db: db_dependency, org_model: org_model_root_claim_body_dependency, request_model: OrgPatchContactRequest):
match request_model.contact_type: match request_model.contact_type:
case "billing": case "billing":

View file

@ -23,11 +23,7 @@ router = APIRouter(
) )
@router.get("/self/claims", @router.get("/self/claims", response_model=OIDCClaims, status_code=status.HTTP_200_OK, responses={
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"}, status.HTTP_200_OK: {"description": "Successful retrieval from database"},
}) })
async def current_user_claims(user: claims_dependency): async def current_user_claims(user: claims_dependency):
@ -38,11 +34,7 @@ async def current_user_claims(user: claims_dependency):
return user return user
@router.get("/self/db", @router.get("/self/db", response_model=UserResponse, status_code=status.HTTP_200_OK, responses={
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_404_NOT_FOUND: {"description": "User not found"},
status.HTTP_200_OK: {"description": "Successful retrieval from database"}, status.HTTP_200_OK: {"description": "Successful retrieval from database"},
}) })
@ -53,11 +45,7 @@ async def current_user(user_model: user_model_claims_dependency):
return user_model return user_model
@router.get("/", @router.get("/", response_model=UserResponse, status_code=status.HTTP_200_OK, responses={
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_404_NOT_FOUND: {"description": "User not found"},
status.HTTP_200_OK: {"description": "Successful retrieval from database"}, status.HTTP_200_OK: {"description": "Successful retrieval from database"},
}) })
@ -68,15 +56,11 @@ async def get_user_by_id(user_model: user_model_query_dependency, su: super_admi
return user_model return user_model
@router.delete("/", @router.delete("/", status_code=status.HTTP_204_NO_CONTENT, responses={
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_204_NO_CONTENT: {"description": "User deleted"},
status.HTTP_404_NOT_FOUND: {"description": "User not found"}, 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, async def delete_user_by_id(db: db_dependency, user_model: user_model_body_dependency, su: super_admin_dependency, request_model: UserDeleteUserRequest):
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. 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.
""" """