diff --git a/src/iam/router.py b/src/iam/router.py index fa33d6c..df4bc95 100644 --- a/src/iam/router.py +++ b/src/iam/router.py @@ -24,7 +24,6 @@ from src.organisation.exceptions import OrgNotFoundException from src.service.exceptions import ServiceNotFoundException from src.exceptions import ConflictException from src.database import db_dependency -from src.schemas import ResourceName from src.auth.exceptions import UnauthorizedException from src.auth.service import claims_dependency from src.auth.dependencies import ( @@ -55,10 +54,11 @@ from src.iam.dependencies import ( perm_model_query_dependency, ) from src.iam.schemas import ( + GroupSchema, + IAMCAoRRequest, IAMGetGroupPermissionsResponse, IAMGetGroupUsersResponse, IAMPostGroupRequest, - GroupSchema, IAMPostGroupResponse, IAMPutGroupPermissionRequest, IAMPutGroupPermissionResponse, @@ -87,10 +87,11 @@ async def can_act_on_resource( valid_key: service_key_dependency, db: db_dependency, user_claims: claims_dependency, - rn: ResourceName, - action: str, + request_model: IAMCAoRRequest, ) -> bool: try: + rn = request_model.rn + action = request_model.action user_id = user_claims["db_id"] rn_org = rn.organisation rn_service = rn.service diff --git a/src/iam/schemas.py b/src/iam/schemas.py index 6a7e9d8..8ab00e4 100644 --- a/src/iam/schemas.py +++ b/src/iam/schemas.py @@ -12,6 +12,7 @@ from pydantic import EmailStr, ConfigDict, Field from src.schemas import ( CustomBaseModel, + ResourceName, ServiceIDMixin, OrgIDMixin, UserIDMixin, @@ -43,6 +44,11 @@ class GroupSchema(CustomBaseModel): name: str +class IAMCAoRRequest(CustomBaseModel): + action: str + rn: ResourceName + + class IAMGetGroupPermissionsResponse(CustomBaseModel): permissions: list[PermissionSchema] diff --git a/src/iam/service.py b/src/iam/service.py index 53142ce..6fe4d5f 100644 --- a/src/iam/service.py +++ b/src/iam/service.py @@ -8,9 +8,9 @@ Exports: from typing import Annotated from datetime import datetime, timedelta, timezone +from src.iam.schemas import IAMCAoRRequest from src.service.models import Service from src.database import db_dependency -from src.schemas import ResourceName from src.auth.exceptions import UnauthorizedException from src.utils import send_email, generate_jwt @@ -18,7 +18,10 @@ from src.utils import send_email, generate_jwt from fastapi import Request, Depends -def valid_service_key(db: db_dependency, request: Request, rn: ResourceName) -> bool: +def valid_service_key( + db: db_dependency, request: Request, request_model: IAMCAoRRequest +) -> bool: + rn = request_model.rn api_key = request.headers.get("X-API-Key", None) if not api_key: raise UnauthorizedException("Missing API key") diff --git a/test/test_iam.py b/test/test_iam.py index 591e789..764c46c 100644 --- a/test/test_iam.py +++ b/test/test_iam.py @@ -18,16 +18,20 @@ pytestmark = [ @pytest.mark.anyio async def test_post_act_on_resource_endpoint_success(default_client: AsyncClient): body = { - "service": "Test Service", - "organisation": "Test Org", - "resource": "test_resource", + "rn": { + "service": "Test Service", + "organisation": "Test Org", + "resource": "test_resource", + "instance": None, + }, + "action": "read", } headers = { "Authorization": "Bearer not_checked_when_auth_is_disabled", "X-API-Key": "123456789", } resp = await default_client.post( - "/iam/can_act_on_resource?action=read", json=body, headers=headers + "/iam/can_act_on_resource", json=body, headers=headers ) data = resp.json() @@ -43,13 +47,20 @@ async def test_post_act_on_resource_endpoint_success(default_client: AsyncClient async def test_act_on_resource_wrong_key( default_client: AsyncClient, db_session, service: str, api_key: str ): - body = {"service": service, "organisation": "Test Org", "resource": "test_resource"} + body = { + "rn": { + "service": service, + "organisation": "Test Org", + "resource": "test_resource", + }, + "action": "read", + } headers = { "Authorization": "Bearer not_checked_when_auth_is_disabled", "X-API-Key": api_key, } resp = await default_client.post( - "/iam/can_act_on_resource?action=read", json=body, headers=headers + "/iam/can_act_on_resource", json=body, headers=headers ) data = resp.json() @@ -60,9 +71,12 @@ async def test_act_on_resource_wrong_key( @pytest.mark.anyio async def test_act_on_resource_missing_key(default_client: AsyncClient): body = { - "service": "Test Service", - "organisation": "Test Org", - "resource": "test_resource", + "rn": { + "service": "Test Service", + "organisation": "Test Org", + "resource": "test_resource", + }, + "action": "read", } headers = {"Authorization": "Bearer not_checked_when_auth_is_disabled"} resp = await default_client.post( @@ -120,13 +134,16 @@ async def test_act_on_resource_logic( action, expected_response: bool, ): - body = {"service": service, "organisation": org, "resource": resource} + body = { + "rn": {"service": service, "organisation": org, "resource": resource}, + "action": action, + } headers = { "Authorization": "Bearer not_checked_when_auth_is_disabled", "X-API-Key": "123456789", } resp = await default_client.post( - f"/iam/can_act_on_resource?action={action}", json=body, headers=headers + "/iam/can_act_on_resource", json=body, headers=headers ) data = resp.json()