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.
- fractal_server/__init__.py +1 -1
- fractal_server/__main__.py +22 -26
- fractal_server/app/models/security.py +19 -21
- fractal_server/app/models/user_settings.py +1 -0
- fractal_server/app/models/v2/task_group.py +1 -0
- fractal_server/app/routes/admin/v2/accounting.py +3 -3
- fractal_server/app/routes/admin/v2/impersonate.py +2 -2
- fractal_server/app/routes/admin/v2/job.py +6 -6
- fractal_server/app/routes/admin/v2/profile.py +18 -4
- fractal_server/app/routes/admin/v2/project.py +2 -2
- fractal_server/app/routes/admin/v2/resource.py +8 -8
- fractal_server/app/routes/admin/v2/task.py +11 -2
- fractal_server/app/routes/admin/v2/task_group.py +16 -12
- fractal_server/app/routes/admin/v2/task_group_lifecycle.py +4 -4
- fractal_server/app/routes/api/__init__.py +14 -5
- fractal_server/app/routes/api/v2/dataset.py +10 -19
- fractal_server/app/routes/api/v2/history.py +8 -8
- fractal_server/app/routes/api/v2/images.py +5 -5
- fractal_server/app/routes/api/v2/job.py +8 -8
- fractal_server/app/routes/api/v2/pre_submission_checks.py +3 -3
- fractal_server/app/routes/api/v2/project.py +6 -6
- fractal_server/app/routes/api/v2/status_legacy.py +2 -2
- fractal_server/app/routes/api/v2/submit.py +25 -29
- fractal_server/app/routes/api/v2/task.py +6 -7
- fractal_server/app/routes/api/v2/task_collection.py +4 -3
- fractal_server/app/routes/api/v2/task_collection_custom.py +4 -3
- fractal_server/app/routes/api/v2/task_collection_pixi.py +2 -2
- fractal_server/app/routes/api/v2/task_group.py +6 -6
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +4 -4
- fractal_server/app/routes/api/v2/task_version_update.py +3 -3
- fractal_server/app/routes/api/v2/workflow.py +9 -9
- fractal_server/app/routes/api/v2/workflow_import.py +2 -2
- fractal_server/app/routes/api/v2/workflowtask.py +5 -5
- fractal_server/app/routes/auth/__init__.py +34 -5
- fractal_server/app/routes/auth/current_user.py +22 -72
- fractal_server/app/routes/auth/group.py +8 -35
- fractal_server/app/routes/auth/oauth.py +1 -1
- fractal_server/app/routes/auth/register.py +2 -2
- fractal_server/app/routes/auth/users.py +6 -48
- fractal_server/app/schemas/__init__.py +0 -1
- fractal_server/app/schemas/user.py +23 -0
- fractal_server/app/schemas/v2/__init__.py +1 -0
- fractal_server/app/schemas/v2/task_group.py +5 -0
- fractal_server/app/security/__init__.py +134 -46
- fractal_server/app/security/signup_email.py +52 -34
- fractal_server/config/__init__.py +6 -0
- fractal_server/config/_data.py +68 -0
- fractal_server/config/_email.py +10 -47
- fractal_server/config/_main.py +3 -56
- fractal_server/config/_oauth.py +2 -2
- fractal_server/main.py +3 -2
- fractal_server/migrations/versions/f65ee53991e3_user_settings_related.py +67 -0
- fractal_server/runner/executors/slurm_common/base_slurm_runner.py +1 -1
- fractal_server/runner/executors/slurm_common/slurm_config.py +5 -8
- fractal_server/runner/executors/slurm_ssh/runner.py +1 -1
- fractal_server/runner/executors/slurm_sudo/runner.py +1 -1
- fractal_server/runner/v2/_slurm_ssh.py +2 -1
- fractal_server/runner/v2/_slurm_sudo.py +1 -1
- fractal_server/runner/v2/submit_workflow.py +12 -12
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/METADATA +4 -6
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/RECORD +64 -65
- fractal_server/app/routes/aux/validate_user_settings.py +0 -76
- fractal_server/app/schemas/user_settings.py +0 -63
- fractal_server/app/user_settings.py +0 -32
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/WHEEL +0 -0
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/entry_points.txt +0 -0
- {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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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.
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
|
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(
|
|
163
|
-
job_create.slurm_account =
|
|
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"
|
|
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
|
-
|
|
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()
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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)
|