Skip to content

Commit 85e77da

Browse files
work
1 parent 5f61219 commit 85e77da

File tree

5 files changed

+44
-16
lines changed

5 files changed

+44
-16
lines changed

packages/models-library/src/models_library/api_schemas_webserver/projects.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ class ProjectPatch(InputSchema):
261261
),
262262
] = None
263263
quality: dict[str, Any] | None = None
264+
template_type: ProjectTemplateType | None = None
264265

265266
def to_domain_model(self) -> dict[str, Any]:
266267
return self.model_dump(exclude_unset=True, by_alias=False)

services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14876,6 +14876,10 @@ components:
1487614876
- type: object
1487714877
- type: 'null'
1487814878
title: Quality
14879+
templateType:
14880+
anyOf:
14881+
- $ref: '#/components/schemas/ProjectTemplateType'
14882+
- type: 'null'
1487914883
type: object
1488014884
title: ProjectPatch
1488114885
ProjectPermalink:

services/web/server/src/simcore_service_webserver/projects/_projects_repository_legacy.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -667,9 +667,6 @@ async def list_projects_dicts( # pylint: disable=too-many-arguments,too-many-st
667667
# order
668668
order_by: OrderBy = DEFAULT_ORDER_BY,
669669
) -> tuple[list[ProjectDict], list[ProjectType], int]:
670-
671-
# Check compatibility of project type and template type
672-
673670
async with self.engine.acquire() as conn:
674671
user_groups_proxy: list[RowProxy] = await self._list_user_groups(
675672
conn, user_id

services/web/server/src/simcore_service_webserver/projects/_projects_service.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
from .exceptions import (
140140
ClustersKeeperNotAvailableError,
141141
DefaultPricingUnitNotFoundError,
142+
InsufficientRoleForProjectTemplateTypeUpdateError,
142143
InvalidEC2TypeInResourcesSpecsError,
143144
InvalidKeysInResourcesSpecsError,
144145
NodeNotFoundError,
@@ -150,6 +151,7 @@
150151
ProjectOwnerNotFoundInTheProjectAccessRightsError,
151152
ProjectStartsTooManyDynamicNodesError,
152153
ProjectTooManyProjectOpenedError,
154+
ProjectTypeAndTemplateIncompatibilityError,
153155
)
154156
from .models import ProjectDict, ProjectPatchInternalExtended
155157
from .settings import ProjectsSettings, get_plugin_settings
@@ -327,7 +329,27 @@ async def patch_project(
327329
if new_prj_access_rights[_prj_owner_primary_group] != _prj_required_permissions:
328330
raise ProjectOwnerNotFoundInTheProjectAccessRightsError
329331

330-
# 4. Patch the project
332+
# 4. If patching template type
333+
if new_template_type := patch_project_data.get("template_type"):
334+
# 4.1 Check if user is a tester
335+
current_user: dict = await get_user(app, user_id)
336+
if not UserRole(current_user["role"]) >= UserRole.TESTER:
337+
raise InsufficientRoleForProjectTemplateTypeUpdateError
338+
# 4.2 Check the compatibility of the template type with the project
339+
if project_db.type == ProjectType.STANDARD and new_template_type is not None:
340+
raise ProjectTypeAndTemplateIncompatibilityError(
341+
project_uuid=project_uuid,
342+
project_type=project_db.type,
343+
project_template=new_template_type,
344+
)
345+
if project_db.type == ProjectType.TEMPLATE and new_template_type is None:
346+
raise ProjectTypeAndTemplateIncompatibilityError(
347+
project_uuid=project_uuid,
348+
project_type=project_db.type,
349+
project_template=new_template_type,
350+
)
351+
352+
# 5. Patch the project
331353
await _projects_repository.patch_project(
332354
app=app,
333355
project_uuid=project_uuid,

services/web/server/src/simcore_service_webserver/projects/exceptions.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ def debug_message(self):
2323
return f"{self.code}: {self}"
2424

2525

26-
class ProjectInvalidUsageError(BaseProjectError):
27-
...
26+
class ProjectInvalidUsageError(BaseProjectError): ...
2827

2928

3029
class ProjectOwnerNotFoundInTheProjectAccessRightsError(BaseProjectError):
@@ -83,8 +82,17 @@ class ProjectsBatchDeleteError(BaseProjectError):
8382
msg_template = "One or more projects could not be deleted in the batch: {errors}"
8483

8584

86-
class ProjectTrashError(BaseProjectError):
87-
...
85+
class ProjectsPatchError(BaseProjectError): ...
86+
87+
88+
class ProjectTypeAndTemplateIncompatibilityError(ProjectsPatchError):
89+
msg_template = "Patching project '{project_uuid}' type {project_type} and template {project_template} is not allowed"
90+
91+
92+
class InsufficientRoleForProjectTemplateTypeUpdateError(ProjectsPatchError): ...
93+
94+
95+
class ProjectTrashError(BaseProjectError): ...
8896

8997

9098
class ProjectStoppingError(ProjectTrashError):
@@ -146,12 +154,10 @@ def __init__(self, *, max_num_projects: int, **ctx):
146154
self.max_num_projects = max_num_projects
147155

148156

149-
class PermalinkNotAllowedError(BaseProjectError):
150-
...
157+
class PermalinkNotAllowedError(BaseProjectError): ...
151158

152159

153-
class PermalinkFactoryError(BaseProjectError):
154-
...
160+
class PermalinkFactoryError(BaseProjectError): ...
155161

156162

157163
class ProjectNodeResourcesInvalidError(BaseProjectError):
@@ -178,12 +184,10 @@ class InvalidEC2TypeInResourcesSpecsError(ProjectNodeResourcesInvalidError):
178184
)
179185

180186

181-
class ProjectNodeResourcesInsufficientRightsError(BaseProjectError):
182-
...
187+
class ProjectNodeResourcesInsufficientRightsError(BaseProjectError): ...
183188

184189

185-
class ProjectNodeRequiredInputsNotSetError(BaseProjectError):
186-
...
190+
class ProjectNodeRequiredInputsNotSetError(BaseProjectError): ...
187191

188192

189193
class ProjectNodeConnectionsMissingError(ProjectNodeRequiredInputsNotSetError):

0 commit comments

Comments
 (0)