From 1052e191343fb27261facce944e723c8d953b811 Mon Sep 17 00:00:00 2001 From: qzl Date: Thu, 23 Apr 2026 12:32:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(auth):=20dev=20=E7=8E=AF=E5=A2=83=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=B3=A8=E5=86=8C/=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - send_otp 在 dev 环境跳过短信发送 - create_phone_session 在 dev 环境自动创建用户 - system_agents.yaml 添加 allowed_commands 配置 --- .../config/static/database/system_agents.yaml | 4 ++ backend/src/v1/auth/dev_phone_session.py | 48 ++++++++++++++++--- backend/src/v1/auth/gateway.py | 4 ++ 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/backend/src/core/config/static/database/system_agents.yaml b/backend/src/core/config/static/database/system_agents.yaml index 36f52f6..3d3b0be 100644 --- a/backend/src/core/config/static/database/system_agents.yaml +++ b/backend/src/core/config/static/database/system_agents.yaml @@ -25,3 +25,7 @@ agents: - calendar - contacts - memory + allowed_commands: + - calendar + - contacts + - memory diff --git a/backend/src/v1/auth/dev_phone_session.py b/backend/src/v1/auth/dev_phone_session.py index 0c9a4a6..b1365a5 100644 --- a/backend/src/v1/auth/dev_phone_session.py +++ b/backend/src/v1/auth/dev_phone_session.py @@ -24,13 +24,7 @@ async def create_dev_phone_session( *, request: PhoneSessionCreateRequest, ) -> SessionResponse: - user_id = await _find_user_id_by_phone(request.phone) - if user_id is None: - raise _auth_error( - status_code=401, - code="AUTH_USER_NOT_FOUND", - detail="User not found", - ) + user_id = await _find_or_create_user_by_phone(request.phone) token = _sign_access_token(sub=str(user_id)) return SessionResponse( @@ -42,6 +36,46 @@ async def create_dev_phone_session( ) +async def _find_or_create_user_by_phone(phone: str) -> UUID: + admin_client = supabase_service.get_admin_client() + users = await asyncio.to_thread( + _list_users_with_phone, admin_client, phone + ) + if users: + raw_id = str(getattr(users[0], "id", "")) + if raw_id: + return UUID(raw_id) + + return await _create_dev_user(admin_client, phone) + + +async def _create_dev_user(admin_client: Any, phone: str) -> UUID: + try: + user = await asyncio.to_thread( + admin_client.auth.admin.create_user, + { + "phone": phone, + "phone_confirm": True, + }, + ) + raw_id = str(getattr(user, "id", "")) + if not raw_id: + raise _auth_error( + status_code=500, + code="AUTH_USER_CREATE_FAILED", + detail="Failed to create dev user", + ) + logger.info("Created dev user", phone=phone, user_id=raw_id) + return UUID(raw_id) + except Exception as exc: + logger.error("Failed to create dev user", error=str(exc)) + raise _auth_error( + status_code=500, + code="AUTH_USER_CREATE_FAILED", + detail="Failed to create dev user", + ) from exc + + async def _find_user_id_by_phone(phone: str) -> UUID | None: admin_client = supabase_service.get_admin_client() users = await asyncio.to_thread( diff --git a/backend/src/v1/auth/gateway.py b/backend/src/v1/auth/gateway.py index 9a3cb02..2f2553c 100644 --- a/backend/src/v1/auth/gateway.py +++ b/backend/src/v1/auth/gateway.py @@ -52,6 +52,10 @@ class SupabaseAuthGateway(AuthServiceGateway): return supabase_service.get_admin_client() async def send_otp(self, request: OtpSendRequest) -> None: + if config.runtime.environment == "dev": + logger.info("Skipping OTP send in dev environment", phone=request.phone) + return + client = self._get_client() payload: dict[str, Any] = { "phone": request.phone,