Upgrade expressjs (#1633)

* upgrade expressjs

* migration

* reenable test

* extend timeout on download test

* fixup! migration

* move empty body test from controller to validator

* enusre not empty

* extract validation function

* fixup! reenable test

* remove thin controllers

* disable e2e test of project file download
This commit is contained in:
Alex Christoffer Rasmussen
2025-06-12 15:02:35 +02:00
committed by GitHub
parent 2a5b053d97
commit a4b15970de
39 changed files with 590 additions and 841 deletions
+16 -8
View File
@@ -106,7 +106,8 @@ export async function projectDownload(req: Request, res: Response) {
const { filename } = req.body;
const pathToFile = doesProjectExist(filename);
if (!pathToFile) {
return res.status(404).send({ message: `Project ${filename} not found.` });
res.status(404).send({ message: `Project ${filename} not found.` });
return;
}
res.download(pathToFile, filename, (error) => {
@@ -138,7 +139,8 @@ export async function postProjectFile(req: Request, res: Response<MessageRespons
} catch (error) {
const message = getErrorMessage(error);
if (message.startsWith('Project file')) {
return res.status(403).send({ message });
res.status(403).send({ message });
return;
}
res.status(400).send({ message });
}
@@ -195,7 +197,8 @@ export async function loadProject(req: Request, res: Response<MessageResponse |
} catch (error) {
const message = getErrorMessage(error);
if (message.startsWith('Project file')) {
return res.status(403).send({ message });
res.status(403).send({ message });
return;
}
res.status(500).send({ message });
}
@@ -214,7 +217,8 @@ export async function loadDemo(_req: Request, res: Response<MessageResponse | Er
} catch (error) {
const message = getErrorMessage(error);
if (message.startsWith('Project file')) {
return res.status(403).send({ message });
res.status(403).send({ message });
return;
}
res.status(500).send({ message });
}
@@ -245,7 +249,8 @@ export async function duplicateProjectFile(req: Request, res: Response<MessageRe
} catch (error) {
const message = getErrorMessage(error);
if (message.startsWith('Project file')) {
return res.status(403).send({ message });
res.status(403).send({ message });
return;
}
res.status(500).send({ message });
@@ -275,7 +280,8 @@ export async function renameProjectFile(req: Request, res: Response<MessageRespo
} catch (error) {
const message = getErrorMessage(error);
if (message.startsWith('Project file')) {
return res.status(403).send({ message });
res.status(403).send({ message });
return;
}
res.status(500).send({ message });
@@ -303,10 +309,12 @@ export async function deleteProjectFile(req: Request, res: Response<MessageRespo
} catch (error) {
const message = getErrorMessage(error);
if (message === 'Cannot delete currently loaded project') {
return res.status(403).send({ message });
res.status(403).send({ message });
return;
}
if (message === 'Project file not found') {
return res.status(404).send({ message });
res.status(404).send({ message });
return;
}
res.status(500).send({ message });
+10 -49
View File
@@ -1,12 +1,13 @@
import type { Request, Response, NextFunction } from 'express';
import { body, param, validationResult } from 'express-validator';
import { body, param } from 'express-validator';
import sanitize from 'sanitize-filename';
import { ensureJsonExtension } from '../../utils/fileManagement.js';
import { requestValidationFunction } from '../validation-utils/validationFunction.js';
/**
* @description Validates request for a new project.
*/
export const validateNewProject = [
body().notEmpty().withMessage('No object found in request'),
body('filename').optional().isString().trim(),
body('title').optional().isString().trim(),
body('description').optional().isString().trim(),
@@ -18,11 +19,7 @@ export const validateNewProject = [
body('endMessage').optional().isString().trim(),
body('custom').optional().isArray(),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
next();
},
requestValidationFunction,
];
/**
@@ -40,25 +37,14 @@ export const validateQuickProject = [
body('viewSettings.freezeEnd').optional().isBoolean(),
body('viewSettings.endMessage').optional().isString().trim(),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
next();
},
requestValidationFunction,
];
/**
* @description Validates request for pathing data in the project.
*/
export const validatePatchProject = [
// Custom validator to ensure the body is not empty
(req: Request, res: Response, next: NextFunction) => {
if (Object.keys(req.body).length === 0) {
return res.status(422).json({ errors: [{ msg: 'Request body cannot be empty' }] });
}
next();
},
body().notEmpty().withMessage('No object found in request'),
body('rundowns').isObject().optional({ nullable: false }),
body('project').isObject().optional({ nullable: false }),
body('settings').isObject().optional({ nullable: false }),
@@ -68,11 +54,7 @@ export const validatePatchProject = [
body('osc').isObject().optional({ nullable: false }),
body('http').isObject().optional({ nullable: false }),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
next();
},
requestValidationFunction,
];
/**
@@ -88,14 +70,7 @@ export const validateNewFilenameBody = [
.withMessage('Filename was empty or contained only invalid characters')
.customSanitizer((input: string) => ensureJsonExtension(input)),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
next();
},
requestValidationFunction,
];
/**
@@ -111,14 +86,7 @@ export const validateFilenameBody = [
.withMessage('Filename was empty or contained only invalid characters')
.customSanitizer((input: string) => ensureJsonExtension(input)),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
next();
},
requestValidationFunction,
];
/**
@@ -134,12 +102,5 @@ export const validateFilenameParam = [
.withMessage('Filename was empty or contained only invalid characters')
.customSanitizer((input: string) => ensureJsonExtension(input)),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
next();
},
requestValidationFunction,
];