22
33from dataclasses import dataclass
44
5- from sanic import HTTPResponse , Request , json
5+ from sanic import HTTPResponse , Request
66from sanic .response import JSONResponse
77from sanic_ext import validate
88
1111from renku_data_services .base_api .auth import authenticate , only_authenticated
1212from renku_data_services .base_api .blueprint import BlueprintFactoryResponse , CustomBlueprint
1313from renku_data_services .base_api .pagination import PaginationRequest , paginate
14+ from renku_data_services .base_models .validation import validate_and_dump , validated_json
1415from renku_data_services .errors import errors
1516from renku_data_services .namespace import apispec
1617from renku_data_services .namespace .db import GroupRepository
@@ -34,7 +35,7 @@ async def _get_all(
3435 ) -> tuple [list [dict ], int ]:
3536 groups , rec_count = await self .group_repo .get_groups (user = user , pagination = pagination )
3637 return (
37- [ apispec .GroupResponse . model_validate ( g ). model_dump ( exclude_none = True , mode = "json" ) for g in groups ] ,
38+ validate_and_dump ( apispec .GroupResponseList , groups ) ,
3839 rec_count ,
3940 )
4041
@@ -48,7 +49,7 @@ def post(self) -> BlueprintFactoryResponse:
4849 @validate (json = apispec .GroupPostRequest )
4950 async def _post (_ : Request , user : base_models .APIUser , body : apispec .GroupPostRequest ) -> JSONResponse :
5051 result = await self .group_repo .insert_group (user = user , payload = body )
51- return json (apispec .GroupResponse . model_validate ( result ). model_dump ( exclude_none = True , mode = "json" ) , 201 )
52+ return validated_json (apispec .GroupResponse , result , 201 )
5253
5354 return "/groups" , ["POST" ], _post
5455
@@ -58,7 +59,7 @@ def get_one(self) -> BlueprintFactoryResponse:
5859 @authenticate (self .authenticator )
5960 async def _get_one (_ : Request , user : base_models .APIUser , slug : str ) -> JSONResponse :
6061 result = await self .group_repo .get_group (user = user , slug = slug )
61- return json (apispec .GroupResponse . model_validate ( result ). model_dump ( exclude_none = True , mode = "json" ) )
62+ return validated_json (apispec .GroupResponse , result )
6263
6364 return "/groups/<slug:renku_slug>" , ["GET" ], _get_one
6465
@@ -84,7 +85,7 @@ async def _patch(
8485 ) -> JSONResponse :
8586 body_dict = body .model_dump (exclude_none = True )
8687 res = await self .group_repo .update_group (user = user , slug = slug , payload = body_dict )
87- return json (apispec .GroupResponse . model_validate ( res ). model_dump ( exclude_none = True , mode = "json" ) )
88+ return validated_json (apispec .GroupResponse , res )
8889
8990 return "/groups/<slug:renku_slug>" , ["PATCH" ], _patch
9091
@@ -94,17 +95,18 @@ def get_all_members(self) -> BlueprintFactoryResponse:
9495 @authenticate (self .authenticator )
9596 async def _get_all_members (_ : Request , user : base_models .APIUser , slug : str ) -> JSONResponse :
9697 members = await self .group_repo .get_group_members (user , slug )
97- return json (
98+ return validated_json (
99+ apispec .GroupMemberResponseList ,
98100 [
99- apispec . GroupMemberResponse (
101+ dict (
100102 id = m .id ,
101103 email = m .email ,
102104 first_name = m .first_name ,
103105 last_name = m .last_name ,
104106 role = apispec .GroupRole (m .role .value ),
105- ). model_dump ( exclude_none = True , mode = "json" )
107+ )
106108 for m in members
107- ]
109+ ],
108110 )
109111
110112 return "/groups/<slug:renku_slug>/members" , ["GET" ], _get_all_members
@@ -114,25 +116,24 @@ def update_members(self) -> BlueprintFactoryResponse:
114116
115117 @authenticate (self .authenticator )
116118 @only_authenticated
119+ @validate (json = apispec .GroupMemberPatchRequestList )
117120 async def _update_members (
118- request : Request ,
119- user : base_models .APIUser ,
120- slug : str ,
121+ request : Request , user : base_models .APIUser , slug : str , body : apispec .GroupMemberPatchRequestList
121122 ) -> JSONResponse :
122- body_validated = apispec .GroupMemberPatchRequestList .model_validate (request .json )
123123 res = await self .group_repo .update_group_members (
124124 user = user ,
125125 slug = slug ,
126- payload = body_validated ,
126+ payload = body ,
127127 )
128- return json (
128+ return validated_json (
129+ apispec .GroupMemberPatchRequest ,
129130 [
130- apispec . GroupMemberPatchRequest (
131+ dict (
131132 id = m .member .user_id ,
132133 role = apispec .GroupRole (m .member .role .value ),
133- ). model_dump ( exclude_none = True , mode = "json" )
134+ )
134135 for m in res
135- ]
136+ ],
136137 )
137138
138139 return "/groups/<slug:renku_slug>/members" , ["PATCH" ], _update_members
@@ -163,17 +164,20 @@ async def _get_namespaces(
163164 nss , total_count = await self .group_repo .get_namespaces (
164165 user = user , pagination = pagination , minimum_role = minimum_role
165166 )
166- return [
167- apispec .NamespaceResponse (
168- id = ns .id ,
169- name = ns .name ,
170- slug = ns .latest_slug if ns .latest_slug else ns .slug ,
171- created_by = ns .created_by ,
172- creation_date = None , # NOTE: we do not save creation date in the DB
173- namespace_kind = apispec .NamespaceKind (ns .kind .value ),
174- ).model_dump (exclude_none = True , mode = "json" )
175- for ns in nss
176- ], total_count
167+ return validate_and_dump (
168+ apispec .NamespaceResponseList ,
169+ [
170+ dict (
171+ id = ns .id ,
172+ name = ns .name ,
173+ slug = ns .latest_slug if ns .latest_slug else ns .slug ,
174+ created_by = ns .created_by ,
175+ creation_date = None , # NOTE: we do not save creation date in the DB
176+ namespace_kind = apispec .NamespaceKind (ns .kind .value ),
177+ )
178+ for ns in nss
179+ ],
180+ ), total_count
177181
178182 return "/namespaces" , ["GET" ], _get_namespaces
179183
@@ -185,15 +189,16 @@ async def _get_namespace(_: Request, user: base_models.APIUser, slug: str) -> JS
185189 ns = await self .group_repo .get_namespace_by_slug (user = user , slug = slug )
186190 if not ns :
187191 raise errors .MissingResourceError (message = f"The namespace with slug { slug } does not exist" )
188- return json (
189- apispec .NamespaceResponse (
192+ return validated_json (
193+ apispec .NamespaceResponse ,
194+ dict (
190195 id = ns .id ,
191196 name = ns .name ,
192197 slug = ns .latest_slug if ns .latest_slug else ns .slug ,
193198 created_by = ns .created_by ,
194199 creation_date = None , # NOTE: we do not save creation date in the DB
195200 namespace_kind = apispec .NamespaceKind (ns .kind .value ),
196- ). model_dump ( exclude_none = True , mode = "json" )
201+ ),
197202 )
198203
199204 return "/namespaces/<slug:renku_slug>" , ["GET" ], _get_namespace
0 commit comments