From 7250682dc533dd722147478248d019702551faaa Mon Sep 17 00:00:00 2001 From: zzhyyyyy <2685922758@qq.com> Date: Tue, 23 Jun 2026 16:07:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(auth):=20=E6=B5=8B=E8=AF=95=E5=8F=B7?= =?UTF-8?q?=E4=B8=8B=E5=8F=91=20force=5Fonboarding,=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=86=85=E9=87=8D=E7=99=BB=E4=B9=9F=E9=87=8D?= =?UTF-8?q?=E8=B5=B0=E5=BC=95=E5=AF=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 TokenWithUser.force_onboarding(仅测试号置 true)。配合客户端:让测试号在 「退出后应用内重新登录」也重走新手引导;普通号 force_onboarding=false、按原逻辑回原页。 与 onboarding_completed 分工:后者管 App 启动路由,本字段管应用内登录后的去向。 Co-Authored-By: Claude Opus 4.8 (1M context) --- app/api/v1/auth.py | 13 +++++++++---- app/schemas/auth.py | 6 ++++++ tests/test_test_account.py | 5 +++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/api/v1/auth.py b/app/api/v1/auth.py index 7cced2e..d5d21c2 100644 --- a/app/api/v1/auth.py +++ b/app/api/v1/auth.py @@ -39,13 +39,17 @@ logger = logging.getLogger("shagua.auth") router = APIRouter(prefix="/api/v1/auth", tags=["auth"]) -def _login_response(user, *, onboarding_completed: bool) -> TokenWithUser: - """登录类接口共用的响应组装。onboarding_completed 据登录请求的 device_id 算好后传入。""" +def _login_response( + user, *, onboarding_completed: bool, force_onboarding: bool = False +) -> TokenWithUser: + """登录类接口共用的响应组装。onboarding_completed 据登录请求的 device_id 算好后传入; + force_onboarding 仅测试号置 True(让应用内重新登录也重走引导)。""" tokens = issue_token_pair(user.id) return TokenWithUser( **tokens, user=UserOut.model_validate(user), onboarding_completed=onboarding_completed, + force_onboarding=force_onboarding, ) @@ -115,8 +119,9 @@ def sms_login(req: SmsLoginRequest, db: DbSession) -> TokenWithUser: if user.status != "active": raise HTTPException(status_code=403, detail="account disabled") logger.info("sms_login test_account ok user_id=%d phone=%s", user.id, mask_phone(req.phone)) - # onboarding 恒 false:每次登录都重走引导,不读/不写 onboarding_completion 表。 - return _login_response(user, onboarding_completed=False) + # onboarding 恒 false + force_onboarding=true:每次登录都重走引导(含应用内退出后重登), + # 不读/不写 onboarding_completion 表。 + return _login_response(user, onboarding_completed=False, force_onboarding=True) if not verify_code(req.phone, req.code): raise HTTPException(status_code=400, detail="invalid sms code") diff --git a/app/schemas/auth.py b/app/schemas/auth.py index 600baaf..3133de0 100644 --- a/app/schemas/auth.py +++ b/app/schemas/auth.py @@ -48,6 +48,12 @@ class TokenWithUser(TokenPair): description="该 设备+账号 是否已走完新手引导(据登录请求里的 device_id 计算)。" "true → 客户端登录后直接进首页,跳过引导。", ) + force_onboarding: bool = Field( + False, + description="是否强制本次登录走新手引导(仅测试号置 true)。客户端据此让【应用内重新登录】" + "(退出后再登)也重走引导,普通号为 false、按原逻辑回原页/首页。与 onboarding_completed " + "分工:后者管 App 启动路由,本字段管应用内登录后的去向。", + ) # ===== 极光一键登录 ===== diff --git a/tests/test_test_account.py b/tests/test_test_account.py index 97f2076..721ef56 100644 --- a/tests/test_test_account.py +++ b/tests/test_test_account.py @@ -13,6 +13,9 @@ import pytest from app.core import test_account from app.integrations import sms +# 测试自注入的固定号:各用例用 monkeypatch 把它塞进 settings.TEST_ACCOUNT_PHONE, +# 再断言行为。它与 .env 配的值【相互独立】——测试不读 .env(保证确定性 / CI 无 .env 也能跑), +# 写成和 .env 同值只为直观;换任意 11 位号测试照样全过,二者无需保持一致。 TEST_PHONE = "11111111111" @@ -58,6 +61,7 @@ def test_login_skips_code_and_returns_tokens(client, enabled) -> None: assert data["user"]["phone"] == TEST_PHONE assert data["user"]["register_channel"] == "sms" assert data["onboarding_completed"] is False + assert data["force_onboarding"] is True # 测试号:应用内重登也强制重走引导 assert "access_token" in data and "refresh_token" in data @@ -158,3 +162,4 @@ def test_non_test_phone_unaffected_when_enabled(client, enabled) -> None: r = client.post("/api/v1/auth/sms/login", json={"phone": phone, "code": "123456", "device_id": "d1"}) assert r.status_code == 200, r.text assert r.json()["user"]["phone"] == phone + assert r.json()["force_onboarding"] is False # 普通号不强制重走,按原逻辑