fractal-server 2.17.0a4__py3-none-any.whl → 2.17.0a6__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 (67) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/__main__.py +22 -26
  3. fractal_server/app/models/security.py +19 -21
  4. fractal_server/app/models/user_settings.py +1 -0
  5. fractal_server/app/models/v2/task_group.py +1 -0
  6. fractal_server/app/routes/admin/v2/accounting.py +3 -3
  7. fractal_server/app/routes/admin/v2/impersonate.py +2 -2
  8. fractal_server/app/routes/admin/v2/job.py +6 -6
  9. fractal_server/app/routes/admin/v2/profile.py +18 -4
  10. fractal_server/app/routes/admin/v2/project.py +2 -2
  11. fractal_server/app/routes/admin/v2/resource.py +8 -8
  12. fractal_server/app/routes/admin/v2/task.py +11 -2
  13. fractal_server/app/routes/admin/v2/task_group.py +16 -12
  14. fractal_server/app/routes/admin/v2/task_group_lifecycle.py +4 -4
  15. fractal_server/app/routes/api/__init__.py +14 -5
  16. fractal_server/app/routes/api/v2/dataset.py +10 -19
  17. fractal_server/app/routes/api/v2/history.py +8 -8
  18. fractal_server/app/routes/api/v2/images.py +5 -5
  19. fractal_server/app/routes/api/v2/job.py +8 -8
  20. fractal_server/app/routes/api/v2/pre_submission_checks.py +3 -3
  21. fractal_server/app/routes/api/v2/project.py +6 -6
  22. fractal_server/app/routes/api/v2/status_legacy.py +2 -2
  23. fractal_server/app/routes/api/v2/submit.py +25 -29
  24. fractal_server/app/routes/api/v2/task.py +6 -7
  25. fractal_server/app/routes/api/v2/task_collection.py +4 -3
  26. fractal_server/app/routes/api/v2/task_collection_custom.py +4 -3
  27. fractal_server/app/routes/api/v2/task_collection_pixi.py +2 -2
  28. fractal_server/app/routes/api/v2/task_group.py +6 -6
  29. fractal_server/app/routes/api/v2/task_group_lifecycle.py +4 -4
  30. fractal_server/app/routes/api/v2/task_version_update.py +3 -3
  31. fractal_server/app/routes/api/v2/workflow.py +9 -9
  32. fractal_server/app/routes/api/v2/workflow_import.py +2 -2
  33. fractal_server/app/routes/api/v2/workflowtask.py +5 -5
  34. fractal_server/app/routes/auth/__init__.py +34 -5
  35. fractal_server/app/routes/auth/current_user.py +22 -72
  36. fractal_server/app/routes/auth/group.py +8 -35
  37. fractal_server/app/routes/auth/oauth.py +1 -1
  38. fractal_server/app/routes/auth/register.py +2 -2
  39. fractal_server/app/routes/auth/users.py +6 -48
  40. fractal_server/app/schemas/__init__.py +0 -1
  41. fractal_server/app/schemas/user.py +23 -0
  42. fractal_server/app/schemas/v2/__init__.py +1 -0
  43. fractal_server/app/schemas/v2/task_group.py +5 -0
  44. fractal_server/app/security/__init__.py +134 -46
  45. fractal_server/app/security/signup_email.py +52 -34
  46. fractal_server/config/__init__.py +6 -0
  47. fractal_server/config/_data.py +68 -0
  48. fractal_server/config/_email.py +10 -47
  49. fractal_server/config/_main.py +3 -56
  50. fractal_server/config/_oauth.py +2 -2
  51. fractal_server/main.py +3 -2
  52. fractal_server/migrations/versions/f65ee53991e3_user_settings_related.py +67 -0
  53. fractal_server/runner/executors/slurm_common/base_slurm_runner.py +1 -1
  54. fractal_server/runner/executors/slurm_common/slurm_config.py +5 -8
  55. fractal_server/runner/executors/slurm_ssh/runner.py +1 -1
  56. fractal_server/runner/executors/slurm_sudo/runner.py +1 -1
  57. fractal_server/runner/v2/_slurm_ssh.py +2 -1
  58. fractal_server/runner/v2/_slurm_sudo.py +1 -1
  59. fractal_server/runner/v2/submit_workflow.py +12 -12
  60. {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/METADATA +4 -6
  61. {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/RECORD +64 -65
  62. fractal_server/app/routes/aux/validate_user_settings.py +0 -76
  63. fractal_server/app/schemas/user_settings.py +0 -63
  64. fractal_server/app/user_settings.py +0 -32
  65. {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/WHEEL +0 -0
  66. {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/entry_points.txt +0 -0
  67. {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/licenses/LICENSE +0 -0
@@ -6,7 +6,8 @@ from fastapi import Depends
6
6
 
7
7
  import fractal_server
8
8
  from fractal_server.app.models import UserOAuth
9
- from fractal_server.app.routes.auth import current_active_superuser
9
+ from fractal_server.app.routes.auth import current_superuser_act
10
+ from fractal_server.config import get_data_settings
10
11
  from fractal_server.config import get_db_settings
11
12
  from fractal_server.config import get_email_settings
12
13
  from fractal_server.config import get_oauth_settings
@@ -26,7 +27,7 @@ async def alive():
26
27
 
27
28
  @router_api.get("/settings/app/")
28
29
  async def view_settings(
29
- user: UserOAuth = Depends(current_active_superuser),
30
+ user: UserOAuth = Depends(current_superuser_act),
30
31
  ):
31
32
  settings = Inject(get_settings)
32
33
  return settings.model_dump()
@@ -34,7 +35,7 @@ async def view_settings(
34
35
 
35
36
  @router_api.get("/settings/database/")
36
37
  async def view_db_settings(
37
- user: UserOAuth = Depends(current_active_superuser),
38
+ user: UserOAuth = Depends(current_superuser_act),
38
39
  ):
39
40
  settings = Inject(get_db_settings)
40
41
  return settings.model_dump()
@@ -42,15 +43,23 @@ async def view_db_settings(
42
43
 
43
44
  @router_api.get("/settings/email/")
44
45
  async def view_email_settings(
45
- user: UserOAuth = Depends(current_active_superuser),
46
+ user: UserOAuth = Depends(current_superuser_act),
46
47
  ):
47
48
  settings = Inject(get_email_settings)
48
49
  return settings.model_dump()
49
50
 
50
51
 
52
+ @router_api.get("/settings/data/")
53
+ async def view_data_settings(
54
+ user: UserOAuth = Depends(current_superuser_act),
55
+ ):
56
+ settings = Inject(get_data_settings)
57
+ return settings.model_dump()
58
+
59
+
51
60
  @router_api.get("/settings/oauth/")
52
61
  async def view_oauth_settings(
53
- user: UserOAuth = Depends(current_active_superuser),
62
+ user: UserOAuth = Depends(current_superuser_act),
54
63
  ):
55
64
  settings = Inject(get_oauth_settings)
56
65
  return settings.model_dump()
@@ -19,7 +19,7 @@ from ._aux_functions import _get_dataset_check_owner
19
19
  from ._aux_functions import _get_project_check_owner
20
20
  from ._aux_functions import _get_submitted_jobs_statement
21
21
  from fractal_server.app.models import UserOAuth
22
- from fractal_server.app.routes.auth import current_active_user
22
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
23
23
  from fractal_server.string_tools import sanitize_string
24
24
  from fractal_server.urls import normalize_url
25
25
 
@@ -34,7 +34,7 @@ router = APIRouter()
34
34
  async def create_dataset(
35
35
  project_id: int,
36
36
  dataset: DatasetCreateV2,
37
- user: UserOAuth = Depends(current_active_user),
37
+ user: UserOAuth = Depends(current_user_act_ver_prof),
38
38
  db: AsyncSession = Depends(get_async_db),
39
39
  ) -> DatasetReadV2 | None:
40
40
  """
@@ -45,15 +45,6 @@ async def create_dataset(
45
45
  )
46
46
 
47
47
  if dataset.zarr_dir is None:
48
- if user.settings.project_dir is None:
49
- raise HTTPException(
50
- status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
51
- detail=(
52
- "Both 'dataset.zarr_dir' and 'user.settings.project_dir' "
53
- "are null"
54
- ),
55
- )
56
-
57
48
  db_dataset = DatasetV2(
58
49
  project_id=project_id,
59
50
  zarr_dir="__PLACEHOLDER__",
@@ -63,7 +54,7 @@ async def create_dataset(
63
54
  await db.commit()
64
55
  await db.refresh(db_dataset)
65
56
  path = (
66
- f"{user.settings.project_dir}/fractal/"
57
+ f"{user.project_dir}/fractal/"
67
58
  f"{project_id}_{sanitize_string(project.name)}/"
68
59
  f"{db_dataset.id}_{sanitize_string(db_dataset.name)}"
69
60
  )
@@ -88,7 +79,7 @@ async def create_dataset(
88
79
  )
89
80
  async def read_dataset_list(
90
81
  project_id: int,
91
- user: UserOAuth = Depends(current_active_user),
82
+ user: UserOAuth = Depends(current_user_act_ver_prof),
92
83
  db: AsyncSession = Depends(get_async_db),
93
84
  ) -> list[DatasetReadV2] | None:
94
85
  """
@@ -116,7 +107,7 @@ async def read_dataset_list(
116
107
  async def read_dataset(
117
108
  project_id: int,
118
109
  dataset_id: int,
119
- user: UserOAuth = Depends(current_active_user),
110
+ user: UserOAuth = Depends(current_user_act_ver_prof),
120
111
  db: AsyncSession = Depends(get_async_db),
121
112
  ) -> DatasetReadV2 | None:
122
113
  """
@@ -141,7 +132,7 @@ async def update_dataset(
141
132
  project_id: int,
142
133
  dataset_id: int,
143
134
  dataset_update: DatasetUpdateV2,
144
- user: UserOAuth = Depends(current_active_user),
135
+ user: UserOAuth = Depends(current_user_act_ver_prof),
145
136
  db: AsyncSession = Depends(get_async_db),
146
137
  ) -> DatasetReadV2 | None:
147
138
  """
@@ -181,7 +172,7 @@ async def update_dataset(
181
172
  async def delete_dataset(
182
173
  project_id: int,
183
174
  dataset_id: int,
184
- user: UserOAuth = Depends(current_active_user),
175
+ user: UserOAuth = Depends(current_user_act_ver_prof),
185
176
  db: AsyncSession = Depends(get_async_db),
186
177
  ) -> Response:
187
178
  """
@@ -219,7 +210,7 @@ async def delete_dataset(
219
210
 
220
211
  @router.get("/dataset/", response_model=list[DatasetReadV2])
221
212
  async def get_user_datasets(
222
- user: UserOAuth = Depends(current_active_user),
213
+ user: UserOAuth = Depends(current_user_act_ver_prof),
223
214
  db: AsyncSession = Depends(get_async_db),
224
215
  ) -> list[DatasetReadV2]:
225
216
  """
@@ -243,7 +234,7 @@ async def get_user_datasets(
243
234
  async def export_dataset(
244
235
  project_id: int,
245
236
  dataset_id: int,
246
- user: UserOAuth = Depends(current_active_user),
237
+ user: UserOAuth = Depends(current_user_act_ver_prof),
247
238
  db: AsyncSession = Depends(get_async_db),
248
239
  ) -> DatasetExportV2 | None:
249
240
  """
@@ -270,7 +261,7 @@ async def export_dataset(
270
261
  async def import_dataset(
271
262
  project_id: int,
272
263
  dataset: DatasetImportV2,
273
- user: UserOAuth = Depends(current_active_user),
264
+ user: UserOAuth = Depends(current_user_act_ver_prof),
274
265
  db: AsyncSession = Depends(get_async_db),
275
266
  ) -> DatasetReadV2 | None:
276
267
  """
@@ -23,7 +23,7 @@ from fractal_server.app.models.v2 import HistoryImageCache
23
23
  from fractal_server.app.models.v2 import HistoryRun
24
24
  from fractal_server.app.models.v2 import HistoryUnit
25
25
  from fractal_server.app.models.v2 import TaskV2
26
- from fractal_server.app.routes.auth import current_active_user
26
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
27
27
  from fractal_server.app.routes.pagination import get_pagination_params
28
28
  from fractal_server.app.routes.pagination import PaginationRequest
29
29
  from fractal_server.app.routes.pagination import PaginationResponse
@@ -68,7 +68,7 @@ async def get_workflow_tasks_statuses(
68
68
  project_id: int,
69
69
  dataset_id: int,
70
70
  workflow_id: int,
71
- user: UserOAuth = Depends(current_active_user),
71
+ user: UserOAuth = Depends(current_user_act_ver_prof),
72
72
  db: AsyncSession = Depends(get_async_db),
73
73
  ) -> JSONResponse:
74
74
  # Access control
@@ -179,7 +179,7 @@ async def get_history_run_list(
179
179
  project_id: int,
180
180
  dataset_id: int,
181
181
  workflowtask_id: int,
182
- user: UserOAuth = Depends(current_active_user),
182
+ user: UserOAuth = Depends(current_user_act_ver_prof),
183
183
  db: AsyncSession = Depends(get_async_db),
184
184
  ) -> list[HistoryRunReadAggregated]:
185
185
  # Access control
@@ -271,7 +271,7 @@ async def get_history_run_units(
271
271
  workflowtask_id: int,
272
272
  history_run_id: int,
273
273
  unit_status: HistoryUnitStatus | None = None,
274
- user: UserOAuth = Depends(current_active_user),
274
+ user: UserOAuth = Depends(current_user_act_ver_prof),
275
275
  db: AsyncSession = Depends(get_async_db),
276
276
  pagination: PaginationRequest = Depends(get_pagination_params),
277
277
  ) -> PaginationResponse[HistoryUnitRead]:
@@ -330,7 +330,7 @@ async def get_history_images(
330
330
  dataset_id: int,
331
331
  workflowtask_id: int,
332
332
  request_body: ImageQuery,
333
- user: UserOAuth = Depends(current_active_user),
333
+ user: UserOAuth = Depends(current_user_act_ver_prof),
334
334
  db: AsyncSession = Depends(get_async_db),
335
335
  pagination: PaginationRequest = Depends(get_pagination_params),
336
336
  ) -> ImagePage:
@@ -412,7 +412,7 @@ async def get_history_images(
412
412
  async def get_image_log(
413
413
  project_id: int,
414
414
  request_data: ImageLogsRequest,
415
- user: UserOAuth = Depends(current_active_user),
415
+ user: UserOAuth = Depends(current_user_act_ver_prof),
416
416
  db: AsyncSession = Depends(get_async_db),
417
417
  ) -> JSONResponse:
418
418
  # Access control
@@ -460,7 +460,7 @@ async def get_history_unit_log(
460
460
  history_unit_id: int,
461
461
  workflowtask_id: int,
462
462
  dataset_id: int,
463
- user: UserOAuth = Depends(current_active_user),
463
+ user: UserOAuth = Depends(current_user_act_ver_prof),
464
464
  db: AsyncSession = Depends(get_async_db),
465
465
  ) -> JSONResponse:
466
466
  # Access control
@@ -508,7 +508,7 @@ async def get_history_unit_log(
508
508
  async def get_dataset_history(
509
509
  project_id: int,
510
510
  dataset_id: int,
511
- user: UserOAuth = Depends(current_active_user),
511
+ user: UserOAuth = Depends(current_user_act_ver_prof),
512
512
  db: AsyncSession = Depends(get_async_db),
513
513
  ) -> list[HistoryRunRead]:
514
514
  """
@@ -13,7 +13,7 @@ from fractal_server.app.db import AsyncSession
13
13
  from fractal_server.app.db import get_async_db
14
14
  from fractal_server.app.models import HistoryImageCache
15
15
  from fractal_server.app.models import UserOAuth
16
- from fractal_server.app.routes.auth import current_active_user
16
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
17
17
  from fractal_server.app.routes.pagination import get_pagination_params
18
18
  from fractal_server.app.routes.pagination import PaginationRequest
19
19
  from fractal_server.app.routes.pagination import PaginationResponse
@@ -60,7 +60,7 @@ async def post_new_image(
60
60
  project_id: int,
61
61
  dataset_id: int,
62
62
  new_image: SingleImage,
63
- user: UserOAuth = Depends(current_active_user),
63
+ user: UserOAuth = Depends(current_user_act_ver_prof),
64
64
  db: AsyncSession = Depends(get_async_db),
65
65
  ) -> Response:
66
66
  output = await _get_dataset_check_owner(
@@ -112,7 +112,7 @@ async def query_dataset_images(
112
112
  dataset_id: int,
113
113
  query: ImageQueryWithZarrUrl | None = None,
114
114
  pagination: PaginationRequest = Depends(get_pagination_params),
115
- user: UserOAuth = Depends(current_active_user),
115
+ user: UserOAuth = Depends(current_user_act_ver_prof),
116
116
  db: AsyncSession = Depends(get_async_db),
117
117
  ) -> ImagePage:
118
118
  page = pagination.page
@@ -183,7 +183,7 @@ async def delete_dataset_images(
183
183
  project_id: int,
184
184
  dataset_id: int,
185
185
  zarr_url: str,
186
- user: UserOAuth = Depends(current_active_user),
186
+ user: UserOAuth = Depends(current_user_act_ver_prof),
187
187
  db: AsyncSession = Depends(get_async_db),
188
188
  ) -> Response:
189
189
  output = await _get_dataset_check_owner(
@@ -227,7 +227,7 @@ async def patch_dataset_image(
227
227
  project_id: int,
228
228
  dataset_id: int,
229
229
  image_update: SingleImageUpdate,
230
- user: UserOAuth = Depends(current_active_user),
230
+ user: UserOAuth = Depends(current_user_act_ver_prof),
231
231
  db: AsyncSession = Depends(get_async_db),
232
232
  ):
233
233
  output = await _get_dataset_check_owner(
@@ -23,7 +23,7 @@ from ._aux_functions import _get_job_check_owner
23
23
  from ._aux_functions import _get_project_check_owner
24
24
  from ._aux_functions import _get_workflow_check_owner
25
25
  from fractal_server.app.models import UserOAuth
26
- from fractal_server.app.routes.auth import current_active_user
26
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
27
27
  from fractal_server.runner.filenames import WORKFLOW_LOG_FILENAME
28
28
 
29
29
 
@@ -39,7 +39,7 @@ router = APIRouter()
39
39
 
40
40
  @router.get("/job/", response_model=list[JobReadV2])
41
41
  async def get_user_jobs(
42
- user: UserOAuth = Depends(current_active_user),
42
+ user: UserOAuth = Depends(current_user_act_ver_prof),
43
43
  log: bool = True,
44
44
  db: AsyncSession = Depends(get_async_db),
45
45
  ) -> list[JobReadV2]:
@@ -68,7 +68,7 @@ async def get_user_jobs(
68
68
  async def get_workflow_jobs(
69
69
  project_id: int,
70
70
  workflow_id: int,
71
- user: UserOAuth = Depends(current_active_user),
71
+ user: UserOAuth = Depends(current_user_act_ver_prof),
72
72
  db: AsyncSession = Depends(get_async_db),
73
73
  ) -> list[JobReadV2] | None:
74
74
  """
@@ -88,7 +88,7 @@ async def get_latest_job(
88
88
  project_id: int,
89
89
  workflow_id: int,
90
90
  dataset_id: int,
91
- user: UserOAuth = Depends(current_active_user),
91
+ user: UserOAuth = Depends(current_user_act_ver_prof),
92
92
  db: AsyncSession = Depends(get_async_db),
93
93
  ) -> JobReadV2:
94
94
  await _get_workflow_check_owner(
@@ -120,7 +120,7 @@ async def read_job(
120
120
  project_id: int,
121
121
  job_id: int,
122
122
  show_tmp_logs: bool = False,
123
- user: UserOAuth = Depends(current_active_user),
123
+ user: UserOAuth = Depends(current_user_act_ver_prof),
124
124
  db: AsyncSession = Depends(get_async_db),
125
125
  ) -> JobReadV2 | None:
126
126
  """
@@ -153,7 +153,7 @@ async def read_job(
153
153
  async def download_job_logs(
154
154
  project_id: int,
155
155
  job_id: int,
156
- user: UserOAuth = Depends(current_active_user),
156
+ user: UserOAuth = Depends(current_user_act_ver_prof),
157
157
  db: AsyncSession = Depends(get_async_db),
158
158
  ) -> StreamingResponse:
159
159
  """
@@ -183,7 +183,7 @@ async def download_job_logs(
183
183
  )
184
184
  async def get_job_list(
185
185
  project_id: int,
186
- user: UserOAuth = Depends(current_active_user),
186
+ user: UserOAuth = Depends(current_user_act_ver_prof),
187
187
  log: bool = True,
188
188
  db: AsyncSession = Depends(get_async_db),
189
189
  ) -> list[JobReadV2] | None:
@@ -212,7 +212,7 @@ async def get_job_list(
212
212
  async def stop_job(
213
213
  project_id: int,
214
214
  job_id: int,
215
- user: UserOAuth = Depends(current_active_user),
215
+ user: UserOAuth = Depends(current_user_act_ver_prof),
216
216
  db: AsyncSession = Depends(get_async_db),
217
217
  ) -> Response:
218
218
  """
@@ -11,7 +11,7 @@ from .images import ImageQuery
11
11
  from fractal_server.app.db import AsyncSession
12
12
  from fractal_server.app.db import get_async_db
13
13
  from fractal_server.app.models import UserOAuth
14
- from fractal_server.app.routes.auth import current_active_user
14
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
15
15
  from fractal_server.app.schemas.v2 import HistoryUnitStatus
16
16
  from fractal_server.app.schemas.v2 import TaskType
17
17
  from fractal_server.images.status_tools import enrich_images_unsorted_async
@@ -32,7 +32,7 @@ async def verify_unique_types(
32
32
  dataset_id: int,
33
33
  workflowtask_id: int,
34
34
  query: ImageQuery | None = None,
35
- user: UserOAuth = Depends(current_active_user),
35
+ user: UserOAuth = Depends(current_user_act_ver_prof),
36
36
  db: AsyncSession = Depends(get_async_db),
37
37
  ) -> list[str]:
38
38
  # Get dataset
@@ -93,7 +93,7 @@ async def check_non_processed_images(
93
93
  workflow_id: int,
94
94
  workflowtask_id: int,
95
95
  filters: NonProcessedImagesPayload,
96
- user: UserOAuth = Depends(current_active_user),
96
+ user: UserOAuth = Depends(current_user_act_ver_prof),
97
97
  db: AsyncSession = Depends(get_async_db),
98
98
  ) -> JSONResponse:
99
99
  db_workflow_task, db_workflow = await _get_workflow_task_check_owner(
@@ -20,14 +20,14 @@ from ._aux_functions import _get_project_check_owner
20
20
  from ._aux_functions import _get_resource_and_profile_ids
21
21
  from ._aux_functions import _get_submitted_jobs_statement
22
22
  from fractal_server.app.models import UserOAuth
23
- from fractal_server.app.routes.auth import current_active_user
23
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
24
24
 
25
25
  router = APIRouter()
26
26
 
27
27
 
28
28
  @router.get("/project/", response_model=list[ProjectReadV2])
29
29
  async def get_list_project(
30
- user: UserOAuth = Depends(current_active_user),
30
+ user: UserOAuth = Depends(current_user_act_ver_prof),
31
31
  db: AsyncSession = Depends(get_async_db),
32
32
  ) -> list[ProjectV2]:
33
33
  """
@@ -47,7 +47,7 @@ async def get_list_project(
47
47
  @router.post("/project/", response_model=ProjectReadV2, status_code=201)
48
48
  async def create_project(
49
49
  project: ProjectCreateV2,
50
- user: UserOAuth = Depends(current_active_user),
50
+ user: UserOAuth = Depends(current_user_act_ver_prof),
51
51
  db: AsyncSession = Depends(get_async_db),
52
52
  ) -> ProjectReadV2 | None:
53
53
  """
@@ -76,7 +76,7 @@ async def create_project(
76
76
  @router.get("/project/{project_id}/", response_model=ProjectReadV2)
77
77
  async def read_project(
78
78
  project_id: int,
79
- user: UserOAuth = Depends(current_active_user),
79
+ user: UserOAuth = Depends(current_user_act_ver_prof),
80
80
  db: AsyncSession = Depends(get_async_db),
81
81
  ) -> ProjectReadV2 | None:
82
82
  """
@@ -93,7 +93,7 @@ async def read_project(
93
93
  async def update_project(
94
94
  project_id: int,
95
95
  project_update: ProjectUpdateV2,
96
- user: UserOAuth = Depends(current_active_user),
96
+ user: UserOAuth = Depends(current_user_act_ver_prof),
97
97
  db: AsyncSession = Depends(get_async_db),
98
98
  ):
99
99
  project = await _get_project_check_owner(
@@ -118,7 +118,7 @@ async def update_project(
118
118
  @router.delete("/project/{project_id}/", status_code=204)
119
119
  async def delete_project(
120
120
  project_id: int,
121
- user: UserOAuth = Depends(current_active_user),
121
+ user: UserOAuth = Depends(current_user_act_ver_prof),
122
122
  db: AsyncSession = Depends(get_async_db),
123
123
  ) -> Response:
124
124
  """
@@ -13,7 +13,7 @@ from ._aux_functions import _get_dataset_check_owner
13
13
  from ._aux_functions import _get_submitted_jobs_statement
14
14
  from ._aux_functions import _get_workflow_check_owner
15
15
  from fractal_server.app.models import UserOAuth
16
- from fractal_server.app.routes.auth import current_active_user
16
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
17
17
 
18
18
  router = APIRouter()
19
19
 
@@ -28,7 +28,7 @@ async def get_workflowtask_status(
28
28
  project_id: int,
29
29
  dataset_id: int,
30
30
  workflow_id: int,
31
- user: UserOAuth = Depends(current_active_user),
31
+ user: UserOAuth = Depends(current_user_act_ver_prof),
32
32
  db: AsyncSession = Depends(get_async_db),
33
33
  ) -> LegacyStatusReadV2 | None:
34
34
  """
@@ -17,16 +17,14 @@ from ._aux_functions import clean_app_job_list_v2
17
17
  from ._aux_functions_tasks import _check_type_filters_compatibility
18
18
  from fractal_server.app.db import AsyncSession
19
19
  from fractal_server.app.db import get_async_db
20
+ from fractal_server.app.models import Profile
20
21
  from fractal_server.app.models import TaskGroupV2
21
22
  from fractal_server.app.models import UserOAuth
22
23
  from fractal_server.app.models.v2 import JobV2
23
24
  from fractal_server.app.routes.api.v2._aux_functions_tasks import (
24
25
  _get_task_read_access,
25
26
  )
26
- from fractal_server.app.routes.auth import current_active_verified_user
27
- from fractal_server.app.routes.aux.validate_user_settings import (
28
- validate_user_settings,
29
- )
27
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
30
28
  from fractal_server.app.schemas.v2 import JobCreateV2
31
29
  from fractal_server.app.schemas.v2 import JobReadV2
32
30
  from fractal_server.app.schemas.v2 import JobStatusTypeV2
@@ -39,7 +37,7 @@ from fractal_server.runner.set_start_and_last_task_index import (
39
37
  from fractal_server.runner.v2.submit_workflow import submit_workflow
40
38
  from fractal_server.syringe import Inject
41
39
 
42
-
40
+ FRACTAL_CACHE_DIR = ".fractal_cache"
43
41
  router = APIRouter()
44
42
  logger = set_logger(__name__)
45
43
 
@@ -56,7 +54,7 @@ async def apply_workflow(
56
54
  job_create: JobCreateV2,
57
55
  background_tasks: BackgroundTasks,
58
56
  request: Request,
59
- user: UserOAuth = Depends(current_active_verified_user),
57
+ user: UserOAuth = Depends(current_user_act_ver_prof),
60
58
  db: AsyncSession = Depends(get_async_db),
61
59
  ) -> JobReadV2 | None:
62
60
  # Remove non-submitted V2 jobs from the app state when the list grows
@@ -80,6 +78,17 @@ async def apply_workflow(
80
78
  project = output["project"]
81
79
  dataset = output["dataset"]
82
80
 
81
+ # Verify that user's resource matches with project resource
82
+ res = await db.execute(
83
+ select(Profile.resource_id).where(Profile.id == user.profile_id)
84
+ )
85
+ user_resource_id = res.scalar_one()
86
+ if project.resource_id != user_resource_id:
87
+ raise HTTPException(
88
+ status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
89
+ detail="Project resource does not match with user's resource",
90
+ )
91
+
83
92
  workflow = await _get_workflow_check_owner(
84
93
  project_id=project_id, workflow_id=workflow_id, user_id=user.id, db=db
85
94
  )
@@ -129,10 +138,7 @@ async def apply_workflow(
129
138
  user=user,
130
139
  db=db,
131
140
  )
132
- # Validate user settings
133
- user_settings = await validate_user_settings(
134
- user=user, backend=resource.type, db=db
135
- )
141
+
136
142
  # Check that no other job with the same dataset_id is SUBMITTED
137
143
  stm = (
138
144
  select(JobV2)
@@ -150,7 +156,7 @@ async def apply_workflow(
150
156
  )
151
157
 
152
158
  if job_create.slurm_account is not None:
153
- if job_create.slurm_account not in user_settings.slurm_accounts:
159
+ if job_create.slurm_account not in user.slurm_accounts:
154
160
  raise HTTPException(
155
161
  status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
156
162
  detail=(
@@ -159,8 +165,8 @@ async def apply_workflow(
159
165
  ),
160
166
  )
161
167
  else:
162
- if len(user_settings.slurm_accounts) > 0:
163
- job_create.slurm_account = user_settings.slurm_accounts[0]
168
+ if len(user.slurm_accounts) > 0:
169
+ job_create.slurm_account = user.slurm_accounts[0]
164
170
 
165
171
  # User appropriate FractalSSH object
166
172
  if resource.type == ResourceType.SLURM_SSH:
@@ -190,10 +196,8 @@ async def apply_workflow(
190
196
  dataset_id=dataset_id,
191
197
  workflow_id=workflow_id,
192
198
  user_email=user.email,
193
- # The 'filters' field is not supported any more but still exists as a
194
- # database column, therefore we manually exclude it from dumps.
195
199
  dataset_dump=json.loads(
196
- dataset.model_dump_json(exclude={"images", "history", "filters"})
200
+ dataset.model_dump_json(exclude={"images", "history"})
197
201
  ),
198
202
  workflow_dump=json.loads(
199
203
  workflow.model_dump_json(exclude={"task_list"})
@@ -226,22 +230,17 @@ async def apply_workflow(
226
230
  )
227
231
 
228
232
  # Define user-side job directory
233
+ cache_dir = Path(user.project_dir, FRACTAL_CACHE_DIR)
229
234
  match resource.type:
230
235
  case ResourceType.LOCAL:
231
236
  WORKFLOW_DIR_REMOTE = WORKFLOW_DIR_LOCAL
232
- cache_dir = None
233
237
  case ResourceType.SLURM_SUDO:
234
- cache_dir = (
235
- Path(user_settings.project_dir) / ".fractal_cache"
236
- if user_settings.project_dir is not None
237
- else None
238
- )
239
238
  WORKFLOW_DIR_REMOTE = cache_dir / WORKFLOW_DIR_LOCAL.name
240
239
  case ResourceType.SLURM_SSH:
241
- WORKFLOW_DIR_REMOTE = (
242
- Path(profile.jobs_remote_dir) / WORKFLOW_DIR_LOCAL.name
240
+ WORKFLOW_DIR_REMOTE = Path(
241
+ profile.jobs_remote_dir,
242
+ WORKFLOW_DIR_LOCAL.name,
243
243
  )
244
- cache_dir = None
245
244
 
246
245
  # Update job folders in the db
247
246
  job.working_dir = WORKFLOW_DIR_LOCAL.as_posix()
@@ -249,9 +248,6 @@ async def apply_workflow(
249
248
  await db.merge(job)
250
249
  await db.commit()
251
250
 
252
- # Expunge user settings from db, to use in background task
253
- db.expunge(user_settings)
254
-
255
251
  background_tasks.add_task(
256
252
  submit_workflow,
257
253
  workflow_id=workflow.id,
@@ -259,7 +255,7 @@ async def apply_workflow(
259
255
  job_id=job.id,
260
256
  user_id=user.id,
261
257
  worker_init=job.worker_init,
262
- user_cache_dir=cache_dir.as_posix() if cache_dir else None,
258
+ user_cache_dir=cache_dir.as_posix(),
263
259
  fractal_ssh=fractal_ssh,
264
260
  resource=resource,
265
261
  profile=profile,
@@ -21,8 +21,7 @@ from fractal_server.app.models import LinkUserGroup
21
21
  from fractal_server.app.models import UserOAuth
22
22
  from fractal_server.app.models.v2 import TaskGroupV2
23
23
  from fractal_server.app.models.v2 import TaskV2
24
- from fractal_server.app.routes.auth import current_active_user
25
- from fractal_server.app.routes.auth import current_active_verified_user
24
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
26
25
  from fractal_server.app.schemas.v2 import TaskCreateV2
27
26
  from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
28
27
  from fractal_server.app.schemas.v2 import TaskReadV2
@@ -41,7 +40,7 @@ async def get_list_task(
41
40
  category: str | None = None,
42
41
  modality: str | None = None,
43
42
  author: str | None = None,
44
- user: UserOAuth = Depends(current_active_user),
43
+ user: UserOAuth = Depends(current_user_act_ver_prof),
45
44
  db: AsyncSession = Depends(get_async_db),
46
45
  ) -> list[TaskReadV2]:
47
46
  """
@@ -83,7 +82,7 @@ async def get_list_task(
83
82
  @router.get("/{task_id}/", response_model=TaskReadV2)
84
83
  async def get_task(
85
84
  task_id: int,
86
- user: UserOAuth = Depends(current_active_user),
85
+ user: UserOAuth = Depends(current_user_act_ver_prof),
87
86
  db: AsyncSession = Depends(get_async_db),
88
87
  ) -> TaskReadV2:
89
88
  """
@@ -97,7 +96,7 @@ async def get_task(
97
96
  async def patch_task(
98
97
  task_id: int,
99
98
  task_update: TaskUpdateV2,
100
- user: UserOAuth = Depends(current_active_verified_user),
99
+ user: UserOAuth = Depends(current_user_act_ver_prof),
101
100
  db: AsyncSession = Depends(get_async_db),
102
101
  ) -> TaskReadV2 | None:
103
102
  """
@@ -138,7 +137,7 @@ async def create_task(
138
137
  task: TaskCreateV2,
139
138
  user_group_id: int | None = None,
140
139
  private: bool = False,
141
- user: UserOAuth = Depends(current_active_verified_user),
140
+ user: UserOAuth = Depends(current_user_act_ver_prof),
142
141
  db: AsyncSession = Depends(get_async_db),
143
142
  ) -> TaskReadV2 | None:
144
143
  """
@@ -212,7 +211,7 @@ async def create_task(
212
211
  @router.delete("/{task_id}/", status_code=204)
213
212
  async def delete_task(
214
213
  task_id: int,
215
- user: UserOAuth = Depends(current_active_user),
214
+ user: UserOAuth = Depends(current_user_act_ver_prof),
216
215
  db: AsyncSession = Depends(get_async_db),
217
216
  ) -> Response:
218
217
  """
@@ -33,7 +33,7 @@ from ._aux_functions_tasks import _verify_non_duplication_group_path
33
33
  from ._aux_functions_tasks import _verify_non_duplication_user_constraint
34
34
  from fractal_server.app.models import UserOAuth
35
35
  from fractal_server.app.models.v2 import TaskGroupActivityV2
36
- from fractal_server.app.routes.auth import current_active_verified_user
36
+ from fractal_server.app.routes.auth import current_user_act_ver_prof
37
37
  from fractal_server.app.schemas.v2 import ResourceType
38
38
  from fractal_server.app.schemas.v2 import (
39
39
  TaskGroupActivityActionV2,
@@ -161,7 +161,7 @@ async def collect_tasks_pip(
161
161
  request_data: CollectionRequestData = Depends(parse_request_data),
162
162
  private: bool = False,
163
163
  user_group_id: int | None = None,
164
- user: UserOAuth = Depends(current_active_verified_user),
164
+ user: UserOAuth = Depends(current_user_act_ver_prof),
165
165
  db: AsyncSession = Depends(get_async_db),
166
166
  ) -> TaskGroupActivityV2Read:
167
167
  """
@@ -183,6 +183,7 @@ async def collect_tasks_pip(
183
183
  # Initialize task-group attributes
184
184
  task_group_attrs = dict(
185
185
  user_id=user.id,
186
+ resource_id=resource_id,
186
187
  origin=request_data.origin,
187
188
  )
188
189
 
@@ -320,7 +321,7 @@ async def collect_tasks_pip(
320
321
  )
321
322
 
322
323
  # Create TaskGroupV2 object
323
- task_group = TaskGroupV2(**task_group_attrs, resource_id=resource_id)
324
+ task_group = TaskGroupV2(**task_group_attrs)
324
325
  db.add(task_group)
325
326
  await db.commit()
326
327
  await db.refresh(task_group)