feat: store editor images in upload bind
This commit is contained in:
@@ -61,6 +61,7 @@ test('upload endpoint accepts a short-lived body-bound grant and rejects replay
|
||||
const config = {
|
||||
maxBodyBytes: 4096,
|
||||
maxUploadBytes: 51200,
|
||||
maxContentUploadBytes: 1048576,
|
||||
syncClientSecrets: { core: 's'.repeat(32) },
|
||||
uploadClientSecrets: { core2026: secret },
|
||||
publicBases: ['https://sam-image.hided.net', 'https://sam.hided.net/image'],
|
||||
@@ -86,6 +87,7 @@ test('upload endpoint accepts a short-lived body-bound grant and rejects replay
|
||||
assert.equal(accepted.status, 201);
|
||||
assert.deepEqual(calls[0], {
|
||||
requestKey: `core2026:${requestId}`,
|
||||
category: 'user-icons',
|
||||
client: 'core2026',
|
||||
filename: `${'a'.repeat(32)}.png`,
|
||||
body,
|
||||
@@ -95,6 +97,31 @@ test('upload endpoint accepts a short-lived body-bound grant and rejects replay
|
||||
`https://sam.hided.net/image/icons/users/core2026/${'a'.repeat(32)}.png`,
|
||||
]);
|
||||
|
||||
const contentPath = `/v1/uploads/content/core2026/${'b'.repeat(32)}.webp`;
|
||||
const contentBody = Buffer.concat([Buffer.from('RIFF'), Buffer.alloc(4), Buffer.from('WEBP'), Buffer.alloc(4)]);
|
||||
const contentRequestId = 'content-request-1234';
|
||||
const contentSignature = uploadSignature(secret, {
|
||||
expires,
|
||||
requestId: contentRequestId,
|
||||
pathname: contentPath,
|
||||
contentType: 'image/webp',
|
||||
body: contentBody,
|
||||
});
|
||||
const contentResponse = await fetch(`http://127.0.0.1:${address.port}${contentPath}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'content-type': 'image/webp',
|
||||
'x-image-client': 'core2026',
|
||||
'x-image-expires': expires,
|
||||
'x-image-request-id': contentRequestId,
|
||||
'x-image-signature': contentSignature,
|
||||
},
|
||||
body: contentBody,
|
||||
});
|
||||
assert.equal(contentResponse.status, 201);
|
||||
assert.equal(calls[1].category, 'content');
|
||||
assert.equal(calls[1].filename, `${'b'.repeat(32)}.webp`);
|
||||
|
||||
const tampered = await fetch(`http://127.0.0.1:${address.port}${pathname}`, {
|
||||
method: 'PUT', headers, body: Buffer.from('89504e470d0a1a0affffffff', 'hex'),
|
||||
});
|
||||
|
||||
@@ -13,19 +13,20 @@ test('stores uploads only in the bind directory and persists replay state', asyn
|
||||
const filename = `${'a'.repeat(32)}.png`;
|
||||
const store = new UploadStore(config);
|
||||
await store.initialize();
|
||||
const first = await store.store({ requestKey: 'core2026:request-1', client: 'core2026', filename, body });
|
||||
const first = await store.store({ requestKey: 'core2026:request-1', category: 'user-icons', client: 'core2026', filename, body });
|
||||
assert.deepEqual(first, { duplicate: false, path: `icons/users/core2026/${filename}` });
|
||||
assert.equal(await readFile(join(root, 'uploads', 'core2026', filename), 'utf8'), 'immutable image bytes');
|
||||
assert.equal(await readFile(join(root, 'uploads', 'user-icons', 'core2026', filename), 'utf8'), 'immutable image bytes');
|
||||
|
||||
const restarted = new UploadStore(config);
|
||||
await restarted.initialize();
|
||||
assert.deepEqual(
|
||||
await restarted.store({ requestKey: 'core2026:request-1', client: 'core2026', filename, body }),
|
||||
await restarted.store({ requestKey: 'core2026:request-1', category: 'user-icons', client: 'core2026', filename, body }),
|
||||
{ duplicate: true, path: `icons/users/core2026/${filename}` },
|
||||
);
|
||||
await assert.rejects(
|
||||
restarted.store({
|
||||
requestKey: 'core2026:request-1',
|
||||
category: 'user-icons',
|
||||
client: 'core2026',
|
||||
filename: `${'b'.repeat(32)}.png`,
|
||||
body,
|
||||
@@ -33,7 +34,18 @@ test('stores uploads only in the bind directory and persists replay state', asyn
|
||||
/already used/,
|
||||
);
|
||||
await assert.rejects(
|
||||
restarted.store({ requestKey: 'core2026:request-2', client: '../escape', filename, body }),
|
||||
restarted.store({ requestKey: 'core2026:request-2', category: 'user-icons', client: '../escape', filename, body }),
|
||||
/Invalid upload path/,
|
||||
);
|
||||
const contentFilename = `${'c'.repeat(32)}.webp`;
|
||||
assert.deepEqual(
|
||||
await restarted.store({
|
||||
requestKey: 'core2026:content-1',
|
||||
category: 'content',
|
||||
client: 'core2026',
|
||||
filename: contentFilename,
|
||||
body: Buffer.from('content image'),
|
||||
}),
|
||||
{ duplicate: false, path: `uploads/core2026/${contentFilename}` },
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user