Skip to content

Commit 11f7b17

Browse files
fix: access right permissions when getting
1 parent 6f80ef8 commit 11f7b17

File tree

6 files changed

+158
-60
lines changed

6 files changed

+158
-60
lines changed

packages/models-library/src/models_library/api_schemas_webserver/functions.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from ..functions import (
77
Function,
8-
FunctionAccessRights,
98
FunctionBase,
109
FunctionClass,
1110
FunctionClassSpecificData,
@@ -49,6 +48,7 @@
4948
UnsupportedFunctionClassError,
5049
UnsupportedFunctionFunctionJobClassCombinationError,
5150
)
51+
from ..groups import GroupID
5252
from ..projects import ProjectID
5353
from ._base import InputSchema, OutputSchema
5454

@@ -114,11 +114,23 @@
114114
]
115115

116116

117+
class FunctionGroupAccessRightsGet(OutputSchema):
118+
read: bool
119+
write: bool
120+
execute: bool
121+
122+
123+
class FunctionGroupAccessRightsUpdate(InputSchema):
124+
read: bool
125+
write: bool
126+
execute: bool
127+
128+
117129
class RegisteredSolverFunctionGet(RegisteredSolverFunction, OutputSchema):
118130
uid: Annotated[FunctionID, Field(alias="uuid")]
119131
created_at: Annotated[datetime.datetime, Field(alias="creationDate")]
120132
modified_at: Annotated[datetime.datetime, Field(alias="lastChangeDate")]
121-
access_rights: FunctionAccessRights | None = None
133+
access_rights: dict[GroupID, FunctionGroupAccessRightsGet] | None = None
122134
thumbnail: HttpUrl | None = None
123135

124136

@@ -127,7 +139,7 @@ class RegisteredProjectFunctionGet(RegisteredProjectFunction, OutputSchema):
127139
project_id: Annotated[ProjectID, Field(alias="templateId")]
128140
created_at: Annotated[datetime.datetime, Field(alias="creationDate")]
129141
modified_at: Annotated[datetime.datetime, Field(alias="lastChangeDate")]
130-
access_rights: FunctionAccessRights | None = None
142+
access_rights: dict[GroupID, FunctionGroupAccessRightsGet] | None = None
131143
thumbnail: HttpUrl | None = None
132144

133145

@@ -149,15 +161,3 @@ class ProjectFunctionToRegister(ProjectFunction, InputSchema): ...
149161

150162

151163
class RegisteredFunctionUpdate(FunctionUpdate, InputSchema): ...
152-
153-
154-
class FunctionGroupAccessRightsGet(OutputSchema):
155-
read: bool
156-
write: bool
157-
execute: bool
158-
159-
160-
class FunctionGroupAccessRightsUpdate(InputSchema):
161-
read: bool
162-
write: bool
163-
execute: bool

services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3505,14 +3505,14 @@ paths:
35053505
content:
35063506
application/json:
35073507
schema:
3508-
$ref: '#/components/schemas/FunctionGroupUpdate'
3508+
$ref: '#/components/schemas/FunctionGroupAccessRightsUpdate'
35093509
responses:
35103510
'200':
35113511
description: Successful Response
35123512
content:
35133513
application/json:
35143514
schema:
3515-
$ref: '#/components/schemas/Envelope_FunctionGroupGet_'
3515+
$ref: '#/components/schemas/Envelope_FunctionGroupAccessRightsGet_'
35163516
delete:
35173517
tags:
35183518
- functions
@@ -10553,19 +10553,19 @@ components:
1055310553
title: Error
1055410554
type: object
1055510555
title: Envelope[FolderGet]
10556-
Envelope_FunctionGroupGet_:
10556+
Envelope_FunctionGroupAccessRightsGet_:
1055710557
properties:
1055810558
data:
1055910559
anyOf:
10560-
- $ref: '#/components/schemas/FunctionGroupGet'
10560+
- $ref: '#/components/schemas/FunctionGroupAccessRightsGet'
1056110561
- type: 'null'
1056210562
error:
1056310563
anyOf:
1056410564
- {}
1056510565
- type: 'null'
1056610566
title: Error
1056710567
type: object
10568-
title: Envelope[FunctionGroupGet]
10568+
title: Envelope[FunctionGroupAccessRightsGet]
1056910569
Envelope_GetProjectInactivityResponse_:
1057010570
properties:
1057110571
data:
@@ -12396,24 +12396,7 @@ components:
1239612396
required:
1239712397
- name
1239812398
title: FolderReplaceBodyParams
12399-
FunctionAccessRights:
12400-
properties:
12401-
read:
12402-
type: boolean
12403-
title: Read
12404-
default: false
12405-
write:
12406-
type: boolean
12407-
title: Write
12408-
default: false
12409-
execute:
12410-
type: boolean
12411-
title: Execute
12412-
default: false
12413-
additionalProperties: false
12414-
type: object
12415-
title: FunctionAccessRights
12416-
FunctionGroupGet:
12399+
FunctionGroupAccessRightsGet:
1241712400
properties:
1241812401
read:
1241912402
type: boolean
@@ -12429,8 +12412,8 @@ components:
1242912412
- read
1243012413
- write
1243112414
- execute
12432-
title: FunctionGroupGet
12433-
FunctionGroupUpdate:
12415+
title: FunctionGroupAccessRightsGet
12416+
FunctionGroupAccessRightsUpdate:
1243412417
properties:
1243512418
read:
1243612419
type: boolean
@@ -12446,7 +12429,7 @@ components:
1244612429
- read
1244712430
- write
1244812431
- execute
12449-
title: FunctionGroupUpdate
12432+
title: FunctionGroupAccessRightsUpdate
1245012433
GetProjectInactivityResponse:
1245112434
properties:
1245212435
is_inactive:
@@ -16184,8 +16167,11 @@ components:
1618416167
title: Templateid
1618516168
accessRights:
1618616169
anyOf:
16187-
- $ref: '#/components/schemas/FunctionAccessRights'
16170+
- additionalProperties:
16171+
$ref: '#/components/schemas/FunctionGroupAccessRightsGet'
16172+
type: object
1618816173
- type: 'null'
16174+
title: Accessrights
1618916175
thumbnail:
1619016176
anyOf:
1619116177
- type: string
@@ -16263,8 +16249,11 @@ components:
1626316249
title: Solverversion
1626416250
accessRights:
1626516251
anyOf:
16266-
- $ref: '#/components/schemas/FunctionAccessRights'
16252+
- additionalProperties:
16253+
$ref: '#/components/schemas/FunctionGroupAccessRightsGet'
16254+
type: object
1626716255
- type: 'null'
16256+
title: Accessrights
1626816257
thumbnail:
1626916258
anyOf:
1627016259
- type: string

