Skip to content

Commit

Permalink
fix race condition in Express server, add extra error checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Coulson committed Jun 20, 2024
1 parent 810e6df commit 06bc9da
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 20 deletions.
51 changes: 31 additions & 20 deletions server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
Expand All @@ -45,14 +46,19 @@ 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;

// 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({
Expand All @@ -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 });
});
});
});

Expand Down
5 changes: 5 additions & 0 deletions src/components/metadata-editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down

0 comments on commit 06bc9da

Please sign in to comment.