feat: more ids returned on endpoints
All checks were successful
ci / lint_and_test (push) Successful in 14s

Issue: #23
This commit is contained in:
Chris Milne 2026-06-10 13:48:59 +01:00
parent 5a433dfe41
commit 294baadcb7
7 changed files with 90 additions and 19 deletions

View file

@ -21,6 +21,7 @@ from sqlalchemy.exc import IntegrityError
from src.iam.exceptions import GroupNotFoundException from src.iam.exceptions import GroupNotFoundException
from src.organisation.exceptions import OrgNotFoundException from src.organisation.exceptions import OrgNotFoundException
from src.schemas import GroupSummary, OrgSummary
from src.service.exceptions import ServiceNotFoundException from src.service.exceptions import ServiceNotFoundException
from src.exceptions import ConflictException from src.exceptions import ConflictException
from src.database import db_dependency from src.database import db_dependency
@ -127,7 +128,11 @@ async def get_group_permissions(
): ):
if group_model.org_id != org_model.id: if group_model.org_id != org_model.id:
raise UnauthorizedException("Group does not belong to this organization") raise UnauthorizedException("Group does not belong to this organization")
return {"permissions": group_model.permission_rel} return {
"organisation": org_model,
"group": group_model,
"permissions": group_model.permission_rel,
}
@router.get("/group/users", response_model=IAMGetGroupUsersResponse) @router.get("/group/users", response_model=IAMGetGroupUsersResponse)
@ -137,7 +142,11 @@ async def get_group_users(
): ):
if group_model.org_id != org_model.id: if group_model.org_id != org_model.id:
raise UnauthorizedException("Group does not belong to this organization") raise UnauthorizedException("Group does not belong to this organization")
return {"users": group_model.user_rel} return {
"organisation": org_model,
"group": group_model,
"users": group_model.user_rel,
}
@router.post("/group", response_model=IAMPostGroupResponse) @router.post("/group", response_model=IAMPostGroupResponse)
@ -180,7 +189,8 @@ async def add_group_permission(
db.flush() db.flush()
response = IAMPutGroupPermissionResponse( response = IAMPutGroupPermissionResponse(
group=GroupSchema(**group_model.__dict__), organisation=OrgSummary(**org_model.__dict__),
group=GroupSummary(**group_model.__dict__),
permissions=group_model.permission_rel, permissions=group_model.permission_rel,
) )
db.commit() db.commit()

View file

@ -18,6 +18,9 @@ from src.schemas import (
UserIDMixin, UserIDMixin,
PermIDMixin, PermIDMixin,
GroupIDMixin, GroupIDMixin,
GroupSummary,
OrgSummary,
UserSummary,
) )
@ -50,11 +53,15 @@ class IAMCAoRRequest(CustomBaseModel):
class IAMGetGroupPermissionsResponse(CustomBaseModel): class IAMGetGroupPermissionsResponse(CustomBaseModel):
organisation: OrgSummary
group: GroupSummary
permissions: list[PermissionSchema] permissions: list[PermissionSchema]
class IAMGetGroupUsersResponse(CustomBaseModel): class IAMGetGroupUsersResponse(CustomBaseModel):
users: list[UserSchema] organisation: OrgSummary
group: GroupSummary
users: list[UserSummary]
class IAMPostGroupRequest(OrgIDMixin): class IAMPostGroupRequest(OrgIDMixin):
@ -70,7 +77,8 @@ class IAMPutGroupPermissionRequest(GroupIDMixin, PermIDMixin, OrgIDMixin):
class IAMPutGroupPermissionResponse(CustomBaseModel): class IAMPutGroupPermissionResponse(CustomBaseModel):
group: GroupSchema organisation: OrgSummary
group: GroupSummary
permissions: list[PermissionSchema] permissions: list[PermissionSchema]

View file

