fix(garmin): 退出账号会把邮箱和令牌一起永久删掉,SSO 账号无处补救
用户刚才绑定失败:`Request failed with status code 400`。查下来是 `delete_token()`("退出 Garmin 账号"背后的函数)的注释说"邮箱留在 user 表, 下次只需要密码",但代码只有 `DELETE FROM garmin_tokens`——而 `garmin_email` 唯一的落脚点就是这张表。`users.garmin_email` 是本地密码登录时代的遗留列, `get_remembered_email` 里写得很清楚:auth-hub 接管之后,没有任何绑定路径再 往那张表写过东西。也就是说现在**所有账号**(auth-hub SSO)退出一次,等于 永久忘记邮箱——注释描述的"安全网"对这些账号从来没生效过。 - `delete_token` 删除前把 `garmin_tokens.garmin_email` 复制一份到 `users.garmin_email`,注释里承诺的行为终于是真的 - 顺带修了一条原有测试掩盖真相的问题:`test_disconnecting_drops_the_ current_binding_but_not_the_legacy_value` 预先在 users 表塞了一条 legacy 邮箱,退出后自然能读到——从来没测过 SSO 账号真正会遇到的情况(legacy 列 本来就是空的)。新增两条测试覆盖这个和"连续退出两次不会把邮箱也搞丢" - 生产账号的邮箱已经从退出前的 dump 备份里手工恢复,不用重新绑定就能补上 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -496,10 +496,22 @@ def delete_token(user_id):
|
||||
"""Forget the stored Garmin OAuth token.
|
||||
|
||||
The next sync or login will have to re-authenticate and mint a fresh token.
|
||||
garmin_email on the user record is left in place so re-login only needs the
|
||||
password. The cached client — built from the old token's session — is dropped
|
||||
in the same step so a stale session can't keep being reused.
|
||||
garmin_email is meant to survive this — the UI's own "只需一次" promise is
|
||||
that a disconnect still leaves the address remembered — but for every
|
||||
auth-hub-era account (i.e. all of them now) that address lives *only* on
|
||||
the row this deletes: `users.garmin_email` is a legacy column nothing
|
||||
since auth-hub has ever written to (see `get_remembered_email`). Without
|
||||
copying it forward first, "退出 Garmin 账号" quietly erases the one thing
|
||||
it promised to keep, and the next bind attempt 400s on a blank email field
|
||||
with no visible connection to the disconnect that caused it.
|
||||
|
||||
The cached client — built from the old token's session — is dropped in
|
||||
the same step so a stale session can't keep being reused.
|
||||
"""
|
||||
row = query_one("SELECT garmin_email FROM garmin_tokens WHERE user_id = ?", [user_id])
|
||||
email = (row or {}).get("garmin_email")
|
||||
if email:
|
||||
execute("UPDATE users SET garmin_email = ? WHERE id = ?", [email, user_id])
|
||||
execute("DELETE FROM garmin_tokens WHERE user_id = ?", [user_id])
|
||||
forget_client(user_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user