From 918b3b2dab7d6a5089cee0fc3ebc892a2c496c9a Mon Sep 17 00:00:00 2001 From: darkskygit Date: Fri, 9 May 2025 07:35:47 +0000 Subject: [PATCH] feat(server): permission check for workspace doc match (#12139) ## Summary by CodeRabbit - **Bug Fixes** - Improved permission checks to ensure users only see document chunks they have read access to. - Enhanced error handling for clearer and more user-friendly error messages. --- .../src/plugins/copilot/context/resolver.ts | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/packages/backend/server/src/plugins/copilot/context/resolver.ts b/packages/backend/server/src/plugins/copilot/context/resolver.ts index faffed4cf0..52b8f29be1 100644 --- a/packages/backend/server/src/plugins/copilot/context/resolver.ts +++ b/packages/backend/server/src/plugins/copilot/context/resolver.ts @@ -710,28 +710,44 @@ export class CopilotContextResolver { return []; } - const session = await this.context.get(context.id); - await this.ac - .user(user.id) - .workspace(session.workspaceId) - .allowLocal() - .assert('Workspace.Copilot'); - const allowEmbedding = await this.models.workspace.allowEmbedding( - session.workspaceId - ); - if (!allowEmbedding) { - return []; - } - try { - return await session.matchWorkspaceChunks( + const session = await this.context.get(context.id); + await this.ac + .user(user.id) + .workspace(session.workspaceId) + .allowLocal() + .assert('Workspace.Copilot'); + const allowEmbedding = await this.models.workspace.allowEmbedding( + session.workspaceId + ); + if (!allowEmbedding) { + return []; + } + + const chunks = await session.matchWorkspaceChunks( content, limit, this.getSignal(ctx.req), scopedThreshold, threshold ); + const docsMap = await Promise.all( + chunks.map(c => + this.ac + .user(user.id) + .workspace(session.workspaceId) + .doc(c.docId) + .can('Doc.Read') + .then(ret => [c.docId, ret] as const) + ) + ).then(r => new Map(r)); + + return chunks.filter(c => docsMap.get(c.docId)); } catch (e: any) { + // passthrough user friendly error + if (e instanceof UserFriendlyError) { + throw e; + } throw new CopilotFailedToMatchContext({ contextId: context.id, // don't record the large content