Skip to content

Commit 570dfcb

Browse files
committed
draft implementation
1 parent 8d79213 commit 570dfcb

File tree

2 files changed

+93
-9
lines changed

2 files changed

+93
-9
lines changed

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

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from contextlib import suppress
33

44
from aiohttp import web
5+
from common_library.user_messages import user_message
56
from models_library.api_schemas_webserver.users import (
67
MyPhoneConfirm,
78
MyPhoneRegister,
@@ -25,13 +26,19 @@
2526
from ....products import products_web
2627
from ....products.models import Product
2728
from ....security.decorators import permission_required
29+
from ....session.api import get_session
2830
from ....utils_aiohttp import envelope_json_response
2931
from ... import _users_service
3032
from ._rest_exceptions import handle_rest_requests_exceptions
3133
from ._rest_schemas import UsersRequestContext
3234

3335
_logger = logging.getLogger(__name__)
3436

37+
# Phone registration session keys
38+
_PHONE_REGISTRATION_KEY = "phone_registration"
39+
_PHONE_PENDING_KEY = "phone_pending"
40+
_PHONE_CODE_KEY = "phone_code"
41+
_PHONE_CODE_VALUE_FAKE = "123456"
3542

3643
routes = web.RouteTableDef()
3744

@@ -104,9 +111,21 @@ async def my_phone_register(request: web.Request) -> web.Response:
104111
req_ctx = UsersRequestContext.model_validate(request)
105112
phone_register = await parse_request_body_as(MyPhoneRegister, request)
106113

107-
# NOTE: Implementation will be added in next PR
108-
msg = "Phone registration not yet implemented"
109-
raise NotImplementedError(msg)
114+
session = await get_session(request)
115+
116+
# Store phone registration state in session
117+
session[_PHONE_REGISTRATION_KEY] = {
118+
"user_id": req_ctx.user_id,
119+
"phone": phone_register.phone,
120+
"status": "pending_confirmation",
121+
}
122+
123+
# NOTE: In real implementation, generate and send SMS code here
124+
# For testing, we'll use a fixed code
125+
session[_PHONE_CODE_KEY] = _PHONE_CODE_VALUE_FAKE
126+
session[_PHONE_PENDING_KEY] = True
127+
128+
return web.json_response(status=status.HTTP_202_ACCEPTED)
110129

111130

112131
@routes.post(f"/{API_VTAG}/me/phone:resend", name="my_phone_resend")
@@ -116,10 +135,25 @@ async def my_phone_register(request: web.Request) -> web.Response:
116135
@handle_rest_requests_exceptions
117136
async def my_phone_resend(request: web.Request) -> web.Response:
118137
req_ctx = UsersRequestContext.model_validate(request)
138+
session = await get_session(request)
139+
140+
# Check if there's a pending phone registration
141+
if not session.get(_PHONE_PENDING_KEY):
142+
raise web.HTTPBadRequest(
143+
text=user_message("No pending phone registration found"),
144+
)
145+
146+
phone_registration = session.get(_PHONE_REGISTRATION_KEY)
147+
if not phone_registration or phone_registration["user_id"] != req_ctx.user_id:
148+
raise web.HTTPBadRequest(
149+
text=user_message("Invalid phone registration session")
150+
)
119151

120-
# NOTE: Implementation will be added in next PR
121-
msg = "Phone code resend not yet implemented"
122-
raise NotImplementedError(msg)
152+
# NOTE: In real implementation, regenerate and resend SMS code here
153+
# For testing, we'll use the same fixed code
154+
session[_PHONE_CODE_KEY] = _PHONE_CODE_VALUE_FAKE
155+
156+
return web.json_response(status=status.HTTP_202_ACCEPTED)
123157

124158

125159
@routes.post(f"/{API_VTAG}/me/phone:confirm", name="my_phone_confirm")
@@ -130,10 +164,40 @@ async def my_phone_resend(request: web.Request) -> web.Response:
130164
async def my_phone_confirm(request: web.Request) -> web.Response:
131165
req_ctx = UsersRequestContext.model_validate(request)
132166
phone_confirm = await parse_request_body_as(MyPhoneConfirm, request)
167+
session = await get_session(request)
168+
169+
# Check if there's a pending phone registration
170+
if not session.get(_PHONE_PENDING_KEY):
171+
raise web.HTTPBadRequest(
172+
text=user_message("No pending phone registration found"),
173+
)
174+
175+
phone_registration = session.get(_PHONE_REGISTRATION_KEY)
176+
if not phone_registration or phone_registration["user_id"] != req_ctx.user_id:
177+
raise web.HTTPBadRequest(
178+
text=user_message("Invalid phone registration session"),
179+
)
180+
181+
# Verify the confirmation code
182+
expected_code = session.get(_PHONE_CODE_KEY)
183+
if not expected_code or phone_confirm.code != expected_code:
184+
raise web.HTTPBadRequest(
185+
text=user_message("Invalid confirmation code"),
186+
)
187+
188+
# Update user's phone number in the database
189+
await _users_service.update_user_phone(
190+
request.app,
191+
user_id=req_ctx.user_id,
192+
phone=phone_registration["phone"],
193+
)
133194

134-
# NOTE: Implementation will be added in next PR
135-
msg = "Phone confirmation not yet implemented"
136-
raise NotImplementedError(msg)
195+
# Clear session data
196+
session.pop(_PHONE_REGISTRATION_KEY, None)
197+
session.pop(_PHONE_PENDING_KEY, None)
198+
session.pop(_PHONE_CODE_KEY, None)
199+
200+
return web.json_response(status=status.HTTP_204_NO_CONTENT)
137201

138202

139203
#

services/web/server/src/simcore_service_webserver/users/_users_service.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,23 @@ async def update_my_profile(
285285
user_id=user_id,
286286
updated_values=UserModelAdapter.from_rest_schema_model(update).to_db_values(),
287287
)
288+
289+
290+
async def update_user_phone(
291+
app: web.Application,
292+
*,
293+
user_id: UserID,
294+
phone: str,
295+
) -> None:
296+
"""Update user's phone number after successful verification
297+
298+
Args:
299+
app: Web application instance
300+
user_id: ID of the user whose phone to update
301+
phone: Verified phone number to set
302+
"""
303+
await _users_repository.update_user_profile(
304+
app,
305+
user_id=user_id,
306+
updated_values={"phone": phone},
307+
)

0 commit comments

Comments
 (0)