Skip to content

Commit 61aaf38

Browse files
committed
moved logic to webserver
1 parent ff17097 commit 61aaf38

File tree

7 files changed

+90
-75
lines changed

7 files changed

+90
-75
lines changed

api/specs/web-server/_users.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
from models_library.api_schemas_webserver.users import (
1111
MyFunctionPermissionsGet,
1212
MyPermissionGet,
13-
MyPhoneConfirm,
14-
MyPhoneRegister,
1513
MyProfileRestGet,
1614
MyProfileRestPatch,
1715
MyTokenCreate,
@@ -32,6 +30,10 @@
3230
UserNotificationCreate,
3331
UserNotificationPatch,
3432
)
33+
from simcore_service_webserver.users._controller.rest._rest_schemas import (
34+
MyPhoneConfirm,
35+
MyPhoneRegister,
36+
)
3537

3638
router = APIRouter(prefix=f"/{API_VTAG}", tags=["users"])
3739

packages/models-library/requirements/_base.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
arrow
88
jsonschema
99
orjson
10-
phonenumbers
1110
pydantic-extra-types
1211
pydantic-settings
1312
pydantic[email]

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

Lines changed: 1 addition & 25 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
@@ -20,7 +20,6 @@
2020
field_validator,
2121
)
2222
from pydantic.config import JsonDict
23-
from pydantic_extra_types.phone_numbers import PhoneNumberValidator
2423

2524
from ..basic_types import IDStr
2625
from ..emails import LowerCaseEmailStr
@@ -208,29 +207,6 @@ def _validate_user_name(cls, value: str):
208207
return value
209208

210209

211-
#
212-
# PHONE REGISTRATION
213-
#
214-
215-
216-
PhoneNumberStr: TypeAlias = Annotated[str, PhoneNumberValidator(number_format="E164")]
217-
218-
219-
class MyPhoneRegister(InputSchema):
220-
phone: Annotated[
221-
PhoneNumberStr,
222-
Field(description="Phone number to register"),
223-
]
224-
225-
226-
class MyPhoneConfirm(InputSchema):
227-
code: Annotated[
228-
str,
229-
StringConstraints(strip_whitespace=True, pattern=r"^[A-Za-z0-9]+$"),
230-
Field(description="Alphanumeric confirmation code"),
231-
]
232-
233-
234210
#
235211
# USER
236212
#
Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import pytest
21
from models_library.api_schemas_webserver.users import (
3-
MyPhoneRegister,
42
MyProfileRestGet,
5-
PhoneNumberStr,
63
)
74
from models_library.api_schemas_webserver.users_preferences import Preference
85
from models_library.groups import AccessRightsDict, Group, GroupsByTypeTuple
96
from models_library.users import MyProfile
10-
from pydantic import TypeAdapter, ValidationError
7+
from pydantic import TypeAdapter
118

129

1310
def test_adapter_from_model_to_schema():
@@ -30,38 +27,3 @@ def test_adapter_from_model_to_schema():
3027
MyProfileRestGet.from_domain_model(
3128
my_profile, my_groups_by_type, my_product_group, my_preferences
3229
)
33-
34-
35-
@pytest.mark.parametrize(
36-
"phone",
37-
["+41763456789", "+19104630364", "+1 301-304-4567"],
38-
)
39-
def test_valid_phone_numbers(phone: str):
40-
# This test is used to tune options of PhoneNumberValidator
41-
assert MyPhoneRegister.model_validate({"phone": phone}).phone == TypeAdapter(
42-
PhoneNumberStr
43-
).validate_python(phone)
44-
45-
46-
@pytest.mark.parametrize(
47-
"phone",
48-
[
49-
"+41763456789",
50-
"+41 76 345 67 89",
51-
"tel:+41-76-345-67-89",
52-
],
53-
ids=["E.164", "INTERNATIONAL", "RFC3966"],
54-
)
55-
def test_autoformat_phone_number_to_e164(phone: str):
56-
# This test is used to tune options of PhoneNumberValidator formatting to E164
57-
assert TypeAdapter(PhoneNumberStr).validate_python(phone) == "+41763456789"
58-
59-
60-
@pytest.mark.parametrize(
61-
"phone",
62-
["41763456789", "+09104630364", "+1 111-304-4567"],
63-
)
64-
def test_invalid_phone_numbers(phone: str):
65-
# This test is used to tune options of PhoneNumberValidator
66-
with pytest.raises(ValidationError):
67-
MyPhoneRegister.model_validate({"phone": phone})

services/web/server/src/simcore_service_webserver/users/_controller/rest/_rest_schemas.py

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,64 @@
77
import re
88
import sys
99
from contextlib import suppress
10-
from typing import Annotated, Any, Final
10+
from typing import Annotated, Any, Final, TypeAlias
1111

