update framework

This commit is contained in:
2026-07-22 10:25:02 +07:00
parent 3da8608cf1
commit a836645728
6 changed files with 160 additions and 124 deletions

View File

@@ -5,6 +5,8 @@ WEB_SERVER_PORT=3005
IMAGE_TAG=1.0.0
DOCKER_NETWORK=robot-installer-net
WEB_SERVER_UPLOADS_DIR=./uploads
MAX_UPLOAD_BYTES=1073741824
AGENT_MAX_UPLOAD_BYTES=1073741824
SQLSERVER_HOST=172.20.235.176
SQLSERVER_PORT=1433
SQLSERVER_DATABASE=RobotInstaller

View File

@@ -14,8 +14,8 @@
"ejs": "^3.1.10",
"express": "^4.19.2",
"mssql": "^12.5.4",
"multer": "^2.1.1",
"nodemailer": "^8.0.7",
"multer": "^2.2.0",
"nodemailer": "^9.0.3",
"notiflix": "^3.2.8"
}
},
@@ -444,9 +444,9 @@
}
},
"node_modules/body-parser": {
"version": "1.20.5",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
"integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
"version": "1.20.6",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz",
"integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
@@ -468,9 +468,9 @@
}
},
"node_modules/brace-expansion": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz",
"integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -1436,9 +1436,9 @@
"license": "MIT"
},
"node_modules/multer": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz",
"integrity": "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/multer/-/multer-2.2.0.tgz",
"integrity": "sha512-6rdyFg2kLrMh9Jee7/BMPuV9lEAd7lLW2YUpF9/YxR7njyoUwwQ0ZPh3TaIY50Sw6vlyD2HW3wGOkTS4P79xrQ==",
"license": "MIT",
"dependencies": {
"append-field": "^1.0.0",
@@ -1470,9 +1470,9 @@
}
},
"node_modules/nodemailer": {
"version": "8.0.7",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.7.tgz",
"integrity": "sha512-pkjE4mkBzQjdJT4/UmlKl3pX0rC9fZmjh7c6C9o7lv66Ac6w9WCnzPzhbPNxwZAzlF4mdq4CSWB5+FbK6FWCow==",
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-9.0.3.tgz",
"integrity": "sha512-n+YP+NKwR5zRWa60k3GiQ6Q3B4KXCoAw40dAKeCtYn020iNN74aWK2liXIC3ZEATeGql7we3tE3t8QwhY0eskw==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"

View File

@@ -15,8 +15,8 @@
"ejs": "^3.1.10",
"express": "^4.19.2",
"mssql": "^12.5.4",
"multer": "^2.1.1",
"nodemailer": "^8.0.7",
"multer": "^2.2.0",
"nodemailer": "^9.0.3",
"notiflix": "^3.2.8"
}
}

View File

@@ -106,9 +106,19 @@ const agentStorage = multer.diskStorage({
}
});
const multipartLimits = Object.freeze({
fieldNameSize: 64,
fieldNestingDepth: 0,
fieldSize: 64 * 1024,
fields: 16,
files: 1,
parts: 17
});
const upload = multer({
storage,
limits: {
...multipartLimits,
fileSize: Number(process.env.MAX_UPLOAD_BYTES || 1024 * 1024 * 1024)
}
});
@@ -116,6 +126,7 @@ const upload = multer({
const agentUpload = multer({
storage: agentStorage,
limits: {
...multipartLimits,
fileSize: Number(process.env.AGENT_MAX_UPLOAD_BYTES || process.env.MAX_UPLOAD_BYTES || 1024 * 1024 * 1024)
}
});
@@ -123,7 +134,7 @@ const agentUpload = multer({
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.urlencoded({ extended: true }));
app.use(express.urlencoded({ extended: true, limit: '32kb', parameterLimit: 100 }));
app.use(express.json({ limit: '32kb' }));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/vendor/notiflix', express.static(path.join(__dirname, 'node_modules/notiflix/dist')));
@@ -2450,6 +2461,29 @@ app.get('/builder', asyncRoute(async (req, res) => {
}));
app.use(async (error, req, res, next) => {
if (error instanceof multer.MulterError) {
const uploadErrorMessages = {
LIMIT_FIELD_COUNT: 'Biểu mẫu upload có quá nhiều trường.',
LIMIT_FIELD_KEY: 'Tên trường upload quá dài.',
LIMIT_FIELD_NESTING: 'Tên trường upload không đúng định dạng.',
LIMIT_FIELD_VALUE: 'Nội dung một trường upload quá dài.',
LIMIT_FILE_COUNT: 'Chỉ được upload một file mỗi lần.',
LIMIT_FILE_SIZE: 'File upload vượt quá dung lượng cho phép.',
LIMIT_PART_COUNT: 'Biểu mẫu upload có quá nhiều thành phần.',
LIMIT_UNEXPECTED_FILE: 'Trường file upload không hợp lệ.'
};
const returnPath = req.path.startsWith('/agent/') ? '/agent' : '/packages';
console.warn(`Rejected multipart upload (${error.code || 'UNKNOWN'}):`, error.message);
redirectWithNotice(
res,
returnPath,
'warning',
uploadErrorMessages[error.code] || 'Biểu mẫu upload không hợp lệ.'
);
return;
}
console.error(error);
if (req.path.startsWith('/api/notifications')) {