From 0d46fc2e6471d8b81b096aa410bedec9672b4953 Mon Sep 17 00:00:00 2001 From: Max Techera Date: Mon, 2 Mar 2026 12:21:05 -0300 Subject: [PATCH 1/3] fix(chatflows): allow cross-workspace access --- packages/server/src/controllers/chatflows/index.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/server/src/controllers/chatflows/index.ts b/packages/server/src/controllers/chatflows/index.ts index 0f160d5ca71..1cd70950027 100644 --- a/packages/server/src/controllers/chatflows/index.ts +++ b/packages/server/src/controllers/chatflows/index.ts @@ -134,14 +134,18 @@ const getChatflowById = async (req: Request, res: Response, next: NextFunction) if (typeof req.params === 'undefined' || !req.params.id) { throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsController.getChatflowById - id not provided!`) } - const workspaceId = req.user?.activeWorkspaceId - if (!workspaceId) { + const apiResponse = await chatflowsService.getChatflowById(req.params.id) + const assignedWorkspaces = + (req.user as { assignedWorkspaces?: Array<{ id: string }> } | undefined)?.assignedWorkspaces || [] + const hasWorkspaceAccess = apiResponse.workspaceId + ? assignedWorkspaces.some((ws: { id: string }) => ws.id === apiResponse.workspaceId) + : false + if (!hasWorkspaceAccess) { throw new InternalFlowiseError( StatusCodes.NOT_FOUND, - `Error: chatflowsController.getChatflowById - workspace ${workspaceId} not found!` + `Error: chatflowsController.getChatflowById - chatflow ${req.params.id} not found!` ) } - const apiResponse = await chatflowsService.getChatflowById(req.params.id, workspaceId) return res.json(apiResponse) } catch (error) { next(error) From febef6a44f20fdb45851fdecf61302c3bb49e48a Mon Sep 17 00:00:00 2001 From: Max Techera Date: Mon, 2 Mar 2026 14:27:46 -0300 Subject: [PATCH 2/3] fix(chatflows): scope sidekick listing --- packages/server/src/controllers/chatflows/index.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/server/src/controllers/chatflows/index.ts b/packages/server/src/controllers/chatflows/index.ts index 1cd70950027..3af659a34c3 100644 --- a/packages/server/src/controllers/chatflows/index.ts +++ b/packages/server/src/controllers/chatflows/index.ts @@ -73,8 +73,15 @@ const getAllChatflows = async (req: Request, res: Response, next: NextFunction) try { const { page, limit } = getPageAndLimitParams(req) + const requestSource = req.headers['x-request-from'] + const isSidekickRequest = Array.isArray(requestSource) + ? requestSource.includes('aai') + : requestSource === 'aai' const assignedWorkspaces = (req.user as any)?.assignedWorkspaces as Array<{ id: string }> | undefined - const workspaceIds = assignedWorkspaces && assignedWorkspaces.length > 0 ? assignedWorkspaces.map((ws) => ws.id) : undefined + const workspaceIds = + isSidekickRequest && assignedWorkspaces && assignedWorkspaces.length > 0 + ? assignedWorkspaces.map((ws) => ws.id) + : undefined const workspaceId = workspaceIds ? undefined : req.user?.activeWorkspaceId const apiResponse = await chatflowsService.getAllChatflows( From ae49171aafac10e2d043d1a21e179607361c2930 Mon Sep 17 00:00:00 2001 From: Max Techera Date: Mon, 2 Mar 2026 14:30:29 -0300 Subject: [PATCH 3/3] fix(sidekick): pass workspace ids --- apps/web/app/api/sidekicks/route.ts | 3 ++- packages-answers/utils/src/findSidekicksForChat.ts | 11 ++++++----- packages/server/src/controllers/chatflows/index.ts | 11 ++--------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/apps/web/app/api/sidekicks/route.ts b/apps/web/app/api/sidekicks/route.ts index 17dee12e9da..770d1c209c4 100644 --- a/apps/web/app/api/sidekicks/route.ts +++ b/apps/web/app/api/sidekicks/route.ts @@ -24,7 +24,8 @@ export async function GET(req: Request) { const user = session?.user if (!session?.user?.email) return respond401() try { - const data = await findSidekicksForChat(user, { lightweight }) + const workspaceIds = user?.assignedWorkspaces?.map((workspace) => workspace.id) ?? [] + const data = await findSidekicksForChat(user, { lightweight, workspaceIds }) const sidekicksWithCloneInfo: SidekickSummary[] = data.sidekicks.map((sidekick) => ({ ...sidekick, isExecutable: true diff --git a/packages-answers/utils/src/findSidekicksForChat.ts b/packages-answers/utils/src/findSidekicksForChat.ts index 06d876407d4..f1e7cece7e5 100644 --- a/packages-answers/utils/src/findSidekicksForChat.ts +++ b/packages-answers/utils/src/findSidekicksForChat.ts @@ -30,12 +30,13 @@ interface Sidekick { interface FindSidekicksOptions { lightweight?: boolean + workspaceIds?: string[] } export async function findSidekicksForChat(user: User, options: FindSidekicksOptions = {}) { - const { lightweight = false } = options + const { lightweight = false, workspaceIds } = options - let token + let token: string | undefined try { const { accessToken } = await auth0.getAccessToken({ authorizationParams: { organization: user.org_name } @@ -50,12 +51,12 @@ export async function findSidekicksForChat(user: User, options: FindSidekicksOpt try { // Apply proper visibility filter to only get user's own chatflows and approved public ones const filterParams = `?filter=${encodeURIComponent(JSON.stringify({ visibility: 'AnswerAI,Organization' }))}` + const workspaceIdsParam = workspaceIds && workspaceIds.length > 0 ? `&workspaceIds=${workspaceIds.join(',')}` : '' - const response = await fetch(`${chatflowDomain}/api/v1/chatflows${filterParams}`, { + const response = await fetch(`${chatflowDomain}/api/v1/chatflows${filterParams}${workspaceIdsParam}`, { method: 'GET', headers: { 'Content-Type': 'application/json', - 'x-request-from': 'aai', Authorization: `Bearer ${token}` } }) @@ -201,7 +202,7 @@ export async function findSidekicksForChat(user: User, options: FindSidekicksOpt } else { const result = await response.json() console.error('Chatflow error:', { result }) - if (result.statusCode == 401) throw new Error('Unauthorized') + if (result.statusCode === 401) throw new Error('Unauthorized') return { sidekicks: [], categories: { top: [], more: [] } } } } catch (err) { diff --git a/packages/server/src/controllers/chatflows/index.ts b/packages/server/src/controllers/chatflows/index.ts index 3af659a34c3..eb2048f4df4 100644 --- a/packages/server/src/controllers/chatflows/index.ts +++ b/packages/server/src/controllers/chatflows/index.ts @@ -73,15 +73,8 @@ const getAllChatflows = async (req: Request, res: Response, next: NextFunction) try { const { page, limit } = getPageAndLimitParams(req) - const requestSource = req.headers['x-request-from'] - const isSidekickRequest = Array.isArray(requestSource) - ? requestSource.includes('aai') - : requestSource === 'aai' - const assignedWorkspaces = (req.user as any)?.assignedWorkspaces as Array<{ id: string }> | undefined - const workspaceIds = - isSidekickRequest && assignedWorkspaces && assignedWorkspaces.length > 0 - ? assignedWorkspaces.map((ws) => ws.id) - : undefined + const workspaceIdsQuery = req.query?.workspaceIds as string | undefined + const workspaceIds = workspaceIdsQuery ? workspaceIdsQuery.split(',').filter(Boolean) : undefined const workspaceId = workspaceIds ? undefined : req.user?.activeWorkspaceId const apiResponse = await chatflowsService.getAllChatflows(