diff --git a/server/index.js b/server/index.js index a97dbf7f..c6a5395e 100644 --- a/server/index.js +++ b/server/index.js @@ -9,7 +9,7 @@ const decompress = require('decompress'); const archiver = require('archiver'); const axios = require('axios'); const responseMessages = []; -require('dotenv').config(); +require('dotenv').config({ path: './.env' }); // CONFIGURATION PORT = 6040; // the Express server will run on this port. @@ -34,7 +34,8 @@ app.use(cors()); app.route(ROUTE_PREFIX + '/upload').post(function (req, res, next) { const options = { uploadDir: UPLOAD_PATH, - keepExtensions: true + keepExtensions: true, + maxFileSize: 300 * 1024 * 1024 }; const form = new formidable.IncomingForm(options); @@ -45,6 +46,12 @@ app.route(ROUTE_PREFIX + '/upload').post(function (req, res, next) { // Upload the file to the server, into the /files/ folder. form.parse(req, function (err, field, file) { + if (err) { + logger('WARNING', 'Upload Aborted: an error has occurred while parsing the uploaded form: ', err); + res.status(500).send({ status: 'Internal Server Error' }); + return; + } + const fileName = `${TARGET_PATH}/${file.data.originalFilename.split('.zip')[0]}`; const secureFilename = `${UPLOAD_PATH}/${file.data.newFilename}`; let newStorylines = false; @@ -52,7 +59,6 @@ app.route(ROUTE_PREFIX + '/upload').post(function (req, res, next) { // SECURITY FEATURE (?): Check if the uploaded filename matches our Storylines UUID format. Prevents overwriting // other folders. //if (!projectNameRegex.test(fileName)) { - // SECURITY FEATURE (temporary): Make sure the project name isn't `scripts`, or `help`, and doesn't contain . or / in order to prevent overwriting folders. if (fileName !== 'scripts' && fileName !== 'help' && !fileName.includes('/') && !fileName.includes('.')) { responseMessages.push({ @@ -76,23 +82,28 @@ app.route(ROUTE_PREFIX + '/upload').post(function (req, res, next) { // Unzip the contents of the uploaded zip file into the target directory. Will overwrite // old files in the folder. - decompress(secureFilename, fileName).then((files) => { - // SECURITY FEATURE: delete all files in the folder that don't have one of the following extensions: - // .json, .jpg, .jpeg, .gif, .png, .csv - // TODO: Disabled until I can find a better regex - // files.forEach((file) => { - // validateFile(file, fileName); - // }); - }); - - // Finally, delete the uploaded zip file. - safeRM(secureFilename, UPLOAD_PATH); - - responseMessages.push({ type: 'INFO', message: `Uploaded files to product ${fileName}` }); - logger('INFO', `Uploaded files to product ${fileName}`); - - // Send a response back to the client. - res.json({ new: newStorylines }); + decompress(secureFilename, fileName) + .then((files) => { + // SECURITY FEATURE: delete all files in the folder that don't have one of the following extensions: + // .json, .jpg, .jpeg, .gif, .png, .csv + // TODO: Disabled until I can find a better regex + // files.forEach((file) => { + // validateFile(file, fileName); + // }); + responseMessages.push({ type: 'INFO', message: `Uploaded files to product ${fileName}` }); + logger('INFO', `Uploaded files to product ${fileName}`); + + // Finally, delete the uploaded zip file. + safeRM(secureFilename, UPLOAD_PATH); + + // Send a response back to the client. + res.json({ new: newStorylines }); + }) + .err((err) => { + logger('WARNING', 'Error occurred while decompressing ZIP file', err); + // Send a response back to the client. + res.json({ new: newStorylines }); + }); }); }); diff --git a/src/components/metadata-editor.vue b/src/components/metadata-editor.vue index d3e55d77..6011a3e3 100644 --- a/src/components/metadata-editor.vue +++ b/src/components/metadata-editor.vue @@ -1017,6 +1017,11 @@ export default class MetadataEditorV extends Vue { .catch((error: any) => console.log(error.response || error)); }) .catch((error: any) => console.log(error.response || error)); + } else { + // padding to prevent save button from being clicked rapidly + setTimeout(() => { + this.saving = false; + }, 500); } }) .catch(() => {