mirror of
https://github.com/plankanban/planka.git
synced 2025-12-25 09:15:00 +03:00
feat: Improve mime type detection, limit image processing size
This commit is contained in:
@@ -26,8 +26,10 @@
|
||||
display: flex;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
height: fit-content;
|
||||
justify-content: center;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
const fsPromises = require('fs').promises;
|
||||
const { rimraf } = require('rimraf');
|
||||
const { fileTypeFromFile } = require('file-type');
|
||||
const { getEncoding } = require('istextorbinary');
|
||||
const mime = require('mime');
|
||||
const sharp = require('sharp');
|
||||
|
||||
const filenamify = require('../../../utils/filenamify');
|
||||
const { MAX_SIZE_TO_GET_ENCODING } = require('../../../constants');
|
||||
const { MAX_SIZE_TO_GET_ENCODING, MAX_SIZE_TO_PROCESS_AS_IMAGE } = require('../../../constants');
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
@@ -24,7 +24,8 @@ module.exports = {
|
||||
const fileManager = sails.hooks['file-manager'].getInstance();
|
||||
|
||||
const filename = filenamify(inputs.file.filename);
|
||||
const mimeType = mime.getType(filename);
|
||||
const fileType = await fileTypeFromFile(inputs.file.fd);
|
||||
const { mime: mimeType = null } = fileType || {};
|
||||
const { size } = inputs.file;
|
||||
|
||||
const { id: uploadedFileId } = await UploadedFile.qm.createOne({
|
||||
@@ -65,7 +66,7 @@ module.exports = {
|
||||
image: null,
|
||||
};
|
||||
|
||||
if (!['image/svg+xml', 'application/pdf'].includes(mimeType)) {
|
||||
if (mimeType && mimeType.startsWith('image/') && size <= MAX_SIZE_TO_PROCESS_AS_IMAGE) {
|
||||
let image = sharp(buffer || filePath || inputs.file.fd, {
|
||||
animated: true,
|
||||
});
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
const { v4: uuid } = require('uuid');
|
||||
const { rimraf } = require('rimraf');
|
||||
const mime = require('mime');
|
||||
const { fileTypeFromFile } = require('file-type');
|
||||
const sharp = require('sharp');
|
||||
|
||||
const { MAX_SIZE_TO_PROCESS_AS_IMAGE } = require('../../../constants');
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
file: {
|
||||
@@ -21,8 +23,13 @@ module.exports = {
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const mimeType = mime.getType(inputs.file.filename);
|
||||
if (['image/svg+xml', 'application/pdf'].includes(mimeType)) {
|
||||
const fileManager = sails.hooks['file-manager'].getInstance();
|
||||
|
||||
const fileType = await fileTypeFromFile(inputs.file.fd);
|
||||
const { mime: mimeType = null } = fileType || {};
|
||||
const { size } = inputs.file;
|
||||
|
||||
if (!mimeType || !mimeType.startsWith('image/') || size > MAX_SIZE_TO_PROCESS_AS_IMAGE) {
|
||||
await rimraf(inputs.file.fd);
|
||||
throw 'fileIsNotImage';
|
||||
}
|
||||
@@ -47,11 +54,6 @@ module.exports = {
|
||||
throw 'fileIsNotImage';
|
||||
}
|
||||
|
||||
const fileManager = sails.hooks['file-manager'].getInstance();
|
||||
|
||||
const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format;
|
||||
const size = originalBuffer.length;
|
||||
|
||||
const { id: uploadedFileId } = await UploadedFile.qm.createOne({
|
||||
mimeType,
|
||||
size,
|
||||
@@ -60,6 +62,7 @@ module.exports = {
|
||||
});
|
||||
|
||||
const dirPathSegment = `${sails.config.custom.backgroundImagesPathSegment}/${uploadedFileId}`;
|
||||
const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format;
|
||||
|
||||
try {
|
||||
await fileManager.save(
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
const { v4: uuid } = require('uuid');
|
||||
const { rimraf } = require('rimraf');
|
||||
const mime = require('mime');
|
||||
const { fileTypeFromFile } = require('file-type');
|
||||
const sharp = require('sharp');
|
||||
|
||||
const { MAX_SIZE_TO_PROCESS_AS_IMAGE } = require('../../../constants');
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
file: {
|
||||
@@ -21,8 +23,13 @@ module.exports = {
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const mimeType = mime.getType(inputs.file.filename);
|
||||
if (['image/svg+xml', 'application/pdf'].includes(mimeType)) {
|
||||
const fileManager = sails.hooks['file-manager'].getInstance();
|
||||
|
||||
const fileType = await fileTypeFromFile(inputs.file.fd);
|
||||
const { mime: mimeType = null } = fileType || {};
|
||||
const { size } = inputs.file;
|
||||
|
||||
if (!mimeType || !mimeType.startsWith('image/') || size > MAX_SIZE_TO_PROCESS_AS_IMAGE) {
|
||||
await rimraf(inputs.file.fd);
|
||||
throw 'fileIsNotImage';
|
||||
}
|
||||
@@ -47,11 +54,6 @@ module.exports = {
|
||||
throw 'fileIsNotImage';
|
||||
}
|
||||
|
||||
const fileManager = sails.hooks['file-manager'].getInstance();
|
||||
|
||||
const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format;
|
||||
const size = originalBuffer.length;
|
||||
|
||||
const { id: uploadedFileId } = await UploadedFile.qm.createOne({
|
||||
mimeType,
|
||||
size,
|
||||
@@ -60,6 +62,7 @@ module.exports = {
|
||||
});
|
||||
|
||||
const dirPathSegment = `${sails.config.custom.userAvatarsPathSegment}/${uploadedFileId}`;
|
||||
const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format;
|
||||
|
||||
try {
|
||||
await fileManager.save(
|
||||
|
||||
@@ -5,9 +5,11 @@ const AccessTokenSteps = {
|
||||
const POSITION_GAP = 65536;
|
||||
|
||||
const MAX_SIZE_TO_GET_ENCODING = 8 * 1024 * 1024;
|
||||
const MAX_SIZE_TO_PROCESS_AS_IMAGE = 64 * 1024 * 1024;
|
||||
|
||||
module.exports = {
|
||||
AccessTokenSteps,
|
||||
POSITION_GAP,
|
||||
MAX_SIZE_TO_GET_ENCODING,
|
||||
MAX_SIZE_TO_PROCESS_AS_IMAGE,
|
||||
};
|
||||
|
||||
118
server/package-lock.json
generated
118
server/package-lock.json
generated
@@ -15,6 +15,7 @@
|
||||
"dotenv-cli": "^7.4.4",
|
||||
"escape-html": "^1.0.3",
|
||||
"escape-markdown": "^1.0.4",
|
||||
"file-type": "^21.1.1",
|
||||
"fs-extra": "^11.3.3",
|
||||
"i18n-2": "^0.7.3",
|
||||
"ico-to-png": "^0.2.2",
|
||||
@@ -1020,6 +1021,16 @@
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@borewit/text-codec": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.1.1.tgz",
|
||||
"integrity": "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/@canvas/image-data": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.1.0.tgz",
|
||||
@@ -2674,6 +2685,29 @@
|
||||
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tokenizer/inflate": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
|
||||
"integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.4.3",
|
||||
"token-types": "^6.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/@tokenizer/token": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/cors": {
|
||||
"version": "2.8.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
|
||||
@@ -5203,6 +5237,24 @@
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-type": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-21.1.1.tgz",
|
||||
"integrity": "sha512-ifJXo8zUqbQ/bLbl9sFoqHNTNWbnPY1COImFfM6CCy7z+E+jC1eY9YfOKkx0fckIg+VljAy2/87T61fp0+eEkg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tokenizer/inflate": "^0.4.1",
|
||||
"strtok3": "^10.3.4",
|
||||
"token-types": "^6.1.1",
|
||||
"uint8array-extras": "^1.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/filelist": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
|
||||
@@ -6059,6 +6111,26 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
|
||||
@@ -10693,6 +10765,22 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/strtok3": {
|
||||
"version": "10.3.4",
|
||||
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz",
|
||||
"integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tokenizer/token": "^0.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/superagent": {
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.3.tgz",
|
||||
@@ -10983,6 +11071,24 @@
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/token-types": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz",
|
||||
"integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@borewit/text-codec": "^0.1.0",
|
||||
"@tokenizer/token": "^0.3.0",
|
||||
"ieee754": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/touch": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
|
||||
@@ -11180,6 +11286,18 @@
|
||||
"resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz",
|
||||
"integrity": "sha512-5gSP1liv10Gjp8cMEnFd6shzkL/D6W1uhXSFNCxDC+YI8+L8wkCYCbJ7n77Ezb4wE/xzMogecE+DtamEe9PZjg=="
|
||||
},
|
||||
"node_modules/uint8array-extras": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
|
||||
"integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"dotenv-cli": "^7.4.4",
|
||||
"escape-html": "^1.0.3",
|
||||
"escape-markdown": "^1.0.4",
|
||||
"file-type": "^21.1.1",
|
||||
"fs-extra": "^11.3.3",
|
||||
"i18n-2": "^0.7.3",
|
||||
"ico-to-png": "^0.2.2",
|
||||
|
||||
Reference in New Issue
Block a user