fix(upload): enforce the chunked-upload cap on bytes received, not declared
The init route checked the client-declared fileSize against general_max_file_size_mb, but nothing checked what then came through the chunk route: a client could declare `fileSize: 1` and stream any amount, and completeUpload only logged the size mismatch before handing the merged file on. The cap the earlier commit added at init was therefore a gate with no fence. The service now carries the cap from init and enforces it on the running byte total per chunk (aborting the upload once crossed, since the chunks on disk are already over the limit), rejects chunk indices outside the announced range, and re-checks the merged file as a backstop. Both routes answer 413/400 for these instead of a blanket 500.
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
* - a file over the configured cap is rejected with a 400 naming the limit
|
||||
* - the chunked-upload init route honours the same cap (it would otherwise
|
||||
* be a trivial bypass of the multipart route's cap)
|
||||
* - the chunk route enforces the cap on the bytes actually received, so a
|
||||
* client can't declare `fileSize: 1` at init and stream past the limit
|
||||
* - a file under the cap still gets past the size gate
|
||||
* - the limit is read per request, so an admin raising it takes effect
|
||||
*/
|
||||
@@ -127,6 +129,20 @@ describe('admin upload per-file size limit (general_max_file_size_mb)', () => {
|
||||
expect(res.body.error).toBe('File too large. Maximum size is 1 MB per file.');
|
||||
});
|
||||
|
||||
it('rejects chunk bytes over the limit regardless of the declared fileSize', async () => {
|
||||
await setLimitMb(1);
|
||||
const initRes = await postChunkedInit(1);
|
||||
expect(initRes.status).toBe(200);
|
||||
|
||||
const res = await request(app)
|
||||
.post(`/api/admin/photos/${eventId}/chunked-upload/${initRes.body.uploadId}/chunk/0`)
|
||||
.set('Authorization', `Bearer ${adminToken}`)
|
||||
.set('Content-Type', 'application/octet-stream')
|
||||
.send(Buffer.alloc(2 * 1024 * 1024, 0x41));
|
||||
expect(res.status).toBe(413);
|
||||
expect(res.body.error).toBe('File too large. Maximum size is 1 MB per file.');
|
||||
});
|
||||
|
||||
it('lets a file under the limit past the size gate', async () => {
|
||||
await setLimitMb(1);
|
||||
// Junk bytes, so it still fails downstream on the content check — that is
|
||||
|
||||
Reference in New Issue
Block a user