1212
import pycountry
1313
from common_library.basic_types import DEFAULT_FACTORY
1414
from models_library.api_schemas_webserver._base import InputSchema
15-
from models_library.api_schemas_webserver.users import PhoneNumberStr, UserAccountGet
15+
from models_library.api_schemas_webserver.users import UserAccountGet
1616
from models_library.emails import LowerCaseEmailStr
17-
from pydantic import ConfigDict, Field, field_validator, model_validator
17+
from pydantic import (
18+
ConfigDict,
19+
Field,
20+
StringConstraints,
21+
field_validator,
22+
model_validator,
23+
)
24+
from pydantic_extra_types.phone_numbers import PhoneNumberValidator
1825

1926
from ....models import AuthenticatedRequestContext
2027

28+
MAX_BYTES_SIZE_EXTRAS: Final[int] = 512
29+
2130

2231
class UsersRequestContext(AuthenticatedRequestContext): ...
2332

2433

25-
MAX_BYTES_SIZE_EXTRAS: Final[int] = 512
34+
#
35+
# PHONE REGISTRATION
36+
#
37+
38+
39+
PhoneNumberStr: TypeAlias = Annotated[
40+
# NOTE: validator require installing `phonenumbers``
41+
str,
42+
PhoneNumberValidator(number_format="E164"),
43+
]
44+
45+
46+
class MyPhoneRegister(InputSchema):
47+
phone: Annotated[
48+
PhoneNumberStr,
49+
Field(description="Phone number to register"),
50+
]
51+
52+
53+
class MyPhoneConfirm(InputSchema):
54+
code: Annotated[
55+
str,
56+
StringConstraints(strip_whitespace=True, pattern=r"^[A-Za-z0-9]+$"),
57+
Field(description="Alphanumeric confirmation code"),
58+
]
59+
60+
61+
#
62+
# USER-ACCCOUNT
63+
#
2664

2765

2866
class UserAccountRestPreRegister(InputSchema):
29-
# NOTE: validators need pycountry!
67+
# NOTE: validators require installing `pycountry`
3068

3169
first_name: str
3270
last_name: str

services/web/server/src/simcore_service_webserver/users/_controller/rest/users_rest.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
from aiohttp import web
55
from models_library.api_schemas_webserver.users import (
6-
MyPhoneConfirm,
7-
MyPhoneRegister,
86
MyProfileRestGet,
97
MyProfileRestPatch,
108
UserGet,
@@ -30,7 +28,7 @@
3028
from ... import _users_service
3129
from ..._users_web import RegistrationSessionManager
3230
from ._rest_exceptions import handle_rest_requests_exceptions
33-
from ._rest_schemas import UsersRequestContext
31+
from ._rest_schemas import MyPhoneConfirm, MyPhoneRegister, UsersRequestContext
3432

3533
_logger = logging.getLogger(__name__)
3634

services/web/server/tests/unit/isolated/test_users_models.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@
1616
)
1717
from models_library.generics import Envelope
1818
from models_library.utils.fastapi_encoders import jsonable_encoder
19+
from pydantic import TypeAdapter, ValidationError
1920
from servicelib.rest_constants import RESPONSE_MODEL_POLICY
2021
from simcore_postgres_database import utils_users
22+
from simcore_service_webserver.users._controller.rest._rest_schemas import (
23+
MyPhoneRegister,
24+
PhoneNumberStr,
25+
)
2126
from simcore_service_webserver.users._models import UserModelAdapter
2227

2328

@@ -150,3 +155,38 @@ def test_utils_user_generates_valid_myprofile_patch():
150155
MyProfileRestPatch.model_validate(
151156
{"userName": utils_users.generate_alternative_username(username)}
152157
)
158+
159+
160+
@pytest.mark.parametrize(
161+
"phone",
162+
["+41763456789", "+19104630364", "+1 301-304-4567"],
163+
)
164+
def test_valid_phone_numbers(phone: str):
165+
# This test is used to tune options of PhoneNumberValidator
166+
assert MyPhoneRegister.model_validate({"phone": phone}).phone == TypeAdapter(
167+
PhoneNumberStr
168+
).validate_python(phone)
169+
170+
171+
@pytest.mark.parametrize(
172+
"phone",
173+
[
174+
"+41763456789",
175+
"+41 76 345 67 89",
176+
"tel:+41-76-345-67-89",
177+
],
178+
ids=["E.164", "INTERNATIONAL", "RFC3966"],
179+
)
180+
def test_autoformat_phone_number_to_e164(phone: str):
181+
# This test is used to tune options of PhoneNumberValidator formatting to E164
182+
assert TypeAdapter(PhoneNumberStr).validate_python(phone) == "+41763456789"
183+
184+
185+
@pytest.mark.parametrize(
186+
"phone",
187+
["41763456789", "+09104630364", "+1 111-304-4567"],
188+
)
189+
def test_invalid_phone_numbers(phone: str):
190+
# This test is used to tune options of PhoneNumberValidator
191+
with pytest.raises(ValidationError):
192+
MyPhoneRegister.model_validate({"phone": phone})

0 commit comments

Comments
 (0)