fractal-server 2.17.1a1__py3-none-any.whl → 2.18.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/__main__.py +21 -19
  3. fractal_server/app/db/__init__.py +3 -3
  4. fractal_server/app/models/__init__.py +1 -0
  5. fractal_server/app/models/linkuserproject.py +43 -1
  6. fractal_server/app/models/security.py +28 -8
  7. fractal_server/app/models/v2/__init__.py +3 -1
  8. fractal_server/app/models/v2/accounting.py +9 -1
  9. fractal_server/app/models/v2/dataset.py +5 -1
  10. fractal_server/app/models/v2/history.py +15 -1
  11. fractal_server/app/models/v2/job.py +17 -2
  12. fractal_server/app/models/v2/profile.py +29 -0
  13. fractal_server/app/models/v2/project.py +4 -10
  14. fractal_server/app/models/v2/resource.py +17 -0
  15. fractal_server/app/models/v2/task_group.py +4 -3
  16. fractal_server/app/models/v2/workflow.py +2 -1
  17. fractal_server/app/routes/admin/v2/__init__.py +12 -13
  18. fractal_server/app/routes/admin/v2/accounting.py +3 -3
  19. fractal_server/app/routes/admin/v2/job.py +35 -24
  20. fractal_server/app/routes/admin/v2/profile.py +3 -2
  21. fractal_server/app/routes/admin/v2/resource.py +5 -5
  22. fractal_server/app/routes/admin/v2/sharing.py +103 -0
  23. fractal_server/app/routes/admin/v2/task.py +37 -26
  24. fractal_server/app/routes/admin/v2/task_group.py +94 -17
  25. fractal_server/app/routes/admin/v2/task_group_lifecycle.py +21 -22
  26. fractal_server/app/routes/api/__init__.py +1 -9
  27. fractal_server/app/routes/api/v2/__init__.py +49 -50
  28. fractal_server/app/routes/api/v2/_aux_functions.py +132 -124
  29. fractal_server/app/routes/api/v2/_aux_functions_history.py +51 -23
  30. fractal_server/app/routes/api/v2/_aux_functions_sharing.py +97 -0
  31. fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +6 -8
  32. fractal_server/app/routes/api/v2/_aux_functions_tasks.py +7 -9
  33. fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +1 -2
  34. fractal_server/app/routes/api/v2/dataset.py +95 -102
  35. fractal_server/app/routes/api/v2/history.py +59 -33
  36. fractal_server/app/routes/api/v2/images.py +24 -9
  37. fractal_server/app/routes/api/v2/job.py +52 -33
  38. fractal_server/app/routes/api/v2/pre_submission_checks.py +16 -8
  39. fractal_server/app/routes/api/v2/project.py +65 -37
  40. fractal_server/app/routes/api/v2/sharing.py +311 -0
  41. fractal_server/app/routes/api/v2/status_legacy.py +31 -41
  42. fractal_server/app/routes/api/v2/submit.py +82 -78
  43. fractal_server/app/routes/api/v2/task.py +19 -20
  44. fractal_server/app/routes/api/v2/task_collection.py +41 -43
  45. fractal_server/app/routes/api/v2/task_collection_custom.py +19 -20
  46. fractal_server/app/routes/api/v2/task_collection_pixi.py +10 -11
  47. fractal_server/app/routes/api/v2/task_group.py +25 -24
  48. fractal_server/app/routes/api/v2/task_group_lifecycle.py +32 -32
  49. fractal_server/app/routes/api/v2/task_version_update.py +23 -19
  50. fractal_server/app/routes/api/v2/workflow.py +50 -55
  51. fractal_server/app/routes/api/v2/workflow_import.py +37 -37
  52. fractal_server/app/routes/api/v2/workflowtask.py +32 -26
  53. fractal_server/app/routes/auth/__init__.py +1 -3
  54. fractal_server/app/routes/auth/_aux_auth.py +101 -2
  55. fractal_server/app/routes/auth/current_user.py +2 -66
  56. fractal_server/app/routes/auth/group.py +8 -35
  57. fractal_server/app/routes/auth/login.py +1 -0
  58. fractal_server/app/routes/auth/oauth.py +4 -3
  59. fractal_server/app/routes/auth/register.py +4 -2
  60. fractal_server/app/routes/auth/router.py +2 -0
  61. fractal_server/app/routes/auth/users.py +19 -10
  62. fractal_server/app/routes/auth/viewer_paths.py +43 -0
  63. fractal_server/app/routes/aux/_job.py +1 -1
  64. fractal_server/app/routes/aux/_runner.py +2 -2
  65. fractal_server/app/routes/pagination.py +1 -1
  66. fractal_server/app/schemas/user.py +29 -12
  67. fractal_server/app/schemas/user_group.py +0 -15
  68. fractal_server/app/schemas/v2/__init__.py +55 -48
  69. fractal_server/app/schemas/v2/accounting.py +11 -0
  70. fractal_server/app/schemas/v2/dataset.py +57 -11
  71. fractal_server/app/schemas/v2/dumps.py +10 -9
  72. fractal_server/app/schemas/v2/job.py +11 -11
  73. fractal_server/app/schemas/v2/manifest.py +4 -3
  74. fractal_server/app/schemas/v2/profile.py +53 -2
  75. fractal_server/app/schemas/v2/project.py +3 -3
  76. fractal_server/app/schemas/v2/resource.py +121 -16
  77. fractal_server/app/schemas/v2/sharing.py +99 -0
  78. fractal_server/app/schemas/v2/status_legacy.py +3 -3
  79. fractal_server/app/schemas/v2/task.py +6 -7
  80. fractal_server/app/schemas/v2/task_collection.py +5 -5
  81. fractal_server/app/schemas/v2/task_group.py +16 -16
  82. fractal_server/app/schemas/v2/workflow.py +16 -16
  83. fractal_server/app/schemas/v2/workflowtask.py +16 -15
  84. fractal_server/app/security/__init__.py +5 -8
  85. fractal_server/app/security/signup_email.py +4 -5
  86. fractal_server/app/shutdown.py +6 -6
  87. fractal_server/config/__init__.py +0 -6
  88. fractal_server/config/_data.py +0 -68
  89. fractal_server/config/_database.py +19 -20
  90. fractal_server/config/_email.py +30 -38
  91. fractal_server/config/_main.py +38 -52
  92. fractal_server/config/_oauth.py +17 -21
  93. fractal_server/data_migrations/2_18_0.py +30 -0
  94. fractal_server/exceptions.py +4 -0
  95. fractal_server/images/models.py +4 -5
  96. fractal_server/images/status_tools.py +4 -2
  97. fractal_server/logger.py +1 -1
  98. fractal_server/main.py +75 -13
  99. fractal_server/migrations/versions/034a469ec2eb_task_groups.py +4 -8
  100. fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +1 -1
  101. fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +1 -0
  102. fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +1 -1
  103. fractal_server/migrations/versions/1a83a5260664_rename.py +1 -1
  104. fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +1 -0
  105. fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +1 -1
  106. fractal_server/migrations/versions/40d6d6511b20_add_index_to_history_models.py +47 -0
  107. fractal_server/migrations/versions/45fbb391d7af_make_resource_id_fk_non_nullable.py +1 -1
  108. fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +1 -0
  109. fractal_server/migrations/versions/49d0856e9569_drop_table.py +2 -3
  110. fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +1 -1
  111. fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +1 -1
  112. fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +2 -1
  113. fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +7 -19
  114. fractal_server/migrations/versions/5bf02391cfef_v2.py +4 -10
  115. fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +1 -0
  116. fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +1 -1
  117. fractal_server/migrations/versions/7673fe18c05d_remove_project_dir_server_default.py +1 -1
  118. fractal_server/migrations/versions/7910eed4cf97_user_project_dirs_and_usergroup_viewer_.py +60 -0
  119. fractal_server/migrations/versions/791ce783d3d8_add_indices.py +1 -1
  120. fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +1 -0
  121. fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +1 -0
  122. fractal_server/migrations/versions/88270f589c9b_add_prevent_new_submissions.py +39 -0
  123. fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +2 -4
  124. fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +1 -1
  125. fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +1 -0
  126. fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +1 -1
  127. fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +1 -1
  128. fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +1 -1
  129. fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +2 -4
  130. fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +1 -1
  131. fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +1 -1
  132. fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +1 -1
  133. fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +1 -1
  134. fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +1 -0
  135. fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +1 -0
  136. fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +1 -1
  137. fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +1 -0
  138. fractal_server/migrations/versions/bc0e8b3327a7_project_sharing.py +72 -0
  139. fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +1 -1
  140. fractal_server/migrations/versions/caba9fb1ea5e_drop_useroauth_user_settings_id.py +1 -1
  141. fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +4 -9
  142. fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +1 -0
  143. fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +1 -1
  144. fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +1 -0
  145. fractal_server/migrations/versions/e0e717ae2f26_delete_linkuserproject_ondelete_project.py +50 -0
  146. fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +1 -0
  147. fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +1 -1
  148. fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +1 -0
  149. fractal_server/migrations/versions/f0702066b007_one_submitted_job_per_dataset.py +40 -0
  150. fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +1 -1
  151. fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +1 -0
  152. fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +4 -9
  153. fractal_server/runner/config/_local.py +8 -5
  154. fractal_server/runner/config/_slurm.py +39 -33
  155. fractal_server/runner/config/slurm_mem_to_MB.py +0 -1
  156. fractal_server/runner/executors/base_runner.py +29 -4
  157. fractal_server/runner/executors/local/get_local_config.py +1 -0
  158. fractal_server/runner/executors/local/runner.py +14 -13
  159. fractal_server/runner/executors/slurm_common/_batching.py +9 -20
  160. fractal_server/runner/executors/slurm_common/base_slurm_runner.py +53 -27
  161. fractal_server/runner/executors/slurm_common/get_slurm_config.py +14 -7
  162. fractal_server/runner/executors/slurm_common/remote.py +3 -1
  163. fractal_server/runner/executors/slurm_common/slurm_config.py +2 -0
  164. fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +1 -3
  165. fractal_server/runner/executors/slurm_ssh/runner.py +16 -11
  166. fractal_server/runner/executors/slurm_ssh/tar_commands.py +1 -0
  167. fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +1 -0
  168. fractal_server/runner/executors/slurm_sudo/runner.py +16 -11
  169. fractal_server/runner/task_files.py +9 -3
  170. fractal_server/runner/v2/_local.py +12 -6
  171. fractal_server/runner/v2/_slurm_ssh.py +14 -7
  172. fractal_server/runner/v2/_slurm_sudo.py +14 -7
  173. fractal_server/runner/v2/db_tools.py +0 -1
  174. fractal_server/runner/v2/deduplicate_list.py +2 -1
  175. fractal_server/runner/v2/runner.py +44 -28
  176. fractal_server/runner/v2/runner_functions.py +22 -28
  177. fractal_server/runner/v2/submit_workflow.py +29 -15
  178. fractal_server/ssh/_fabric.py +6 -13
  179. fractal_server/string_tools.py +0 -1
  180. fractal_server/syringe.py +1 -1
  181. fractal_server/tasks/config/_pixi.py +1 -1
  182. fractal_server/tasks/config/_python.py +16 -9
  183. fractal_server/tasks/utils.py +0 -1
  184. fractal_server/tasks/v2/local/_utils.py +3 -3
  185. fractal_server/tasks/v2/local/collect.py +15 -18
  186. fractal_server/tasks/v2/local/collect_pixi.py +14 -16
  187. fractal_server/tasks/v2/local/deactivate.py +14 -15
  188. fractal_server/tasks/v2/local/deactivate_pixi.py +7 -7
  189. fractal_server/tasks/v2/local/delete.py +6 -8
  190. fractal_server/tasks/v2/local/reactivate.py +12 -12
  191. fractal_server/tasks/v2/local/reactivate_pixi.py +12 -12
  192. fractal_server/tasks/v2/ssh/_utils.py +3 -3
  193. fractal_server/tasks/v2/ssh/collect.py +19 -24
  194. fractal_server/tasks/v2/ssh/collect_pixi.py +22 -24
  195. fractal_server/tasks/v2/ssh/deactivate.py +17 -15
  196. fractal_server/tasks/v2/ssh/deactivate_pixi.py +8 -7
  197. fractal_server/tasks/v2/ssh/delete.py +12 -10
  198. fractal_server/tasks/v2/ssh/reactivate.py +16 -16
  199. fractal_server/tasks/v2/ssh/reactivate_pixi.py +13 -14
  200. fractal_server/tasks/v2/templates/1_create_venv.sh +2 -0
  201. fractal_server/tasks/v2/templates/2_pip_install.sh +2 -0
  202. fractal_server/tasks/v2/templates/3_pip_freeze.sh +2 -0
  203. fractal_server/tasks/v2/templates/4_pip_show.sh +2 -0
  204. fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +3 -1
  205. fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +2 -0
  206. fractal_server/tasks/v2/templates/pixi_1_extract.sh +2 -0
  207. fractal_server/tasks/v2/templates/pixi_2_install.sh +2 -0
  208. fractal_server/tasks/v2/templates/pixi_3_post_install.sh +2 -0
  209. fractal_server/tasks/v2/utils_background.py +10 -10
  210. fractal_server/tasks/v2/utils_database.py +5 -5
  211. fractal_server/tasks/v2/utils_package_names.py +1 -2
  212. fractal_server/tasks/v2/utils_pixi.py +1 -3
  213. fractal_server/types/__init__.py +98 -1
  214. fractal_server/types/validators/__init__.py +3 -0
  215. fractal_server/types/validators/_common_validators.py +33 -3
  216. fractal_server/types/validators/_workflow_task_arguments_validators.py +1 -2
  217. fractal_server/utils.py +1 -0
  218. fractal_server/zip_tools.py +34 -0
  219. {fractal_server-2.17.1a1.dist-info → fractal_server-2.18.0.dist-info}/METADATA +3 -2
  220. fractal_server-2.18.0.dist-info/RECORD +275 -0
  221. fractal_server/app/routes/admin/v2/project.py +0 -41
  222. fractal_server-2.17.1a1.dist-info/RECORD +0 -264
  223. {fractal_server-2.17.1a1.dist-info → fractal_server-2.18.0.dist-info}/WHEEL +0 -0
  224. {fractal_server-2.17.1a1.dist-info → fractal_server-2.18.0.dist-info}/entry_points.txt +0 -0
  225. {fractal_server-2.17.1a1.dist-info → fractal_server-2.18.0.dist-info}/licenses/LICENSE +0 -0
