diff --git a/example.env b/example.env deleted file mode 100644 index b2ab4c9..0000000 --- a/example.env +++ /dev/null @@ -1,10 +0,0 @@ -SECRET_KEY="" -OIDC_CONFIG="https://sso.sr2.uk/realms/sr2/.well-known/openid-configuration" -OIDC_ISSUER="https://sso.sr2.uk/realms/sr2" -OIDC_AUDIENCE="account" -CLIENT_ID="" - -DATABASE_NAME="cloud-api" -DATABASE_PORT="5432" -DATABASE_HOSTNAME="localhost" -DATABASE_CREDENTIALS="user:password" diff --git a/src/admin/config.py b/src/admin/config.py index 46e4142..3139962 100644 --- a/src/admin/config.py +++ b/src/admin/config.py @@ -1,3 +1,7 @@ """ Configurations for the admin module + +Configurations: + - List: Description + - Configs: Description """ \ No newline at end of file diff --git a/src/admin/constants.py b/src/admin/constants.py index c75163f..58a3b2a 100644 --- a/src/admin/constants.py +++ b/src/admin/constants.py @@ -1,3 +1,7 @@ """ -Constants for the admin module +Constants and error codes for the admin module + +Constants: + - List: Description + - Consts: Description """ \ No newline at end of file diff --git a/src/admin/dependencies.py b/src/admin/dependencies.py index aff00b3..cb4c147 100644 --- a/src/admin/dependencies.py +++ b/src/admin/dependencies.py @@ -1,3 +1,11 @@ """ -Dependencies for the admin module +Router dependencies for the admin module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/admin/exceptions.py b/src/admin/exceptions.py index 513805c..644a8b0 100644 --- a/src/admin/exceptions.py +++ b/src/admin/exceptions.py @@ -1,3 +1,7 @@ """ -Custom exceptions for the admin module +Module specific exceptions for the admin module + +Exceptions: + - List: Description + - Exceptions: Description """ \ No newline at end of file diff --git a/src/admin/models.py b/src/admin/models.py index 304e336..1b60920 100644 --- a/src/admin/models.py +++ b/src/admin/models.py @@ -1,3 +1,7 @@ """ Database models for the admin module + +Models: + - List: Description + - Models: Description """ \ No newline at end of file diff --git a/src/admin/router.py b/src/admin/router.py index e0246a4..13ac897 100644 --- a/src/admin/router.py +++ b/src/admin/router.py @@ -1,8 +1,9 @@ """ Router endpoints for the admin module -Exports: - - router: fastapi.APIRouter +Endpoints: + - List: Description + - Endpoints: Description """ from fastapi import APIRouter diff --git a/src/admin/schemas.py b/src/admin/schemas.py index 1289bcb..4490920 100644 --- a/src/admin/schemas.py +++ b/src/admin/schemas.py @@ -1,3 +1,7 @@ """ Pydantic models for the admin module + +Models: + - List: Description + - Models: Description """ \ No newline at end of file diff --git a/src/admin/service.py b/src/admin/service.py index 1db3599..1cd5069 100644 --- a/src/admin/service.py +++ b/src/admin/service.py @@ -1,3 +1,11 @@ """ Module specific business logic for the admin module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/admin/utils.py b/src/admin/utils.py index e570f14..4e316d1 100644 --- a/src/admin/utils.py +++ b/src/admin/utils.py @@ -1,3 +1,11 @@ """ Non-business logic reusable functions and classes for the admin module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/auth/config.py b/src/auth/config.py index 82646d2..37de6a7 100644 --- a/src/auth/config.py +++ b/src/auth/config.py @@ -1,8 +1,9 @@ """ -Configurations for the auth module +Configurations for auth module, import auth_settings -Exports: - - auth_settings: Contains OIDC information +Configurations: + - List: Description + - Configs: Description """ from src.config import CustomBaseSettings diff --git a/src/auth/constants.py b/src/auth/constants.py index faabd82..1ab3fd6 100644 --- a/src/auth/constants.py +++ b/src/auth/constants.py @@ -1,3 +1,7 @@ """ -Constants for the auth module +Constants and error codes for auth module + +Constants: + - List: Description + - Consts: Description """ \ No newline at end of file diff --git a/src/auth/dependencies.py b/src/auth/dependencies.py index f87064a..e85ef9c 100644 --- a/src/auth/dependencies.py +++ b/src/auth/dependencies.py @@ -1,17 +1,18 @@ """ -Auth dependencies +Router dependencies for auth module -Exports: - - org_query_user_claims_dependency: bool: Verifies user belongs to org - - org_model_root_claim_query_dependency: org_model: verifies org exists and user is either root or su, gets org from query - - org_model_root_claim_body_dependency: org_model: verifies org exists and user is either root or su, gets org from body - - super_admin_dependency: user_model: verifies the user is a super admin +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ from typing import Annotated from fastapi import Depends from src.user.dependencies import user_model_claims_dependency -from src.user.models import User from src.organisation.dependencies import org_model_query_dependency, org_model_body_dependency from src.organisation.models import Organisation as Org @@ -68,4 +69,4 @@ async def user_model_super_admin(user_model: user_model_claims_dependency): raise UnauthorizedException() -super_admin_dependency = Annotated[type[User], Depends(user_model_super_admin)] +super_admin_dependency = Annotated[bool, Depends(user_model_super_admin)] diff --git a/src/auth/exceptions.py b/src/auth/exceptions.py index 613b166..71aede1 100644 --- a/src/auth/exceptions.py +++ b/src/auth/exceptions.py @@ -1,8 +1,9 @@ """ -Module specific exceptions for the auth module +Module specific exceptions for auth module Exceptions: - - UnauthorizedException: Takes an optional message string + - List: Description + - Exceptions: Description """ from typing import Optional diff --git a/src/auth/models.py b/src/auth/models.py index 4717477..487b3d1 100644 --- a/src/auth/models.py +++ b/src/auth/models.py @@ -1,3 +1,7 @@ """ -Database models for the auth module +Database models for auth module + +Models: + - List: Description + - Models: Description """ \ No newline at end of file diff --git a/src/auth/router.py b/src/auth/router.py index 9cd7fad..5e8871d 100644 --- a/src/auth/router.py +++ b/src/auth/router.py @@ -1,8 +1,8 @@ """ -Router endpoints for the auth module +Router endpoints for auth module +Contains oauth registration -Exports: - - router: fastapi.APIRouter +Endpoints: """ from fastapi import APIRouter diff --git a/src/auth/schemas.py b/src/auth/schemas.py index 279bb1b..92afae5 100644 --- a/src/auth/schemas.py +++ b/src/auth/schemas.py @@ -1,3 +1,7 @@ """ -Pydantic models for the auth module +Pydantic models for auth module + +Models: + - List: Description + - Models: Description """ \ No newline at end of file diff --git a/src/auth/service.py b/src/auth/service.py index dce8217..e0a764e 100644 --- a/src/auth/service.py +++ b/src/auth/service.py @@ -1,8 +1,8 @@ """ -Module specific business logic for the auth module +Module specific business logic for auth module Exports: - - claims_dependency: Dict[str, Any] containing OIDC claims and database ID + - claims_dependency """ import json import requests diff --git a/src/auth/utils.py b/src/auth/utils.py index ed66e7c..e913437 100644 --- a/src/auth/utils.py +++ b/src/auth/utils.py @@ -1,3 +1,11 @@ """ -Non-business logic reusable functions and classes for the auth module +Non-business logic reusable functions and classes for auth module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/contact/config.py b/src/contact/config.py index 2253a68..5e7f864 100644 --- a/src/contact/config.py +++ b/src/contact/config.py @@ -1,3 +1,7 @@ """ -Configurations for the contact module +Configurations for contact module + +Configurations: + - List: Description + - Configs: Description """ \ No newline at end of file diff --git a/src/contact/constants.py b/src/contact/constants.py index 41f6ded..49898d6 100644 --- a/src/contact/constants.py +++ b/src/contact/constants.py @@ -1,3 +1,7 @@ """ -Constants for the contact module +Constants and error codes for contact module + +Constants: + - List: Description + - Consts: Description """ \ No newline at end of file diff --git a/src/contact/dependencies.py b/src/contact/dependencies.py index de1d404..2450730 100644 --- a/src/contact/dependencies.py +++ b/src/contact/dependencies.py @@ -1,3 +1,11 @@ """ -Dependencies for the contact module +Router dependencies for contact module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/contact/exceptions.py b/src/contact/exceptions.py index 6710bf3..b3f8e11 100644 --- a/src/contact/exceptions.py +++ b/src/contact/exceptions.py @@ -1,8 +1,9 @@ """ -Exceptions related to the contact module +Module specific exceptions for contact module -Exports: - - ContactNotFoundException: Takes an optional contact ID int +Exceptions: + - List: Description + - Exceptions: Description """ from typing import Optional diff --git a/src/contact/models.py b/src/contact/models.py index 3369501..e3d0d05 100644 --- a/src/contact/models.py +++ b/src/contact/models.py @@ -1,9 +1,9 @@ """ -Database models for the contact module +Database models for contact module Models: - Contact: id[pk], email, first_name, last_name, phonenumber, vat_number - street_address, street_address_line_2, post_office_box_number, address_locality, country_code, address_region, postal_code + street_address, post_office_box_number, address_locality, country_code, address_region, postal_code """ from sqlalchemy import Column, Integer, String, ForeignKey diff --git a/src/contact/router.py b/src/contact/router.py index cdab37f..9528fd9 100644 --- a/src/contact/router.py +++ b/src/contact/router.py @@ -1,5 +1,13 @@ """ -Router endpoints for the contact module +Router endpoints for contact module + +Endpoints: + - [get]/{contact_id} - Returns non-address type details for contact + - [get]/{contact_id}/address - Returns address details for contact + - [get]/{contact_id}/orgs - Returns a list of orgs which the contact is assigned to, and what they are assigned as + - [post]/ - Creates a new contact + - [patch]/{contact_id} - Updates the details of an existing contact + - [delete]/{contact_id} - Deletes a contact by ID """ from fastapi import APIRouter diff --git a/src/contact/schemas.py b/src/contact/schemas.py index b008739..b5103f0 100644 --- a/src/contact/schemas.py +++ b/src/contact/schemas.py @@ -1,9 +1,9 @@ """ -Pydantic models for the contact module +Pydantic models for contact module Models: - - ContactAddress - - ContactModel: Contains ContactAddress as a property + - List: Description + - Models: Description """ from typing import Optional diff --git a/src/contact/service.py b/src/contact/service.py index e04866a..ee4af6c 100644 --- a/src/contact/service.py +++ b/src/contact/service.py @@ -1,3 +1,11 @@ """ -Module specific business logic for the contact module +Module specific business logic for contact module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/contact/utils.py b/src/contact/utils.py index 6a1d14a..74ec5c5 100644 --- a/src/contact/utils.py +++ b/src/contact/utils.py @@ -1,3 +1,11 @@ """ -Non-business logic reusable functions and classes for the contact module +Non-business logic reusable functions and classes for contact module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/iam/config.py b/src/iam/config.py index 165dc07..4be170e 100644 --- a/src/iam/config.py +++ b/src/iam/config.py @@ -1,3 +1,7 @@ """ -Configurations for the IAM module +Configurations for + +Configurations: + - List: Description + - Configs: Description """ \ No newline at end of file diff --git a/src/iam/constants.py b/src/iam/constants.py index 0dc94e7..e1df957 100644 --- a/src/iam/constants.py +++ b/src/iam/constants.py @@ -1,3 +1,7 @@ """ -Constants for the IAM module +Constants and error codes for + +Constants: + - List: Description + - Consts: Description """ \ No newline at end of file diff --git a/src/iam/dependencies.py b/src/iam/dependencies.py index 37b8e87..d5632c7 100644 --- a/src/iam/dependencies.py +++ b/src/iam/dependencies.py @@ -1,10 +1,13 @@ """ -Dependencies for the IAM module +Router dependencies for the IAM module -Exports: - - group_model_query_dependency: group_model: Gets group model from db, if it exists. Uses group_id from query param. - - group_model_body_dependency: group_model: Gets group model from db, if it exists. Uses group_id from request body. - - perm_model_body_dependency: perm_model: Gets perm model from db, if it exists. Uses perm_id from request body. +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ from typing import Annotated, Optional @@ -12,7 +15,7 @@ from fastapi import Depends, Query from src.database import db_dependency -from src.iam.models import Group, Permission +from src.iam.models import Group from src.iam.exceptions import GroupNotFoundException, PermNotFoundException from src.iam.schemas import GroupIDMixin, PermIDMixin @@ -40,14 +43,14 @@ def get_group_model_body(db: db_dependency, request_model: Optional[GroupIDMixin group_model_body_dependency = Annotated[type[Group], Depends(get_group_model_body)] -def get_perm_model_body(db: db_dependency, request_model: Optional[PermIDMixin] = None) -> type[Permission]: +def get_perm_model_body(db: db_dependency, request_model: Optional[PermIDMixin] = None) -> type[Group]: perm_id = getattr(request_model, "permission_id", None) if perm_id is None: raise PermNotFoundException - perm_model = db.get(Permission, perm_id) - if perm_model is None: + group_model = db.get(Group, perm_id) + if group_model is None: raise PermNotFoundException(perm_id) - return perm_model + return group_model -perm_model_body_dependency = Annotated[type[Permission], Depends(get_perm_model_body)] +perm_model_body_dependency = Annotated[type[Group], Depends(get_perm_model_body)] diff --git a/src/iam/exceptions.py b/src/iam/exceptions.py index 84a77ed..5c97b9a 100644 --- a/src/iam/exceptions.py +++ b/src/iam/exceptions.py @@ -1,9 +1,9 @@ """ -Exceptions related to the IAM module +Module specific exceptions for the IAM module Exceptions: - - GroupNotFoundException: Takes an optional group_id int - - PermNotFoundException: Takes an optional perm_id int + - List: Description + - Exceptions: Description """ from typing import Optional diff --git a/src/iam/models.py b/src/iam/models.py index ea12c0f..83d1ae2 100644 --- a/src/iam/models.py +++ b/src/iam/models.py @@ -2,11 +2,8 @@ Database models for the IAM module Models: - - Permission: - - id[PK], resource[U1], action[U1], service_id[FK][U1] - - service_rel: ORM relationship over service_id FK - - group_rel: ORM relationship backpops to Group.permission_rel - - service_name: Calc property service_rel.name + - List: Description + - Models: Description """ from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint from sqlalchemy.orm import relationship diff --git a/src/iam/router.py b/src/iam/router.py index a6398a9..4b2bbb4 100644 --- a/src/iam/router.py +++ b/src/iam/router.py @@ -1,19 +1,9 @@ """ -Router endpoints for IAM +Router endpoints for Endpoints: - - [POST](/iam/can_act_on_resource): [API key & user claim]: Service access point to verify user permissions - - [GET](/iam/group/permissions): [root user]: Gets list of perms(service, resource, action) the given group(id) has - - [DELETE](/iam/group/permissions): [root user]: Removes a given perm(id) from the given group(id) - - [GET](/iam/group/users): [root user]: Gets a list of users(id, name, email) that are assigned to the given group(id) - - [POST](/iam/group): [root user]: Creates a new group for the given org(id) - - [PUT](/iam/group/permission): [root user]: Assigns a perm(id) to the given group(id) - - [PUT](/iam/group/user): [root user]: Assigns a user(id) to a group(id) - - [DELETE](/iam/group/user): [root user]: Removes a user(id) from the given group(id) - - [GET](/iam/permissions): [root user]: Gets a list of all permissions - - [POST](/iam/permission): [super admin]: Creates a new permission - - [DELETE](/iam/permission): [super admin]: Removes a permission - - [GET](/iam/permissions/search): [root user]: Returns a list of permissions matching a filter(service|resource|action) + - List: Description + - Endpoints: Description """ from fastapi import APIRouter, status from sqlalchemy.exc import IntegrityError @@ -35,10 +25,10 @@ from src.iam.service import service_key_dependency from src.iam.models import Permission as Perm, GroupPermissions as GPerms, Group, UserGroups from src.iam.dependencies import group_model_query_dependency, group_model_body_dependency, perm_model_body_dependency from src.iam.schemas import IAMGetGroupPermissionsResponse, IAMGetGroupUsersResponse, IAMPostGroupRequest, \ - GroupSchema, IAMPostGroupResponse, IAMPutGroupPermissionRequest, IAMPutGroupPermissionResponse, \ + GroupResponse, IAMPostGroupResponse, IAMPutGroupPermissionRequest, IAMPutGroupPermissionResponse, \ IAMPutGroupUserRequest, IAMPutGroupUserResponse, IAMDeleteGroupPermissionRequest, IAMDeleteGroupPermissionResponse, \ IAMDeleteGroupUserRequest, IAMDeleteGroupUserResponse, IAMGetPermissionsResponse, IAMPostPermissionRequest, \ - IAMPostPermissionResponse, PermissionSchema, IAMDeletePermissionRequest, IAMGetPermissionsSearchRequest, IAMGetPermissionsSearchResponse + IAMPostPermissionResponse, PermissionResponse, IAMDeletePermissionRequest, IAMGetPermissionsSearchRequest, IAMGetPermissionsSearchResponse router = APIRouter( tags=["IAM"], @@ -101,7 +91,7 @@ async def create_group(db: db_dependency, org_model: org_model_root_claim_body_d except IntegrityError as e: if isinstance(e.orig, errors.UniqueViolation): raise Conflict("Group with this name already exists") - response = GroupSchema(**group_model.__dict__) + response = GroupResponse(**group_model.__dict__) db.commit() return {"group": response} @@ -117,7 +107,7 @@ async def add_group_permission(db: db_dependency, group_model: group_model_body_ group_model.permission_rel.append(perm_model) db.flush() - response = IAMPutGroupPermissionResponse(group=GroupSchema(**group_model.__dict__), permissions=group_model.permission_rel) + response = IAMPutGroupPermissionResponse(group=GroupResponse(**group_model.__dict__), permissions=group_model.permission_rel) db.commit() return response @@ -132,7 +122,7 @@ async def add_group_user(db: db_dependency, group_model: group_model_body_depend group_model.user_rel.append(user_model) db.flush() - response = IAMPutGroupUserResponse(group=GroupSchema(**group_model.__dict__), users=group_model.user_rel) + response = IAMPutGroupUserResponse(group=GroupResponse(**group_model.__dict__), users=group_model.user_rel) db.commit() return response @@ -144,8 +134,8 @@ async def remove_group_permissions(db: db_dependency, group_model: group_model_b group_model.permission_rel.remove(perm_model) db.flush() - response = IAMDeleteGroupPermissionResponse(group=GroupSchema(**group_model.__dict__), - permissions=group_model.permission_rel) + response = IAMDeleteGroupPermissionResponse(group=GroupResponse(**group_model.__dict__), + permissions=group_model.permission_rel) db.commit() return response @@ -157,7 +147,7 @@ async def remove_group_user(db: db_dependency, group_model: group_model_body_dep user_model.group_rel.remove(group_model) db.flush() - response = IAMDeleteGroupUserResponse(group=GroupSchema(**group_model.__dict__), users=group_model.user_rel) + response = IAMDeleteGroupUserResponse(group=GroupResponse(**group_model.__dict__), users=group_model.user_rel) db.commit() return response @@ -179,7 +169,7 @@ async def create_new_permission(db: db_dependency, su: super_admin_dependency, r if isinstance(e.orig, errors.UniqueViolation): raise Conflict(message="Permission already exists") db.flush() - response = IAMPostPermissionResponse(permission=PermissionSchema(**perm_model.__dict__)) + response = IAMPostPermissionResponse(permission=PermissionResponse(**perm_model.__dict__)) db.commit() return response diff --git a/src/iam/schemas.py b/src/iam/schemas.py index 3f34390..f6cd7bb 100644 --- a/src/iam/schemas.py +++ b/src/iam/schemas.py @@ -1,10 +1,9 @@ """ Pydantic models for the IAM module -Models follow the nomenclature of: -- Sub-models: "Schema" -- Mixins: "Mixin" -- Models: "" ie "IAMGetGroupPermissionsResponse" +Models: + - List: Description + - Models: Description """ from typing import Optional @@ -15,20 +14,20 @@ from src.schemas import CustomBaseModel from user.schemas import UserIDMixin -class UserSchema(CustomBaseModel): +class UserResponse(CustomBaseModel): id: int first_name: str last_name: str email: EmailStr -class PermissionSchema(CustomBaseModel): +class PermissionResponse(CustomBaseModel): model_config = ConfigDict(from_attributes=True, extra="ignore") service_name: str resource: str action: str -class GroupSchema(CustomBaseModel): +class GroupResponse(CustomBaseModel): id: int name: str @@ -39,47 +38,47 @@ class PermIDMixin(CustomBaseModel): permission_id: int class IAMGetGroupPermissionsResponse(CustomBaseModel): - permissions: list[PermissionSchema] + permissions: list[PermissionResponse] class IAMGetGroupUsersResponse(CustomBaseModel): - users : list[UserSchema] + users : list[UserResponse] class IAMPostGroupRequest(OrgIDMixin): name: str class IAMPostGroupResponse(CustomBaseModel): - group: GroupSchema + group: GroupResponse class IAMPutGroupPermissionRequest(GroupIDMixin, PermIDMixin): pass class IAMPutGroupPermissionResponse(CustomBaseModel): - group: GroupSchema - permissions: list[PermissionSchema] + group: GroupResponse + permissions: list[PermissionResponse] class IAMPutGroupUserRequest(GroupIDMixin, UserIDMixin): pass class IAMPutGroupUserResponse(CustomBaseModel): - group: GroupSchema - users: list[UserSchema] + group: GroupResponse + users: list[UserResponse] class IAMDeleteGroupPermissionRequest(GroupIDMixin, PermIDMixin): pass class IAMDeleteGroupPermissionResponse(CustomBaseModel): - group: GroupSchema - permissions: list[PermissionSchema] + group: GroupResponse + permissions: list[PermissionResponse] class IAMDeleteGroupUserRequest(GroupIDMixin, UserIDMixin): pass class IAMDeleteGroupUserResponse(CustomBaseModel): - group: GroupSchema - users: list[UserSchema] + group: GroupResponse + users: list[UserResponse] class IAMGetPermissionsResponse(CustomBaseModel): - permissions: list[PermissionSchema] + permissions: list[PermissionResponse] class IAMPostPermissionRequest(CustomBaseModel): service_id: int @@ -87,7 +86,7 @@ class IAMPostPermissionRequest(CustomBaseModel): action: str class IAMPostPermissionResponse(CustomBaseModel): - permission: PermissionSchema + permission: PermissionResponse class IAMDeletePermissionRequest(PermIDMixin): pass @@ -98,4 +97,4 @@ class IAMGetPermissionsSearchRequest(CustomBaseModel): action: Optional[str] = None class IAMGetPermissionsSearchResponse(CustomBaseModel): - permissions: list[PermissionSchema] + permissions: list[PermissionResponse] diff --git a/src/iam/service.py b/src/iam/service.py index b1d416b..1607cd0 100644 --- a/src/iam/service.py +++ b/src/iam/service.py @@ -1,8 +1,7 @@ """ -Business logic reusable functions related to IAM +Module specific business logic for -Exports: - - service_key_dependency: bool: verifies request headers contain the correct api key for the service +Exports service_key_dependency """ from typing import Annotated diff --git a/src/iam/utils.py b/src/iam/utils.py index d948f09..5afbb54 100644 --- a/src/iam/utils.py +++ b/src/iam/utils.py @@ -1,3 +1,11 @@ """ -Non-business logic reusable functions and classes for the IAM module +Non-business logic reusable functions and classes for + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ diff --git a/src/organisation/config.py b/src/organisation/config.py index e24ca5b..51f5dd9 100644 --- a/src/organisation/config.py +++ b/src/organisation/config.py @@ -1,3 +1,7 @@ """ -Configurations for the organisation module +Configurations for organisation module + +Configurations: + - List: Description + - Configs: Description """ \ No newline at end of file diff --git a/src/organisation/constants.py b/src/organisation/constants.py index ced0682..6cae1fd 100644 --- a/src/organisation/constants.py +++ b/src/organisation/constants.py @@ -1,5 +1,5 @@ """ -Constants for the organisation module +Constants and error codes for organisation module Classes: - Status(StrEnum): PARTIAL, SUBMITTED, REMEDIATION, APPROVED, REJECTED, REMOVED diff --git a/src/organisation/dependencies.py b/src/organisation/dependencies.py index 51ee569..3edd8be 100644 --- a/src/organisation/dependencies.py +++ b/src/organisation/dependencies.py @@ -1,9 +1,13 @@ """ -Dependencies related to the organisation module +Router dependencies for organisation module -Exports: - - org_model_query_dependency: org_model: Gets org model from db, if it exists. Uses org_id from query param. Also verifies if the org has been approved. - - org_model_body_dependency: org_model: Gets org model from db, if it exists. Uses org_id from request body. Also verifies if the org has been approved. +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ from typing import Annotated, Optional @@ -22,7 +26,7 @@ def get_org_model(db, request: Request, org_id: int): if org_model is None: raise OrgNotFoundException(org_id) - pre_approval_endpoints = ["PATCH/org/status", "PATCH/org/questionnaire", "GET/org/id", "GET/org/contact", "PATCH/org/contact"] + pre_approval_endpoints = ["PATCH/org/status", "PATCH/org/questionnaire", "GET/org/id"] current_request = f"{request.method}{request.url.path}" if current_request not in pre_approval_endpoints and org_model.status != OrgStatus.APPROVED: raise AwaitingApprovalException(org_id) diff --git a/src/organisation/exceptions.py b/src/organisation/exceptions.py index 8fe61cc..c7d6a0c 100644 --- a/src/organisation/exceptions.py +++ b/src/organisation/exceptions.py @@ -1,9 +1,9 @@ """ -Exceptions related to the organisation module +Module specific exceptions for organisation module Exceptions: - - OrgNotFoundException: Takes an optional org_id int - - AwaitingApprovalException: Takes an optional org_id int + - List: Description + - Exceptions: Description """ from typing import Optional diff --git a/src/organisation/models.py b/src/organisation/models.py index 3663f2c..f696824 100644 --- a/src/organisation/models.py +++ b/src/organisation/models.py @@ -2,16 +2,9 @@ Database models for organisation module Models: - - Organisation: - - id[PK], name, status, intake_questionnaire, root_user_id[FK], billing_contact_id[FK], security_contact_id[FK], owner_contact_id[FK] - - user_rel: ORM relationship to User via OrgUsers relationship table - - group_rel: ORM relationship to Group, backprops Group.org_rel - - root_user_rel: ORM relationship to User with root_user_id FK - - root_user_email: Calc property root_user_rel.email - - billing_contact_rel: ORM relationship to Contact with billing_contact FK - - security_contact_rel: ORM relationship to Contact with security_contact FK - - owner_contact_rel: ORM relationship to Contact with owner_contact FK - - OrgUsers: org_id[FK][PK], user_id[FK][PK] + - Organisation: id[pk], name, status, intake_questionnaire, + billing_contact_id[fk], security_contact_id[fk], owner_contact_id[fk] + - OrgUsers: org_id[fk][cpk], user_id[fk][cpk], is_admin """ from sqlalchemy import Column, Integer, String, ForeignKey, JSON from sqlalchemy.orm import relationship diff --git a/src/organisation/router.py b/src/organisation/router.py index 2e71fba..c26bc2f 100644 --- a/src/organisation/router.py +++ b/src/organisation/router.py @@ -2,18 +2,15 @@ Router endpoints for organisation module Endpoints: - - [GET](/org/id): [root user]: Get details about an organisation(id) - - [POST](/org/): [oidc claim]: Creates an organisation, adds the current user as a user and sets them to be the root user - - [PATCH](/org/questionnaire): [root user]: Updates the org's intake questionnaire and optionally be submitted for review - - [PATCH](/org/status): [super admin]: Allows a super admin to update an org(id) status(Status enum) - - [GET](/org/users): [root user]: Gets a list of the org(id) users(email) - - [POST](/org/users): [root user]: Adds a new user(id) to the org(id) - - [DELETE](/org/): [super admin]: Deletes an organisation(id) - - [PATCH](/org/root_user): [super admin]: Updates an org(id) root user(id) - - [GET](/org/groups): [root user]: Gets a list of the org(id) groups(name) - - [DELETE](/org/user): [root user]: Removes a user(id) from an org(id) - - [GET](/org/contact): [root user]: Gets the (contact_type) contact for an org(id) - - [PATCH](/org/contact): [root user]: Updates the (contact_type) contact for an org(id). Any number of details can be changed. + - [get]/id/{org_id} - Retrieves an organisation by its ID + - [post]/ - Creates a new organisation + - [patch]/{org_id}/questionnaire - Updates the questionnaire data for an organisation (can be partial or final submission) + - [patch]/{org_id}/status - Updates the status of an organisation + - [patch]/{org_id}/contact - Assigns a contact to an organisation (as billing, security, or owner) + - [get]/{org_id}/users - Retrieves all users associated with an organisation + - [post]/{org_id}/users - Adds a new user to an organisation + - [delete]/{org_id} - Deletes an organisation by ID + - [get]/{org_id}/contact/{contact_type} - Retrieves the contact of a specific type (owner, billing, security) for an organisation """ from typing import Annotated, Optional diff --git a/src/organisation/schemas.py b/src/organisation/schemas.py index 0fb13c5..d727b98 100644 --- a/src/organisation/schemas.py +++ b/src/organisation/schemas.py @@ -1,10 +1,9 @@ """ Pydantic models for organisation module -Models follow the nomenclature of: -- Sub-models: "Schema" -- Mixins: "Mixin" -- Models: "" ie "OrgPostOrgRequest" +Models: + - List: Description + - Models: Description """ from typing import Optional @@ -17,7 +16,7 @@ from src.user.schemas import UserIDMixin from src.organisation.constants import Status, ContactType -class Questionnaire(CustomBaseModel): +class OrgQuestionnaire(CustomBaseModel): question_one: str question_two: str question_three: str @@ -28,10 +27,10 @@ class OrgIDMixin(CustomBaseModel): class OrgPostOrgRequest(CustomBaseModel): name: str - intake_questionnaire: Optional[Questionnaire] = None + intake_questionnaire: Optional[OrgQuestionnaire] = None class OrgPatchQuestionnaireRequest(OrgIDMixin): - intake_questionnaire: Questionnaire + intake_questionnaire: OrgQuestionnaire partial: bool class OrgPatchStatusRequest(OrgIDMixin): diff --git a/src/organisation/service.py b/src/organisation/service.py index 6d73399..b401681 100644 --- a/src/organisation/service.py +++ b/src/organisation/service.py @@ -1,3 +1,11 @@ """ -Reusable business logic functions for the organisation module +Module specific business logic for organisation module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/organisation/utils.py b/src/organisation/utils.py index ead22ca..32b2842 100644 --- a/src/organisation/utils.py +++ b/src/organisation/utils.py @@ -1,3 +1,11 @@ """ -Non-business logic reusable functions and classes for the organisation module +Non-business logic reusable functions and classes for organisation module + +Classes: + - List: Description + - Classes: Description + +Functions: + - List: Description + - Functions: Description """ \ No newline at end of file diff --git a/src/service/router.py b/src/service/router.py index f53d666..9bef22b 100644 --- a/src/service/router.py +++ b/src/service/router.py @@ -17,7 +17,7 @@ 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 + ServiceWithKeyResponse, ServicePatchKeyResponse, ServicePatchKeyRequest, ServiceDeleteServiceRequest router = APIRouter( tags=["Service"], @@ -42,7 +42,7 @@ async def register_service(db: db_dependency, su: super_admin_dependency, servic if isinstance(e.orig, UniqueViolation): raise Conflict(message="Service with this name already exists") db.commit() - response = ServiceWithKeySchema(**service_model.__dict__) + response = ServiceWithKeyResponse(**service_model.__dict__) db.commit() return {"service": response} @@ -52,7 +52,7 @@ async def regenerate_api_key(db: db_dependency, su: super_admin_dependency, serv service_model.api_key = key db.flush() - response = ServiceWithKeySchema(**service_model.__dict__) + response = ServiceWithKeyResponse(**service_model.__dict__) db.commit() return {"service": response} diff --git a/src/service/schemas.py b/src/service/schemas.py index d6f2882..deef4e3 100644 --- a/src/service/schemas.py +++ b/src/service/schemas.py @@ -12,29 +12,29 @@ from src.schemas import CustomBaseModel class ServiceIDMixin(CustomBaseModel): service_id: int -class ServiceSchema(CustomBaseModel): +class ServiceResponse(CustomBaseModel): model_config = ConfigDict(from_attributes=True, extra="ignore") id: int name: str -class ServiceWithKeySchema(ServiceSchema): +class ServiceWithKeyResponse(ServiceResponse): api_key: str class ServiceGetServiceResponse(CustomBaseModel): - services: list[ServiceSchema] + services: list[ServiceResponse] class ServicePostServiceRequest(CustomBaseModel): name: str class ServicePostServiceResponse(CustomBaseModel): - service: ServiceWithKeySchema + service: ServiceWithKeyResponse class ServicePatchKeyRequest(ServiceIDMixin): pass class ServicePatchKeyResponse(CustomBaseModel): - service: ServiceWithKeySchema + service: ServiceWithKeyResponse class ServiceDeleteServiceRequest(ServiceIDMixin): pass