Skip to content

Commit b0016b0

Browse files
committed
Merge branch 'enh/distinguish-product-groups' of github.com:odeimaiz/osparc-simcore into enh/distinguish-product-groups
2 parents c30f1e2 + 58f4a1a commit b0016b0

File tree

38 files changed

+757
-366
lines changed

38 files changed

+757
-366
lines changed

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

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import re
22
from datetime import date, datetime
33
from enum import Enum
4-
from typing import Annotated, Any, Literal, Self
4+
from typing import Annotated, Any, Literal, Self, TypeAlias
55

66
import annotated_types
77
from common_library.basic_types import DEFAULT_FACTORY
@@ -18,6 +18,7 @@
1818
StringConstraints,
1919
ValidationInfo,
2020
field_validator,
21+
model_validator,
2122
)
2223
from pydantic.config import JsonDict
2324

@@ -83,7 +84,14 @@ class MyProfileRestGet(OutputSchemaWithoutCamelCase):
8384
login: LowerCaseEmailStr
8485
phone: str | None = None
8586

86-
role: Literal["ANONYMOUS", "GUEST", "USER", "TESTER", "PRODUCT_OWNER", "ADMIN"]
87+
role: Literal[
88+
"ANONYMOUS",
89+
"GUEST",
90+
"USER",
91+
"TESTER",
92+
"PRODUCT_OWNER",
93+
"ADMIN",
94+
]
8795
groups: MyGroupsGet | None = None
8896
gravatar_id: Annotated[str | None, Field(deprecated=True)] = None
8997

@@ -306,15 +314,41 @@ class UserAccountReject(InputSchema):
306314
email: EmailStr
307315

308316

317+
GlobString: TypeAlias = Annotated[
318+
str,
319+
StringConstraints(
320+
min_length=3, max_length=200, strip_whitespace=True, pattern=r"^[^%]*$"
321+
),
322+
]
323+
324+
309325
class UserAccountSearchQueryParams(RequestParameters):
310326
email: Annotated[
311-
str,
327+
GlobString | None,
312328
Field(
313-
min_length=3,
314-
max_length=200,
315329
description="complete or glob pattern for an email",
316330
),
317-
]
331+
] = None
332+
primary_group_id: Annotated[
333+
GroupID | None,
334+
Field(
335+
description="Filter by primary group ID",
336+
),
337+
] = None
338+
user_name: Annotated[
339+
GlobString | None,
340+
Field(
341+
description="complete or glob pattern for a username",
342+
),
343+
] = None
344+
345+
@model_validator(mode="after")
346+
def _validate_at_least_one_filter(self) -> Self:
347+
field_names = list(self.__class__.model_fields)
348+
if not any(getattr(self, field_name, None) for field_name in field_names):
349+
msg = f"At least one filter {field_names} must be provided"
350+
raise ValueError(msg)
351+
return self
318352

319353

320354
class UserAccountGet(OutputSchema):
@@ -340,9 +374,9 @@ class UserAccountGet(OutputSchema):
340374
# pre-registration NOTE: that some users have no pre-registartion and therefore all options here can be none
341375
pre_registration_id: int | None
342376
pre_registration_created: datetime | None
343-
invited_by: str | None = None
377+
invited_by: UserNameID | None = None
344378
account_request_status: AccountRequestStatus | None
345-
account_request_reviewed_by: UserID | None = None
379+
account_request_reviewed_by: UserNameID | None = None
346380
account_request_reviewed_at: datetime | None = None
347381

348382
# user status

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from typing import Annotated, TypeAlias
33

