Skip to content

fix(dataset): 修复 folder 权限下发与移到根目录清空权限 - #8059

Open
SteelHe wants to merge 2 commits into
labring:mainfrom
SteelHe:fix/dataset-permission-inherit-root-move
Open

SteelHe wants to merge 2 commits into
labring:mainfrom
SteelHe:fix/dataset-permission-inherit-root-move

Conversation

@SteelHe

@SteelHe SteelHe commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

问题描述(复现步骤)

  1. 在知识库目录(MongoDataset type=folder)上配置协作者后, 后代知识库本身的权限正常,但知识库内的文件夹/文件(collection)始终没有该协作者。 复现:F(folder) → D(知识库,开启文件级权限) → CF(folder) → FILE;在 F 上给成员新增 manage,查询 resource_permissions,CF/FILE 仍只有 owner。

根因分析

1a. syncDatasetToCollections 入口用被改节点自身的 collectionPermissionEnabled 短路。
folder 类型永远不会开启文件级权限,于是整棵后代 collection 树被跳过。
1b. 调用顺序错误:collaborator 更新先写 dataset 树,再触发 collection 同步;同步时读到的
后代快照已是新值,diff 为空,提前返回。
1c. resumeInheritPermission 同样在写完 dataset 树后才读取 newEffectiveClbs,跨树 diff 丢失。

修复:

  • syncDatasetToCollections 的开关判断下沉到每个 dataset:关闭态 dataset 跳过自身 collection,但继续遍历后代;folder 不再短路整棵树。
  • collaborator 更新(pro)与 resumeInheritPermission 改为先同步 collection 再写 dataset 树;resume 在事务内按 merge(父级, 自身) 公式预计算 newEffectiveClbs。

测试

  • packages/service test/support/permission/collection/controller.test.ts:44/44 通过 (含 TD 回归、按 dataset 独立开关、变更前快照顺序契约)
  • projects/app test/api/core/dataset/update.test.ts、test/api/core/app/move.test.ts、 test/api/core/ai/skill/move.test.ts:38/38 通过(含 parentId=null/'' 移到根目录保留 ACL)
  • e2e场景测试覆盖

@SteelHe
SteelHe force-pushed the fix/dataset-permission-inherit-root-move branch from f363fd2 to 44967f2 Compare October 21, 2026 04:09
@SteelHe
SteelHe marked this pull request as ready for review October 21, 2026 06:46
# 问题描述(复现步骤)
在知识库目录(MongoDataset type=folder)上配置协作者、生效范围选"所有子级"后,
后代知识库本身的权限正常,但知识库内的文件夹/文件(collection)始终没有该协作者。
复现:F(folder) → D(知识库,开启文件级权限) → CF(folder) → FILE;在 F 上给成员新增
manage,查询 resource_permissions,CF/FILE 仍只有 owner。(TD 2026082400078)

# 根因分析
1a. syncDatasetToCollections 入口用被改节点自身的 collectionPermissionEnabled 短路。
    folder 类型永远不会开启文件级权限,于是整棵后代 collection 树被跳过。
1b. 调用顺序错误:collaborator 更新先写 dataset 树,再触发 collection 同步;同步时读到的
    后代快照已是新值,diff 为空,提前返回。
1c. resumeInheritPermission 同样在写完 dataset 树后才读取 newEffectiveClbs,跨树 diff 丢失。

修复:
- syncDatasetToCollections 的开关判断下沉到每个 dataset:关闭态 dataset 跳过自身
  collection,但继续遍历后代;folder 不再短路整棵树。
- collaborator 更新(pro)与 resumeInheritPermission 改为先同步 collection 再写 dataset
  树;resume 在事务内按 merge(父级, 自身) 公式预计算 newEffectiveClbs。

# 测试
- packages/service test/support/permission/collection/controller.test.ts:含 TD 回归、
  按 dataset 独立开关、变更前快照顺序契约
- prettier 检查通过

Co-Authored-By: Claude <noreply@anthropic.com>
@SteelHe
SteelHe force-pushed the fix/dataset-permission-inherit-root-move branch from 44967f2 to d82a520 Compare October 21, 2026 08:03

@c121914yu c121914yu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

基于 d82a520 重新审查:根目录移动相关实现和测试已移除,当前变更范围围绕目录权限下发,范围合理。仍有下列两项问题,其中 Pro 真实入口的调用顺序导致修复尚未闭环。

