Skip to content

Commit 1e1f70a

Browse files
Merge branch 'master' into chatbot-improvements
2 parents bb3cb53 + 48c7ccc commit 1e1f70a

File tree

17 files changed

+523
-125
lines changed

17 files changed

+523
-125
lines changed

packages/models-library/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.2.0
1+
0.3.0

packages/models-library/setup.cfg

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.2.0
2+
current_version = 0.3.0
33
commit = True
44
message = packages/models-library version: {current_version} → {new_version}
55
tag = False
@@ -16,10 +16,10 @@ test = pytest
1616
[tool:pytest]
1717
asyncio_mode = auto
1818
asyncio_default_fixture_loop_scope = function
19-
markers =
19+
markers =
2020
diagnostics: "can be used to run diagnostics against deployed data (e.g. database, registry etc)"
2121
testit: "marks test to run during development"
2222

2323
[mypy]
24-
plugins =
24+
plugins =
2525
pydantic.mypy

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from datetime import datetime
22
from typing import Annotated, Self
33

4+
from models_library.string_types import DisplaySafeStr
45
from pydantic import ConfigDict, Field, field_validator
56

67
from ..access_rights import AccessRights
7-
from ..basic_types import IDStr
88
from ..folders import FolderDB, FolderID
99
from ..groups import GroupID
1010
from ..utils.common_validators import null_or_none_str_to_none_validator
@@ -53,7 +53,7 @@ def from_domain_model(
5353

5454

5555
class FolderCreateBodyParams(InputSchema):
56-
name: IDStr
56+
name: DisplaySafeStr
5757
parent_folder_id: FolderID | None = None
5858
workspace_id: WorkspaceID | None = None
5959
model_config = ConfigDict(extra="forbid")
@@ -68,7 +68,7 @@ class FolderCreateBodyParams(InputSchema):
6868

6969

7070
class FolderReplaceBodyParams(InputSchema):
71-
name: IDStr
71+
name: DisplaySafeStr
7272
parent_folder_id: FolderID | None = None
7373
model_config = ConfigDict(extra="forbid")
7474

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from common_library.basic_types import DEFAULT_FACTORY
55
from common_library.dict_tools import remap_keys
6+
from models_library.string_types import DescriptionSafeStr, NameSafeStr
67
from pydantic import (
78
AnyHttpUrl,
89
AnyUrl,
@@ -27,7 +28,7 @@
2728
StandardGroupCreate,
2829
StandardGroupUpdate,
2930
)
30-
from ..users import UserID, UserNameID
31+
from ..users import UserID, UserNameID, UserNameSafeID
3132
from ..utils.common_validators import create__check_only_one_is_set__root_validator
3233
from ._base import InputSchema, OutputSchema, OutputSchemaWithoutCamelCase
3334

@@ -155,8 +156,8 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
155156

156157

157158
class GroupCreate(InputSchema):
158-
label: str
159-
description: str
159+
label: NameSafeStr
160+
description: DescriptionSafeStr
160161
thumbnail: AnyUrl | None = None
161162

162163
def to_domain_model(self) -> StandardGroupCreate:
@@ -173,8 +174,8 @@ def to_domain_model(self) -> StandardGroupCreate:
173174

174175

175176
class GroupUpdate(InputSchema):
176-
label: str | None = None
177-
description: str | None = None
177+
label: NameSafeStr | None = None
178+
description: DescriptionSafeStr | None = None
178179
thumbnail: AnyUrl | None = None
179180

180181
def to_domain_model(self) -> StandardGroupUpdate:
@@ -393,7 +394,7 @@ class GroupUserAdd(InputSchema):
393394
"""
394395

395396
uid: UserID | None = None
396-
user_name: Annotated[UserNameID | None, Field(alias="userName")] = None
397+
user_name: Annotated[UserNameSafeID | None, Field(alias="userName")] = None
397398
email: Annotated[
398399
LowerCaseEmailStr | None,
399400
Field(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from pydantic.config import JsonDict
2323

2424
from ..api_schemas_long_running_tasks.tasks import TaskGet
25-
from ..basic_types import LongTruncatedStr, ShortTruncatedStr
2625
from ..emails import LowerCaseEmailStr
2726
from ..folders import FolderID
2827
from ..groups import GroupID
@@ -41,6 +40,7 @@
4140
ProjectShareStatus,
4241
ProjectStateRunningState,
4342
)
43+
from ..string_types import LongTruncatedStr, ShortTruncatedStr
4444
from ..utils._original_fastapi_encoders import jsonable_encoder
4545
from ..utils.common_validators import (
4646
empty_str_to_none_pre_validator,

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

Lines changed: 25 additions & 17 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, TypeAlias
4+
from typing import Annotated, Any, Literal, Self
55

66
import annotated_types
77
from common_library.basic_types import DEFAULT_FACTORY
@@ -11,11 +11,11 @@
1111
from models_library.rest_filters import Filters
1212
from models_library.rest_pagination import PageQueryParameters
1313
from pydantic import (
14+
AfterValidator,
1415
BaseModel,
1516
ConfigDict,
1617
EmailStr,
1718
Field,
18-
StringConstraints,
1919
ValidationInfo,
2020
field_validator,
2121
model_validator,
@@ -27,12 +27,18 @@
2727
from ..groups import AccessRightsDict, Group, GroupID, GroupsByTypeTuple, PrimaryGroupID
2828
from ..products import ProductName
2929
from ..rest_base import RequestParameters
30+
from ..string_types import (
31+
GlobPatternSafeStr,
32+
SearchPatternSafeStr,
33+
validate_input_xss_safety,
34+
)
3035
from ..users import (
3136
FirstNameStr,
3237
LastNameStr,
3338
MyProfile,
3439
UserID,
3540
UserNameID,
41+
UserNameSafeID,
3642
UserPermission,
3743
UserThirdPartyToken,
3844
)
@@ -205,10 +211,21 @@ def from_domain_model(
205211
)
206212

207213

214+
FirstNameSafeStr = Annotated[
215+
FirstNameStr,
216+
AfterValidator(validate_input_xss_safety),
217+
]
218+
219+
LastNameSafeStr = Annotated[
220+
LastNameStr,
221+
AfterValidator(validate_input_xss_safety),
222+
]
223+
224+
208225
class MyProfileRestPatch(InputSchemaWithoutCamelCase):
209-
first_name: FirstNameStr | None = None
210-
last_name: LastNameStr | None = None
211-
user_name: Annotated[IDStr | None, Field(alias="userName", min_length=4)] = None
226+
first_name: FirstNameSafeStr | None = None
227+
last_name: LastNameSafeStr | None = None
228+
user_name: Annotated[UserNameSafeID | None, Field(alias="userName")] = None
212229
# NOTE: phone is updated via a dedicated endpoint!
213230

214231
privacy: MyProfilePrivacyPatch | None = None
@@ -266,8 +283,7 @@ class UsersGetParams(RequestParameters):
266283

267284
class UsersSearch(InputSchema):
268285
match_: Annotated[
269-
str,
270-
StringConstraints(strip_whitespace=True, min_length=1, max_length=80),
286+
SearchPatternSafeStr,
271287
Field(
272288
description="Search string to match with usernames and public profiles (e.g. emails, first/last name)",
273289
alias="match",
@@ -318,17 +334,9 @@ class UserAccountReject(InputSchema):
318334
email: EmailStr
319335

320336

321-
GlobString: TypeAlias = Annotated[
322-
str,
323-
StringConstraints(
324-
min_length=3, max_length=200, strip_whitespace=True, pattern=r"^[^%]*$"
325-
),
326-
]
327-
328-
329337
class UserAccountSearchQueryParams(RequestParameters):
330338
email: Annotated[
331-
GlobString | None,
339+
GlobPatternSafeStr | None,
332340
Field(
333341
description="complete or glob pattern for an email",
334342
),
@@ -340,7 +348,7 @@ class UserAccountSearchQueryParams(RequestParameters):
340348
),
341349
] = None
342350
user_name: Annotated[
343-
GlobString | None,
351+
GlobPatternSafeStr | None,
344352
Field(
345353
description="complete or glob pattern for a username",
346354
),

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

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
SIMPLE_VERSION_RE,
1515
UUID_RE,
1616
)
17-
from .utils.common_validators import trim_string_before
1817

1918
assert issubclass(LogLevel, Enum) # nosec
2019
assert issubclass(BootModeEnum, Enum) # nosec
@@ -151,38 +150,6 @@ def concatenate(*args: "IDStr", link_char: str = " ") -> "IDStr":
151150
return IDStr(result)
152151

153152

154-
_SHORT_TRUNCATED_STR_MAX_LENGTH: Final[int] = 600
155-
ShortTruncatedStr: TypeAlias = Annotated[
156-
str,
157-
StringConstraints(strip_whitespace=True),
158-
trim_string_before(max_length=_SHORT_TRUNCATED_STR_MAX_LENGTH),
159-
annotated_types.doc(
160-
"""
161-
A truncated string used to input e.g. titles or display names.
162-
Strips whitespaces and truncate strings that exceed the specified characters limit (curtail_length).
163-
Ensures that the **input** data length to the API is controlled and prevents exceeding large inputs silently,
164-
i.e. without raising errors.
165-
"""
166-
# SEE https://github.com/ITISFoundation/osparc-simcore/pull/5989#discussion_r1650506583
167-
),
168-
]
169-
170-
_LONG_TRUNCATED_STR_MAX_LENGTH: Final[int] = 65536 # same as github description
171-
LongTruncatedStr: TypeAlias = Annotated[
172-
str,
173-
StringConstraints(strip_whitespace=True),
174-
trim_string_before(max_length=_LONG_TRUNCATED_STR_MAX_LENGTH),
175-
annotated_types.doc(
176-
"""
177-
A truncated string used to input e.g. descriptions or summaries.
178-
Strips whitespaces and truncate strings that exceed the specified characters limit (curtail_length).
179-
Ensures that the **input** data length to the API is controlled and prevents exceeding large inputs silently,
180-
i.e. without raising errors.
181-
"""
182-
),
183-
]
184-
185-
186153
# auto-incremented primary-key IDs
187154
IdInt: TypeAlias = PositiveInt
188155
PrimaryKeyInt: TypeAlias = PositiveInt

0 commit comments

Comments
 (0)