Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
feda097
🎨 Refactor string type definitions: Move LongTruncatedStr and ShortTr…
pcrespov Oct 16, 2025
84813ac
🎨 Enhance string safety: Refactor string types to include validation …
pcrespov Oct 16, 2025
d8d5c39
🎨 Refactor string safety validation: Rename validation function and u…
pcrespov Oct 16, 2025
3ff0cb0
🎨 Enhance user input safety: Add validation to first and last name fi…
pcrespov Oct 16, 2025
f2aa4f7
🎨 Enhance input validation: Add length and pattern constraints for na…
pcrespov Oct 16, 2025
3c57f7b
🎨 Add ColorStr type: Introduce ColorStr for hex color validation in s…
pcrespov Oct 16, 2025
1250b44
🎨 Update schemas to use safe string types: Replace IDStr with NameSaf…
pcrespov Oct 16, 2025
ba713ef
🎨 Improve documentation clarity: Update comments in ShortTruncatedStr…
pcrespov Oct 16, 2025
bf6cb5e
🎨 Enhance input validation: Update SQL and JS injection patterns for …
pcrespov Oct 16, 2025
eac19dd
fixes username str
pcrespov Oct 16, 2025
3a30b7c
search
pcrespov Oct 16, 2025
c386a5f
packages/models-library version: 0.2.0 → 0.3.0
pcrespov Oct 16, 2025
b455092
oas
pcrespov Oct 16, 2025
1704aed
🔒 Enhance security: Update SQL and JS injection patterns; add tests f…
pcrespov Oct 16, 2025
b0f33cd
🔒 Enhance security: Refactor SQL and JS injection patterns; add ReDoS…
pcrespov Oct 16, 2025
6f3b22b
🔒 Enhance security: Refine SQL and JS injection patterns; improve ReD…
pcrespov Oct 16, 2025
a206f71
🔒 Fix validation error type in username length test
pcrespov Oct 16, 2025
7f2e907
🔒 Enhance security: Add XSS detection pattern and update validation t…
pcrespov Oct 17, 2025
3af1371
🔒 Enhance security: Implement comprehensive XSS detection patterns an…
pcrespov Oct 17, 2025
df455a2
🔒 Enhance security: Improve obfuscated protocol detection in input va…
pcrespov Oct 17, 2025
5cbb20b
🔒 Enhance security: Rename input validation function to improve XSS s…
pcrespov Oct 17, 2025
8f2ddcf
oas
pcrespov Oct 17, 2025
1261930
🔒 Enhance security: Update XSS pattern to improve detection of unsafe…
pcrespov Oct 17, 2025
9bd3e93
updates
pcrespov Oct 20, 2025
e56435b
udpates oas
pcrespov Oct 20, 2025
ace2d31
include @ for emails
pcrespov Oct 21, 2025
dd3ca38
updates OAS
pcrespov Oct 21, 2025
49e4eb4
Merge branch 'master' into mai/description-type
pcrespov Oct 21, 2025
f75cc46
Merge branch 'master' into mai/description-type
pcrespov Oct 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/models-library/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.0
0.3.0
6 changes: 3 additions & 3 deletions packages/models-library/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.2.0
current_version = 0.3.0
commit = True
message = packages/models-library version: {current_version} → {new_version}
tag = False
Expand All @@ -16,10 +16,10 @@ test = pytest
[tool:pytest]
asyncio_mode = auto
asyncio_default_fixture_loop_scope = function
markers =
markers =
diagnostics: "can be used to run diagnostics against deployed data (e.g. database, registry etc)"
testit: "marks test to run during development"

[mypy]
plugins =
plugins =
pydantic.mypy
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from datetime import datetime
from typing import Annotated, Self

from models_library.string_types import DisplaySafeStr
from pydantic import ConfigDict, Field, field_validator

