feat(auth): 测试号下发 force_onboarding,驱动应用内重登也重走引导
新增 TokenWithUser.force_onboarding(仅测试号置 true)。配合客户端:让测试号在 「退出后应用内重新登录」也重走新手引导;普通号 force_onboarding=false、按原逻辑回原页。 与 onboarding_completed 分工:后者管 App 启动路由,本字段管应用内登录后的去向。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+9
-4
@@ -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")
|
||||
|
||||
@@ -48,6 +48,12 @@ class TokenWithUser(TokenPair):
|
||||
description="该 设备+账号 是否已走完新手引导(据登录请求里的 device_id 计算)。"
|
||||
"true → 客户端登录后直接进首页,跳过引导。",
|
||||
)
|
||||
force_onboarding: bool = Field(
|
||||
False,
|
||||
description="是否强制本次登录走新手引导(仅测试号置 true)。客户端据此让【应用内重新登录】"
|
||||
"(退出后再登)也重走引导,普通号为 false、按原逻辑回原页/首页。与 onboarding_completed "
|
||||
"分工:后者管 App 启动路由,本字段管应用内登录后的去向。",
|
||||
)
|
||||
|
||||
|
||||
# ===== 极光一键登录 =====
|
||||
|
||||
@@ -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 # 普通号不强制重走,按原逻辑
|
||||
|
||||
Reference in New Issue
Block a user