Skip to content
8 changes: 8 additions & 0 deletions apps/sim/lib/copilot/chat/post.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,18 @@ vi.mock('@sim/db', () => ({
})),
})),
})),
select: vi.fn(() => ({
from: vi.fn(() => ({
where: vi.fn(() => ({
limit: vi.fn().mockResolvedValue([{ permissionType: 'write' }]),
})),
})),
})),
},
}))

vi.mock('drizzle-orm', () => ({
and: vi.fn(() => ({})),
eq: vi.fn(() => ({})),
sql: (strings: TemplateStringsArray, ...values: unknown[]) => ({ strings, values }),
}))
Expand Down
34 changes: 24 additions & 10 deletions apps/sim/lib/copilot/chat/post.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { type Context as OtelContext, context as otelContextApi } from '@opentelemetry/api'
import { db } from '@sim/db'
import { copilotChats } from '@sim/db/schema'
import { copilotChats, permissions } from '@sim/db/schema'
import { createLogger } from '@sim/logger'
import { generateId } from '@sim/utils/id'
import { eq, sql } from 'drizzle-orm'
import { and, eq, sql } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { isZodError, validationErrorResponse } from '@/lib/api/server'
Expand Down Expand Up @@ -506,14 +506,12 @@ async function resolveBranch(params: {
}

const resolvedWorkflowId = resolved.workflowId
let resolvedWorkspaceId = requestedWorkspaceId
if (!resolvedWorkspaceId) {
try {
const workflow = await getWorkflowById(resolvedWorkflowId)
resolvedWorkspaceId = workflow?.workspaceId ?? undefined
} catch {
// best effort; downstream calls can still proceed
}
let resolvedWorkspaceId: string | undefined
try {
const workflow = await getWorkflowById(resolvedWorkflowId)
resolvedWorkspaceId = workflow?.workspaceId ?? requestedWorkspaceId
} catch {
resolvedWorkspaceId = requestedWorkspaceId
}

const selectedModel = model || DEFAULT_MODEL
Expand Down Expand Up @@ -569,6 +567,22 @@ async function resolveBranch(params: {
return createBadRequestResponse('workspaceId is required when workflowId is not provided')
}

const [permissionRow] = await db
.select({ permissionType: permissions.permissionType })
.from(permissions)
.where(
and(
eq(permissions.userId, authenticatedUserId),
eq(permissions.entityType, 'workspace'),
eq(permissions.entityId, requestedWorkspaceId)
)
)
.limit(1)

if (!permissionRow) {
return createBadRequestResponse('Workspace not found or access denied')
}
Comment thread
waleedlatif1 marked this conversation as resolved.

return {
kind: 'workspace',
workspaceId: requestedWorkspaceId,
Expand Down
20 changes: 12 additions & 8 deletions apps/sim/lib/copilot/chat/process-contents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ export async function processContextsServer(
currentWorkspaceId
)
}
if (ctx.kind === 'table' && ctx.tableId) {
const result = await resolveTableResource(ctx.tableId)
if (ctx.kind === 'table' && ctx.tableId && currentWorkspaceId) {
const result = await resolveTableResource(ctx.tableId, currentWorkspaceId)
if (!result) return null
return { type: 'table', tag: ctx.label ? `@${ctx.label}` : '@', content: result.content }
}
Expand Down Expand Up @@ -701,18 +701,18 @@ export async function resolveActiveResourceContext(
resourceType: string,
resourceId: string,
workspaceId: string,
_userId: string,
userId: string,
chatId?: string
): Promise<AgentContext | null> {
try {
switch (resourceType) {
case 'workflow': {
const ctx = await processWorkflowFromDb(
resourceId,
undefined,
userId,
'@active_resource',
'current_workflow',
undefined,
workspaceId,
chatId
)
if (!ctx) return null
Expand All @@ -721,15 +721,15 @@ export async function resolveActiveResourceContext(
case 'knowledgebase': {
const ctx = await processKnowledgeFromDb(
resourceId,
undefined,
userId,
'@active_resource',
workspaceId
)
if (!ctx) return null
return { type: 'active_resource', tag: '@active_resource', content: ctx.content }
}
case 'table': {
return await resolveTableResource(resourceId)
return await resolveTableResource(resourceId, workspaceId)
}
case 'file': {
return await resolveFileResource(resourceId, workspaceId)
Expand All @@ -745,9 +745,13 @@ export async function resolveActiveResourceContext(
return null
}
}
async function resolveTableResource(tableId: string): Promise<AgentContext | null> {
async function resolveTableResource(
tableId: string,
workspaceId: string
): Promise<AgentContext | null> {
const table = await getTableById(tableId)
if (!table) return null
if (table.workspaceId !== workspaceId) return null
Comment thread
waleedlatif1 marked this conversation as resolved.
return {
type: 'active_resource',
tag: '@active_resource',
Expand Down
3 changes: 1 addition & 2 deletions apps/sim/lib/data-drains/destinations/webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,11 @@ function sign(body: Buffer, secret: string, timestamp: number): string {
function sleepUntilAborted(ms: number, signal: AbortSignal): Promise<void> {
if (signal.aborted) return Promise.resolve()
return new Promise((resolve) => {
let timeoutId: ReturnType<typeof setTimeout>
const onAbort = () => {
clearTimeout(timeoutId)
resolve()
}
timeoutId = setTimeout(() => {
const timeoutId = setTimeout(() => {
signal.removeEventListener('abort', onAbort)
resolve()
}, ms)
Expand Down
Loading