fractal-server 2.6.2__py3-none-any.whl → 2.6.3__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 +4 -0
- fractal_server/app/routes/auth/current_user.py +29 -0
- fractal_server/app/routes/auth/group.py +16 -1
- fractal_server/app/runner/executors/slurm/sudo/executor.py +5 -1
- fractal_server/app/schemas/user_group.py +18 -1
- fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +36 -0
- {fractal_server-2.6.2.dist-info → fractal_server-2.6.3.dist-info}/METADATA +1 -1
- {fractal_server-2.6.2.dist-info → fractal_server-2.6.3.dist-info}/RECORD +12 -11
- {fractal_server-2.6.2.dist-info → fractal_server-2.6.3.dist-info}/LICENSE +0 -0
- {fractal_server-2.6.2.dist-info → fractal_server-2.6.3.dist-info}/WHEEL +0 -0
- {fractal_server-2.6.2.dist-info → fractal_server-2.6.3.dist-info}/entry_points.txt +0 -0
fractal_server/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "2.6.
|
1
|
+
__VERSION__ = "2.6.3"
|
@@ -15,6 +15,7 @@ from typing import Optional
|
|
15
15
|
from pydantic import EmailStr
|
16
16
|
from sqlalchemy import Column
|
17
17
|
from sqlalchemy.types import DateTime
|
18
|
+
from sqlalchemy.types import JSON
|
18
19
|
from sqlmodel import Field
|
19
20
|
from sqlmodel import Relationship
|
20
21
|
from sqlmodel import SQLModel
|
@@ -126,3 +127,6 @@ class UserGroup(SQLModel, table=True):
|
|
126
127
|
default_factory=get_timestamp,
|
127
128
|
sa_column=Column(DateTime(timezone=True), nullable=False),
|
128
129
|
)
|
130
|
+
viewer_paths: list[str] = Field(
|
131
|
+
sa_column=Column(JSON, server_default="[]", nullable=False)
|
132
|
+
)
|
@@ -5,6 +5,7 @@ from fastapi import APIRouter
|
|
5
5
|
from fastapi import Depends
|
6
6
|
from fastapi_users import schemas
|
7
7
|
from sqlalchemy.ext.asyncio import AsyncSession
|
8
|
+
from sqlmodel import select
|
8
9
|
|
9
10
|
from . import current_active_user
|
10
11
|
from ...db import get_async_db
|
@@ -13,6 +14,8 @@ from ...schemas.user import UserUpdate
|
|
13
14
|
from ...schemas.user import UserUpdateStrict
|
14
15
|
from ..aux.validate_user_settings import verify_user_has_settings
|
15
16
|
from ._aux_auth import _get_single_user_with_group_names
|
17
|
+
from fractal_server.app.models import LinkUserGroup
|
18
|
+
from fractal_server.app.models import UserGroup
|
16
19
|
from fractal_server.app.models import UserOAuth
|
17
20
|
from fractal_server.app.models import UserSettings
|
18
21
|
from fractal_server.app.schemas import UserSettingsReadStrict
|
@@ -103,3 +106,29 @@ async def patch_current_user_settings(
|
|
103
106
|
await db.refresh(current_user_settings)
|
104
107
|
|
105
108
|
return current_user_settings
|
109
|
+
|
110
|
+
|
111
|
+
@router_current_user.get(
|
112
|
+
"/current-user/viewer-paths/", response_model=list[str]
|
113
|
+
)
|
114
|
+
async def get_current_user_viewer_paths(
|
115
|
+
current_user: UserOAuth = Depends(current_active_user),
|
116
|
+
db: AsyncSession = Depends(get_async_db),
|
117
|
+
) -> list[str]:
|
118
|
+
"""Returns the union of `viewer_paths` for all user's groups"""
|
119
|
+
cmd = (
|
120
|
+
select(UserGroup.viewer_paths)
|
121
|
+
.join(LinkUserGroup)
|
122
|
+
.where(LinkUserGroup.group_id == UserGroup.id)
|
123
|
+
.where(LinkUserGroup.user_id == current_user.id)
|
124
|
+
)
|
125
|
+
res = await db.execute(cmd)
|
126
|
+
viewer_paths_nested = res.scalars().all()
|
127
|
+
|
128
|
+
# Flatten a nested object and make its elements unique
|
129
|
+
all_viewer_paths_set = set(
|
130
|
+
path for _viewer_paths in viewer_paths_nested for path in _viewer_paths
|
131
|
+
)
|
132
|
+
all_viewer_paths = list(all_viewer_paths_set)
|
133
|
+
|
134
|
+
return all_viewer_paths
|
@@ -97,7 +97,9 @@ async def create_single_group(
|
|
97
97
|
)
|
98
98
|
|
99
99
|
# Create and return new group
|
100
|
-
new_group = UserGroup(
|
100
|
+
new_group = UserGroup(
|
101
|
+
name=group_create.name, viewer_paths=group_create.viewer_paths
|
102
|
+
)
|
101
103
|
db.add(new_group)
|
102
104
|
await db.commit()
|
103
105
|
|
@@ -116,6 +118,13 @@ async def update_single_group(
|
|
116
118
|
db: AsyncSession = Depends(get_async_db),
|
117
119
|
) -> UserGroupRead:
|
118
120
|
|
121
|
+
group = await db.get(UserGroup, group_id)
|
122
|
+
if group is None:
|
123
|
+
raise HTTPException(
|
124
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
125
|
+
detail=f"UserGroup {group_id} not found.",
|
126
|
+
)
|
127
|
+
|
119
128
|
# Check that all required users exist
|
120
129
|
# Note: The reason for introducing `col` is as in
|
121
130
|
# https://sqlmodel.tiangolo.com/tutorial/where/#type-annotations-and-errors,
|
@@ -152,6 +161,12 @@ async def update_single_group(
|
|
152
161
|
detail=error_msg,
|
153
162
|
)
|
154
163
|
|
164
|
+
# Patch `viewer_paths`
|
165
|
+
if group_update.viewer_paths is not None:
|
166
|
+
group.viewer_paths = group_update.viewer_paths
|
167
|
+
db.add(group)
|
168
|
+
await db.commit()
|
169
|
+
|
155
170
|
updated_group = await _get_single_group_with_user_ids(
|
156
171
|
group_id=group_id, db=db
|
157
172
|
)
|
@@ -246,6 +246,11 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
246
246
|
|
247
247
|
super().__init__(*args, **kwargs)
|
248
248
|
|
249
|
+
# Assign `wait_thread.shutdown_callback` early, since it may be called
|
250
|
+
# from within `_stop_and_join_wait_thread` (e.g. if an exception is
|
251
|
+
# raised within `__init__`).
|
252
|
+
self.wait_thread.shutdown_callback = self.shutdown
|
253
|
+
|
249
254
|
self.keep_pickle_files = keep_pickle_files
|
250
255
|
self.slurm_user = slurm_user
|
251
256
|
self.slurm_account = slurm_account
|
@@ -291,7 +296,6 @@ class FractalSlurmExecutor(SlurmExecutor):
|
|
291
296
|
shutdown_file
|
292
297
|
or (self.workflow_dir_local / SHUTDOWN_FILENAME).as_posix()
|
293
298
|
)
|
294
|
-
self.wait_thread.shutdown_callback = self.shutdown
|
295
299
|
|
296
300
|
def _cleanup(self, jobid: str) -> None:
|
297
301
|
"""
|
@@ -6,9 +6,9 @@ from pydantic import Extra
|
|
6
6
|
from pydantic import Field
|
7
7
|
from pydantic import validator
|
8
8
|
|
9
|
+
from ._validators import val_absolute_path
|
9
10
|
from ._validators import val_unique_list
|
10
11
|
|
11
|
-
|
12
12
|
__all__ = (
|
13
13
|
"UserGroupRead",
|
14
14
|
"UserGroupUpdate",
|
@@ -34,6 +34,7 @@ class UserGroupRead(BaseModel):
|
|
34
34
|
name: str
|
35
35
|
timestamp_created: datetime
|
36
36
|
user_ids: Optional[list[int]] = None
|
37
|
+
viewer_paths: list[str]
|
37
38
|
|
38
39
|
|
39
40
|
class UserGroupCreate(BaseModel, extra=Extra.forbid):
|
@@ -45,6 +46,14 @@ class UserGroupCreate(BaseModel, extra=Extra.forbid):
|
|
45
46
|
"""
|
46
47
|
|
47
48
|
name: str
|
49
|
+
viewer_paths: list[str] = Field(default_factory=list)
|
50
|
+
|
51
|
+
@validator("viewer_paths")
|
52
|
+
def viewer_paths_validator(cls, value):
|
53
|
+
for i, path in enumerate(value):
|
54
|
+
value[i] = val_absolute_path(f"viewer_paths[{i}]")(path)
|
55
|
+
value = val_unique_list("viewer_paths")(value)
|
56
|
+
return value
|
48
57
|
|
49
58
|
|
50
59
|
class UserGroupUpdate(BaseModel, extra=Extra.forbid):
|
@@ -59,7 +68,15 @@ class UserGroupUpdate(BaseModel, extra=Extra.forbid):
|
|
59
68
|
"""
|
60
69
|
|
61
70
|
new_user_ids: list[int] = Field(default_factory=list)
|
71
|
+
viewer_paths: Optional[list[str]] = None
|
62
72
|
|
63
73
|
_val_unique = validator("new_user_ids", allow_reuse=True)(
|
64
74
|
val_unique_list("new_user_ids")
|
65
75
|
)
|
76
|
+
|
77
|
+
@validator("viewer_paths")
|
78
|
+
def viewer_paths_validator(cls, value):
|
79
|
+
for i, path in enumerate(value):
|
80
|
+
value[i] = val_absolute_path(f"viewer_paths[{i}]")(path)
|
81
|
+
value = val_unique_list("viewer_paths")(value)
|
82
|
+
return value
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"""user group viewer paths
|
2
|
+
|
3
|
+
Revision ID: da2cb2ac4255
|
4
|
+
Revises: 94a47ea2d3ff
|
5
|
+
Create Date: 2024-09-26 14:39:26.135101
|
6
|
+
|
7
|
+
"""
|
8
|
+
import sqlalchemy as sa
|
9
|
+
from alembic import op
|
10
|
+
|
11
|
+
|
12
|
+
# revision identifiers, used by Alembic.
|
13
|
+
revision = "da2cb2ac4255"
|
14
|
+
down_revision = "94a47ea2d3ff"
|
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("usergroup", schema=None) as batch_op:
|
22
|
+
batch_op.add_column(
|
23
|
+
sa.Column(
|
24
|
+
"viewer_paths", sa.JSON(), server_default="[]", 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("usergroup", schema=None) as batch_op:
|
34
|
+
batch_op.drop_column("viewer_paths")
|
35
|
+
|
36
|
+
# ### end Alembic commands ###
|
@@ -1,4 +1,4 @@
|
|
1
|
-
fractal_server/__init__.py,sha256=
|
1
|
+
fractal_server/__init__.py,sha256=Xl00aUdi67dqYV36pJ6CjXHphNon7e48hzkQAE3HlRQ,22
|
2
2
|
fractal_server/__main__.py,sha256=WcBAkmVE9aH5mDI6wGkVmPAql2N5Vyk0A-7zuUl8WX0,6122
|
3
3
|
fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
|
4
4
|
fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -6,7 +6,7 @@ fractal_server/app/db/__init__.py,sha256=81rK9w1__Z6PJ5cEcChPVc-wI9YOK4fN--_5Opr
|
|
6
6
|
fractal_server/app/models/__init__.py,sha256=aG7mf1zZbsgzDSp7GHEcZhdjHfW3TGPOLCI8MrvYhPw,500
|
7
7
|
fractal_server/app/models/linkusergroup.py,sha256=ufthlbLFAWMU_dJmsVZzVlQa_D9C9SmgydxypQ2Xq1U,309
|
8
8
|
fractal_server/app/models/linkuserproject.py,sha256=eQaourbGRshvlMVlKzLYJKHEjfsW1CbWws9yW4eHXhA,567
|
9
|
-
fractal_server/app/models/security.py,sha256=
|
9
|
+
fractal_server/app/models/security.py,sha256=2npjgRKBZ7OAnhAXNbYxjtuOsSm1P4kak__qfk2SpeM,3770
|
10
10
|
fractal_server/app/models/user_settings.py,sha256=0YXCAwoAVGqI2irRLdXgr9-JS0STtHhSaoFENigAnrk,1312
|
11
11
|
fractal_server/app/models/v1/__init__.py,sha256=hUI7dEbPaiZGN0IbHW4RSmSicyvtn_xeuevoX7zvUwI,466
|
12
12
|
fractal_server/app/models/v1/dataset.py,sha256=99GDgt7njx8yYQApkImqp_7bHA5HH3ElvbR6Oyj9kVI,2017
|
@@ -52,8 +52,8 @@ fractal_server/app/routes/api/v2/workflow.py,sha256=rMCcclz9aJAMSVLncUdSDGrgkKbn
|
|
52
52
|
fractal_server/app/routes/api/v2/workflowtask.py,sha256=-3-c8DDnxGjMwWbX_h5V5OLaC_iCLXYzwWKBUaL-5wE,7060
|
53
53
|
fractal_server/app/routes/auth/__init__.py,sha256=fao6CS0WiAjHDTvBzgBVV_bSXFpEAeDBF6Z6q7rRkPc,1658
|
54
54
|
fractal_server/app/routes/auth/_aux_auth.py,sha256=a3DCj6_tekf4Bfu8Kax9uxVGbTuVsONgki7E6AJUN_8,3269
|
55
|
-
fractal_server/app/routes/auth/current_user.py,sha256=
|
56
|
-
fractal_server/app/routes/auth/group.py,sha256=
|
55
|
+
fractal_server/app/routes/auth/current_user.py,sha256=s3R1O53Qnow1LqDW-UpkYvfKKSJwLrDWGeMtsIEMUNs,4462
|
56
|
+
fractal_server/app/routes/auth/group.py,sha256=eT-1c0Ow8KbYkKEMQ5ebhEAeRixwJs2kQW45UIutH5w,5833
|
57
57
|
fractal_server/app/routes/auth/group_names.py,sha256=zvYDfhxKlDmbSr-oLXYy6WUVkPPTvzH6ZJtuoNdGZbE,960
|
58
58
|
fractal_server/app/routes/auth/login.py,sha256=tSu6OBLOieoBtMZB4JkBAdEgH2Y8KqPGSbwy7NIypIo,566
|
59
59
|
fractal_server/app/routes/auth/oauth.py,sha256=AnFHbjqL2AgBX3eksI931xD6RTtmbciHBEuGf9YJLjU,1895
|
@@ -83,7 +83,7 @@ fractal_server/app/runner/executors/slurm/sudo/__init__.py,sha256=Cjn1rYvljddi96
|
|
83
83
|
fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py,sha256=wAgwpVcr6JIslKHOuS0FhRa_6T1KCManyRJqA-fifzw,1909
|
84
84
|
fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py,sha256=z5LlhaiqAb8pHsF1WwdzXN39C5anQmwjo1rSQgtRAYE,4422
|
85
85
|
fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py,sha256=g8wqUjSicN17UZVXlfaMomYZ-xOIbBu1oE7HdJTzfvw,5218
|
86
|
-
fractal_server/app/runner/executors/slurm/sudo/executor.py,sha256=
|
86
|
+
fractal_server/app/runner/executors/slurm/sudo/executor.py,sha256=mTqTSvoRukvocyMLvlGuGWMaL6hy3McYLx_7bUW1pEM,48918
|
87
87
|
fractal_server/app/runner/extract_archive.py,sha256=tLpjDrX47OjTNhhoWvm6iNukg8KoieWyTb7ZfvE9eWU,2483
|
88
88
|
fractal_server/app/runner/filenames.py,sha256=9lwu3yB4C67yiijYw8XIKaLFn3mJUt6_TCyVFM_aZUQ,206
|
89
89
|
fractal_server/app/runner/run_subprocess.py,sha256=c3JbYXq3hX2aaflQU19qJ5Xs6J6oXGNvnTEoAfv2bxc,959
|
@@ -127,7 +127,7 @@ fractal_server/app/runner/versions.py,sha256=dSaPRWqmFPHjg20kTCHmi_dmGNcCETflDtD
|
|
127
127
|
fractal_server/app/schemas/__init__.py,sha256=stURAU_t3AOBaH0HSUbV-GKhlPKngnnIMoqWc3orFyI,135
|
128
128
|
fractal_server/app/schemas/_validators.py,sha256=XKEGEHxp3H6YSJewtFWXe_2Nh7SDdNtAXmlEmJO6Vb0,3606
|
129
129
|
fractal_server/app/schemas/user.py,sha256=VNnAPnAVK6X0PZlw7XehocAshVNuUHdDwiZVWCCor6Y,2156
|
130
|
-
fractal_server/app/schemas/user_group.py,sha256=
|
130
|
+
fractal_server/app/schemas/user_group.py,sha256=YwJvYgj-PI66LWy38CEd_FIZPsBV1_2N5zJPGFcFvBw,2143
|
131
131
|
fractal_server/app/schemas/user_settings.py,sha256=UEST1MSmd9w2YypCji3SONSFlJcr2u4uG3bTczZy_Pk,3102
|
132
132
|
fractal_server/app/schemas/v1/__init__.py,sha256=CrBGgBhoemCvmZ70ZUchM-jfVAICnoa7AjZBAtL2UB0,1852
|
133
133
|
fractal_server/app/schemas/v1/applyworkflow.py,sha256=uuIh7fHlHEL4yLqL-dePI6-nfCsqgBYATmht7w_KITw,4302
|
@@ -182,6 +182,7 @@ fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py,sha25
|
|
182
182
|
fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py,sha256=4l1AHGUsa0ONoJVZlr3fTXw_xbbQ8O7wlD92Az2aRfM,1849
|
183
183
|
fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py,sha256=ekDUML7ILpmdoqEclKbEUdyLi4uw9HSG_sTjG2hp_JE,867
|
184
184
|
fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py,sha256=6cHEZFuTXiQg9yu32Y3RH1XAl71av141WQ6UMbiITIg,949
|
185
|
+
fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py,sha256=yGWSA2HIHUybcVy66xBITk08opV2DFYSCIIrulaUZhI,901
|
185
186
|
fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py,sha256=lOggSvzGWqQvnxxFuSM6W50Ui49R918A-uBuiZJ0pNM,963
|
186
187
|
fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py,sha256=jilQW3QIqYQ4Q6hCnUiG7UtNMpA41ujqrB3tPFiPM1Q,1221
|
187
188
|
fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py,sha256=9BwqUS9Gf7UW_KjrzHbtViC880qhD452KAytkHWWZyk,746
|
@@ -213,8 +214,8 @@ fractal_server/tasks/v2/utils.py,sha256=JOyCacb6MNvrwfLNTyLwcz8y79J29YuJeJ2MK5kq
|
|
213
214
|
fractal_server/urls.py,sha256=5o_qq7PzKKbwq12NHSQZDmDitn5RAOeQ4xufu-2v9Zk,448
|
214
215
|
fractal_server/utils.py,sha256=b7WwFdcFZ8unyT65mloFToYuEDXpQoHRcmRNqrhd_dQ,2115
|
215
216
|
fractal_server/zip_tools.py,sha256=xYpzBshysD2nmxkD5WLYqMzPYUcCRM3kYy-7n9bJL-U,4426
|
216
|
-
fractal_server-2.6.
|
217
|
-
fractal_server-2.6.
|
218
|
-
fractal_server-2.6.
|
219
|
-
fractal_server-2.6.
|
220
|
-
fractal_server-2.6.
|
217
|
+
fractal_server-2.6.3.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
|
218
|
+
fractal_server-2.6.3.dist-info/METADATA,sha256=hlZ8xt1P6qEjNO4ySIUzSMfqgQv6RilEJfaWaS5fqBs,4628
|
219
|
+
fractal_server-2.6.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
220
|
+
fractal_server-2.6.3.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
|
221
|
+
fractal_server-2.6.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|