Skip to content

Commit e0a5c39

Browse files
fix(auth): project legacy knowledge audits
1 parent 1858bad commit e0a5c39

5 files changed

Lines changed: 56 additions & 11 deletions

File tree

apps/sim/lib/core/application/authorized-workspace-use-case.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,17 @@ function isAuthorizationOptionsResolver<
7575
return typeof options === 'function'
7676
}
7777

78-
function recordProjectedAuditEntries<O extends WorkspaceOperation>(
78+
export function recordProjectedUseCaseAuditEntries<O extends WorkspaceOperation>(
7979
operation: O,
80-
context: WorkspaceAuthorizationContext,
81-
attribution: PrincipalAuditAttribution,
80+
workspaceId: string | null | undefined,
81+
principal: PrincipalForOperation<O>,
8282
request: OrchestrationRequestContext | undefined,
8383
entries: readonly WorkspaceUseCaseAuditEntry[]
8484
): void {
85+
const attribution: PrincipalAuditAttribution = resolvePrincipalAuditAttribution(principal)
8586
for (const entry of entries) {
8687
recordAudit({
87-
workspaceId: context.workspaceId,
88+
workspaceId,
8889
actorId: attribution.actorId,
8990
actorName: attribution.actorName,
9091
action: entry.action,
@@ -135,11 +136,10 @@ export function defineAuthorizedWorkspaceUseCase<
135136
if (projectedAudit !== undefined) {
136137
const auditEntries = Array.isArray(projectedAudit) ? projectedAudit : [projectedAudit]
137138
if (auditEntries.length > 0) {
138-
const auditAttribution = resolvePrincipalAuditAttribution(principal)
139-
recordProjectedAuditEntries(
139+
recordProjectedUseCaseAuditEntries(
140140
definition.operation,
141-
context,
142-
auditAttribution,
141+
context.workspaceId,
142+
principal,
143143
request,
144144
auditEntries
145145
)

apps/sim/lib/core/application/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export {
33
type AuthorizedWorkspaceUseCaseDefinition,
44
type AuthorizedWorkspaceUseCaseResultContext,
55
defineAuthorizedWorkspaceUseCase,
6+
recordProjectedUseCaseAuditEntries,
67
type WorkspaceUseCaseAuditEntry,
78
} from '@/lib/core/application/authorized-workspace-use-case'
89
export type {

apps/sim/lib/knowledge/application/authorized-knowledge-use-case.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
defineAuthorizedWorkspaceUseCase,
44
type OperationUseCase,
55
type PrincipalForOperation,
6+
recordProjectedUseCaseAuditEntries,
67
requireAllowedWorkspacePrincipal,
78
type WorkspaceOperation,
89
type WorkspaceUseCaseAuditEntry,
@@ -131,7 +132,21 @@ export function defineAuthorizedKnowledgeUseCase<
131132
}
132133
const executionContext = { principal, input, context, request }
133134
const result = await definition.execute(executionContext)
134-
await definition.afterSuccess?.({ ...executionContext, result })
135+
const resultContext = { ...executionContext, result }
136+
const projectedAudit = definition.projectAudit?.(resultContext)
137+
if (projectedAudit !== undefined) {
138+
const auditEntries = Array.isArray(projectedAudit) ? projectedAudit : [projectedAudit]
139+
if (auditEntries.length > 0) {
140+
recordProjectedUseCaseAuditEntries(
141+
definition.operation,
142+
context.workspaceId,
143+
principal,
144+
request,
145+
auditEntries
146+
)
147+
}
148+
}
149+
await definition.afterSuccess?.(resultContext)
135150
return result
136151
}
137152

apps/sim/lib/knowledge/application/documents.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,37 @@ describe('knowledge document application use cases', () => {
195195
expect(mocks.recordAudit).not.toHaveBeenCalled()
196196
})
197197

198+
it('projects mutation audit entries for an owning legacy personal principal', async () => {
199+
mocks.resolveDocument.mockResolvedValueOnce({
200+
workspaceId: undefined,
201+
legacyPersonalOwnerUserId: 'user-1',
202+
knowledgeBaseId: 'legacy-knowledge',
203+
knowledgeBase: { id: 'legacy-knowledge', name: 'Personal docs', userId: 'user-1' },
204+
documentId: document.id,
205+
document: { ...document, knowledgeBaseId: 'legacy-knowledge' },
206+
})
207+
208+
await deleteKnowledgeDocument.execute({
209+
principal: { kind: 'session', userId: 'user-1', sessionId: 'session-1' },
210+
input: { knowledgeBaseId: 'legacy-knowledge', documentId: document.id, source: 'legacy' },
211+
})
212+
213+
expect(mocks.resolvePermission).not.toHaveBeenCalled()
214+
expect(mocks.recordAudit).toHaveBeenCalledWith(
215+
expect.objectContaining({
216+
workspaceId: undefined,
217+
actorId: 'user-1',
218+
action: 'document.deleted',
219+
resourceId: document.id,
220+
metadata: expect.objectContaining({
221+
operation: 'knowledge.documents.delete',
222+
knowledgeBaseId: 'legacy-knowledge',
223+
actor: { kind: 'session', userId: 'user-1' },
224+
}),
225+
})
226+
)
227+
})
228+
198229
it('conceals legacy personal documents from a non-owner', async () => {
199230
mocks.resolveKnowledgeBase.mockResolvedValueOnce({
200231
workspaceId: undefined,

apps/sim/lib/mcp/middleware.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export interface McpAuthContext {
2424
userEmail?: string | null
2525
authType?: AuthTypeValue
2626
workspaceId: string
27-
canWrite: boolean
2827
requestId: string
2928
/**
3029
* The caller's resolved workspace permission, which satisfies but may exceed
@@ -203,7 +202,6 @@ async function validateMcpAuth(
203202
userEmail: auth.userEmail,
204203
authType: auth.authType,
205204
workspaceId,
206-
canWrite: permissionSatisfies(userPermissions as PermissionType, 'write'),
207205
requestId,
208206
permission: userPermissions,
209207
},

0 commit comments

Comments
 (0)