Uh oh!
There was an error while loading. Please reload this page.
feat(usercenter): M2a 身份查看/解绑后端 - #46
Closed
longsizhuo wants to merge 5 commits into
Closed
Conversation
RFC involutionhell-backend#42 / ADR-001 的第一阶段,纯增量零行为变化: - user_identities 表:UNIQUE(provider,provider_user_id) + UNIQUE(user_id,provider) + provider 小写 CHECK + FK ON DELETE CASCADE - 启动回填存量 github_id → provider='github' 行,ON CONFLICT DO NOTHING 保幂等 - UserIdentity model + JdbcUserIdentityRepository(沿用 JDBC 惯例) - 5 个仓库测试覆盖两条 UNIQUE、级联删除、回填幂等 - ADR-001(OKF frontmatter)记录设计决策与 OAuth state 防护协议 生产数据干跑验证:51 个 github_id 账号,0 重复 / 0 非数字 cast,回填无冲突。 全量 251 测试通过。
xhigh review (PR #43) 的已确认问题: - init.sql 补 user_identities 表:三处 schema 同步惯例(INV-004 教训), 否则 docker-compose 起的库缺表,M1 登录 500 - ADR 的 state 不变量 INV-006 → INV-007:INV-006 已被 PR #41 限流占用 - 回填注释澄清边界:依赖 SPRING_SQL_INIT_MODE=always;只治行缺失不治值变化; M2 解绑 github 须同时清 github_id 列,否则重启静默复活已撤销绑定 - 仓库层 provider 归一化小写:JustAuth source 名大写,不归一化查询侧静默查空 - insert() javadoc 声明忽略 linkedAt/lastLoginAt(由 DB default 生成) - 幂等测试改从 classpath 的 schema.sql 机械提取回填语句,不再手抄副本 全量 252 测试通过。
M0 的 user_identities 回填读 user_accounts.github_id,但 docker/init-db/init.sql 建的 user_accounts 只有 7 列、缺 github_id/avatar_url/email/preferences,schema.sql 的 CREATE TABLE IF NOT EXISTS 又补不上已存在表的列——全新 docker 卷首启时回填 直接 column "github_id" does not exist 崩,后端起不来(既有 bug:github 登录 INSERT 本就缺列,M0 把它升级成硬崩)。 - init.sql 的 user_accounts 补齐到与 schema.sql 一致 - .env.example / application.properties 去掉"改成 never"的误导建议:schema.sql 幂等,always 是安全默认;改 never 会让后续新增表在本地缺失(曾踩坑) - README 加建表两路径说明 + 缺表/缺列排查(down -v 重建卷) 验证:一次性 throwaway 容器跑 init.sql→schema.sql 两遍 exit=0、无缺列崩溃、 user_identities 建成且幂等。全量 252 测试通过。
RFC #42 / ADR-001 第二阶段。 loginByProvider(loginByGithub 委托至此): - 账号仍按 "{provider}_{id}" 用户名主查(双写期,M3 才翻转到 identity 主查) - 无论新建/已存在都维护一行 user_identities(identity 双写),缺行惰性补齐, 兜住 M0-M1 窗口回填未覆盖的账号;identity 写失败不阻断登录(同 INV-003 策略) - github_id 列双写沿用(createUser/updateProfile 已写) OAuth state/cookie 硬化(INV-007,登录 CSRF): - render 种 httpOnly + SameSite=Lax 的 ih_oauth_state cookie - callback 在换 token 前校验 URL state == cookie,缺失/不匹配即拒(error=oauth_state) - callback 端点保持 github 专用(泛化 AuthRequest 工厂留到 M3 真接第二个 provider) 新增 INV-007 进 SECURITY.md(INV-006 已被限流占用,按流水规则顺延)。 全量 257 测试通过;生产数据核查:51 个 github 账号 username 约定 0 例外。
RFC #42 / ADR-001。绑定新 provider(M2b)走 OAuth 流程另开 PR;本 PR 做查看+解绑, 自包含,闭合 M0 review 的两个发现。 - GET /api/user-center/identities:列出当前用户已绑定身份(不泄漏 provider_user_id) - DELETE /api/user-center/identities/{provider}:解绑 - 不能解绑最后一种登录方式(防永久锁死;OAuth 随机密码不可靠,保守按剩余身份数判定) - 解绑 github 同事务清空 github_id 列(否则 schema.sql 启动回填按残留列值静默复活) - repository 加 deleteByUserIdAndProvider / clearGithubId 全量 263 测试通过(+6:列表/解绑/锁死拦截/未拥有拒绝/清列/匿名 401)。
longsizhuo
commented
Jul 19, 2026
MemberAuthor
被 #47 替代(M2a 分支与 squash 后的 main 冲突,改用从 main cherry-pick 的干净分支) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RFC #42 / ADR-001。栈在 M1(#44)上。绑定新 provider(M2b:intent store + callback 分支 + 设置页前端)另开 PR;本 PR 是自包含的查看+解绑,正好闭合 M0 review 的两个已确认发现。
M1 的双写让每次登录都建 identity,所以"列出/解绑已绑定身份"现在就是完整可用的功能。
端点(走
/api/user-center/*,现有 rewrite 覆盖)GET /api/user-center/identities(@SaCheckLogin):列出当前用户已绑定身份,不泄漏 provider_user_id(只回 provider / 绑定时间 / 最近登录 / 绑定时展示名)。DELETE /api/user-center/identities/{provider}(@SaCheckLogin):解绑。两条安全规则(闭合 review 发现)
github_id列——否则 schema.sql 启动回填会按残留列值把身份静默复活(review finding refactor: 重构ai对话方法 #2/feat(user-center): 用户偏好读写 API + preferences JSONB 列 #7)。@Transactional保证删身份+清列原子。验证
后续
M2b:
POST /link/{provider}/start+ callback bind 分支(intent store,Caffeine)+ 前端设置页 UI(列表 + 连接/解绑按钮 + 二次授权)。🤖 Generated with Claude Code
https://claude.ai/code/session_01RtSNVtrEkCsFVHrbt4Zjgi