@@ -7,8 +7,8 @@ from fastapi import Depends
7
7
  from fastapi import Form
8
8
  from fastapi import HTTPException
9
9
  from fastapi import Response
10
- from fastapi import status
11
10
  from fastapi import UploadFile
11
+ from fastapi import status
12
12
 
13
13
  from fractal_server.app.db import AsyncSession
14
14
  from fractal_server.app.db import get_async_db
@@ -33,17 +33,16 @@ from fractal_server.app.routes.aux.validate_user_profile import (
33
33
  )
34
34
  from fractal_server.app.schemas.v2 import FractalUploadedFile
35
35
  from fractal_server.app.schemas.v2 import ResourceType
36
- from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
37
- from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
38
- from fractal_server.app.schemas.v2 import TaskGroupActivityV2Read
39
- from fractal_server.app.schemas.v2.task_group import TaskGroupV2OriginEnum
36
+ from fractal_server.app.schemas.v2 import TaskGroupActivityAction
37
+ from fractal_server.app.schemas.v2 import TaskGroupActivityRead
38
+ from fractal_server.app.schemas.v2 import TaskGroupActivityStatus
39
+ from fractal_server.app.schemas.v2.task_group import TaskGroupOriginEnum
40
40
  from fractal_server.logger import set_logger
41
41
  from fractal_server.tasks.v2.local import collect_local_pixi
