Skip to content

Commit 73f95a3

Browse files
committed
Merge branch 'master' into 7846-require-parent-info-when-running-function
2 parents c9dc011 + 975e587 commit 73f95a3

File tree

12 files changed

+219
-70
lines changed

12 files changed

+219
-70
lines changed

api/specs/web-server/_users.py

Lines changed: 8 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,23 @@
44
# pylint: disable=too-many-arguments
55

66

7-
from enum import Enum
87
from typing import Annotated
98

10-
from _common import as_query
119
from fastapi import APIRouter, Depends, status
1210
from models_library.api_schemas_webserver.users import (
11+
MyFunctionPermissionsGet,
1312
MyPermissionGet,
1413
MyProfileGet,
1514
MyProfilePatch,
1615
MyTokenCreate,
1716
MyTokenGet,
18-
UserAccountApprove,
19-
UserAccountGet,
20-
UserAccountReject,
21-
UserAccountSearchQueryParams,
2217
UserGet,
23-
UsersAccountListQueryParams,
2418
UsersSearch,
2519
)
2620
from models_library.api_schemas_webserver.users_preferences import PatchRequestBody
2721
from models_library.generics import Envelope
28-
from models_library.rest_pagination import Page
2922
from models_library.user_preferences import PreferenceIdentifier
3023
from simcore_service_webserver._meta import API_VTAG
31-
from simcore_service_webserver.users._common.schemas import PreRegisteredUserGet
3224
from simcore_service_webserver.users._notifications import (
3325
UserNotification,
3426
UserNotificationCreate,
@@ -128,6 +120,13 @@ async def mark_notification_as_read(
128120
async def list_user_permissions(): ...
129121

130122

123+
@router.get(
124+
"/me/function-permissions",
125+
response_model=Envelope[MyFunctionPermissionsGet],
126+
)
127+
async def list_user_functions_permissions(): ...
128+
129+
131130
#
132131
# USERS public
133132
#
@@ -139,56 +138,3 @@ async def list_user_permissions(): ...
139138
description="Search among users who are publicly visible to the caller (i.e., me) based on their privacy settings.",
140139
)
141140
async def search_users(_body: UsersSearch): ...
142-
143-
144-
#
145-
# USERS admin
146-
#
147-
148-
_extra_tags: list[str | Enum] = ["admin"]
149-
150-
151-
@router.get(
152-
"/admin/user-accounts",
153-
response_model=Page[UserAccountGet],
154-
tags=_extra_tags,
155-
)
156-
async def list_users_accounts(
157-
_query: Annotated[as_query(UsersAccountListQueryParams), Depends()],
158-
): ...
159-
160-
161-
@router.post(
162-
"/admin/user-accounts:approve",
163-
status_code=status.HTTP_204_NO_CONTENT,
164-
tags=_extra_tags,
165-
)
166-
async def approve_user_account(_body: UserAccountApprove): ...
167-
168-
169-
@router.post(
170-
"/admin/user-accounts:reject",
171-
status_code=status.HTTP_204_NO_CONTENT,
172-
tags=_extra_tags,
173-
)
174-
async def reject_user_account(_body: UserAccountReject): ...
175-
176-
177-
@router.get(
178-
"/admin/user-accounts:search",
179-
response_model=Envelope[list[UserAccountGet]],
180-
tags=_extra_tags,
181-
)
182-
async def search_user_accounts(
183-
_query: Annotated[UserAccountSearchQueryParams, Depends()],
184-
):
185-
# NOTE: see `Search` in `Common Custom Methods` in https://cloud.google.com/apis/design/custom_methods
186-
...
187-
188-
189-
@router.post(
190-
"/admin/user-accounts:pre-register",
191-
response_model=Envelope[UserAccountGet],
192-
tags=_extra_tags,
193-
)
194-
async def pre_register_user_account(_body: PreRegisteredUserGet): ...
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# pylint: disable=redefined-outer-name
2+
# pylint: disable=unused-argument
3+
# pylint: disable=unused-variable
4+
# pylint: disable=too-many-arguments
5+
6+
7+
from enum import Enum
8+
from typing import Annotated
9+
10+
from _common import as_query
11+
from fastapi import APIRouter, Depends, status
12+
from models_library.api_schemas_webserver.users import (
13+
UserAccountApprove,
14+
UserAccountGet,
15+
UserAccountReject,
16+
UserAccountSearchQueryParams,
17+
UsersAccountListQueryParams,
18+
)
19+
from models_library.generics import Envelope
20+
from models_library.rest_pagination import Page
21+
from simcore_service_webserver._meta import API_VTAG
22+
from simcore_service_webserver.users._common.schemas import PreRegisteredUserGet
23+
24+
router = APIRouter(prefix=f"/{API_VTAG}", tags=["users"])
25+
26+
_extra_tags: list[str | Enum] = ["admin"]
27+
28+
29+
@router.get(
30+
"/admin/user-accounts",
31+
response_model=Page[UserAccountGet],
32+
tags=_extra_tags,
33+
)
34+
async def list_users_accounts(
35+
_query: Annotated[as_query(UsersAccountListQueryParams), Depends()],
36+
): ...
37+
38+
39+
@router.post(
40+
"/admin/user-accounts:approve",
41+
status_code=status.HTTP_204_NO_CONTENT,
42+
tags=_extra_tags,
43+
)
44+
async def approve_user_account(_body: UserAccountApprove): ...
45+
46+
47+
@router.post(
48+
"/admin/user-accounts:reject",
49+
status_code=status.HTTP_204_NO_CONTENT,
50+
tags=_extra_tags,
51+
)
52+
async def reject_user_account(_body: UserAccountReject): ...
53+
54+
55+
@router.get(
56+
"/admin/user-accounts:search",
57+
response_model=Envelope[list[UserAccountGet]],
58+
tags=_extra_tags,
59+
)
60+
async def search_user_accounts(
61+
_query: Annotated[UserAccountSearchQueryParams, Depends()],
62+
):
63+
# NOTE: see `Search` in `Common Custom Methods` in https://cloud.google.com/apis/design/custom_methods
64+
...
65+
66+
67+
@router.post(
68+
"/admin/user-accounts:pre-register",
69+
response_model=Envelope[UserAccountGet],
70+
tags=_extra_tags,
71+
)
72+
async def pre_register_user_account(_body: PreRegisteredUserGet): ...

api/specs/web-server/openapi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"_tags_groups", # after _tags
2727
"_products",
2828
"_users",
29+
"_users_admin", # after _users
2930
"_wallets",
3031
# add-ons ---
3132
"_activity",

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,3 +377,7 @@ class MyPermissionGet(OutputSchema):
377377
@classmethod
378378
def from_domain_model(cls, permission: UserPermission) -> Self:
379379
return cls(name=permission.name, allowed=permission.allowed)
380+
381+
382+
class MyFunctionPermissionsGet(OutputSchema):
383+
write_functions: bool

services/api-server/src/simcore_service_api_server/services_http/webserver.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
import logging
44
import urllib.parse
55
from dataclasses import dataclass
6+
from datetime import timedelta
67
from functools import partial
7-
from typing import Any, Self
8+
from typing import Any, Final, Self
89
from uuid import UUID
910

1011
import httpx
@@ -94,6 +95,8 @@
9495

9596
_exception_mapper = partial(service_exception_mapper, service_name="Webserver")
9697

98+
_POLL_TIMEOUT: Final[timedelta] = timedelta(minutes=10)
99+
97100
_JOB_STATUS_MAP = {
98101
status.HTTP_402_PAYMENT_REQUIRED: PaymentRequiredError,
99102
status.HTTP_404_NOT_FOUND: JobNotFoundError,
@@ -251,7 +254,7 @@ async def _wait_for_long_running_task_results(self, lrt_response: httpx.Response
251254
# GET task status now until done
252255
async for attempt in AsyncRetrying(
253256
wait=wait_fixed(0.5),
254-
stop=stop_after_delay(60),
257+
stop=stop_after_delay(_POLL_TIMEOUT),
255258
reraise=True,
256259
retry=retry_if_exception_type(TryAgain),
257260
before_sleep=before_sleep_log(_logger, logging.INFO),

services/static-webserver/client/source/class/osparc/auth/ui/RequestAccount.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ qx.Class.define("osparc.auth.ui.RequestAccount", {
158158
case "s4ldesktopacad": {
159159
const application = new qx.ui.form.SelectBox();
160160
[{
161+
id: "other",
162+
label: "Other"
163+
}, {
161164
id: "Antenna_Design_for_Wireless_Communication",
162165
label: "Antenna Design for Wireless Communication"
163166
}, {
@@ -284,6 +287,9 @@ qx.Class.define("osparc.auth.ui.RequestAccount", {
284287
break;
285288
default:
286289
hearOptions = [{
290+
id: "Other",
291+
label: "Other"
292+
}, {
287293
id: "Search_Engine",
288294
label: "Search Engine"
289295
}, {
@@ -295,9 +301,6 @@ qx.Class.define("osparc.auth.ui.RequestAccount", {
295301
}, {
296302
id: "Social_Media",
297303
label: "Social Media"
298-
}, {
299-
id: "Other",
300-
label: "Other"
301304
}];
302305
break;
303306
}

services/web/server/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.68.1
1+
0.69.0

services/web/server/setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.68.1
2+
current_version = 0.69.0
33
commit = True
44
message = services/webserver api version: {current_version} → {new_version}
55
tag = False

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ openapi: 3.1.0
22
info:
33
title: simcore-service-webserver
44
description: Main service with an interface (http-API & websockets) to the web front-end
5-
version: 0.68.1
5+
version: 0.69.0
66
servers:
77
- url: ''
88
description: webserver
@@ -1352,6 +1352,19 @@ paths:
13521352
application/json:
13531353
schema:
13541354
$ref: '#/components/schemas/Envelope_list_MyPermissionGet__'
1355+
/v0/me/function-permissions:
1356+
get:
1357+
tags:
1358+
- users
1359+
summary: List User Functions Permissions
1360+
operationId: list_user_functions_permissions
1361+
responses:
1362+
'200':
1363+
description: Successful Response
1364+
content:
1365+
application/json:
1366+
schema:
1367+
$ref: '#/components/schemas/Envelope_MyFunctionPermissionsGet_'
13551368
/v0/users:search:
13561369
post:
13571370
tags:
@@ -10213,6 +10226,19 @@ components:
1021310226
title: Error
1021410227
type: object
1021510228
title: Envelope[LoginNextPage]
10229+
Envelope_MyFunctionPermissionsGet_:
10230+
properties:
10231+
data:
10232+
anyOf:
10233+
- $ref: '#/components/schemas/MyFunctionPermissionsGet'
10234+
- type: 'null'
10235+
error:
10236+
anyOf:
10237+
- {}
10238+
- type: 'null'
10239+
title: Error
10240+
type: object
10241+
title: Envelope[MyFunctionPermissionsGet]
1021610242
Envelope_MyGroupsGet_:
1021710243
properties:
1021810244
data:
@@ -12642,6 +12668,15 @@ components:
1264212668
required:
1264312669
- color
1264412670
title: MarkerUI
12671+
MyFunctionPermissionsGet:
12672+
properties:
12673+
writeFunctions:
12674+
type: boolean
12675+
title: Writefunctions
12676+
type: object
12677+
required:
12678+
- writeFunctions
12679+
title: MyFunctionPermissionsGet
1264512680
MyGroupsGet:
1264612681
properties:
1264712682
me:

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
RegisteredFunction,
66
RegisteredFunctionGet,
77
)
8+
from models_library.api_schemas_webserver.users import MyFunctionPermissionsGet
89
from pydantic import TypeAdapter
910
from servicelib.aiohttp import status
1011
from servicelib.aiohttp.requests_validation import (
@@ -100,3 +101,29 @@ async def delete_function(request: web.Request) -> web.Response:
100101
)
101102

102103
return web.json_response(status=status.HTTP_204_NO_CONTENT)
104+
105+
106+
#
107+
# /me/* endpoints
108+
#
109+
110+
111+
@routes.get(f"/{VTAG}/me/function-permissions", name="list_user_functions_permissions")
112+
@login_required
113+
@handle_rest_requests_exceptions
114+
async def list_user_functions_permissions(request: web.Request) -> web.Response:
115+
req_ctx = AuthenticatedRequestContext.model_validate(request)
116+
117+
function_permissions = (
118+
await _functions_service.get_functions_user_api_access_rights(
119+
app=request.app,
120+
user_id=req_ctx.user_id,
121+
product_name=req_ctx.product_name,
122+
)
123+
)
124+
125+
assert function_permissions.user_id == req_ctx.user_id # nosec
126+
127+
return envelope_json_response(
128+
MyFunctionPermissionsGet(write_functions=function_permissions.write_functions)
129+
)

0 commit comments

Comments
 (0)