Skip to content

feat(settings): 登录方式加「连接」按钮(M2b 绑定入口) - #394

Open
longsizhuo wants to merge 3 commits into
mainfrom
feat/linked-accounts-connect
Open

feat(settings): 登录方式加「连接」按钮(M2b 绑定入口)#394
longsizhuo wants to merge 3 commits into
mainfrom
feat/linked-accounts-connect

Conversation

@longsizhuo

Copy link
Copy Markdown
Member

配套后端 involutionhell-backend#57请 review,我不合并(后端先合)。

之前为什么没有绑定入口

设置页只有「解绑」。组件注释自己写着:

绑定新 provider 走 OAuth 流程,待绑定流程(M2b)上线后再加"连接"按钮——现在加会把用户登成新账号(分叉)

现在后端有了 /oauth/bind/{provider}(要求已登录,把身份挂到当前账号,不建号、不换会话),按钮可以放出来了。

改动

  • 「连接」按钮指向 /oauth/bind/{provider},不是普通登录入口 —— 走后者会分叉,而分叉后那个第三方身份被新账号占住,本尊再也补绑不回来
  • 可绑列表来自后端新端点 GET /api/user-center/identities/providers,前端不再维护"有哪些登录方式"的写死列表。接入 Google 时按钮会自动出现
  • PROVIDER_LABEL 退化成纯展示名,查不到就显示原始 key —— 保证新 provider 不会静默消失。顺带用 Object.hasOwn 查表,避免原型链键(同 LoginErrorNotice 那个崩页的成因)。
  • 绑定回调结果?bind=ok / ?bind_error=<code> 给出可区分文案。其中 bind_taken(该账号已绑到别人)必须说清"先去那个账号解绑",否则用户只看到一个无法自助解决的失败。
  • 新增 useSearchParams → 用 <Suspense> 包裹。

验证

pnpm test 72 通过 · typecheck 干净 · lint 0 error · build 通过。

build 表:login 仍是 SSG;settings 改动前后都是 ƒ(它本来就缺 generateStaticParams/setRequestLocale),非本次引入。

github-actions Bot added 3 commits July 25, 2026 18:05
线上活跃缺陷:LoginErrorNotice 里 messages[error] 是无保护的原型链查找。
messages["__proto__"] 取到的是 Object.prototype(对象而非 undefined,所以
?? 兜底不触发),把非字符串交给 React 渲染会抛错;/login 没有 error boundary,
整个登录页被替换成 "Application error",连 GitHub 登录一起不可用。
constructor / toString / valueOf 同理(取到函数)。发条链接即可让人登不了录。

改为显式 code→i18n key 白名单 + Object.hasOwn,未知 code 一律落到通用文案。

顺带(同区域):
- 补齐 4 个 error code 的映射。后端实发 discord_canary / oauth_failed /
  oauth_state / oauth_provider,此前后两者塌缩成"请重试"——而 oauth_state
  (cookie 被拦或超 300s)重试会无限复现,oauth_provider(服务端缺配置)
  再怎么重试都不可能好,给的建议是错的。
- 去掉 messages prop:NextIntlClientProvider 已在 layout 包裹全站,直接
  useTranslations 即可,省掉"加一个 error code 要改三个文件"的同步负担。
- 删掉按钮旁叙述当前灰度阶段的注释(CLAUDE.md §3 禁止的任务性注释,且 GA 是
  改另一个仓库的 env,没人会回来删它)。

新增 tests/login-error-notice.test.ts(5 条),含 __proto__ 系列回归。
72 测试通过,typecheck / lint 干净,build 表 login 仍为 ● SSG。
配套后端的 /oauth/bind/{provider}。此前设置页只有"解绑",没有绑定入口——
组件注释自己也写着"现在加会把用户登成新账号(分叉)",因为绑定流程还没做。

现在绑定走 /oauth/bind/{provider}(后端要求已登录,把身份挂到当前账号,
不建号、不换会话),所以按钮可以放出来了。

可绑列表来自新端点 GET /api/user-center/identities/providers,返回后端已注册的
provider——前端不再维护"有哪些登录方式"的写死列表,接入新 provider 时按钮会自动
出现。PROVIDER_LABEL 退化成纯展示名,查不到就显示原始 key,保证新 provider 不会
静默消失(顺带用 Object.hasOwn 查表,避免原型链键)。

绑定回调结果 ?bind=ok / ?bind_error=<code> 给出可区分文案,其中 bind_taken
(该第三方账号已绑到别人)必须说清楚"先去那个账号解绑",否则用户只会看到
一个无法自助解决的失败。

用 Suspense 包裹(新增 useSearchParams)。settings 页改动前后均为 ƒ 动态,
非本次引入。72 测试通过 / typecheck / lint 0 error / build 通过。
Copilot AI review requested due to automatic review settings July 26, 2026 12:05
@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
involutionhell-github-io Ready Ready Preview, Comment Jul 26, 2026 12:14pm
website-preview Ready Ready Preview, Comment Jul 26, 2026 12:14pm

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants