feat(2fa): 动态码改为可选校验,未验证条目支持就地补验
痛点:secret 多为历史留存,录入那一刻手上常常没有能出码的验证器,
原先「绑定必须 secret + 当前 6 位码校验通过」直接把用户挡在门外。
改为「能验则验,没验就标」,抄错风险由角标持续提醒 + 后置补验兜住。
- 后端:新增 otp_verified_at 记账;code 可选(填了必须通过,错码 400
且不覆盖已绑 secret);POST /{id}/otp/verify 补验转正;更换 secret
一律重置为未验证;_migrate_assets_db 幂等补列并回填旧数据,避免升级
后全量误报未验证
- 前端:列表区分「2FA 已验证/未验证」徽章,展开区未验证提醒条 + 就地
补验输入;账号查看密码弹窗增加未验证提示;移除 CredentialModal.save()
里的必填预校验(这是留空保存连请求都不发出的根因)
- 测试:pytest 74 绿(新增契约反转 + 6 个补验用例 + 迁移回填用例);
Playwright 端到端 13/13(留空保存 → 未验证角标 → 错码 400 保持未验证
→ 正码补验转正 → 移动端 375px 无横向溢出 → 无 JS 运行时报错)
- 文档:goal-spec §1/§2/§4/§5/§6/§7/§9 同步新决策,替换旧的必填校验约定
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
- login_password / api_config:Create 时传入即加密存储;Update 时 None 表示不修改。
|
||||
- login_password 的唯一事实源在 credentials 表(账号通过 credential_id 关联),
|
||||
本 schema 字段仅为录入入口,服务层重定向写入凭据。
|
||||
- Read 永不返回凭证明文/密文,只给布尔标记(has_login_password / has_api_config / has_otp)。
|
||||
- Read 永不返回凭证明文/密文,只给布尔标记(has_login_password / has_api_config / has_otp / otp_verified)。
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
@@ -42,4 +42,5 @@ class AccountRead(AccountBase):
|
||||
has_api_config: bool = False
|
||||
credential_id: Optional[int] = None # 关联的登录凭据(密码唯一事实源)
|
||||
has_otp: bool = False # 关联凭据是否绑定了 2FA
|
||||
otp_verified: bool = False # 该 2FA 是否已过动态码校验(False = 仅录入 secret)
|
||||
last_synced_at: Optional[datetime] = None
|
||||
|
||||
Reference in New Issue
Block a user