Skip to content

Commit b3f4cc0

Browse files
committed
Avoid relying fully on multer
1 parent 783d908 commit b3f4cc0

2 files changed

Lines changed: 40 additions & 5 deletions

File tree

src/main/app/document/DocumentManagementController.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { Response } from 'express';
33
import { v4 as generateUuid } from 'uuid';
44
import { LoggerInstance } from 'winston';
55

6+
import { HTTPError } from '../../steps/error/error.controller';
67
import {
78
APPLICANT_2,
89
DETAILS_OTHER_PROCEEDINGS,
@@ -30,6 +31,7 @@ import type { AppRequest, UserDetails } from '../controller/AppRequest';
3031

3132
import { CaseDocumentManagementClient, Classification } from './CaseDocumentManagementClient';
3233
import { userCanUploadDocuments } from './DocumentManagementConstants';
34+
import { MAX_UPLOAD_FILE_SIZE_BYTES } from './DocumentUploadLimits';
3335
import FileUploadJourneyConfigurationMap, { FileUploadJourneyConfiguration } from './FileUploadJourneyConfiguration';
3436

3537
@autobind
@@ -86,8 +88,16 @@ export class DocumentManagerController {
8688
}
8789
}
8890

91+
const uploadedFiles = (
92+
Array.isArray(req.files) ? req.files : Object.values(req.files).flat()
93+
) as Express.Multer.File[];
94+
95+
if (uploadedFiles.some(file => file.size > MAX_UPLOAD_FILE_SIZE_BYTES)) {
96+
throw new HTTPError('Uploaded file exceeds the limit', 413);
97+
}
98+
8999
const filesCreated = await this.getApiClient(req.session.user).create({
90-
files: req.files,
100+
files: uploadedFiles,
91101
classification: Classification.Public,
92102
});
93103

src/main/routes.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { AppRequest } from './app/controller/AppRequest';
1010
import { GetController } from './app/controller/GetController';
1111
import { PostController } from './app/controller/PostController';
1212
import { DocumentManagerController } from './app/document/DocumentManagementController';
13+
import { MAX_UPLOAD_FILE_COUNT, MAX_UPLOAD_FILE_SIZE_BYTES } from './app/document/DocumentUploadLimits';
1314
import { getUserSequence, stepsWithContent } from './steps';
1415
import { AccessibilityStatementGetController } from './steps/accessibility-statement/get';
1516
import * as applicant1AccessCodeContent from './steps/applicant1/enter-your-access-code/content';
@@ -22,7 +23,7 @@ import { ApplicationWithdrawnGetController } from './steps/application-withdrawn
2223
import { ContactUsGetController } from './steps/contact-us/get';
2324
import { CookiesGetController } from './steps/cookies/get';
2425
import { DraftApplicationSaveSignOutGetController } from './steps/draft-application-save-sign-out/get';
25-
import { ErrorController } from './steps/error/error.controller';
26+
import { ErrorController, HTTPError } from './steps/error/error.controller';
2627
import * as existingApplicationContent from './steps/existing-application/content';
2728
import { ExistingApplicationGetController } from './steps/existing-application/get';
2829
import { ExistingApplicationPostController } from './steps/existing-application/post';
@@ -70,11 +71,35 @@ import { WebChatGetController } from './steps/webchat/get';
7071

7172
const handleUploads = multer({
7273
limits: {
73-
fileSize: 25 * 1024 * 1024,
74-
files: 5,
74+
fileSize: MAX_UPLOAD_FILE_SIZE_BYTES,
75+
files: MAX_UPLOAD_FILE_COUNT,
7576
},
7677
});
7778

79+
const uploadFilesMiddleware: RequestHandler = (req, res, next) => {
80+
handleUploads.array('files[]', MAX_UPLOAD_FILE_COUNT)(req, res, err => {
81+
if (!err) {
82+
return next();
83+
}
84+
85+
if (err instanceof multer.MulterError) {
86+
(req as AppRequest).locals?.logger?.warn(
87+
`Multer rejected upload(code=${err.code}, contentLength=${req.headers['content-length'] || 'n/a'})`
88+
);
89+
90+
if (err.code === 'LIMIT_FILE_SIZE') {
91+
return next(new HTTPError('Uploaded file exceeds the 25MB limit', 413));
92+
}
93+
94+
if (err.code === 'LIMIT_FILE_COUNT') {
95+
return next(new HTTPError('Uploaded file count exceeds the allowed limit', 400));
96+
}
97+
}
98+
99+
return next(err);
100+
});
101+
};
102+
78103
const ext = extname(__filename);
79104

80105
export class Routes {
@@ -111,7 +136,7 @@ export class Routes {
111136
app.post(POSTCODE_LOOKUP, errorHandler(new PostcodeLookupPostController().post));
112137

113138
const documentManagerController = new DocumentManagerController();
114-
app.post(DOCUMENT_MANAGER, handleUploads.array('files[]', 5), errorHandler(documentManagerController.post));
139+
app.post(DOCUMENT_MANAGER, uploadFilesMiddleware, errorHandler(documentManagerController.post));
115140
app.get(`${DOCUMENT_MANAGER}/delete/:index`, errorHandler(documentManagerController.delete));
116141

117142
for (const step of stepsWithContent) {

0 commit comments

Comments
 (0)