11"""Session blueprint."""
22
33from dataclasses import dataclass
4+ from datetime import UTC , datetime
45
5- from sanic import HTTPResponse , Request , json
6+ from sanic import HTTPResponse , Request
67from sanic .response import JSONResponse
78from sanic_ext import validate
89from ulid import ULID
910
1011import renku_data_services .base_models as base_models
11- from renku_data_services .base_api .auth import authenticate , validate_path_project_id
12+ from renku_data_services import errors
13+ from renku_data_services .base_api .auth import authenticate , only_authenticated
1214from renku_data_services .base_api .blueprint import BlueprintFactoryResponse , CustomBlueprint
13- from renku_data_services .session import apispec
15+ from renku_data_services .base_models .validation import validated_json
16+ from renku_data_services .session import apispec , models
1417from renku_data_services .session .db import SessionRepository
1518
1619
@@ -26,9 +29,7 @@ def get_all(self) -> BlueprintFactoryResponse:
2629
2730 async def _get_all (_ : Request ) -> JSONResponse :
2831 environments = await self .session_repo .get_environments ()
29- return json (
30- [apispec .Environment .model_validate (e ).model_dump (exclude_none = True , mode = "json" ) for e in environments ]
31- )
32+ return validated_json (apispec .EnvironmentList , environments )
3233
3334 return "/environments" , ["GET" ], _get_all
3435
@@ -37,7 +38,7 @@ def get_one(self) -> BlueprintFactoryResponse:
3738
3839 async def _get_one (_ : Request , environment_id : ULID ) -> JSONResponse :
3940 environment = await self .session_repo .get_environment (environment_id = environment_id )
40- return json (apispec .Environment . model_validate ( environment ). model_dump ( exclude_none = True , mode = "json" ) )
41+ return validated_json (apispec .Environment , environment )
4142
4243 return "/environments/<environment_id:ulid>" , ["GET" ], _get_one
4344
@@ -47,8 +48,17 @@ def post(self) -> BlueprintFactoryResponse:
4748 @authenticate (self .authenticator )
4849 @validate (json = apispec .EnvironmentPost )
4950 async def _post (_ : Request , user : base_models .APIUser , body : apispec .EnvironmentPost ) -> JSONResponse :
50- environment = await self .session_repo .insert_environment (user = user , new_environment = body )
51- return json (apispec .Environment .model_validate (environment ).model_dump (exclude_none = True , mode = "json" ), 201 )
51+ assert user .id
52+ environment_model = models .UnsavedEnvironment (
53+ name = body .name ,
54+ description = body .description ,
55+ container_image = body .container_image ,
56+ default_url = body .default_url ,
57+ created_by = models .Member (id = user .id ),
58+ creation_date = datetime .now (UTC ).replace (microsecond = 0 ),
59+ )
60+ environment = await self .session_repo .insert_environment (user = user , new_environment = environment_model )
61+ return validated_json (apispec .Environment , environment , 201 )
5262
5363 return "/environments" , ["POST" ], _post
5464
@@ -64,7 +74,7 @@ async def _patch(
6474 environment = await self .session_repo .update_environment (
6575 user = user , environment_id = environment_id , ** body_dict
6676 )
67- return json (apispec .Environment . model_validate ( environment ). model_dump ( exclude_none = True , mode = "json" ) )
77+ return validated_json (apispec .Environment , environment )
6878
6979 return "/environments/<environment_id:ulid>" , ["PATCH" ], _patch
7080
@@ -92,12 +102,7 @@ def get_all(self) -> BlueprintFactoryResponse:
92102 @authenticate (self .authenticator )
93103 async def _get_all (_ : Request , user : base_models .APIUser ) -> JSONResponse :
94104 launchers = await self .session_repo .get_launchers (user = user )
95- return json (
96- [
97- apispec .SessionLauncher .model_validate (item ).model_dump (exclude_none = True , mode = "json" )
98- for item in launchers
99- ]
100- )
105+ return validated_json (apispec .SessionLaunchersList , launchers )
101106
102107 return "/session_launchers" , ["GET" ], _get_all
103108
@@ -107,20 +112,39 @@ def get_one(self) -> BlueprintFactoryResponse:
107112 @authenticate (self .authenticator )
108113 async def _get_one (_ : Request , user : base_models .APIUser , launcher_id : ULID ) -> JSONResponse :
109114 launcher = await self .session_repo .get_launcher (user = user , launcher_id = launcher_id )
110- return json (apispec .SessionLauncher . model_validate ( launcher ). model_dump ( exclude_none = True , mode = "json" ) )
115+ return validated_json (apispec .SessionLauncher , launcher )
111116
112117 return "/session_launchers/<launcher_id:ulid>" , ["GET" ], _get_one
113118
114119 def post (self ) -> BlueprintFactoryResponse :
115120 """Create a new session launcher."""
116121
117122 @authenticate (self .authenticator )
123+ @only_authenticated
118124 @validate (json = apispec .SessionLauncherPost )
119125 async def _post (_ : Request , user : base_models .APIUser , body : apispec .SessionLauncherPost ) -> JSONResponse :
120- launcher = await self .session_repo .insert_launcher (user = user , new_launcher = body )
121- return json (
122- apispec .SessionLauncher .model_validate (launcher ).model_dump (exclude_none = True , mode = "json" ), 201
126+ match body .environment_kind :
127+ case apispec .EnvironmentKind .global_environment :
128+ environment_kind = models .EnvironmentKind .global_environment
129+ case apispec .EnvironmentKind .container_image :
130+ environment_kind = models .EnvironmentKind .container_image
131+ case _:
132+ raise errors .ValidationError (message = f"Unknown environment kind { body .environment_kind } " )
133+ assert user .id
134+ launcher_model = models .UnsavedSessionLauncher (
135+ name = body .name ,
136+ project_id = ULID .from_str (body .project_id ),
137+ description = body .description ,
138+ environment_kind = environment_kind ,
139+ environment_id = body .environment_id ,
140+ resource_class_id = body .resource_class_id ,
141+ container_image = body .container_image ,
142+ default_url = body .default_url ,
143+ created_by = models .Member (id = user .id ),
144+ creation_date = datetime .now (UTC ).replace (microsecond = 0 ),
123145 )
146+ launcher = await self .session_repo .insert_launcher (user = user , new_launcher = launcher_model )
147+ return validated_json (apispec .SessionLauncher , launcher , 201 )
124148
125149 return "/session_launchers" , ["POST" ], _post
126150
@@ -134,7 +158,7 @@ async def _patch(
134158 ) -> JSONResponse :
135159 body_dict = body .model_dump (exclude_none = True )
136160 launcher = await self .session_repo .update_launcher (user = user , launcher_id = launcher_id , ** body_dict )
137- return json (apispec .SessionLauncher . model_validate ( launcher ). model_dump ( exclude_none = True , mode = "json" ) )
161+ return validated_json (apispec .SessionLauncher , launcher )
138162
139163 return "/session_launchers/<launcher_id:ulid>" , ["PATCH" ], _patch
140164
@@ -152,14 +176,8 @@ def get_project_launchers(self) -> BlueprintFactoryResponse:
152176 """Get all launchers belonging to a project."""
153177
154178 @authenticate (self .authenticator )
155- @validate_path_project_id
156- async def _get_launcher (_ : Request , user : base_models .APIUser , project_id : str ) -> JSONResponse :
179+ async def _get_launcher (_ : Request , user : base_models .APIUser , project_id : ULID ) -> JSONResponse :
157180 launchers = await self .session_repo .get_project_launchers (user = user , project_id = project_id )
158- return json (
159- [
160- apispec .SessionLauncher .model_validate (item ).model_dump (exclude_none = True , mode = "json" )
161- for item in launchers
162- ]
163- )
181+ return validated_json (apispec .SessionLaunchersList , launchers )
164182
165- return "/projects/<project_id>/session_launchers" , ["GET" ], _get_launcher
183+ return "/projects/<project_id:ulid >/session_launchers" , ["GET" ], _get_launcher
0 commit comments