42
42
  from fractal_server.tasks.v2.ssh import collect_ssh_pixi
43
43
  from fractal_server.tasks.v2.utils_package_names import normalize_package_name
44
44
  from fractal_server.types import NonEmptyStr
45
45
 
46
-
47
46
  router = APIRouter()
48
47
 
49
48
  logger = set_logger(__name__)
@@ -75,7 +74,7 @@ def validate_pkgname_and_version(filename: str) -> tuple[str, str]:
75
74
  @router.post(
76
75
  "/collect/pixi/",
77
76
  status_code=202,
78
- response_model=TaskGroupActivityV2Read,
77
+ response_model=TaskGroupActivityRead,
79
78
  )
80
79
  async def collect_task_pixi(
81
80
  response: Response,
@@ -86,7 +85,7 @@ async def collect_task_pixi(
86
85
  user_group_id: int | None = None,
87
86
  user: UserOAuth = Depends(current_user_act_ver_prof),
88
87
  db: AsyncSession = Depends(get_async_db),
89
- ) -> TaskGroupActivityV2Read:
88
+ ) -> TaskGroupActivityRead:
90
89
  # Get validated resource and profile
91
90
  resource, profile = await validate_user_profile(user=user, db=db)
92
91
  resource_id = resource.id
@@ -137,7 +136,7 @@ async def collect_task_pixi(
137
136
  user_id=user.id,
138
137
  user_group_id=user_group_id,
139
138
  resource_id=resource_id,
140
- origin=TaskGroupV2OriginEnum.PIXI,
139
+ origin=TaskGroupOriginEnum.PIXI,
141
140
  pixi_version=pixi_version,
142
141
  pkg_name=pkg_name,
143
142
  version=version,
@@ -179,8 +178,8 @@ async def collect_task_pixi(
179
178
  task_group_activity = TaskGroupActivityV2(
180
179
  user_id=task_group.user_id,
181
180
  taskgroupv2_id=task_group.id,
182
- status=TaskGroupActivityStatusV2.PENDING,
183
- action=TaskGroupActivityActionV2.COLLECT,
181
+ status=TaskGroupActivityStatus.PENDING,
182
+ action=TaskGroupActivityAction.COLLECT,
184
183
  pkg_name=task_group.pkg_name,
185
184
  version=task_group.version,
186
185
  )
@@ -5,17 +5,12 @@ from fastapi import Depends
5
5
  from fastapi import HTTPException
6
6
  from fastapi import status
7
7
  from packaging.version import InvalidVersion
8
- from packaging.version import parse
9
8
  from packaging.version import Version
9
+ from packaging.version import parse
10
10
  from pydantic.types import AwareDatetime
11
11
  from sqlmodel import or_
12
12
  from sqlmodel import select
13
13
 
14
- from ._aux_functions import _get_user_resource_id
15
- from ._aux_functions_tasks import _get_task_group_full_access
16
- from ._aux_functions_tasks import _get_task_group_read_access
17
- from ._aux_functions_tasks import _verify_non_duplication_group_constraint
18
- from ._aux_task_group_disambiguation import remove_duplicate_task_groups
19
14
  from fractal_server.app.db import AsyncSession
20
15
  from fractal_server.app.db import get_async_db
21
16
  from fractal_server.app.models import LinkUserGroup
@@ -29,13 +24,19 @@ from fractal_server.app.routes.auth._aux_auth import (
29
24
  from fractal_server.app.routes.auth._aux_auth import (
30
25
  _verify_user_belongs_to_group,
31
26
  )
32
- from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
33
- from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
34
- from fractal_server.app.schemas.v2 import TaskGroupActivityV2Read
35
- from fractal_server.app.schemas.v2 import TaskGroupReadV2
36
- from fractal_server.app.schemas.v2 import TaskGroupUpdateV2
27
+ from fractal_server.app.schemas.v2 import TaskGroupActivityAction
28
+ from fractal_server.app.schemas.v2 import TaskGroupActivityRead
29
+ from fractal_server.app.schemas.v2 import TaskGroupActivityStatus
30
+ from fractal_server.app.schemas.v2 import TaskGroupRead
31
+ from fractal_server.app.schemas.v2 import TaskGroupUpdate
37
32
  from fractal_server.logger import set_logger
38
33
 
34
+ from ._aux_functions import _get_user_resource_id
35
+ from ._aux_functions_tasks import _get_task_group_full_access
36
+ from ._aux_functions_tasks import _get_task_group_read_access
37
+ from ._aux_functions_tasks import _verify_non_duplication_group_constraint
38
+ from ._aux_task_group_disambiguation import remove_duplicate_task_groups
39
+
39
40
  router = APIRouter()
40
41
 
41
42
  logger = set_logger(__name__)
@@ -61,17 +62,17 @@ def _version_sort_key(
61
62
  return (1, task_group.version)
62
63
 
63
64
 
64
- @router.get("/activity/", response_model=list[TaskGroupActivityV2Read])
65
+ @router.get("/activity/", response_model=list[TaskGroupActivityRead])
65
66
  async def get_task_group_activity_list(
66
67
  task_group_activity_id: int | None = None,
67
68
  taskgroupv2_id: int | None = None,
68
69
  pkg_name: str | None = None,
69
- status: TaskGroupActivityStatusV2 | None = None,
70
- action: TaskGroupActivityActionV2 | None = None,
70
+ status: TaskGroupActivityStatus | None = None,
71
+ action: TaskGroupActivityAction | None = None,
71
72
  timestamp_started_min: AwareDatetime | None = None,
72
73
  user: UserOAuth = Depends(current_user_act_ver_prof),
73
74
  db: AsyncSession = Depends(get_async_db),
74
- ) -> list[TaskGroupActivityV2Read]:
75
+ ) -> list[TaskGroupActivityRead]:
75
76
  stm = select(TaskGroupActivityV2).where(
76
77
  TaskGroupActivityV2.user_id == user.id
77
78
  )
@@ -97,13 +98,13 @@ async def get_task_group_activity_list(
97
98
 
98
99
  @router.get(
99
100
  "/activity/{task_group_activity_id}/",
100
- response_model=TaskGroupActivityV2Read,
101
+ response_model=TaskGroupActivityRead,
101
102
  )
102
103
  async def get_task_group_activity(
103
104
  task_group_activity_id: int,
104
105
  user: UserOAuth = Depends(current_user_act_ver_prof),
105
106
  db: AsyncSession = Depends(get_async_db),
106
- ) -> TaskGroupActivityV2Read:
107
+ ) -> TaskGroupActivityRead:
107
108
  activity = await db.get(TaskGroupActivityV2, task_group_activity_id)
108
109
 
109
110
  if activity is None:
@@ -123,14 +124,14 @@ async def get_task_group_activity(
123
124
  return activity
124
125
 
125
126
 
126
- @router.get("/", response_model=list[tuple[str, list[TaskGroupReadV2]]])
127
+ @router.get("/", response_model=list[tuple[str, list[TaskGroupRead]]])
127
128
  async def get_task_group_list(
128
129
  user: UserOAuth = Depends(current_user_act_ver_prof),
129
130
  db: AsyncSession = Depends(get_async_db),
130
131
  only_active: bool = False,
131
132
  only_owner: bool = False,
132
133
  args_schema: bool = True,
133
- ) -> list[tuple[str, list[TaskGroupReadV2]]]:
134
+ ) -> list[tuple[str, list[TaskGroupRead]]]:
134
135
  """
135
136
  Get all accessible TaskGroups
136
137
  """
@@ -189,12 +190,12 @@ async def get_task_group_list(
189
190
  return grouped_result
190
191
 
191
192
 
192
- @router.get("/{task_group_id}/", response_model=TaskGroupReadV2)
193
+ @router.get("/{task_group_id}/", response_model=TaskGroupRead)
193
194
  async def get_task_group(
194
195
  task_group_id: int,
195
196
  user: UserOAuth = Depends(current_user_act_ver_prof),
196
197
  db: AsyncSession = Depends(get_async_db),
197
- ) -> TaskGroupReadV2:
198
+ ) -> TaskGroupRead:
198
199
  """
199
200
  Get single TaskGroup
200
201
  """
@@ -206,13 +207,13 @@ async def get_task_group(
206
207
  return task_group
207
208
 
208
209
 
209
- @router.patch("/{task_group_id}/", response_model=TaskGroupReadV2)
210
+ @router.patch("/{task_group_id}/", response_model=TaskGroupRead)
210
211
  async def patch_task_group(
211
212
  task_group_id: int,
212
- task_group_update: TaskGroupUpdateV2,
213
+ task_group_update: TaskGroupUpdate,
213
214
  user: UserOAuth = Depends(current_user_act_ver_prof),
214
215
  db: AsyncSession = Depends(get_async_db),
215
- ) -> TaskGroupReadV2:
216
+ ) -> TaskGroupRead:
216
217
  """
217
218
  Patch single TaskGroup
218
219
  """
@@ -5,10 +5,6 @@ from fastapi import HTTPException
5
5
  from fastapi import Response
6
6
  from fastapi import status
7
7
 
8
- from ._aux_functions_task_lifecycle import check_no_ongoing_activity
9
- from ._aux_functions_task_lifecycle import check_no_related_workflowtask
10
- from ._aux_functions_task_lifecycle import check_no_submitted_job
11
- from ._aux_functions_tasks import _get_task_group_full_access
12
8
  from fractal_server.app.db import AsyncSession
13
9
  from fractal_server.app.db import get_async_db
14
10
  from fractal_server.app.models import UserOAuth
@@ -18,11 +14,11 @@ from fractal_server.app.routes.aux.validate_user_profile import (
18
14
  validate_user_profile,
19
15
  )
20
16
  from fractal_server.app.schemas.v2 import ResourceType
21
- from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
22
- from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
23
- from fractal_server.app.schemas.v2 import TaskGroupActivityV2Read
24
- from fractal_server.app.schemas.v2 import TaskGroupReadV2
25
- from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
17
+ from fractal_server.app.schemas.v2 import TaskGroupActivityAction
18
+ from fractal_server.app.schemas.v2 import TaskGroupActivityRead
19
+ from fractal_server.app.schemas.v2 import TaskGroupActivityStatus
20
+ from fractal_server.app.schemas.v2 import TaskGroupOriginEnum
21
+ from fractal_server.app.schemas.v2 import TaskGroupRead
26
22
  from fractal_server.logger import set_logger
27
23
  from fractal_server.tasks.v2.local import deactivate_local
28
24
  from fractal_server.tasks.v2.local import deactivate_local_pixi
@@ -36,6 +32,11 @@ from fractal_server.tasks.v2.ssh import reactivate_ssh
36
32
  from fractal_server.tasks.v2.ssh import reactivate_ssh_pixi
37
33
  from fractal_server.utils import get_timestamp
38
34
 
35
+ from ._aux_functions_task_lifecycle import check_no_ongoing_activity
36
+ from ._aux_functions_task_lifecycle import check_no_related_workflowtask
37
+ from ._aux_functions_task_lifecycle import check_no_submitted_job
38
+ from ._aux_functions_tasks import _get_task_group_full_access
39
+
39
40
  router = APIRouter()
40
41
 
41
42
 
@@ -44,7 +45,7 @@ logger = set_logger(__name__)
44
45
 
45
46
  @router.post(
46
47
  "/{task_group_id}/deactivate/",
47
- response_model=TaskGroupActivityV2Read,
48
+ response_model=TaskGroupActivityRead,
48
49
  )
49
50
  async def deactivate_task_group(
50
51
  task_group_id: int,
@@ -52,7 +53,7 @@ async def deactivate_task_group(
52
53
  response: Response,
53
54
  user: UserOAuth = Depends(current_user_act_ver_prof),
54
55
  db: AsyncSession = Depends(get_async_db),
55
- ) -> TaskGroupActivityV2Read:
56
+ ) -> TaskGroupActivityRead:
56
57
  """
57
58
  Deactivate task-group venv
58
59
  """
@@ -83,13 +84,13 @@ async def deactivate_task_group(
83
84
  )
84
85
 
85
86
  # Shortcut for task-group with origin="other"
86
- if task_group.origin == TaskGroupV2OriginEnum.OTHER:
87
+ if task_group.origin == TaskGroupOriginEnum.OTHER:
87
88
  task_group.active = False
88
89
  task_group_activity = TaskGroupActivityV2(
89
90
  user_id=task_group.user_id,
90
91
  taskgroupv2_id=task_group.id,
91
- status=TaskGroupActivityStatusV2.OK,
92
- action=TaskGroupActivityActionV2.DEACTIVATE,
92
+ status=TaskGroupActivityStatus.OK,
93
+ action=TaskGroupActivityAction.DEACTIVATE,
93
94
  pkg_name=task_group.pkg_name,
94
95
  version=(task_group.version or "N/A"),
95
96
  log=(
@@ -108,8 +109,8 @@ async def deactivate_task_group(
108
109
  task_group_activity = TaskGroupActivityV2(
109
110
  user_id=task_group.user_id,
110
111
  taskgroupv2_id=task_group.id,
111
- status=TaskGroupActivityStatusV2.PENDING,
112
- action=TaskGroupActivityActionV2.DEACTIVATE,
112
+ status=TaskGroupActivityStatus.PENDING,
113
+ action=TaskGroupActivityAction.DEACTIVATE,
113
114
  pkg_name=task_group.pkg_name,
114
115
  version=task_group.version,
115
116
  timestamp_started=get_timestamp(),
@@ -121,12 +122,12 @@ async def deactivate_task_group(
121
122
 
122
123
  # Submit background task
123
124
  if resource.type == ResourceType.SLURM_SSH:
124
- if task_group.origin == TaskGroupV2OriginEnum.PIXI:
125
+ if task_group.origin == TaskGroupOriginEnum.PIXI:
125
126
  deactivate_function = deactivate_ssh_pixi
126
127
  else:
127
128
  deactivate_function = deactivate_ssh
128
129
  else:
129
- if task_group.origin == TaskGroupV2OriginEnum.PIXI:
130
+ if task_group.origin == TaskGroupOriginEnum.PIXI:
130
131
  deactivate_function = deactivate_local_pixi
131
132
  else:
132
133
  deactivate_function = deactivate_local
@@ -148,7 +149,7 @@ async def deactivate_task_group(
148
149
 
149
150
  @router.post(
150
151
  "/{task_group_id}/reactivate/",
151
- response_model=TaskGroupActivityV2Read,
152
+ response_model=TaskGroupActivityRead,
152
153
  )
153
154
  async def reactivate_task_group(
154
155
  task_group_id: int,
@@ -156,7 +157,7 @@ async def reactivate_task_group(
156
157
  response: Response,
157
158
  user: UserOAuth = Depends(current_user_act_ver_prof),
158
159
  db: AsyncSession = Depends(get_async_db),
159
- ) -> TaskGroupReadV2:
160
+ ) -> TaskGroupRead:
160
161
  """
161
162
  Deactivate task-group venv
162
163
  """
@@ -186,13 +187,13 @@ async def reactivate_task_group(
186
187
  await check_no_submitted_job(task_group_id=task_group.id, db=db)
187
188
 
188
189
  # Shortcut for task-group with origin="other"
189
- if task_group.origin == TaskGroupV2OriginEnum.OTHER:
190
+ if task_group.origin == TaskGroupOriginEnum.OTHER:
190
191
  task_group.active = True
191
192
  task_group_activity = TaskGroupActivityV2(
192
193
  user_id=task_group.user_id,
193
194
  taskgroupv2_id=task_group.id,
194
- status=TaskGroupActivityStatusV2.OK,
195
- action=TaskGroupActivityActionV2.REACTIVATE,
195
+ status=TaskGroupActivityStatus.OK,
196
+ action=TaskGroupActivityAction.REACTIVATE,
196
197
  pkg_name=task_group.pkg_name,
197
198
  version=(task_group.version or "N/A"),
198
199
  log=(
@@ -212,16 +213,15 @@ async def reactivate_task_group(
212
213
  raise HTTPException(
213
214
  status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
214
215
  detail=(
215
- "Cannot reactivate a task group with "
216
- f"{task_group.env_info=}."
216
+ f"Cannot reactivate a task group with {task_group.env_info=}."
217
217
  ),
218
218
  )
219
219
 
220
220
  task_group_activity = TaskGroupActivityV2(
221
221
  user_id=task_group.user_id,
222
222
  taskgroupv2_id=task_group.id,
223
- status=TaskGroupActivityStatusV2.PENDING,
224
- action=TaskGroupActivityActionV2.REACTIVATE,
223
+ status=TaskGroupActivityStatus.PENDING,
224
+ action=TaskGroupActivityAction.REACTIVATE,
225
225
  pkg_name=task_group.pkg_name,
226
226
  version=task_group.version,
227
227
  timestamp_started=get_timestamp(),
@@ -231,12 +231,12 @@ async def reactivate_task_group(
231
231
 
232
232
  # Submit background task
233
233
  if resource.type == ResourceType.SLURM_SSH:
234
- if task_group.origin == TaskGroupV2OriginEnum.PIXI:
234
+ if task_group.origin == TaskGroupOriginEnum.PIXI:
235
235
  reactivate_function = reactivate_ssh_pixi
236
236
  else:
237
237
  reactivate_function = reactivate_ssh
238
238
  else:
239
- if task_group.origin == TaskGroupV2OriginEnum.PIXI:
239
+ if task_group.origin == TaskGroupOriginEnum.PIXI:
240
240
  reactivate_function = reactivate_local_pixi
241
241
  else:
242
242
  reactivate_function = reactivate_local
@@ -265,7 +265,7 @@ async def delete_task_group(
265
265
  response: Response,
266
266
  user: UserOAuth = Depends(current_user_act_ver_prof),
267
267
  db: AsyncSession = Depends(get_async_db),
268
- ) -> TaskGroupActivityV2Read:
268
+ ) -> TaskGroupActivityRead:
269
269
  """
270
270
  Deletion of task-group from db and file system
271
271
  """
@@ -283,8 +283,8 @@ async def delete_task_group(
283
283
  task_group_activity = TaskGroupActivityV2(
284
284
  user_id=task_group.user_id,
285
285
  taskgroupv2_id=task_group.id,
286
- status=TaskGroupActivityStatusV2.PENDING,
287
- action=TaskGroupActivityActionV2.DELETE,
286
+ status=TaskGroupActivityStatus.PENDING,
287
+ action=TaskGroupActivityAction.DELETE,
288
288
  pkg_name=task_group.pkg_name,
289
289
  version=(task_group.version or "N/A"),
290
290
  timestamp_started=get_timestamp(),
@@ -2,31 +2,33 @@ from fastapi import APIRouter
2
2
  from fastapi import Depends
3
3
  from fastapi import HTTPException
4
4
  from fastapi import status
5
- from packaging.version import parse
6
5
  from packaging.version import Version
6
+ from packaging.version import parse
7
7
  from pydantic import BaseModel
8
8
  from pydantic import ConfigDict
9
+ from sqlmodel import String
9
10
  from sqlmodel import cast
10
11
  from sqlmodel import or_
11
12
  from sqlmodel import select
12
- from sqlmodel import String
13
13
 
14
- from ....db import AsyncSession
15
- from ....db import get_async_db
16
- from ....models import LinkUserGroup
17
- from ....models.v2 import TaskV2
18
- from ._aux_functions import _get_workflow_check_owner
19
- from ._aux_functions import _get_workflow_task_check_owner
20
- from ._aux_functions_task_version_update import get_new_workflow_task_meta
21
- from ._aux_functions_tasks import _check_type_filters_compatibility
22
- from ._aux_functions_tasks import _get_task_group_or_404
23
- from ._aux_functions_tasks import _get_task_read_access
14
+ from fractal_server.app.db import AsyncSession
15
+ from fractal_server.app.db import get_async_db
16
+ from fractal_server.app.models import LinkUserGroup
24
17
  from fractal_server.app.models import UserOAuth
25
18
  from fractal_server.app.models.v2 import TaskGroupV2
19
+ from fractal_server.app.models.v2 import TaskV2
26
20
  from fractal_server.app.routes.auth import current_user_act_ver_prof
27
21
  from fractal_server.app.schemas.v2 import TaskType
28
- from fractal_server.app.schemas.v2 import WorkflowTaskReadV2
29
- from fractal_server.app.schemas.v2 import WorkflowTaskReplaceV2
22
+ from fractal_server.app.schemas.v2 import WorkflowTaskRead
23
+ from fractal_server.app.schemas.v2 import WorkflowTaskReplace
24
+ from fractal_server.app.schemas.v2.sharing import ProjectPermissions
25
+
26
+ from ._aux_functions import _get_workflow_check_access
27
+ from ._aux_functions import _get_workflow_task_check_access
28
+ from ._aux_functions_task_version_update import get_new_workflow_task_meta
29
+ from ._aux_functions_tasks import _check_type_filters_compatibility
30
+ from ._aux_functions_tasks import _get_task_group_or_404
31
+ from ._aux_functions_tasks import _get_task_read_access
30
32
 
31
33
  router = APIRouter()
32
34
 
@@ -78,10 +80,11 @@ async def get_workflow_version_update_candidates(
78
80
  user: UserOAuth = Depends(current_user_act_ver_prof),
79
81
  db: AsyncSession = Depends(get_async_db),
80
82
  ) -> list[list[TaskVersionRead]]:
81
- workflow = await _get_workflow_check_owner(
83
+ workflow = await _get_workflow_check_access(
82
84
  project_id=project_id,
83
85
  workflow_id=workflow_id,
84
86
  user_id=user.id,
87
+ required_permissions=ProjectPermissions.READ,
85
88
  db=db,
86
89
  )
87
90
 
@@ -168,7 +171,7 @@ async def get_workflow_version_update_candidates(
168
171
 
169
172
  @router.post(
170
173
  "/project/{project_id}/workflow/{workflow_id}/wftask/replace-task/",
171
- response_model=WorkflowTaskReadV2,
174
+ response_model=WorkflowTaskRead,
172
175
  status_code=status.HTTP_201_CREATED,
173
176
  )
174
177
  async def replace_workflowtask(
@@ -176,16 +179,17 @@ async def replace_workflowtask(
176
179
  workflow_id: int,
177
180
  workflow_task_id: int,
178
181
  task_id: int,
179
- replace: WorkflowTaskReplaceV2,
182
+ replace: WorkflowTaskReplace,
180
183
  user: UserOAuth = Depends(current_user_act_ver_prof),
181
184
  db: AsyncSession = Depends(get_async_db),
182
- ) -> WorkflowTaskReadV2:
185
+ ) -> WorkflowTaskRead:
183
186
  # Get objects from database
184
- workflow_task, workflow = await _get_workflow_task_check_owner(
187
+ workflow_task, workflow = await _get_workflow_task_check_access(
185
188
  project_id=project_id,
186
189
  workflow_id=workflow_id,
187
190
  workflow_task_id=workflow_task_id,
188
191
  user_id=user.id,
192
+ required_permissions=ProjectPermissions.WRITE,
189
193
  db=db,
190
194
  )
191
195
  new_task = await _get_task_read_access(