33from dataclasses import dataclass
44from typing import Any
55
6- from sanic import HTTPResponse , Request , json
6+ from sanic import HTTPResponse , Request
77from sanic .response import JSONResponse
88from sanic_ext import validate
99from ulid import ULID
1313from renku_data_services .base_api .auth import (
1414 authenticate ,
1515 only_authenticated ,
16- validate_path_project_id ,
1716 validate_path_user_id ,
1817)
1918from renku_data_services .base_api .blueprint import BlueprintFactoryResponse , CustomBlueprint
@@ -94,7 +93,7 @@ async def _get_one(
9493 headers = {"ETag" : project .etag } if project .etag is not None else None
9594 return validated_json (apispec .Project , self ._dump_project (project ), headers = headers )
9695
97- return "/projects/<project_id>" , ["GET" ], _get_one
96+ return "/projects/<project_id:ulid >" , ["GET" ], _get_one
9897
9998 def get_one_by_namespace_slug (self ) -> BlueprintFactoryResponse :
10099 """Get a specific project by namespace/slug."""
@@ -112,34 +111,32 @@ async def _get_one_by_namespace_slug(
112111 headers = {"ETag" : project .etag } if project .etag is not None else None
113112 return validated_json (apispec .Project , self ._dump_project (project ), headers = headers )
114113
115- return "/projects /<namespace>/<slug:renku_slug>" , ["GET" ], _get_one_by_namespace_slug
114+ return "/namespaces /<namespace>/projects /<slug:renku_slug>" , ["GET" ], _get_one_by_namespace_slug
116115
117116 def delete (self ) -> BlueprintFactoryResponse :
118117 """Delete a specific project."""
119118
120119 @authenticate (self .authenticator )
121120 @only_authenticated
122- @validate_path_project_id
123- async def _delete (_ : Request , user : base_models .APIUser , project_id : str ) -> HTTPResponse :
124- await self .project_repo .delete_project (user = user , project_id = ULID .from_str (project_id ))
121+ async def _delete (_ : Request , user : base_models .APIUser , project_id : ULID ) -> HTTPResponse :
122+ await self .project_repo .delete_project (user = user , project_id = project_id )
125123 return HTTPResponse (status = 204 )
126124
127- return "/projects/<project_id>" , ["DELETE" ], _delete
125+ return "/projects/<project_id:ulid >" , ["DELETE" ], _delete
128126
129127 def patch (self ) -> BlueprintFactoryResponse :
130128 """Partially update a specific project."""
131129
132130 @authenticate (self .authenticator )
133131 @only_authenticated
134- @validate_path_project_id
135132 @if_match_required
136133 @validate (json = apispec .ProjectPatch )
137134 async def _patch (
138- _ : Request , user : base_models .APIUser , project_id : str , body : apispec .ProjectPatch , etag : str
135+ _ : Request , user : base_models .APIUser , project_id : ULID , body : apispec .ProjectPatch , etag : str
139136 ) -> JSONResponse :
140137 project_patch = validate_project_patch (body )
141138 project_update = await self .project_repo .update_project (
142- user = user , project_id = ULID . from_str ( project_id ) , etag = etag , patch = project_patch
139+ user = user , project_id = project_id , etag = etag , patch = project_patch
143140 )
144141
145142 if not isinstance (project_update , project_models .ProjectUpdate ):
@@ -151,15 +148,14 @@ async def _patch(
151148 updated_project = project_update .new
152149 return validated_json (apispec .Project , self ._dump_project (updated_project ))
153150
154- return "/projects/<project_id>" , ["PATCH" ], _patch
151+ return "/projects/<project_id:ulid >" , ["PATCH" ], _patch
155152
156153 def get_all_members (self ) -> BlueprintFactoryResponse :
157154 """List all project members."""
158155
159156 @authenticate (self .authenticator )
160- @validate_path_project_id
161- async def _get_all_members (_ : Request , user : base_models .APIUser , project_id : str ) -> JSONResponse :
162- members = await self .project_member_repo .get_members (user , ULID .from_str (project_id ))
157+ async def _get_all_members (_ : Request , user : base_models .APIUser , project_id : ULID ) -> JSONResponse :
158+ members = await self .project_member_repo .get_members (user , project_id )
163159
164160 users = []
165161
@@ -179,35 +175,33 @@ async def _get_all_members(_: Request, user: base_models.APIUser, project_id: st
179175 ).model_dump (exclude_none = True , mode = "json" )
180176 users .append (user_with_id )
181177
182- return json ( users )
178+ return validated_json ( apispec . ProjectMemberListResponse , users )
183179
184- return "/projects/<project_id>/members" , ["GET" ], _get_all_members
180+ return "/projects/<project_id:ulid >/members" , ["GET" ], _get_all_members
185181
186182 def update_members (self ) -> BlueprintFactoryResponse :
187183 """Update or add project members."""
188184
189185 @authenticate (self .authenticator )
190- @validate_path_project_id
191186 @validate_body_root_model (json = apispec .ProjectMemberListPatchRequest )
192187 async def _update_members (
193- _ : Request , user : base_models .APIUser , project_id : str , body : apispec .ProjectMemberListPatchRequest
188+ _ : Request , user : base_models .APIUser , project_id : ULID , body : apispec .ProjectMemberListPatchRequest
194189 ) -> HTTPResponse :
195190 members = [Member (Role (i .role .value ), i .id , project_id ) for i in body .root ]
196- await self .project_member_repo .update_members (user , ULID . from_str ( project_id ) , members )
191+ await self .project_member_repo .update_members (user , project_id , members )
197192 return HTTPResponse (status = 200 )
198193
199- return "/projects/<project_id>/members" , ["PATCH" ], _update_members
194+ return "/projects/<project_id:ulid >/members" , ["PATCH" ], _update_members
200195
201196 def delete_member (self ) -> BlueprintFactoryResponse :
202197 """Delete a specific project."""
203198
204199 @authenticate (self .authenticator )
205- @validate_path_project_id
206200 @validate_path_user_id
207201 async def _delete_member (
208- _ : Request , user : base_models .APIUser , project_id : str , member_id : str
202+ _ : Request , user : base_models .APIUser , project_id : ULID , member_id : str
209203 ) -> HTTPResponse :
210- await self .project_member_repo .delete_members (user , ULID . from_str ( project_id ) , [member_id ])
204+ await self .project_member_repo .delete_members (user , project_id , [member_id ])
211205 return HTTPResponse (status = 204 )
212206
213207 return "/projects/<project_id>/members/<member_id>" , ["DELETE" ], _delete_member
0 commit comments