@ -314,7 +314,10 @@ async def add_user_to_org(
raise ConflictException(message="User already a part of this organisation") raise ConflictException(message="User already a part of this organisation")
org_model.user_rel.append(user_model) org_model.user_rel.append(user_model)
db.flush() db.flush()
response = {"users": [user.email for user in org_model.user_rel]} response = {
"organisation": org_model,
"users": [{"id": user.id, "email": user.email} for user in org_model.user_rel],
}
db.commit() db.commit()
return response return response
@ -437,7 +440,12 @@ 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. Returns a list of the names of all IAM groups created by the organisation.
""" """
return {"groups": [group.name for group in org_model.group_rel]} return {
"organisation": org_model,
"groups": [
{"id": group.id, "name": group.name} for group in org_model.group_rel
],
}
@router.delete( @router.delete(

View file

@ -10,7 +10,14 @@ from typing import Optional
from pydantic import EmailStr, ConfigDict from pydantic import EmailStr, ConfigDict
from src.schemas import CustomBaseModel, OrgIDMixin, UserIDMixin from src.schemas import (
CustomBaseModel,
OrgIDMixin,
UserIDMixin,
GroupSummary,
OrgSummary,
UserSummary,
)
from src.contact.schemas import ContactModel from src.contact.schemas import ContactModel
from src.organisation.constants import Status, ContactType from src.organisation.constants import Status, ContactType
@ -22,11 +29,6 @@ class Questionnaire(CustomBaseModel):
question_three: Optional[str] = None question_three: Optional[str] = None
class OrgSummary(CustomBaseModel):
id: int
name: str
class ContactSummary(CustomBaseModel): class ContactSummary(CustomBaseModel):
id: int id: int
email: Optional[EmailStr] = None email: Optional[EmailStr] = None
@ -49,6 +51,7 @@ class OrgPostOrgRequest(CustomBaseModel):
class OrgPostOrgResponse(CustomBaseModel): class OrgPostOrgResponse(CustomBaseModel):
id: int
name: str name: str
status: Status status: Status
@ -59,6 +62,7 @@ class OrgPatchQuestionnaireRequest(OrgIDMixin):
class OrgPatchQuestionnaireResponse(CustomBaseModel): class OrgPatchQuestionnaireResponse(CustomBaseModel):
id: int
name: str name: str
intake_questionnaire: Questionnaire intake_questionnaire: Questionnaire
status: Status status: Status
@ -69,6 +73,7 @@ class OrgPatchStatusRequest(OrgIDMixin):
class OrgPatchStatusResponse(CustomBaseModel): class OrgPatchStatusResponse(CustomBaseModel):
id: int
name: str name: str
status: Status status: Status
@ -95,7 +100,8 @@ class OrgPostUserRequest(OrgIDMixin, UserIDMixin):
class OrgPostUserResponse(CustomBaseModel): class OrgPostUserResponse(CustomBaseModel):
users: list[str] organisation: OrgSummary
users: list[UserSummary]
class OrgPatchRootRequest(OrgIDMixin, UserIDMixin): class OrgPatchRootRequest(OrgIDMixin, UserIDMixin):
@ -113,7 +119,8 @@ class OrgGetUserResponse(CustomBaseModel):
class OrgGetGroupResponse(CustomBaseModel): class OrgGetGroupResponse(CustomBaseModel):
groups: list[str] organisation: OrgSummary
groups: list[GroupSummary]
class OrgGetContactResponse(CustomBaseModel): class OrgGetContactResponse(CustomBaseModel):

View file

@ -40,3 +40,18 @@ class ServiceIDMixin(CustomBaseModel):
class UserIDMixin(CustomBaseModel): class UserIDMixin(CustomBaseModel):
user_id: int = Field(gt=0) 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

View file

@ -221,10 +221,18 @@ async def test_get_group_users_success(default_client: AsyncClient):
user = data["users"][0] user = data["users"][0]
assert user["id"] == 1 assert user["id"] == 1
assert user["first_name"] == "Admin"
assert user["last_name"] == "Test"
assert user["email"] == "admin@test.com" 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( @pytest.mark.parametrize(
"query, expected_status", generate_query_and_status(["group_id", "org_id"]) "query, expected_status", generate_query_and_status(["group_id", "org_id"])

View file

@ -265,9 +265,16 @@ async def test_post_org_user_success(default_client: AsyncClient, db_session):
data = resp.json() 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 "users" in data
assert isinstance(data["users"], list) assert isinstance(data["users"], list)
assert "user@test.org" in data["users"] assert (
len([user for user in data["users"] if user["email"] == "user@test.org"]) == 1
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -386,9 +393,17 @@ async def test_get_org_groups_success(default_client: AsyncClient):
data = resp.json() 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 "groups" in data
assert isinstance(data["groups"], list) assert isinstance(data["groups"], list)
assert "Test Group" in data["groups"] group = data["groups"][0]
assert isinstance(group, dict)
assert group["id"] == 1
assert group["name"] == "Test Group"
@pytest.mark.parametrize( @pytest.mark.parametrize(