feat(server): filter docs by access role (#12311)

close CLOUD-208

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Enhanced document access control with batch permission checks, enabling efficient filtering of documents based on user roles and permissions.
  - Added detailed document-level role and permission management for workspace users.
- **Bug Fixes**
  - Improved accuracy in filtering search results to only display documents users have permission to read.
- **Tests**
  - Added comprehensive tests for document-level permission filtering and search result accuracy.
  - Introduced new mock utilities to support permission-related test scenarios.
- **Refactor**
  - Simplified and optimized permission logic for determining user roles and document access.
- **Documentation**
  - Updated type definitions for improved clarity in permission handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
fengmk2
2025-05-19 03:28:22 +00:00
parent 85bb728ca8
commit 1e7774929c
16 changed files with 703 additions and 87 deletions

View File

@@ -113,6 +113,10 @@ export class IndexerResolver {
user: UserType,
nodes: SearchNodeWithMeta[]
) {
if (nodes.length === 0) {
return nodes;
}
const isTeamWorkspace = await this.models.workspaceFeature.has(
workspace.id,
'team_plan_v1'
@@ -120,17 +124,17 @@ export class IndexerResolver {
if (!isTeamWorkspace) {
return nodes;
}
const needs: SearchNodeWithMeta[] = [];
// TODO(@fengmk2): CLOUD-208 support batch check
for (const node of nodes) {
const canRead = await this.ac
.user(user.id)
.doc(node._source.workspaceId, node._source.docId)
.can('Doc.Read');
if (canRead) {
needs.push(node);
}
}
return needs;
const needs = await this.ac
.user(user.id)
.workspace(workspace.id)
.docs(
nodes.map(node => ({
node,
docId: node._source.docId,
})),
'Doc.Read'
);
return needs.map(node => node.node);
}
}