[U-02][medium] 群操作的校验不在写事务里;建群输入不去重;后台建群不校验群主 #40

Closed
opened 2026-09-30 13:57:00 +08:00 by nixevol · 1 comment
Owner

编号:U-02 严重级:medium 工作线:身份、群、在线与认证基础(internal/app/identity、group、presence、internal/auth) 来源:审查 I-09
依赖:C-04 (#35)(同改 group 包,C-04 (#35) 先合) 被依赖:无

结论与统一方案

采用审查 I-09 的方案:

  1. 在写事务内重新读群主、成员关系、成员数和目标端 enabled,不满足时返回原有错误码;argon2 校验仍在事务外,事务里只做廉价复核。
  2. 建群和加人时先去重、去掉自己,再按上限截断(超出的记 group_full),然后才做密码校验;单个请求的成员数设上限。
  3. createAdmin 校验群主格式、存在且已启用;成员去重;建成后补推 member_added。
  4. 可选:新增迁移给 group_members 加指向 groups 的外键(迁移号排在 C-03 的 0003 之后)。

改动文件

internal/app/group/app.go(可选新增迁移)。

与其他问题的交互 / 冲突说明

只改 group/app.go 的校验逻辑,不动 emit(T-01)与 void.go(C-04);与 U-03 在 checkAddMember 附近相邻,身份线内顺序合入。

验收与测试

  • 用注入的 TalkGate 在校验回调里解散该群:加人返回 not_found,没有孤儿行。
  • 带重复成员建群:创建成功,成员只有一条。
  • 后台建群时群主不存在或已停用:创建失败。
  • 并发加人不超过上限。

问题明细(各区审查原文,证据含文件与行号)

以下是本次复审各区审查报告的原文段落。A、M、I、P、S 开头的是原始发现编号(A 管理后台与网页、M 消息核心、I 身份认证群在线、P 传输平台部署、S SDK)。解决方案以本 issue 上方的"结论与统一方案"为准;原文里的方案与之不一致时,按上方执行。

[I-09] 群操作的校验不在写事务里;建群输入不去重;后台建群不校验群主

  • 严重级:medium
  • 分类:并发 / 数据
  • 现象与影响
    • (a) 加人、踢人、退群、转让、改名、解散都先用读池判断群主和成员,再到写队列里无条件修改。群主和其他成员、后台操作、删除端的级联之间是并发的:
      • 加人与解散并发时,INSERT OR IGNORE INTO group_members 会留下孤儿成员。group_members 没有外键,之后同编号新建的群会自带这些成员。
      • 转让给 B 与 B 自己退群并发时,群主可能不在成员里。
      • 并发加人可能超过成员上限;校验后被停用的端仍会被加进去。
    • (b) group.create 不去重:同一个编号出现两次,会做两次密码校验、计两次锁定,插入时主键冲突,整个建群失败并返回 busy(客户端按可重试处理,会一直失败)。成员数没有上限,一个请求可以带上万个成员。
    • (c) createAdmin 不校验 owner_id 的格式、是否存在、是否停用;成员也不去重;建群时不推 member_added。
  • 证据
    • 读后写:group/app.go:181-187、208-220、230-266、270-304、307-334、364-396,读池取群信息:636-657。
    • 建群:group/app.go:120-133、155-160;协议校验不去重:protocol/validate.go:498-525。
    • 后台建群:group/app.go:505-511、567-627。
    • 无外键:store/migrations/0002_schema.sql:42-47。
  • 文档依据:PRD F16(341-349)「群主同时是成员」「已停用的端不能加入」「成员上限」「新群收不到旧群的任何消息」;DEVELOPMENT 6.7(508)。
  • 为何不是故意设计:没有相关偏差记录。
  • 解决方案
    1. 在写事务内重新读群主、成员关系、成员数和目标端的 enabled,不满足时返回原有错误码。argon2 校验仍在事务外,事务里只做廉价的复核。
    2. 建群和加人时先去重、去掉自己,再按上限截断(超出的记 group_full),然后才做密码校验。
    3. createAdmin 校验群主格式、存在且已启用;成员去重;建成后补推 member_added。
    4. 可选:新增迁移,给 group_members 加指向 groups 的外键(按 TASKS 4.2 的流程)。
  • 改动文件:group/app.go(可选新增迁移)。
  • 与其他模块的交互/冲突风险:后台先读群主再以群主身份调用;竞态时事务内复核会返回 forbidden,需要提示重试。
  • 需补测试
    • 用注入的 TalkGate 在校验回调里解散该群:加人返回 not_found,没有孤儿行。
    • 带重复成员建群:创建成功,成员只有一条。
    • 后台建群时群主不存在或已停用:创建失败。
  • 置信度:代码阅读确定。

复审基线:main 4059a15(2026-09-30)。编号说明、各工作线的合并顺序、共享文件归属见总览 #7。

**编号**:U-02 **严重级**:medium **工作线**:身份、群、在线与认证基础(internal/app/identity、group、presence、internal/auth) **来源**:审查 I-09 **依赖**:C-04 (#35)(同改 group 包,C-04 (#35) 先合) **被依赖**:无 ### 结论与统一方案 采用审查 I-09 的方案: 1. 在写事务内重新读群主、成员关系、成员数和目标端 enabled,不满足时返回原有错误码;argon2 校验仍在事务外,事务里只做廉价复核。 2. 建群和加人时先去重、去掉自己,再按上限截断(超出的记 `group_full`),然后才做密码校验;单个请求的成员数设上限。 3. `createAdmin` 校验群主格式、存在且已启用;成员去重;建成后补推 `member_added`。 4. 可选:新增迁移给 group_members 加指向 groups 的外键(迁移号排在 C-03 的 0003 之后)。 ### 改动文件 `internal/app/group/app.go`(可选新增迁移)。 ### 与其他问题的交互 / 冲突说明 只改 group/app.go 的校验逻辑,不动 `emit`(T-01)与 void.go(C-04);与 U-03 在 `checkAddMember` 附近相邻,身份线内顺序合入。 ### 验收与测试 - 用注入的 TalkGate 在校验回调里解散该群:加人返回 not_found,没有孤儿行。 - 带重复成员建群:创建成功,成员只有一条。 - 后台建群时群主不存在或已停用:创建失败。 - 并发加人不超过上限。 --- ### 问题明细(各区审查原文,证据含文件与行号) > 以下是本次复审各区审查报告的原文段落。A、M、I、P、S 开头的是原始发现编号(A 管理后台与网页、M 消息核心、I 身份认证群在线、P 传输平台部署、S SDK)。**解决方案以本 issue 上方的"结论与统一方案"为准**;原文里的方案与之不一致时,按上方执行。 #### [I-09] 群操作的校验不在写事务里;建群输入不去重;后台建群不校验群主 - **严重级**:medium - **分类**:并发 / 数据 - **现象与影响** - (a) 加人、踢人、退群、转让、改名、解散都先用读池判断群主和成员,再到写队列里无条件修改。群主和其他成员、后台操作、删除端的级联之间是并发的: - 加人与解散并发时,`INSERT OR IGNORE INTO group_members` 会留下孤儿成员。group_members 没有外键,之后同编号新建的群会自带这些成员。 - 转让给 B 与 B 自己退群并发时,群主可能不在成员里。 - 并发加人可能超过成员上限;校验后被停用的端仍会被加进去。 - (b) `group.create` 不去重:同一个编号出现两次,会做两次密码校验、计两次锁定,插入时主键冲突,整个建群失败并返回 `busy`(客户端按可重试处理,会一直失败)。成员数没有上限,一个请求可以带上万个成员。 - (c) `createAdmin` 不校验 owner_id 的格式、是否存在、是否停用;成员也不去重;建群时不推 member_added。 - **证据** - 读后写:`group/app.go:181-187`、`208-220`、`230-266`、`270-304`、`307-334`、`364-396`,读池取群信息:`636-657`。 - 建群:`group/app.go:120-133`、`155-160`;协议校验不去重:`protocol/validate.go:498-525`。 - 后台建群:`group/app.go:505-511`、`567-627`。 - 无外键:`store/migrations/0002_schema.sql:42-47`。 - **文档依据**:PRD F16(341-349)「群主同时是成员」「已停用的端不能加入」「成员上限」「新群收不到旧群的任何消息」;DEVELOPMENT 6.7(508)。 - **为何不是故意设计**:没有相关偏差记录。 - **解决方案** 1. 在写事务内重新读群主、成员关系、成员数和目标端的 enabled,不满足时返回原有错误码。argon2 校验仍在事务外,事务里只做廉价的复核。 2. 建群和加人时先去重、去掉自己,再按上限截断(超出的记 `group_full`),然后才做密码校验。 3. `createAdmin` 校验群主格式、存在且已启用;成员去重;建成后补推 `member_added`。 4. 可选:新增迁移,给 group_members 加指向 groups 的外键(按 TASKS 4.2 的流程)。 - **改动文件**:`group/app.go`(可选新增迁移)。 - **与其他模块的交互/冲突风险**:后台先读群主再以群主身份调用;竞态时事务内复核会返回 forbidden,需要提示重试。 - **需补测试** - 用注入的 TalkGate 在校验回调里解散该群:加人返回 not_found,没有孤儿行。 - 带重复成员建群:创建成功,成员只有一条。 - 后台建群时群主不存在或已停用:创建失败。 - **置信度**:代码阅读确定。 --- <sub>复审基线:main `4059a15`(2026-09-30)。编号说明、各工作线的合并顺序、共享文件归属见总览 #7。</sub>
nixevol added the P2-mediumlane/identityreview-2026-09-30 labels 2026-09-30 13:57:00 +08:00
Author
Owner

已合入 origin/main 0c9b459。落地提交 ad4f131 fix: 群写操作在事务内复核并去重建群成员 (#40)。迁移 0003 已与 C-03 的 0004 一并合入。

已合入 origin/main `0c9b459`。落地提交 `ad4f131` fix: 群写操作在事务内复核并去重建群成员 (#40)。迁移 0003 已与 C-03 的 0004 一并合入。
Sign in to join this conversation.