验证范围:使用此提交的原始 TypeScript 函数和内存数据库/鉴权桩复现新增、撤销、降权及无关分支扫描;恢复继承能够将权限同步到 collection 子树并保留子级额外授权;git diff --check 通过。未复跑 MongoDB/API 测试或全量测试。

建议补充真实 Pro 协作者更新入口的授权、撤销/降权回归,以及非根目录恢复继承后 collection 子树的回归用例。另请同步清理 PR 标题和正文测试说明中已移除的根目录移动内容。

* 根级继承态 collection 从 oldEffectiveClbs 物化到 newEffectiveClbs,folder 递归同步子树。
* 由 dataset 写路径(collaborator/move/resume)在同一事务内调用。幂等(diff 写入)。
*
* 调用约束:必须在 dataset 树写入**之前**调用,`syncDatasetToCollections` 需要读到后代

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] 补齐 Pro 真实入口的同步顺序修复

这里新增了“必须在 dataset 树写入之前调用”的约束,但本 PR 固定的 Pro 提交仍为 c089f2836158a39b37b88103801559e34c7eb1c0。该版本 admin/src/service/support/permission/controller.ts:109–123 仍先执行 updateResourceCollaborators(已更新 dataset 及其继承子树),再执行 onUpdated 中的 syncDatasetToCollections。此时读取到的后代 dataset 已是新快照,计算出的后代 old/new 权限相同,collection 同步会提前返回。

使用原始函数和内存仓储复现 F(folder) → D(开启文件级权限) → CF(folder) → FILE:新增 manage 后 D 获得权限,但 CF/FILE 没有;撤销后 CF/FILE 仍保留旧权限;manage 降为 read 后 D 已是 read,CF/FILE 仍为 manage。新增回归测试手动先调用 collection 同步再更新 dataset,未走真实 Pro 入口,因此测试通过仍无法验证生产链路。

请补齐 Pro 的调用顺序修改,并确保依赖版本包含该修复,同时通过真实协作者更新入口验证新增、撤销和降权。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

const children = await MongoDataset.find(
{ teamId, parentId: currentId },
'_id parentId inheritPermission'
'_id parentId inheritPermission collectionPermissionEnabled'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] 在收集阶段剪掉独立子树,并按层批量查询

删除顶部的关闭态短路后,关闭文件权限的 dataset folder 也会进入这段遍历。目前每个节点单独执行一次 MongoDataset.find,且 collectQueue 无条件加入所有子节点;inheritPermission=false 仅在后面的同步阶段跳过,其整棵独立子树仍被扫描并加载 ACL。

内存桩复现 F → I(inheritPermission=false) → 100 个后代时,虽然这些后代不受 F 的授权变化影响,仍触发 102 次目录查询,并将 101 个无关资源 ID 送入 ACL 查询。目录规模增大后,这些串行查询会拉长权限更新事务。

建议沿用 syncResourceTreePermissions 的按层 frontier/$in 查询方式,在收集阶段就停止独立权限分支;开启状态的判断仍按各 dataset 独立执行。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

已修改

# 问题描述(复现步骤)
syncDatasetToCollections 去掉顶部关闭态短路后,folder 入口会完整遍历后代:
每个节点单独执行一次 MongoDataset.find,且 inheritPermission=false 的独立子树
也被无条件收集,随后整批送入 ACL 查询。F → I(independent) → 100 个后代时,
产生 102 次目录查询和 101 个无关资源 ID 的 ACL 读取,全部发生在权限更新事务内,
串行往返会拉长事务。

# 根因分析
- 收集阶段是单节点 BFS,没有按层批量查询;
- inheritPermission 只在同步阶段跳过,收集阶段未剪枝;
- 同步阶段对每个节点扫描全量后代列表找直接子节点,复杂度 O(n²)。

修复:
- 收集阶段改为 frontier + parentId $in 按层查询;
- 继承态判断(shouldInheritResourcePermission)前移到收集阶段,独立分支不遍历、
  不加载 ACL;collectionPermissionEnabled 仍按 dataset 独立判断,不参与剪枝;
- 收集时建立父子邻接表,同步阶段按层下推,去掉全量扫描。

# 测试
- packages/service test/support/permission/collection/controller.test.ts:45/45 通过
  (新增:独立子树不查询后代、不加载其 ACL)
- projects/app test/api/core/dataset/resumeInheritPermission.test.ts、update.test.ts:25/25 通过
- prettier / eslint 通过

Co-Authored-By: Claude <noreply@anthropic.com>

This branch has not been deployed

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants