fractal-server 2.18.6__py3-none-any.whl → 2.19.0a0__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/app/models/security.py +16 -0
- fractal_server/app/routes/admin/v2/sharing.py +47 -0
- fractal_server/app/routes/api/__init__.py +4 -52
- fractal_server/app/routes/api/alive.py +13 -0
- fractal_server/app/routes/api/settings.py +44 -0
- fractal_server/app/routes/api/v2/dataset.py +9 -8
- fractal_server/app/routes/api/v2/history.py +8 -8
- fractal_server/app/routes/api/v2/images.py +6 -5
- fractal_server/app/routes/api/v2/job.py +10 -9
- fractal_server/app/routes/api/v2/pre_submission_checks.py +3 -3
- fractal_server/app/routes/api/v2/project.py +7 -6
- fractal_server/app/routes/api/v2/sharing.py +17 -9
- fractal_server/app/routes/api/v2/status_legacy.py +2 -2
- fractal_server/app/routes/api/v2/submit.py +2 -2
- fractal_server/app/routes/api/v2/task.py +7 -6
- fractal_server/app/routes/api/v2/task_collection.py +2 -2
- fractal_server/app/routes/api/v2/task_collection_custom.py +2 -2
- fractal_server/app/routes/api/v2/task_collection_pixi.py +2 -2
- fractal_server/app/routes/api/v2/task_group.py +7 -6
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +4 -4
- fractal_server/app/routes/api/v2/task_version_update.py +4 -3
- fractal_server/app/routes/api/v2/workflow.py +9 -8
- fractal_server/app/routes/api/v2/workflow_import.py +2 -2
- fractal_server/app/routes/api/v2/workflowtask.py +6 -5
- fractal_server/app/routes/auth/__init__.py +18 -1
- fractal_server/app/routes/auth/users.py +11 -0
- fractal_server/app/schemas/user.py +7 -0
- fractal_server/migrations/versions/e53dc51fdf93_add_useroauth_is_guest.py +36 -0
- {fractal_server-2.18.6.dist-info → fractal_server-2.19.0a0.dist-info}/METADATA +1 -1
- {fractal_server-2.18.6.dist-info → fractal_server-2.19.0a0.dist-info}/RECORD +34 -31
- {fractal_server-2.18.6.dist-info → fractal_server-2.19.0a0.dist-info}/WHEEL +0 -0
- {fractal_server-2.18.6.dist-info → fractal_server-2.19.0a0.dist-info}/entry_points.txt +0 -0
- {fractal_server-2.18.6.dist-info → fractal_server-2.19.0a0.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,7 +5,7 @@ from fractal_server.app.db import AsyncSession
|
|
|
5
5
|
from fractal_server.app.db import get_async_db
|
|
6
6
|
from fractal_server.app.models import UserOAuth
|
|
7
7
|
from fractal_server.app.models.v2 import JobV2
|
|
8
|
-
from fractal_server.app.routes.auth import
|
|
8
|
+
from fractal_server.app.routes.auth import get_api_guest
|
|
9
9
|
from fractal_server.app.schemas.v2.sharing import ProjectPermissions
|
|
10
10
|
from fractal_server.app.schemas.v2.status_legacy import LegacyStatusRead
|
|
11
11
|
from fractal_server.app.schemas.v2.status_legacy import WorkflowTaskStatusType
|
|
@@ -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(get_api_guest),
|
|
32
32
|
db: AsyncSession = Depends(get_async_db),
|
|
33
33
|
) -> LegacyStatusRead | None:
|
|
34
34
|
"""
|
|
@@ -20,7 +20,7 @@ from fractal_server.app.models.v2 import JobV2
|
|
|
20
20
|
from fractal_server.app.routes.api.v2._aux_functions_tasks import (
|
|
21
21
|
_get_task_read_access,
|
|
22
22
|
)
|
|
23
|
-
from fractal_server.app.routes.auth import
|
|
23
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
24
24
|
from fractal_server.app.routes.aux.validate_user_profile import (
|
|
25
25
|
validate_user_profile,
|
|
26
26
|
)
|
|
@@ -59,7 +59,7 @@ async def submit_job(
|
|
|
59
59
|
job_create: JobCreate,
|
|
60
60
|
background_tasks: BackgroundTasks,
|
|
61
61
|
request: Request,
|
|
62
|
-
user: UserOAuth = Depends(
|
|
62
|
+
user: UserOAuth = Depends(get_api_user),
|
|
63
63
|
db: AsyncSession = Depends(get_async_db),
|
|
64
64
|
) -> JobRead | None:
|
|
65
65
|
# Remove non-submitted Jobs from the app state when the list grows
|
|
@@ -24,7 +24,8 @@ from fractal_server.app.models import LinkUserGroup
|
|
|
24
24
|
from fractal_server.app.models import UserOAuth
|
|
25
25
|
from fractal_server.app.models.v2 import TaskGroupV2
|
|
26
26
|
from fractal_server.app.models.v2 import TaskV2
|
|
27
|
-
from fractal_server.app.routes.auth import
|
|
27
|
+
from fractal_server.app.routes.auth import get_api_guest
|
|
28
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
28
29
|
from fractal_server.app.schemas.v2 import TaskCreate
|
|
29
30
|
from fractal_server.app.schemas.v2 import TaskGroupOriginEnum
|
|
30
31
|
from fractal_server.app.schemas.v2 import TaskRead
|
|
@@ -43,7 +44,7 @@ async def get_list_task(
|
|
|
43
44
|
category: str | None = None,
|
|
44
45
|
modality: str | None = None,
|
|
45
46
|
author: str | None = None,
|
|
46
|
-
user: UserOAuth = Depends(
|
|
47
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
47
48
|
db: AsyncSession = Depends(get_async_db),
|
|
48
49
|
) -> list[TaskRead]:
|
|
49
50
|
"""
|
|
@@ -88,7 +89,7 @@ async def get_list_task(
|
|
|
88
89
|
@router.get("/{task_id}/", response_model=TaskRead)
|
|
89
90
|
async def get_task(
|
|
90
91
|
task_id: int,
|
|
91
|
-
user: UserOAuth = Depends(
|
|
92
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
92
93
|
db: AsyncSession = Depends(get_async_db),
|
|
93
94
|
) -> TaskRead:
|
|
94
95
|
"""
|
|
@@ -102,7 +103,7 @@ async def get_task(
|
|
|
102
103
|
async def patch_task(
|
|
103
104
|
task_id: int,
|
|
104
105
|
task_update: TaskUpdate,
|
|
105
|
-
user: UserOAuth = Depends(
|
|
106
|
+
user: UserOAuth = Depends(get_api_user),
|
|
106
107
|
db: AsyncSession = Depends(get_async_db),
|
|
107
108
|
) -> TaskRead | None:
|
|
108
109
|
"""
|
|
@@ -140,7 +141,7 @@ async def create_task(
|
|
|
140
141
|
task: TaskCreate,
|
|
141
142
|
user_group_id: int | None = None,
|
|
142
143
|
private: bool = False,
|
|
143
|
-
user: UserOAuth = Depends(
|
|
144
|
+
user: UserOAuth = Depends(get_api_user),
|
|
144
145
|
db: AsyncSession = Depends(get_async_db),
|
|
145
146
|
) -> TaskRead | None:
|
|
146
147
|
"""
|
|
@@ -221,7 +222,7 @@ async def create_task(
|
|
|
221
222
|
@router.delete("/{task_id}/", status_code=204)
|
|
222
223
|
async def delete_task(
|
|
223
224
|
task_id: int,
|
|
224
|
-
user: UserOAuth = Depends(
|
|
225
|
+
user: UserOAuth = Depends(get_api_user),
|
|
225
226
|
db: AsyncSession = Depends(get_async_db),
|
|
226
227
|
) -> Response:
|
|
227
228
|
"""
|
|
@@ -19,7 +19,7 @@ from fractal_server.app.db import get_async_db
|
|
|
19
19
|
from fractal_server.app.models import UserOAuth
|
|
20
20
|
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
|
21
21
|
from fractal_server.app.models.v2 import TaskGroupV2
|
|
22
|
-
from fractal_server.app.routes.auth import
|
|
22
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
23
23
|
from fractal_server.app.routes.aux.validate_user_profile import (
|
|
24
24
|
validate_user_profile,
|
|
25
25
|
)
|
|
@@ -158,7 +158,7 @@ async def collect_tasks_pip(
|
|
|
158
158
|
request_data: CollectionRequestData = Depends(parse_request_data),
|
|
159
159
|
private: bool = False,
|
|
160
160
|
user_group_id: int | None = None,
|
|
161
|
-
user: UserOAuth = Depends(
|
|
161
|
+
user: UserOAuth = Depends(get_api_user),
|
|
162
162
|
db: AsyncSession = Depends(get_async_db),
|
|
163
163
|
) -> TaskGroupActivityRead:
|
|
164
164
|
"""
|
|
@@ -12,7 +12,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
12
12
|
from fractal_server.app.db import get_async_db
|
|
13
13
|
from fractal_server.app.models import UserOAuth
|
|
14
14
|
from fractal_server.app.models.v2 import TaskGroupV2
|
|
15
|
-
from fractal_server.app.routes.auth import
|
|
15
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
16
16
|
from fractal_server.app.routes.aux.validate_user_profile import (
|
|
17
17
|
validate_user_profile,
|
|
18
18
|
)
|
|
@@ -43,7 +43,7 @@ async def collect_task_custom(
|
|
|
43
43
|
task_collect: TaskCollectCustom,
|
|
44
44
|
private: bool = False,
|
|
45
45
|
user_group_id: int | None = None,
|
|
46
|
-
user: UserOAuth = Depends(
|
|
46
|
+
user: UserOAuth = Depends(get_api_user),
|
|
47
47
|
db: AsyncSession = Depends(get_async_db),
|
|
48
48
|
) -> list[TaskRead]:
|
|
49
49
|
# Get validated resource and profile
|
|
@@ -27,7 +27,7 @@ from fractal_server.app.routes.api.v2._aux_functions_tasks import (
|
|
|
27
27
|
from fractal_server.app.routes.api.v2._aux_functions_tasks import (
|
|
28
28
|
_verify_non_duplication_user_constraint,
|
|
29
29
|
)
|
|
30
|
-
from fractal_server.app.routes.auth import
|
|
30
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
31
31
|
from fractal_server.app.routes.aux.validate_user_profile import (
|
|
32
32
|
validate_user_profile,
|
|
33
33
|
)
|
|
@@ -83,7 +83,7 @@ async def collect_task_pixi(
|
|
|
83
83
|
pixi_version: NonEmptyStr | None = Form(None),
|
|
84
84
|
private: bool = False,
|
|
85
85
|
user_group_id: int | None = None,
|
|
86
|
-
user: UserOAuth = Depends(
|
|
86
|
+
user: UserOAuth = Depends(get_api_user),
|
|
87
87
|
db: AsyncSession = Depends(get_async_db),
|
|
88
88
|
) -> TaskGroupActivityRead:
|
|
89
89
|
# Get validated resource and profile
|
|
@@ -17,7 +17,8 @@ from fractal_server.app.models import LinkUserGroup
|
|
|
17
17
|
from fractal_server.app.models import UserOAuth
|
|
18
18
|
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
|
19
19
|
from fractal_server.app.models.v2 import TaskGroupV2
|
|
20
|
-
from fractal_server.app.routes.auth import
|
|
20
|
+
from fractal_server.app.routes.auth import get_api_guest
|
|
21
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
21
22
|
from fractal_server.app.routes.auth._aux_auth import (
|
|
22
23
|
_get_default_usergroup_id_or_none,
|
|
23
24
|
)
|
|
@@ -70,7 +71,7 @@ async def get_task_group_activity_list(
|
|
|
70
71
|
status: TaskGroupActivityStatus | None = None,
|
|
71
72
|
action: TaskGroupActivityAction | None = None,
|
|
72
73
|
timestamp_started_min: AwareDatetime | None = None,
|
|
73
|
-
user: UserOAuth = Depends(
|
|
74
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
74
75
|
db: AsyncSession = Depends(get_async_db),
|
|
75
76
|
) -> list[TaskGroupActivityRead]:
|
|
76
77
|
stm = select(TaskGroupActivityV2).where(
|
|
@@ -102,7 +103,7 @@ async def get_task_group_activity_list(
|
|
|
102
103
|
)
|
|
103
104
|
async def get_task_group_activity(
|
|
104
105
|
task_group_activity_id: int,
|
|
105
|
-
user: UserOAuth = Depends(
|
|
106
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
106
107
|
db: AsyncSession = Depends(get_async_db),
|
|
107
108
|
) -> TaskGroupActivityRead:
|
|
108
109
|
activity = await db.get(TaskGroupActivityV2, task_group_activity_id)
|
|
@@ -126,7 +127,7 @@ async def get_task_group_activity(
|
|
|
126
127
|
|
|
127
128
|
@router.get("/", response_model=list[tuple[str, list[TaskGroupRead]]])
|
|
128
129
|
async def get_task_group_list(
|
|
129
|
-
user: UserOAuth = Depends(
|
|
130
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
130
131
|
db: AsyncSession = Depends(get_async_db),
|
|
131
132
|
only_active: bool = False,
|
|
132
133
|
only_owner: bool = False,
|
|
@@ -194,7 +195,7 @@ async def get_task_group_list(
|
|
|
194
195
|
@router.get("/{task_group_id}/", response_model=TaskGroupRead)
|
|
195
196
|
async def get_task_group(
|
|
196
197
|
task_group_id: int,
|
|
197
|
-
user: UserOAuth = Depends(
|
|
198
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
198
199
|
db: AsyncSession = Depends(get_async_db),
|
|
199
200
|
) -> TaskGroupRead:
|
|
200
201
|
"""
|
|
@@ -212,7 +213,7 @@ async def get_task_group(
|
|
|
212
213
|
async def patch_task_group(
|
|
213
214
|
task_group_id: int,
|
|
214
215
|
task_group_update: TaskGroupUpdate,
|
|
215
|
-
user: UserOAuth = Depends(
|
|
216
|
+
user: UserOAuth = Depends(get_api_user),
|
|
216
217
|
db: AsyncSession = Depends(get_async_db),
|
|
217
218
|
) -> TaskGroupRead:
|
|
218
219
|
"""
|
|
@@ -9,7 +9,7 @@ from fractal_server.app.db import AsyncSession
|
|
|
9
9
|
from fractal_server.app.db import get_async_db
|
|
10
10
|
from fractal_server.app.models import UserOAuth
|
|
11
11
|
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
|
12
|
-
from fractal_server.app.routes.auth import
|
|
12
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
13
13
|
from fractal_server.app.routes.aux.validate_user_profile import (
|
|
14
14
|
validate_user_profile,
|
|
15
15
|
)
|
|
@@ -51,7 +51,7 @@ async def deactivate_task_group(
|
|
|
51
51
|
task_group_id: int,
|
|
52
52
|
background_tasks: BackgroundTasks,
|
|
53
53
|
response: Response,
|
|
54
|
-
user: UserOAuth = Depends(
|
|
54
|
+
user: UserOAuth = Depends(get_api_user),
|
|
55
55
|
db: AsyncSession = Depends(get_async_db),
|
|
56
56
|
) -> TaskGroupActivityRead:
|
|
57
57
|
"""
|
|
@@ -155,7 +155,7 @@ async def reactivate_task_group(
|
|
|
155
155
|
task_group_id: int,
|
|
156
156
|
background_tasks: BackgroundTasks,
|
|
157
157
|
response: Response,
|
|
158
|
-
user: UserOAuth = Depends(
|
|
158
|
+
user: UserOAuth = Depends(get_api_user),
|
|
159
159
|
db: AsyncSession = Depends(get_async_db),
|
|
160
160
|
) -> TaskGroupRead:
|
|
161
161
|
"""
|
|
@@ -263,7 +263,7 @@ async def delete_task_group(
|
|
|
263
263
|
task_group_id: int,
|
|
264
264
|
background_tasks: BackgroundTasks,
|
|
265
265
|
response: Response,
|
|
266
|
-
user: UserOAuth = Depends(
|
|
266
|
+
user: UserOAuth = Depends(get_api_user),
|
|
267
267
|
db: AsyncSession = Depends(get_async_db),
|
|
268
268
|
) -> TaskGroupActivityRead:
|
|
269
269
|
"""
|
|
@@ -17,7 +17,8 @@ from fractal_server.app.models import LinkUserGroup
|
|
|
17
17
|
from fractal_server.app.models import UserOAuth
|
|
18
18
|
from fractal_server.app.models.v2 import TaskGroupV2
|
|
19
19
|
from fractal_server.app.models.v2 import TaskV2
|
|
20
|
-
from fractal_server.app.routes.auth import
|
|
20
|
+
from fractal_server.app.routes.auth import get_api_guest
|
|
21
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
21
22
|
from fractal_server.app.schemas.v2 import TaskType
|
|
22
23
|
from fractal_server.app.schemas.v2 import WorkflowTaskRead
|
|
23
24
|
from fractal_server.app.schemas.v2 import WorkflowTaskReplace
|
|
@@ -77,7 +78,7 @@ class TaskVersionRead(BaseModel):
|
|
|
77
78
|
async def get_workflow_version_update_candidates(
|
|
78
79
|
project_id: int,
|
|
79
80
|
workflow_id: int,
|
|
80
|
-
user: UserOAuth = Depends(
|
|
81
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
81
82
|
db: AsyncSession = Depends(get_async_db),
|
|
82
83
|
) -> list[list[TaskVersionRead]]:
|
|
83
84
|
workflow = await _get_workflow_check_access(
|
|
@@ -180,7 +181,7 @@ async def replace_workflowtask(
|
|
|
180
181
|
workflow_task_id: int,
|
|
181
182
|
task_id: int,
|
|
182
183
|
replace: WorkflowTaskReplace,
|
|
183
|
-
user: UserOAuth = Depends(
|
|
184
|
+
user: UserOAuth = Depends(get_api_user),
|
|
184
185
|
db: AsyncSession = Depends(get_async_db),
|
|
185
186
|
) -> WorkflowTaskRead:
|
|
186
187
|
# Get objects from database
|
|
@@ -14,7 +14,8 @@ from fractal_server.app.models import UserOAuth
|
|
|
14
14
|
from fractal_server.app.models.v2 import JobV2
|
|
15
15
|
from fractal_server.app.models.v2 import TaskGroupV2
|
|
16
16
|
from fractal_server.app.models.v2 import WorkflowV2
|
|
17
|
-
from fractal_server.app.routes.auth import
|
|
17
|
+
from fractal_server.app.routes.auth import get_api_guest
|
|
18
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
18
19
|
from fractal_server.app.schemas.v2 import WorkflowCreate
|
|
19
20
|
from fractal_server.app.schemas.v2 import WorkflowExport
|
|
20
21
|
from fractal_server.app.schemas.v2 import WorkflowRead
|
|
@@ -39,7 +40,7 @@ router = APIRouter()
|
|
|
39
40
|
)
|
|
40
41
|
async def get_workflow_list(
|
|
41
42
|
project_id: int,
|
|
42
|
-
user: UserOAuth = Depends(
|
|
43
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
43
44
|
db: AsyncSession = Depends(get_async_db),
|
|
44
45
|
) -> list[WorkflowRead] | None:
|
|
45
46
|
"""
|
|
@@ -69,7 +70,7 @@ async def get_workflow_list(
|
|
|
69
70
|
async def create_workflow(
|
|
70
71
|
project_id: int,
|
|
71
72
|
workflow: WorkflowCreate,
|
|
72
|
-
user: UserOAuth = Depends(
|
|
73
|
+
user: UserOAuth = Depends(get_api_user),
|
|
73
74
|
db: AsyncSession = Depends(get_async_db),
|
|
74
75
|
) -> WorkflowRead | None:
|
|
75
76
|
"""
|
|
@@ -99,7 +100,7 @@ async def create_workflow(
|
|
|
99
100
|
async def read_workflow(
|
|
100
101
|
project_id: int,
|
|
101
102
|
workflow_id: int,
|
|
102
|
-
user: UserOAuth = Depends(
|
|
103
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
103
104
|
db: AsyncSession = Depends(get_async_db),
|
|
104
105
|
) -> WorkflowReadWithWarnings | None:
|
|
105
106
|
"""
|
|
@@ -134,7 +135,7 @@ async def update_workflow(
|
|
|
134
135
|
project_id: int,
|
|
135
136
|
workflow_id: int,
|
|
136
137
|
patch: WorkflowUpdate,
|
|
137
|
-
user: UserOAuth = Depends(
|
|
138
|
+
user: UserOAuth = Depends(get_api_user),
|
|
138
139
|
db: AsyncSession = Depends(get_async_db),
|
|
139
140
|
) -> WorkflowReadWithWarnings | None:
|
|
140
141
|
"""
|
|
@@ -208,7 +209,7 @@ async def update_workflow(
|
|
|
208
209
|
async def delete_workflow(
|
|
209
210
|
project_id: int,
|
|
210
211
|
workflow_id: int,
|
|
211
|
-
user: UserOAuth = Depends(
|
|
212
|
+
user: UserOAuth = Depends(get_api_user),
|
|
212
213
|
db: AsyncSession = Depends(get_async_db),
|
|
213
214
|
) -> Response:
|
|
214
215
|
"""
|
|
@@ -254,7 +255,7 @@ async def delete_workflow(
|
|
|
254
255
|
async def export_workflow(
|
|
255
256
|
project_id: int,
|
|
256
257
|
workflow_id: int,
|
|
257
|
-
user: UserOAuth = Depends(
|
|
258
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
258
259
|
db: AsyncSession = Depends(get_async_db),
|
|
259
260
|
) -> WorkflowExport | None:
|
|
260
261
|
"""
|
|
@@ -295,7 +296,7 @@ class WorkflowTaskTypeFiltersInfo(BaseModel):
|
|
|
295
296
|
async def get_workflow_type_filters(
|
|
296
297
|
project_id: int,
|
|
297
298
|
workflow_id: int,
|
|
298
|
-
user: UserOAuth = Depends(
|
|
299
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
299
300
|
db: AsyncSession = Depends(get_async_db),
|
|
300
301
|
) -> list[WorkflowTaskTypeFiltersInfo]:
|
|
301
302
|
"""
|
|
@@ -15,7 +15,7 @@ from fractal_server.app.models.v2 import WorkflowV2
|
|
|
15
15
|
from fractal_server.app.routes.api.v2._aux_task_group_disambiguation import (
|
|
16
16
|
_disambiguate_task_groups,
|
|
17
17
|
)
|
|
18
|
-
from fractal_server.app.routes.auth import
|
|
18
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
19
19
|
from fractal_server.app.routes.auth._aux_auth import (
|
|
20
20
|
_get_default_usergroup_id_or_none,
|
|
21
21
|
)
|
|
@@ -213,7 +213,7 @@ async def _get_task_by_taskimport(
|
|
|
213
213
|
async def import_workflow(
|
|
214
214
|
project_id: int,
|
|
215
215
|
workflow_import: WorkflowImport,
|
|
216
|
-
user: UserOAuth = Depends(
|
|
216
|
+
user: UserOAuth = Depends(get_api_user),
|
|
217
217
|
db: AsyncSession = Depends(get_async_db),
|
|
218
218
|
) -> WorkflowReadWithWarnings:
|
|
219
219
|
"""
|
|
@@ -9,7 +9,8 @@ from fastapi import status
|
|
|
9
9
|
from fractal_server.app.db import AsyncSession
|
|
10
10
|
from fractal_server.app.db import get_async_db
|
|
11
11
|
from fractal_server.app.models import UserOAuth
|
|
12
|
-
from fractal_server.app.routes.auth import
|
|
12
|
+
from fractal_server.app.routes.auth import get_api_guest
|
|
13
|
+
from fractal_server.app.routes.auth import get_api_user
|
|
13
14
|
from fractal_server.app.schemas.v2 import TaskType
|
|
14
15
|
from fractal_server.app.schemas.v2 import WorkflowTaskCreate
|
|
15
16
|
from fractal_server.app.schemas.v2 import WorkflowTaskRead
|
|
@@ -36,7 +37,7 @@ async def create_workflowtask(
|
|
|
36
37
|
workflow_id: int,
|
|
37
38
|
task_id: int,
|
|
38
39
|
wftask: WorkflowTaskCreate,
|
|
39
|
-
user: UserOAuth = Depends(
|
|
40
|
+
user: UserOAuth = Depends(get_api_user),
|
|
40
41
|
db: AsyncSession = Depends(get_async_db),
|
|
41
42
|
) -> WorkflowTaskRead | None:
|
|
42
43
|
"""
|
|
@@ -106,7 +107,7 @@ async def read_workflowtask(
|
|
|
106
107
|
project_id: int,
|
|
107
108
|
workflow_id: int,
|
|
108
109
|
workflow_task_id: int,
|
|
109
|
-
user: UserOAuth = Depends(
|
|
110
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
110
111
|
db: AsyncSession = Depends(get_async_db),
|
|
111
112
|
):
|
|
112
113
|
workflow_task, _ = await _get_workflow_task_check_access(
|
|
@@ -129,7 +130,7 @@ async def update_workflowtask(
|
|
|
129
130
|
workflow_id: int,
|
|
130
131
|
workflow_task_id: int,
|
|
131
132
|
workflow_task_update: WorkflowTaskUpdate,
|
|
132
|
-
user: UserOAuth = Depends(
|
|
133
|
+
user: UserOAuth = Depends(get_api_user),
|
|
133
134
|
db: AsyncSession = Depends(get_async_db),
|
|
134
135
|
) -> WorkflowTaskRead | None:
|
|
135
136
|
"""
|
|
@@ -214,7 +215,7 @@ async def delete_workflowtask(
|
|
|
214
215
|
project_id: int,
|
|
215
216
|
workflow_id: int,
|
|
216
217
|
workflow_task_id: int,
|
|
217
|
-
user: UserOAuth = Depends(
|
|
218
|
+
user: UserOAuth = Depends(get_api_user),
|
|
218
219
|
db: AsyncSession = Depends(get_async_db),
|
|
219
220
|
) -> Response:
|
|
220
221
|
"""
|
|
@@ -57,7 +57,7 @@ current_user_act_ver = fastapi_users.current_user(
|
|
|
57
57
|
)
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
async def
|
|
60
|
+
async def get_api_guest(
|
|
61
61
|
user: UserOAuth = Depends(current_user_act_ver),
|
|
62
62
|
) -> UserOAuth:
|
|
63
63
|
"""
|
|
@@ -76,6 +76,23 @@ async def current_user_act_ver_prof(
|
|
|
76
76
|
return user
|
|
77
77
|
|
|
78
78
|
|
|
79
|
+
async def get_api_user(
|
|
80
|
+
user: UserOAuth = Depends(get_api_guest),
|
|
81
|
+
) -> UserOAuth:
|
|
82
|
+
"""
|
|
83
|
+
Require a active&verified non-guest user, with a non-null `profile_id`.
|
|
84
|
+
|
|
85
|
+
Raises 401 if user does not exist or is not active.
|
|
86
|
+
Raises 403 if user is not verified, is a guest or has null `profile_id`.
|
|
87
|
+
"""
|
|
88
|
+
if user.is_guest:
|
|
89
|
+
raise HTTPException(
|
|
90
|
+
status_code=status.HTTP_403_FORBIDDEN,
|
|
91
|
+
detail="This feature is not available for guest users.",
|
|
92
|
+
)
|
|
93
|
+
return user
|
|
94
|
+
|
|
95
|
+
|
|
79
96
|
current_superuser_act = fastapi_users.current_user(
|
|
80
97
|
active=True,
|
|
81
98
|
superuser=True,
|
|
@@ -83,6 +83,17 @@ async def patch_user(
|
|
|
83
83
|
db=db,
|
|
84
84
|
)
|
|
85
85
|
|
|
86
|
+
will_be_superuser = (
|
|
87
|
+
user_update.is_superuser
|
|
88
|
+
if user_update.is_superuser is not None
|
|
89
|
+
else user_to_patch.is_superuser
|
|
90
|
+
)
|
|
91
|
+
if user_update.is_guest and will_be_superuser:
|
|
92
|
+
raise HTTPException(
|
|
93
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
94
|
+
detail="Superuser cannot be guest.",
|
|
95
|
+
)
|
|
96
|
+
|
|
86
97
|
# Modify user attributes
|
|
87
98
|
try:
|
|
88
99
|
user = await user_manager.update(
|
|
@@ -41,13 +41,16 @@ class UserRead(schemas.BaseUser[int]):
|
|
|
41
41
|
Schema for `User` read from database.
|
|
42
42
|
|
|
43
43
|
Attributes:
|
|
44
|
+
is_guest:
|
|
44
45
|
group_ids_names:
|
|
45
46
|
oauth_accounts:
|
|
46
47
|
profile_id:
|
|
47
48
|
project_dirs:
|
|
48
49
|
slurm_accounts:
|
|
50
|
+
|
|
49
51
|
"""
|
|
50
52
|
|
|
53
|
+
is_guest: bool
|
|
51
54
|
group_ids_names: list[tuple[int, str]] | None = None
|
|
52
55
|
oauth_accounts: list[OAuthAccountRead]
|
|
53
56
|
profile_id: int | None = None
|
|
@@ -65,6 +68,7 @@ class UserUpdate(schemas.BaseUserUpdate):
|
|
|
65
68
|
is_active:
|
|
66
69
|
is_superuser:
|
|
67
70
|
is_verified:
|
|
71
|
+
is_guest:
|
|
68
72
|
profile_id:
|
|
69
73
|
project_dirs:
|
|
70
74
|
slurm_accounts:
|
|
@@ -76,6 +80,7 @@ class UserUpdate(schemas.BaseUserUpdate):
|
|
|
76
80
|
is_active: bool = None
|
|
77
81
|
is_superuser: bool = None
|
|
78
82
|
is_verified: bool = None
|
|
83
|
+
is_guest: bool = None
|
|
79
84
|
profile_id: int | None = None
|
|
80
85
|
project_dirs: Annotated[
|
|
81
86
|
ListUniqueAbsolutePathStr, AfterValidator(_validate_cmd_list)
|
|
@@ -100,11 +105,13 @@ class UserCreate(schemas.BaseUserCreate):
|
|
|
100
105
|
Schema for `User` creation.
|
|
101
106
|
|
|
102
107
|
Attributes:
|
|
108
|
+
is_guest:
|
|
103
109
|
profile_id:
|
|
104
110
|
project_dirs:
|
|
105
111
|
slurm_accounts:
|
|
106
112
|
"""
|
|
107
113
|
|
|
114
|
+
is_guest: bool = False
|
|
108
115
|
profile_id: int | None = None
|
|
109
116
|
project_dirs: Annotated[
|
|
110
117
|
ListUniqueAbsolutePathStr, AfterValidator(_validate_cmd_list)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""add UserOAuth.is_guest
|
|
2
|
+
|
|
3
|
+
Revision ID: e53dc51fdf93
|
|
4
|
+
Revises: 068496367952
|
|
5
|
+
Create Date: 2026-01-14 14:32:25.044504
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sqlalchemy as sa
|
|
10
|
+
from alembic import op
|
|
11
|
+
|
|
12
|
+
# revision identifiers, used by Alembic.
|
|
13
|
+
revision = "e53dc51fdf93"
|
|
14
|
+
down_revision = "068496367952"
|
|
15
|
+
branch_labels = None
|
|
16
|
+
depends_on = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
21
|
+
with op.batch_alter_table("user_oauth", schema=None) as batch_op:
|
|
22
|
+
batch_op.add_column(
|
|
23
|
+
sa.Column(
|
|
24
|
+
"is_guest", sa.BOOLEAN(), server_default="false", nullable=False
|
|
25
|
+
)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# ### end Alembic commands ###
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def downgrade() -> None:
|
|
32
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
33
|
+
with op.batch_alter_table("user_oauth", schema=None) as batch_op:
|
|
34
|
+
batch_op.drop_column("is_guest")
|
|
35
|
+
|
|
36
|
+
# ### end Alembic commands ###
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fractal-server
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.19.0a0
|
|
4
4
|
Summary: Backend component of the Fractal analytics platform
|
|
5
5
|
Author: Tommaso Comparin, Marco Franzon, Yuri Chiucconi, Jacopo Nespolo
|
|
6
6
|
Author-email: Tommaso Comparin <tommaso.comparin@exact-lab.it>, Marco Franzon <marco.franzon@exact-lab.it>, Yuri Chiucconi <yuri.chiucconi@exact-lab.it>, Jacopo Nespolo <jacopo.nespolo@exact-lab.it>
|