diff --git a/src/iam/router.py b/src/iam/router.py index 07bd960..df4bc95 100644 --- a/src/iam/router.py +++ b/src/iam/router.py @@ -21,7 +21,6 @@ from sqlalchemy.exc import IntegrityError from src.iam.exceptions import GroupNotFoundException from src.organisation.exceptions import OrgNotFoundException -from src.schemas import GroupSummary, OrgSummary from src.service.exceptions import ServiceNotFoundException from src.exceptions import ConflictException from src.database import db_dependency @@ -128,11 +127,7 @@ async def get_group_permissions( ): if group_model.org_id != org_model.id: raise UnauthorizedException("Group does not belong to this organization") - return { - "organisation": org_model, - "group": group_model, - "permissions": group_model.permission_rel, - } + return {"permissions": group_model.permission_rel} @router.get("/group/users", response_model=IAMGetGroupUsersResponse) @@ -142,11 +137,7 @@ async def get_group_users( ): if group_model.org_id != org_model.id: raise UnauthorizedException("Group does not belong to this organization") - return { - "organisation": org_model, - "group": group_model, - "users": group_model.user_rel, - } + return {"users": group_model.user_rel} @router.post("/group", response_model=IAMPostGroupResponse) @@ -189,8 +180,7 @@ async def add_group_permission( db.flush() response = IAMPutGroupPermissionResponse( - organisation=OrgSummary(**org_model.__dict__), - group=GroupSummary(**group_model.__dict__), + group=GroupSchema(**group_model.__dict__), permissions=group_model.permission_rel, ) db.commit() diff --git a/src/iam/schemas.py b/src/iam/schemas.py index 66e3954..8ab00e4 100644 --- a/src/iam/schemas.py +++ b/src/iam/schemas.py @@ -18,9 +18,6 @@ from src.schemas import ( UserIDMixin, PermIDMixin, GroupIDMixin, - GroupSummary, - OrgSummary, - UserSummary, ) @@ -53,15 +50,11 @@ class IAMCAoRRequest(CustomBaseModel): class IAMGetGroupPermissionsResponse(CustomBaseModel): - organisation: OrgSummary - group: GroupSummary permissions: list[PermissionSchema] class IAMGetGroupUsersResponse(CustomBaseModel): - organisation: OrgSummary - group: GroupSummary - users: list[UserSummary] + users: list[UserSchema] class IAMPostGroupRequest(OrgIDMixin): @@ -77,8 +70,7 @@ class IAMPutGroupPermissionRequest(GroupIDMixin, PermIDMixin, OrgIDMixin): class IAMPutGroupPermissionResponse(CustomBaseModel): - organisation: OrgSummary - group: GroupSummary + group: GroupSchema permissions: list[PermissionSchema] diff --git a/src/organisation/router.py b/src/organisation/router.py index 5c862ea..96c59e1 100644 --- a/src/organisation/router.py +++ b/src/organisation/router.py @@ -314,10 +314,7 @@ async def add_user_to_org( raise ConflictException(message="User already a part of this organisation") org_model.user_rel.append(user_model) db.flush() - response = { - "organisation": org_model, - "users": [{"id": user.id, "email": user.email} for user in org_model.user_rel], - } + response = {"users": [user.email for user in org_model.user_rel]} db.commit() return response @@ -440,12 +437,7 @@ async def get_org_groups(org_model: org_model_root_claim_query_dependency): """ Returns a list of the names of all IAM groups created by the organisation. """ - return { - "organisation": org_model, - "groups": [ - {"id": group.id, "name": group.name} for group in org_model.group_rel - ], - } + return {"groups": [group.name for group in org_model.group_rel]} @router.delete( diff --git a/src/organisation/schemas.py b/src/organisation/schemas.py index b4e9f23..01085c5 100644 --- a/src/organisation/schemas.py +++ b/src/organisation/schemas.py @@ -10,14 +10,7 @@ from typing import Optional from pydantic import EmailStr, ConfigDict -from src.schemas import ( - CustomBaseModel, - OrgIDMixin, - UserIDMixin, - GroupSummary, - OrgSummary, - UserSummary, -) +from src.schemas import CustomBaseModel, OrgIDMixin, UserIDMixin from src.contact.schemas import ContactModel from src.organisation.constants import Status, ContactType @@ -29,6 +22,11 @@ class Questionnaire(CustomBaseModel): question_three: Optional[str] = None +class OrgSummary(CustomBaseModel): + id: int + name: str + + class ContactSummary(CustomBaseModel): id: int email: Optional[EmailStr] = None @@ -51,7 +49,6 @@ class OrgPostOrgRequest(CustomBaseModel): class OrgPostOrgResponse(CustomBaseModel): - id: int name: str status: Status @@ -62,7 +59,6 @@ class OrgPatchQuestionnaireRequest(OrgIDMixin): class OrgPatchQuestionnaireResponse(CustomBaseModel): - id: int name: str intake_questionnaire: Questionnaire status: Status @@ -73,7 +69,6 @@ class OrgPatchStatusRequest(OrgIDMixin): class OrgPatchStatusResponse(CustomBaseModel): - id: int name: str status: Status @@ -100,8 +95,7 @@ class OrgPostUserRequest(OrgIDMixin, UserIDMixin): class OrgPostUserResponse(CustomBaseModel): - organisation: OrgSummary - users: list[UserSummary] + users: list[str] class OrgPatchRootRequest(OrgIDMixin, UserIDMixin): @@ -119,8 +113,7 @@ class OrgGetUserResponse(CustomBaseModel): class OrgGetGroupResponse(CustomBaseModel): - organisation: OrgSummary - groups: list[GroupSummary] + groups: list[str] class OrgGetContactResponse(CustomBaseModel): diff --git a/src/schemas.py b/src/schemas.py index 0244c11..e281fd5 100644 --- a/src/schemas.py +++ b/src/schemas.py @@ -40,18 +40,3 @@ class ServiceIDMixin(CustomBaseModel): class UserIDMixin(CustomBaseModel): user_id: int = Field(gt=0) - - -class OrgSummary(CustomBaseModel): - id: int - name: str - - -class GroupSummary(CustomBaseModel): - id: int - name: str - - -class UserSummary(CustomBaseModel): - id: int - email: str diff --git a/test/conftest.py b/test/conftest.py index 05c8174..e06b3d0 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,8 +1,7 @@ -import pytest - from typing import AsyncGenerator from itertools import combinations -from fastapi.routing import APIRoute + +import pytest from httpx import AsyncClient, ASGITransport from sqlalchemy.orm import sessionmaker @@ -13,6 +12,7 @@ from src.contact.models import Contact from src.iam.models import Group, Permission from src.auth.service import get_current_user, get_dev_user from src.auth.dependencies import empty_su_list, get_super_admin_list, testing_su_list + from src.main import app # inited FastAPI app from src.database import engine, Base, get_db @@ -156,22 +156,25 @@ def generate_query_and_status(params) -> list[tuple[str, int]]: return query_and_status -def get_testable_routes(): - routes = [] - - for route in app.routes: - if not isinstance(route, APIRoute): - continue - - for method in route.methods: - if method in {"HEAD", "OPTIONS"}: - continue - - routes.append((method, route.path, route.status_code, route.response_model)) - - return routes - - +# # Produces a text file with method and path for every endpoint in the API +# from fastapi.routing import APIRoute +# +# def get_testable_routes(): +# routes = [] +# +# for route in app.routes: +# if not isinstance(route, APIRoute): +# continue +# +# for method in route.methods: +# if method in {"HEAD", "OPTIONS"}: +# continue +# +# routes.append((route.path, method)) +# +# return routes +# +# # with open("endpoints.txt", "w") as f: # for ep in get_testable_routes(): -# f.write(f"[{ep[0]}]{ep[1]}({ep[2]}) -> {ep[2]}: {ep[3]}\n") +# f.write(f"{ep[1]} {ep[0]}\n") diff --git a/test/test_iam.py b/test/test_iam.py index 0176f9d..764c46c 100644 --- a/test/test_iam.py +++ b/test/test_iam.py @@ -221,18 +221,10 @@ async def test_get_group_users_success(default_client: AsyncClient): user = data["users"][0] assert user["id"] == 1 + assert user["first_name"] == "Admin" + assert user["last_name"] == "Test" assert user["email"] == "admin@test.com" - assert "group" in data - assert isinstance(data["group"], dict) - assert data["group"]["id"] == 1 - assert data["group"]["name"] == "Test Group" - - assert "organisation" in data - assert isinstance(data["organisation"], dict) - assert data["organisation"]["id"] == 1 - assert data["organisation"]["name"] == "Test Org" - @pytest.mark.parametrize( "query, expected_status", generate_query_and_status(["group_id", "org_id"]) diff --git a/test/test_organisation.py b/test/test_organisation.py index 364c753..69e3eac 100644 --- a/test/test_organisation.py +++ b/test/test_organisation.py @@ -265,16 +265,9 @@ async def test_post_org_user_success(default_client: AsyncClient, db_session): data = resp.json() - assert "organisation" in data - assert isinstance(data["organisation"], dict) - assert data["organisation"]["id"] == 1 - assert data["organisation"]["name"] == "Test Org" - assert "users" in data assert isinstance(data["users"], list) - assert ( - len([user for user in data["users"] if user["email"] == "user@test.org"]) == 1 - ) + assert "user@test.org" in data["users"] @pytest.mark.parametrize( @@ -393,17 +386,9 @@ async def test_get_org_groups_success(default_client: AsyncClient): data = resp.json() - assert "organisation" in data - assert isinstance(data["organisation"], dict) - assert data["organisation"]["id"] == 1 - assert data["organisation"]["name"] == "Test Org" - assert "groups" in data assert isinstance(data["groups"], list) - group = data["groups"][0] - assert isinstance(group, dict) - assert group["id"] == 1 - assert group["name"] == "Test Group" + assert "Test Group" in data["groups"] @pytest.mark.parametrize( diff --git a/test/test_user.py b/test/test_user.py index ad924f7..c86914d 100644 --- a/test/test_user.py +++ b/test/test_user.py @@ -5,7 +5,6 @@ import pytest from httpx import AsyncClient -from fastapi.routing import APIRoute from .conftest import generate_query_and_status @@ -144,51 +143,3 @@ async def test_get_self_orgs_success(default_client: AsyncClient): assert isinstance(org["security_contact"], dict) assert org["security_contact"]["email"] == "security@test.org" assert org["security_contact"]["id"] == 3 - - -@pytest.mark.anyio -async def test_get_self_orgs_dynamic(default_client: AsyncClient): - method = "GET" - path = "/user/self/orgs" - expected_data = { - "organisations": [ - { - "organisation_id": 1, - "name": "Test Org", - "status": "approved", - "root_user_email": "admin@test.com", - "owner_contact": {"email": "owner@test.org", "id": 2}, - "security_contact": {"email": "security@test.org", "id": 3}, - "billing_contact": {"email": "billing@test.org", "id": 1}, - "intake_questionnaire": { - "question_one": None, - "question_three": None, - "question_two": "answer two", - }, - } - ] - } - - resp = await default_client.get(path) - - route = next( - route - for route in default_client._transport.app.routes - if isinstance(route, APIRoute) - and path in route.path - and method in route.methods - ) - - assert resp.status_code == route.status_code - if route.status_code == 204: - return - - expected_response_schema = route.response_model - data = resp.json() - - response_model = expected_response_schema(**data) - assert isinstance(response_model, expected_response_schema) - - expected_response_model = expected_response_schema(**expected_data) - - assert response_model == expected_response_model