from ..access_rights import AccessRights
from ..basic_types import IDStr
from ..folders import FolderDB, FolderID
from ..groups import GroupID
from ..utils.common_validators import null_or_none_str_to_none_validator
Expand Down Expand Up @@ -53,7 +53,7 @@ def from_domain_model(


class FolderCreateBodyParams(InputSchema):
name: IDStr
name: DisplaySafeStr
parent_folder_id: FolderID | None = None
workspace_id: WorkspaceID | None = None
model_config = ConfigDict(extra="forbid")
Expand All @@ -68,7 +68,7 @@ class FolderCreateBodyParams(InputSchema):


class FolderReplaceBodyParams(InputSchema):
name: IDStr
name: DisplaySafeStr
parent_folder_id: FolderID | None = None
model_config = ConfigDict(extra="forbid")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from common_library.basic_types import DEFAULT_FACTORY
from common_library.dict_tools import remap_keys
from models_library.string_types import DescriptionSafeStr, NameSafeStr
from pydantic import (
AnyHttpUrl,
AnyUrl,
Expand All @@ -27,7 +28,7 @@
StandardGroupCreate,
StandardGroupUpdate,
)
from ..users import UserID, UserNameID
from ..users import UserID, UserNameID, UserNameSafeID
from ..utils.common_validators import create__check_only_one_is_set__root_validator
from ._base import InputSchema, OutputSchema, OutputSchemaWithoutCamelCase

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


class GroupCreate(InputSchema):
label: str
description: str
label: NameSafeStr
description: DescriptionSafeStr
thumbnail: AnyUrl | None = None

def to_domain_model(self) -> StandardGroupCreate:
Expand All @@ -173,8 +174,8 @@ def to_domain_model(self) -> StandardGroupCreate:


class GroupUpdate(InputSchema):
label: str | None = None
description: str | None = None
label: NameSafeStr | None = None
description: DescriptionSafeStr | None = None
thumbnail: AnyUrl | None = None

def to_domain_model(self) -> StandardGroupUpdate:
Expand Down Expand Up @@ -373,7 +374,7 @@ class GroupUserAdd(InputSchema):
"""

uid: UserID | None = None
user_name: Annotated[UserNameID | None, Field(alias="userName")] = None
user_name: Annotated[UserNameSafeID | None, Field(alias="userName")] = None
email: Annotated[
LowerCaseEmailStr | None,
Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from pydantic.config import JsonDict

from ..api_schemas_long_running_tasks.tasks import TaskGet
from ..basic_types import LongTruncatedStr, ShortTruncatedStr
from ..emails import LowerCaseEmailStr
from ..folders import FolderID
from ..groups import GroupID
Expand All @@ -41,6 +40,7 @@
ProjectShareStatus,
ProjectStateRunningState,
)
from ..string_types import LongTruncatedStr, ShortTruncatedStr
from ..utils._original_fastapi_encoders import jsonable_encoder
from ..utils.common_validators import (
empty_str_to_none_pre_validator,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
from datetime import date, datetime
from enum import Enum
from typing import Annotated, Any, Literal, Self, TypeAlias
from typing import Annotated, Any, Literal, Self

import annotated_types
from common_library.basic_types import DEFAULT_FACTORY
Expand All @@ -11,11 +11,11 @@
from models_library.rest_filters import Filters
from models_library.rest_pagination import PageQueryParameters
from pydantic import (
AfterValidator,
BaseModel,
ConfigDict,
EmailStr,
Field,
StringConstraints,
ValidationInfo,
field_validator,
model_validator,
Expand All @@ -27,12 +27,18 @@
from ..groups import AccessRightsDict, Group, GroupID, GroupsByTypeTuple, PrimaryGroupID
from ..products import ProductName
from ..rest_base import RequestParameters
from ..string_types import (
GlobPatternSafeStr,
SearchPatternSafeStr,
validate_input_xss_safety,
)
from ..users import (
FirstNameStr,
LastNameStr,
MyProfile,
UserID,
UserNameID,
UserNameSafeID,
UserPermission,
UserThirdPartyToken,
)
Expand Down Expand Up @@ -201,10 +207,21 @@ def from_domain_model(
)


FirstNameSafeStr = Annotated[
FirstNameStr,
AfterValidator(validate_input_xss_safety),
]

LastNameSafeStr = Annotated[
LastNameStr,
AfterValidator(validate_input_xss_safety),
]


class MyProfileRestPatch(InputSchemaWithoutCamelCase):
first_name: FirstNameStr | None = None
last_name: LastNameStr | None = None
user_name: Annotated[IDStr | None, Field(alias="userName", min_length=4)] = None
first_name: FirstNameSafeStr | None = None
last_name: LastNameSafeStr | None = None
user_name: Annotated[UserNameSafeID | None, Field(alias="userName")] = None
# NOTE: phone is updated via a dedicated endpoint!

privacy: MyProfilePrivacyPatch | None = None
Expand Down Expand Up @@ -262,8 +279,7 @@ class UsersGetParams(RequestParameters):

class UsersSearch(InputSchema):
match_: Annotated[
str,
StringConstraints(strip_whitespace=True, min_length=1, max_length=80),
SearchPatternSafeStr,
Field(
description="Search string to match with usernames and public profiles (e.g. emails, first/last name)",
alias="match",
Expand Down Expand Up @@ -314,17 +330,9 @@ class UserAccountReject(InputSchema):
email: EmailStr


GlobString: TypeAlias = Annotated[
str,
StringConstraints(
min_length=3, max_length=200, strip_whitespace=True, pattern=r"^[^%]*$"
),
]


class UserAccountSearchQueryParams(RequestParameters):
email: Annotated[
GlobString | None,
GlobPatternSafeStr | None,
Field(
description="complete or glob pattern for an email",
),
Expand All @@ -336,7 +344,7 @@ class UserAccountSearchQueryParams(RequestParameters):
),
] = None
user_name: Annotated[
GlobString | None,
GlobPatternSafeStr | None,
Field(
description="complete or glob pattern for a username",
),
Expand Down
33 changes: 0 additions & 33 deletions packages/models-library/src/models_library/basic_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
SIMPLE_VERSION_RE,
UUID_RE,
)
from .utils.common_validators import trim_string_before

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


_SHORT_TRUNCATED_STR_MAX_LENGTH: Final[int] = 600
ShortTruncatedStr: TypeAlias = Annotated[
str,
StringConstraints(strip_whitespace=True),
trim_string_before(max_length=_SHORT_TRUNCATED_STR_MAX_LENGTH),
annotated_types.doc(
"""
A truncated string used to input e.g. titles or display names.
Strips whitespaces and truncate strings that exceed the specified characters limit (curtail_length).
Ensures that the **input** data length to the API is controlled and prevents exceeding large inputs silently,
i.e. without raising errors.
"""
# SEE https://github.com/ITISFoundation/osparc-simcore/pull/5989#discussion_r1650506583
),
]

_LONG_TRUNCATED_STR_MAX_LENGTH: Final[int] = 65536 # same as github description
LongTruncatedStr: TypeAlias = Annotated[
str,
StringConstraints(strip_whitespace=True),
trim_string_before(max_length=_LONG_TRUNCATED_STR_MAX_LENGTH),
annotated_types.doc(
"""
A truncated string used to input e.g. descriptions or summaries.
Strips whitespaces and truncate strings that exceed the specified characters limit (curtail_length).
Ensures that the **input** data length to the API is controlled and prevents exceeding large inputs silently,
i.e. without raising errors.
"""
),
]


# auto-incremented primary-key IDs
IdInt: TypeAlias = PositiveInt
PrimaryKeyInt: TypeAlias = PositiveInt
Expand Down
Loading
Loading