services/web/server/src/simcore_service_webserver/functions/_controller/_functions_rest.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
)
1313
from models_library.api_schemas_webserver.users import MyFunctionPermissionsGet
1414
from models_library.functions import (
15-
FunctionAccessRights,
1615
FunctionClass,
1716
FunctionGroupAccessRights,
1817
FunctionID,
1918
RegisteredProjectFunction,
2019
RegisteredSolverFunction,
2120
)
21+
from models_library.groups import GroupID
2222
from models_library.products import ProductName
2323
from models_library.rest_pagination import Page
2424
from models_library.rest_pagination_utils import paginate_data
@@ -52,24 +52,27 @@
5252
routes = web.RouteTableDef()
5353

5454

55-
async def _build_function_access_rights(
55+
async def _build_function_group_access_rights(
5656
app: web.Application,
5757
user_id: UserID,
5858
product_name: ProductName,
5959
function_id: FunctionID,
60-
) -> FunctionAccessRights:
61-
access_rights = await _functions_service.get_function_user_permissions(
60+
) -> dict[GroupID, FunctionGroupAccessRightsGet]:
61+
access_rights_list = await _functions_service.get_function_group_permissions(
6262
app=app,
6363
user_id=user_id,
6464
product_name=product_name,
6565
function_id=function_id,
6666
)
6767

68-
return FunctionAccessRights(
69-
read=access_rights.read,
70-
write=access_rights.write,
71-
execute=access_rights.execute,
72-
)
68+
return {
69+
access_rights.group_id: FunctionGroupAccessRightsGet(
70+
read=access_rights.read,
71+
write=access_rights.write,
72+
execute=access_rights.execute,
73+
)
74+
for access_rights in access_rights_list
75+
}
7376

7477

7578
def _build_project_function_extras_dict(
@@ -221,7 +224,7 @@ async def list_functions(request: web.Request) -> web.Response:
221224
)
222225

223226
for function in functions:
224-
access_rights = await _build_function_access_rights(
227+
access_rights = await _build_function_group_access_rights(
225228
request.app,
226229
user_id=req_ctx.user_id,
227230
product_name=req_ctx.product_name,
@@ -271,7 +274,7 @@ async def get_function(request: web.Request) -> web.Response:
271274
product_name=req_ctx.product_name,
272275
)
273276

274-
access_rights = await _build_function_access_rights(
277+
access_rights = await _build_function_group_access_rights(
275278
request.app,
276279
user_id=req_ctx.user_id,
277280
product_name=req_ctx.product_name,
@@ -319,7 +322,7 @@ async def update_function(request: web.Request) -> web.Response:
319322
function=function_update,
320323
)
321324

322-
access_rights = await _build_function_access_rights(
325+
access_rights = await _build_function_group_access_rights(
323326
request.app,
324327
user_id=req_ctx.user_id,
325328
product_name=req_ctx.product_name,

services/web/server/src/simcore_service_webserver/functions/_functions_exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33

44
class FunctionGroupAccessRightsNotFoundError(OsparcErrorMixin, Exception):
5-
msg_template = "Group '{group_id}' does not have access rights to {object_type} '{object_id}' in product '{product_name}'"
5+
msg_template = "Group access rights not found for {object_type} '{object_id}' in product '{product_name}'"

services/web/server/src/simcore_service_webserver/functions/_functions_repository.py

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,36 @@ async def delete_function_job_collection(
10641064
)
10651065

10661066

1067+
async def get_group_permissions(
1068+
app: web.Application,
1069+
connection: AsyncConnection | None = None,
1070+
*,
1071+
user_id: UserID,
1072+
product_name: ProductName,
1073+
object_type: Literal["function", "function_job", "function_job_collection"],
1074+
object_ids: list[UUID],
1075+
) -> list[tuple[UUID, list[FunctionGroupAccessRights]]]:
1076+
async with pass_or_acquire_connection(get_asyncpg_engine(app), connection) as conn:
1077+
for object_id in object_ids:
1078+
await check_user_permissions(
1079+
app,
1080+
connection=conn,
1081+
user_id=user_id,
1082+
product_name=product_name,
1083+
object_id=object_id,
1084+
object_type=object_type,
1085+
permissions=["read"],
1086+
)
1087+
1088+
return await _internal_get_group_permissions(
1089+
app,
1090+
connection=connection,
1091+
product_name=product_name,
1092+
object_type=object_type,
1093+
object_ids=object_ids,
1094+
)
1095+
1096+
10671097
async def set_group_permissions(
10681098
app: web.Application,
10691099
connection: AsyncConnection | None = None,
@@ -1170,6 +1200,55 @@ async def _internal_remove_group_permissions(
11701200
)
11711201

11721202

1203+
async def _internal_get_group_permissions(
1204+
app: web.Application,
1205+
connection: AsyncConnection | None = None,
1206+
*,
1207+
product_name: ProductName,
1208+
object_type: Literal["function", "function_job", "function_job_collection"],
1209+
object_ids: list[UUID],
1210+
) -> list[tuple[UUID, list[FunctionGroupAccessRights]]]:
1211+
access_rights_table = None
1212+
field_name = None
1213+
if object_type == "function":
1214+
access_rights_table = functions_access_rights_table
1215+
field_name = "function_uuid"
1216+
elif object_type == "function_job":
1217+
access_rights_table = function_jobs_access_rights_table
1218+
field_name = "function_job_uuid"
1219+
elif object_type == "function_job_collection":
1220+
access_rights_table = function_job_collections_access_rights_table
1221+
field_name = "function_job_collection_uuid"
1222+
1223+
assert access_rights_table is not None # nosec
1224+
assert field_name is not None # nosec
1225+
1226+
access_rights_list: list[tuple[UUID, list[FunctionGroupAccessRights]]] = []
1227+
async with pass_or_acquire_connection(get_asyncpg_engine(app), connection) as conn:
1228+
for object_id in object_ids:
1229+
rows = [
1230+
row
1231+
async for row in await conn.stream(
1232+
access_rights_table.select().where(
1233+
getattr(access_rights_table.c, field_name) == object_id,
1234+
access_rights_table.c.product_name == product_name,
1235+
)
1236+
)
1237+
]
1238+
group_permissions = [
1239+
FunctionGroupAccessRights(
1240+
group_id=row.group_id,
1241+
read=row.read,
1242+
write=row.write,
1243+
execute=row.execute,
1244+
)
1245+
for row in rows
1246+
]
1247+
access_rights_list.append((object_id, group_permissions))
1248+
1249+
return access_rights_list
1250+
1251+
11731252
async def _internal_set_group_permissions(
11741253
app: web.Application,
11751254
connection: AsyncConnection | None = None,
@@ -1238,7 +1317,7 @@ async def _internal_set_group_permissions(
12381317
"execute": execute if execute is not None else row["execute"],
12391318
}
12401319

1241-
await transaction.execute(
1320+
update_result = await transaction.execute(
12421321
access_rights_table.update()
12431322
.where(
12441323
getattr(access_rights_table.c, field_name) == object_id,
@@ -1252,8 +1331,10 @@ async def _internal_set_group_permissions(
12521331
access_rights_table.c.execute,
12531332
)
12541333
)
1255-
row = result.one()
1256-
access_rights_list.append((object_id, FunctionGroupAccessRights(**row)))
1334+
updated_row = update_result.one()
1335+
access_rights_list.append(
1336+
(object_id, FunctionGroupAccessRights(**updated_row))
1337+
)
12571338

12581339
return access_rights_list
12591340

0 commit comments

Comments
 (0)