44
from common_library.users_enums import UserRole
5-
from models_library.basic_types import IDStr
65
from pydantic import BaseModel, ConfigDict, Field, PositiveInt, StringConstraints
76
from pydantic.config import JsonDict
87
from typing_extensions import ( # https://docs.pydantic.dev/latest/api/standard_library_types/#typeddict
@@ -12,8 +11,9 @@
1211
from .emails import LowerCaseEmailStr
1312

1413
UserID: TypeAlias = PositiveInt
15-
UserNameID: TypeAlias = IDStr
16-
14+
UserNameID: TypeAlias = Annotated[
15+
str, StringConstraints(strip_whitespace=True, min_length=1, max_length=100)
16+
]
1717

1818
FirstNameStr: TypeAlias = Annotated[
1919
str, StringConstraints(strip_whitespace=True, max_length=255)

services/api-server/setup.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ commit_args = --no-verify
1111
asyncio_mode = auto
1212
asyncio_default_fixture_loop_scope = function
1313
addopts = --strict-markers
14-
markers =
14+
markers =
1515
slow: marks tests as slow (deselect with '-m "not slow"')
1616
acceptance_test: "marks tests as 'acceptance tests' i.e. does the system do what the user expects? Typically those are workflows."
1717
testit: "marks test to run during development"
1818

1919
[mypy]
20-
plugins =
20+
plugins =
2121
pydantic.mypy
2222
sqlalchemy.ext.mypy.plugin

services/api-server/src/simcore_service_api_server/models/schemas/profiles.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ class ProfileCommon(BaseModel):
1313
last_name: LastNameStr | None = Field(None, examples=["Maxwell"])
1414

1515

16-
class ProfileUpdate(ProfileCommon):
17-
...
16+
class ProfileUpdate(ProfileCommon): ...
1817

1918

2019
class UserRoleEnum(StrAutoEnum):

services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,9 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
526526
if (!osparc.desktop.credits.Utils.areWalletsEnabled()) {
527527
return;
528528
}
529+
if (osparc.utils.Resources.isStudyLike(this.__resourceData) && !osparc.data.model.Study.canIWrite(this.__resourceData["accessRights"])) {
530+
return;
531+
}
529532

530533
const resourceData = this.__resourceData;
531534
if (osparc.utils.Resources.isStudy(resourceData)) {
@@ -634,6 +637,13 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
634637
},
635638

636639
__addPermissionsPage: function() {
640+
if (osparc.utils.Resources.isStudyLike(this.__resourceData) && !osparc.data.model.Study.canIWrite(this.__resourceData["accessRights"])) {
641+
return;
642+
}
643+
if (osparc.utils.Resources.isService(this.__resourceData) && !osparc.data.model.Service.canIWrite(this.__resourceData["accessRights"])) {
644+
return;
645+
}
646+
637647
const id = "Permissions";
638648
const title = this.tr("Sharing");
639649
const iconSrc = "@FontAwesome5Solid/share-alt/22";
@@ -695,7 +705,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
695705
let classifiers = null;
696706
if (
697707
(osparc.utils.Resources.isStudy(resourceData) || osparc.utils.Resources.isTemplate(resourceData)) && osparc.data.model.Study.canIWrite(resourceData["accessRights"]) ||
698-
osparc.utils.Resources.isService(resourceData) && osparc.service.Utils.canIWrite(resourceData["accessRights"])
708+
osparc.utils.Resources.isService(resourceData) && osparc.data.model.Service.canIWrite(resourceData["accessRights"])
699709
) {
700710
classifiers = new osparc.metadata.ClassifiersEditor(resourceData);
701711
classifiers.addListener("updateClassifiers", e => {
@@ -779,6 +789,9 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
779789
if (osparc.utils.Resources.isService(resourceData)) {
780790
return;
781791
}
792+
if (osparc.utils.Resources.isStudyLike(this.__resourceData) && !osparc.data.model.Study.canIWrite(this.__resourceData["accessRights"])) {
793+
return;
794+
}
782795

783796
const id = "ServicesUpdate";
784797
const title = this.tr("Services Updates");
@@ -813,6 +826,9 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
813826
) {
814827
return;
815828
}
829+
if (osparc.utils.Resources.isStudyLike(this.__resourceData) && !osparc.data.model.Study.canIWrite(this.__resourceData["accessRights"])) {
830+
return;
831+
}
816832

817833
const id = "ServicesBootOptions";
818834
const title = this.tr("Boot Options");

services/static-webserver/client/source/class/osparc/data/model/Service.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,13 @@ qx.Class.define("osparc.data.model.Service", {
161161
nullable: false
162162
},
163163
},
164+
165+
statics: {
166+
canIWrite: function(serviceAccessRights) {
167+
const groupsStore = osparc.store.Groups.getInstance();
168+
const orgIDs = groupsStore.getOrganizationIds();
169+
orgIDs.push(groupsStore.getMyGroupId());
170+
return osparc.share.CollaboratorsService.canGroupsWrite(serviceAccessRights, orgIDs);
171+
},
172+
},
164173
});

services/static-webserver/client/source/class/osparc/editor/HtmlEditor.js

Lines changed: 0 additions & 61 deletions
This file was deleted.

services/static-webserver/client/source/class/osparc/info/ServiceLarge.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ qx.Class.define("osparc.info.ServiceLarge", {
110110

111111
if (
112112
this.getService()["descriptionUi"] &&
113-
!osparc.service.Utils.canIWrite(this.getService()["accessRights"])
113+
!osparc.data.model.Service.canIWrite(this.getService()["accessRights"])
114114
) {
115115
// In case of service instance, show also the copy Id buttons too
116116
const buttonsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10));
@@ -177,7 +177,7 @@ qx.Class.define("osparc.info.ServiceLarge", {
177177
alignY: "middle"
178178
}));
179179
layout.add(view);
180-
if (osparc.service.Utils.canIWrite(this.getService()["accessRights"])) {
180+
if (osparc.data.model.Service.canIWrite(this.getService()["accessRights"])) {
181181
const editBtn = osparc.utils.Utils.getEditButton();
182182
editBtn.addListener("execute", () => cb.call(this), this);
183183
layout.add(editBtn);
@@ -221,7 +221,7 @@ qx.Class.define("osparc.info.ServiceLarge", {
221221
},
222222

223223
__infoElements: function() {
224-
const canIWrite = osparc.service.Utils.canIWrite(this.getService()["accessRights"]);
224+
const canIWrite = osparc.data.model.Service.canIWrite(this.getService()["accessRights"]);
225225

226226
const infoLayout = {
227227
"THUMBNAIL": {

services/static-webserver/client/source/class/osparc/metadata/QualityEditor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ qx.Class.define("osparc.metadata.QualityEditor", {
484484
const myGid = osparc.auth.Data.getInstance().getGroupId();
485485
if (myGid) {
486486
if (osparc.utils.Resources.isService(this.__resourceData)) {
487-
return osparc.service.Utils.canIWrite(this.__resourceData["accessRights"]);
487+
return osparc.data.model.Service.canIWrite(this.__resourceData["accessRights"]);
488488
}
489489
return osparc.data.model.Study.canIWrite(this.__resourceData["accessRights"]);
490490
}

0 commit comments

Comments
 (0)