Skip to content

Commit 0bc1fb9

Browse files
fix(files): validate ensured folder paths
1 parent c64d74f commit 0bc1fb9

2 files changed

Lines changed: 21 additions & 4 deletions

File tree

apps/sim/lib/uploads/contexts/workspace/workspace-file-folder-manager.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
*/
44

55
import { describe, expect, it } from 'vitest'
6+
import { MAX_FOLDER_PATH_SEGMENTS } from '@/lib/folders/paths'
67
import {
78
buildWorkspaceFileFolderPathMap,
9+
ensureWorkspaceFileFolderPath,
810
normalizeWorkspaceFileItemName,
9-
} from './workspace-file-folder-manager'
11+
} from '@/lib/uploads/contexts/workspace/workspace-file-folder-manager'
1012

1113
describe('workspace file folder paths', () => {
1214
it('builds nested paths from parent relationships', () => {
@@ -30,4 +32,14 @@ describe('workspace file folder paths', () => {
3032
'File name cannot contain path separators or dot segments'
3133
)
3234
})
35+
36+
it('rejects oversized ensured paths before persisting any folders', async () => {
37+
await expect(
38+
ensureWorkspaceFileFolderPath({
39+
workspaceId: 'workspace-1',
40+
userId: 'user-1',
41+
pathSegments: Array.from({ length: MAX_FOLDER_PATH_SEGMENTS + 1 }, () => 'nested'),
42+
})
43+
).rejects.toThrow(`Folder paths cannot exceed ${MAX_FOLDER_PATH_SEGMENTS} segments`)
44+
})
3345
})

apps/sim/lib/uploads/contexts/workspace/workspace-file-folder-manager.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { DbOrTx } from '@/lib/db/types'
99
import { acquireFolderMutationLock } from '@/lib/folders/locks'
1010
import { deduplicateFolderName } from '@/lib/folders/naming'
1111
import {
12+
buildFolderPath,
1213
buildFolderPathIndex,
1314
folderNameFromPath,
1415
parentFolderPath,
@@ -558,10 +559,15 @@ export async function ensureWorkspaceFileFolderPath(params: {
558559
}): Promise<string | null> {
559560
if (params.pathSegments.length === 0) return null
560561

562+
const pathSegments = params.pathSegments.map((segment) =>
563+
normalizeWorkspaceFileItemName(segment, 'Folder')
564+
)
565+
buildFolderPath(pathSegments)
566+
561567
// Fast path: the whole chain already exists (the common case for repeated
562568
// writes into known folders) — per-segment indexed lookups instead of
563569
// loading the workspace's entire folder table.
564-
const existing = await findWorkspaceFileFolderIdByPath(params.workspaceId, params.pathSegments)
570+
const existing = await findWorkspaceFileFolderIdByPath(params.workspaceId, pathSegments)
565571
if (existing) return existing
566572

567573
// Load all active folders once and build a lookup keyed by "name|parentId"
@@ -585,8 +591,7 @@ export async function ensureWorkspaceFileFolderPath(params: {
585591

586592
let parentId: string | null = null
587593

588-
for (const rawSegment of params.pathSegments) {
589-
const name = normalizeWorkspaceFileItemName(rawSegment, 'Folder')
594+
for (const name of pathSegments) {
590595
const lookupKey = `${name}|${parentId ?? ''}`
591596

592597
const cached = folderByNameParent.get(lookupKey)

0 commit comments

Comments
 (0)