diff --git a/src/iam/models.py b/src/iam/models.py index c9ccc51..a06ff79 100644 --- a/src/iam/models.py +++ b/src/iam/models.py @@ -42,9 +42,7 @@ class Permission(Base): ), ) - service_rel = relationship( - "Service", back_populates="permission_rel", foreign_keys="Permission.service_id" - ) + service_rel = relationship("Service", foreign_keys="Permission.service_id") @property def service_name(self): diff --git a/src/iam/router.py b/src/iam/router.py index 5d824eb..69073ea 100644 --- a/src/iam/router.py +++ b/src/iam/router.py @@ -23,7 +23,6 @@ from sqlalchemy.exc import IntegrityError from psycopg.errors import UniqueViolation from src.iam.exceptions import GroupNotFoundException -from src.organisation.dependencies import org_model_body_dependency from src.organisation.exceptions import OrgNotFoundException from src.schemas import GroupSummary, OrgSummary, ResourceName from src.service.dependencies import service_model_body_dependency @@ -83,8 +82,6 @@ from src.iam.schemas import ( IAMCAoRResponse, IAMPutGroupInvitationAcceptResponse, IAMPutGroupInvitationResponse, - IAMPutOrgPermissionsRequest, - IAMPutOrgPermissionsResponse, ) from src.utils import verify_email_token @@ -550,7 +547,7 @@ async def delete_permission( response_model=IAMGetPermissionsSearchResponse, responses={}, ) -async def permissions_search( +async def post_permissions( db: db_dependency, org_model: org_model_root_claim_body_dependency, request_model: IAMGetPermissionsSearchRequest, @@ -675,36 +672,3 @@ async def accept_invitation( db.commit() return response - - -@router.put( - path="/org/permissions", - summary="Grants an org access to permissions", - status_code=status.HTTP_200_OK, - response_model=IAMPutOrgPermissionsResponse, - responses={ - status.HTTP_401_UNAUTHORIZED: {"description": "Must be super user."}, - }, -) -async def add_org_permissions( - db: db_dependency, - su: super_admin_dependency, - org_model: org_model_body_dependency, - request_model: IAMPutOrgPermissionsRequest, -): - """ - Grants a permission to a group. Returns a list of the permissions in the group as well as a summary for the org and group. - """ - for permission in request_model.permissions: - perm_model = db.get(Perm, permission) - - if perm_model not in org_model.permission_rel: - org_model.permission_rel.append(perm_model) - - db.flush() - response = IAMPutOrgPermissionsResponse( - organisation=OrgSummary(**org_model.__dict__), - permissions=org_model.permission_rel, - ) - db.commit() - return response diff --git a/src/iam/schemas.py b/src/iam/schemas.py index 8072914..d8e526b 100644 --- a/src/iam/schemas.py +++ b/src/iam/schemas.py @@ -150,12 +150,3 @@ class IAMPutGroupInvitationAcceptResponse(CustomBaseModel): organisation: OrgSummary user: UserSummary group: GroupDetails - - -class IAMPutOrgPermissionsRequest(OrgIDMixin): - permissions: list[int] - - -class IAMPutOrgPermissionsResponse(CustomBaseModel): - organisation: OrgSummary - permissions: list[PermissionSchema] diff --git a/src/iam/service.py b/src/iam/service.py index e3c8740..056b39c 100644 --- a/src/iam/service.py +++ b/src/iam/service.py @@ -7,19 +7,21 @@ Exports: from typing import Annotated from datetime import datetime, timedelta, timezone -from fastapi import Request, Depends +from src.service.models import Service from src.database import db_dependency from src.exceptions import UnauthorizedException from src.utils import send_email, generate_jwt + +from src.iam.schemas import IAMCAoRRequest from src.iam.models import Group -from src.service.models import Service -from src.service.schemas import HasServiceName + +from fastapi import Request, Depends def valid_service_key( - db: db_dependency, request: Request, request_model: HasServiceName + db: db_dependency, request: Request, request_model: IAMCAoRRequest ) -> bool: rn = request_model.rn api_key = request.headers.get("X-API-Key", None) diff --git a/src/schemas.py b/src/schemas.py index 30f4f90..cb2e742 100644 --- a/src/schemas.py +++ b/src/schemas.py @@ -14,6 +14,13 @@ class CustomBaseModel(BaseModel): pass +class ResourceName(CustomBaseModel): + service: str + organisation: str + resource: str + instance: Optional[str] = None + + ### Mixins ### class OrgIDMixin(CustomBaseModel): organisation_id: int = Field(gt=0) @@ -35,10 +42,6 @@ class UserIDMixin(CustomBaseModel): user_id: int = Field(gt=0) -class ServiceNameMixin(CustomBaseModel): - service: str - - class OrgSummary(CustomBaseModel): id: int name: str @@ -57,9 +60,3 @@ class UserSummary(CustomBaseModel): class ServiceSummary(CustomBaseModel): id: int name: str - - -class ResourceName(ServiceNameMixin): - organisation: str - resource: str - instance: Optional[str] = None diff --git a/src/service/models.py b/src/service/models.py index 414de5d..82bdba1 100644 --- a/src/service/models.py +++ b/src/service/models.py @@ -7,7 +7,6 @@ Models: """ from sqlalchemy import Column, Integer, String -from sqlalchemy.orm import relationship from src.database import Base @@ -18,5 +17,3 @@ class Service(Base): id = Column(Integer, primary_key=True) name = Column(String, unique=True) api_key = Column(String, unique=True) - - permission_rel = relationship("Permission", back_populates="service_rel") diff --git a/src/service/router.py b/src/service/router.py index 22e8594..d4954fd 100644 --- a/src/service/router.py +++ b/src/service/router.py @@ -18,9 +18,6 @@ from src.auth.dependencies import ( super_admin_dependency, org_model_root_claim_query_dependency, ) -from src.iam.service import service_key_dependency -from src.iam.models import Permission as Perm -from src.service.exceptions import ServiceNotFoundException from src.service.models import Service from src.service.utils import generate_api_key @@ -35,8 +32,6 @@ from src.service.schemas import ( ServiceWithKeySchema, ServicePatchKeyResponse, ServicePatchKeyRequest, - ServicePostPermissionsResponse, - ServicePostPermissionsRequest, ) router = APIRouter( @@ -175,66 +170,3 @@ async def remove_service( """ db.delete(service_model) db.commit() - - -@router.post( - path="/permissions", - summary="Service endpoint for creating its own permissions.", - status_code=status.HTTP_200_OK, - response_model=ServicePostPermissionsResponse, - responses={ - status.HTTP_401_UNAUTHORIZED: { - "description": "API Key missing or invalid | Issue verifying user OIDC claims" - }, - }, -) -async def service_create_new_permissions( - db: db_dependency, - request_model: ServicePostPermissionsRequest, - valid_key: service_key_dependency, -): - """ - Allows a service to register its own set of permissions. - """ - service_model = ( - db.query(Service).filter(Service.name == request_model.rn.service).first() - ) - if service_model is None: - raise ServiceNotFoundException() - else: - service_id = service_model.id - response_list = [] - for new_permission in request_model.permissions: - perm_model = ( - db.query(Perm) - .filter(Perm.service_id == service_id) - .filter(Perm.resource == new_permission.resource) - .filter(Perm.action == new_permission.action) - .first() - ) - if perm_model is not None: - response_code = 409 - response = { - "id": perm_model.id, - "service_name": perm_model.service_name, - "resource": perm_model.resource, - "action": perm_model.action, - } - response_list.append((response, response_code)) - continue - - new_perm_model = Perm(**new_permission.__dict__) - new_perm_model.service_id = service_id - db.add(new_perm_model) - db.flush() - response_code = 201 - response = { - "id": new_perm_model.id, - "service_name": new_perm_model.service_name, - "resource": new_perm_model.resource, - "action": new_perm_model.action, - } - response_list.append((response, response_code)) - - db.commit() - return {"permissions": response_list} diff --git a/src/service/schemas.py b/src/service/schemas.py index 544dac3..71bb215 100644 --- a/src/service/schemas.py +++ b/src/service/schemas.py @@ -6,36 +6,9 @@ Models follow the nomenclature of: - Models: "" ie "ServiceGetServiceResponse" """ -from typing import Generic, TypeVar -from pydantic import Field, ConfigDict +from pydantic import Field -from src.schemas import ( - CustomBaseModel, - ServiceIDMixin, - ServiceSummary, - ServiceNameMixin, -) - - -T = TypeVar("T", bound=ServiceNameMixin) - - -class HasServiceName(CustomBaseModel, Generic[T]): - rn: T - - -class PermissionResponseSchema(CustomBaseModel): - model_config = ConfigDict(from_attributes=True, extra="ignore") - - id: int - service_name: str - resource: str - action: str - - -class PermissionRequestSchema(CustomBaseModel): - resource: str - action: str +from src.schemas import CustomBaseModel, ServiceIDMixin, ServiceSummary class ServiceWithKeySchema(ServiceSummary): @@ -60,12 +33,3 @@ class ServicePatchKeyRequest(ServiceIDMixin): class ServicePatchKeyResponse(CustomBaseModel): service: ServiceWithKeySchema - - -class ServicePostPermissionsRequest(CustomBaseModel): - rn: ServiceNameMixin - permissions: list[PermissionRequestSchema] - - -class ServicePostPermissionsResponse(CustomBaseModel): - permissions: list[tuple[PermissionResponseSchema, int]]