Skip to content

feat(auth): Discord 登录灰度白名单 + OTP 本地 dev-console 兜底 - #53

Merged
longsizhuo merged 1 commit into
mainfrom
feat/discord-canary
Jul 24, 2026
Merged

feat(auth): Discord 登录灰度白名单 + OTP 本地 dev-console 兜底#53
longsizhuo merged 1 commit into
mainfrom
feat/discord-canary

Conversation

@longsizhuo

Copy link
Copy Markdown
Member

1. Discord 登录灰度(线上"打开一半")

OAuthController 回调处按 Discord user id 白名单放行:

  • auth.discord.allowlistAUTH_DISCORD_ALLOWLIST,逗号分隔)非空 → 只有名单内 id 能登入;其他人被弹回 /login?error=discord_canary
  • 直连 /oauth/render/discord 绕过前端按钮的人一并挡在回调处(这其实收紧了此前无闸、手动 URL 即可登入的面)。
  • 空名单 = 对所有人开放,GA 时清空即回到全量放开。
  • 名单外的人换 token 已发生但不建号/不登入,不触碰未完成的新用户 OTP 路径。

配套前端 PR 放出 Discord 按钮并显示灰度提示。

2. OTP 本地 dev-console 兜底

RegistrationService.sendOtp 在 Resend 未配置时把验证码打到控制台并返 SENT(Django/Rails 的 console email backend 同款),让贡献者不配 Resend key 也能本地跑通完整注册流。生产必配 key,走不到此分支。

验证

全量 289 通过;新增用例:Resend 未配置时不调 sendHtml、仍返 SENT

🤖 Generated with Claude Code

https://claude.ai/code/session_01RtSNVtrEkCsFVHrbt4Zjgi

两件事:

1) Discord 登录灰度(线上"打开一半")
   OAuthController 回调处新增 Discord user id 白名单闸:
   auth.discord.allowlist 非空时,只有名单内的 Discord id 能登入,其他人
   (含直连 /oauth/render/discord 绕过前端按钮的)被弹回 /login?error=discord_canary。
   空名单=对所有人开放,GA(OTP wiring 完成)时清空即可。
   白名单外的人换 token 已发生,但不建号/不登入——不碰未完成的新用户 OTP 路径。

2) OTP 本地 dev-console 兜底
   RegistrationService.sendOtp 在 Resend 未配置(isConfigured()==false)时,
   把验证码打到控制台并返 SENT,而非 SEND_FAILED——让贡献者不配 Resend key 也能
   本地跑通完整注册流(Django/Rails 的 console email backend 同款)。生产必配 key,
   走不到这里。新增用例锁定:未配置时不调 sendHtml、仍返 SENT。

全量 289 测试通过。
Copilot AI review requested due to automatic review settings July 24, 2026 16:40

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.

@longsizhuo
longsizhuo merged commit a073050 into main Jul 24, 2026
@longsizhuo
longsizhuo deleted the feat/discord-canary branch July 24, 2026 16:42
longsizhuo added a commit that referenced this pull request Jul 26, 2026
xhigh review(#54)对已上线的 Discord 灰度(#53)查出的后端问题,逐条修:

灰度闸
- 白名单启动时解析成 Set 并**播报当前模式**:缺 env 与故意 GA 行为完全一致,
  没有这条日志,一次丢掉 AUTH_DISCORD_ALLOWLIST 的部署会静默把 Discord 对全网
  打开,唯一信号是"没有拒绝日志"。
- 配了值却解析不出任何 id(清列表时手滑留个逗号;Java 的 ",".split(",") 返回零长
  数组)不再塌缩成全开放:保持拒绝并 ERROR 告警——错误方向要选"没人能登"。
- 剥引号:docker-compose env_file 不剥,ALLOWLIST="123" 会带引号比对失败,
  把本该放行的人也锁在外面。
- 空 uuid 不放行。
- **已有账号的回访登录豁免**:灰度要拦的是"建新号"(OTP wiring 未完成会分叉账号),
  不是把已有账号的人锁在自己账号外面、还只提示"敬请期待"。
- 拒绝时撤销刚换到的 access token(AuthDiscordRequest#revokeToken):既然不让登,
  就别把用不上的 token 和授权留在人家 Discord 账号里。撤销失败不阻断拒绝流程。

OTP dev 兜底
- 改由显式开关 registration.otp.dev-console 驱动,不再只看"Resend 没配"——后者同时
  也是生产掉 key 的样子,那样 prod 丢 key 会假装发送成功,用户永远卡在输码页
  (改前是 SEND_FAILED,可重试)。关掉开关即恢复该行为。
- 日志不再打印收件邮箱(PII),只留 pendingId + code,与本文件下方及
  ResendEmailService 的既有规则一致。

测试与文档
- 新增 OAuthControllerAllowlistTests(10 条):畸形取值解析、未配即全开、配了却
  解析不出 id 时拒绝所有人、空 uuid、已有 identity 放行、identity 查询失败不放行。
- RegistrationServiceTests:dev 兜底改测"会话状态确实写入"(限流已计数),挡住把
  isConfigured() 检查上提导致本地流程静默坏掉的重构;补"没开开关时仍返 SEND_FAILED"。
- application-test.properties pin 掉两个新属性:本机 .env 会渗进测试 JVM,否则同一
  个测试在本机和 CI 结论不同(与 justauth.type.discord.* 既有 pin 同因)。
- .env.example 补 AUTH_DISCORD_ALLOWLIST / REGISTRATION_OTP_DEV_CONSOLE:照文档配出来
  的环境此前 = 白名单为空 = 全开放。
- SECURITY.md 补 INV-008(闸只放行白名单与已有账号,且不得静默失效)。

全量 300 测试通过(289 → +11)。
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