55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
|
|
import config from '../src/config.ts';
|
|
import {
|
|
createErrorResponse,
|
|
generatePresignedUrls,
|
|
isValidPath,
|
|
} from '../src/services/file.ts';
|
|
|
|
void test('isValidPath allows relative storage keys and rejects traversal or protocol inputs', () => {
|
|
assert.equal(isValidPath('projects/demo/image.jpg'), true);
|
|
assert.equal(isValidPath('nested/folder/video.mp4'), true);
|
|
|
|
assert.equal(isValidPath('../secret.txt'), false);
|
|
assert.equal(isValidPath('folder/../../secret.txt'), false);
|
|
assert.equal(isValidPath('https://example.test/file.jpg'), false);
|
|
assert.equal(isValidPath('s3://bucket/file.jpg'), false);
|
|
assert.equal(isValidPath('folder//file.jpg'), false);
|
|
assert.equal(isValidPath('folder/\0/file.jpg'), false);
|
|
assert.equal(isValidPath(' '), false);
|
|
assert.equal(isValidPath(null), false);
|
|
});
|
|
|
|
void test('createErrorResponse returns a stable structured error payload', () => {
|
|
assert.deepEqual(
|
|
createErrorResponse('Invalid file paths detected', 'INVALID_PATH', {
|
|
invalidPaths: ['../secret.txt'],
|
|
}),
|
|
{
|
|
message: 'Invalid file paths detected',
|
|
code: 'INVALID_PATH',
|
|
details: {
|
|
invalidPaths: ['../secret.txt'],
|
|
},
|
|
},
|
|
);
|
|
});
|
|
|
|
void test('generatePresignedUrls returns backend download URLs for local storage provider', async () => {
|
|
const previousProvider = config.fileStorage.provider;
|
|
config.fileStorage.provider = 'local';
|
|
try {
|
|
assert.deepEqual(
|
|
await generatePresignedUrls(['projects/demo/image 1.jpg']),
|
|
{
|
|
'projects/demo/image 1.jpg':
|
|
'/api/file/download?privateUrl=projects%2Fdemo%2Fimage%201.jpg',
|
|
},
|
|
);
|
|
} finally {
|
|
config.fileStorage.provider = previousProvider;
|
|
}
|
|
});
|