4
\$\begingroup\$

This code checks user permissions for uploading file, and if user can upload, then the file undergoes a check to see if it exists in SharePoint. If so then the file is pulled and uploaded to S3 bucket. This all works fine, but I have been told all these catches create callback hell. I've been trying to implement promises but I am very confused on how to change these callbacks to promises. Appreciate any help.

//////////////////
// Dependencies //
//////////////////
const path = require('path');
const fs = require('fs');
const ping = require('tcp-ping');
const Semaphore = require('mysql-semaphore');
const dateFormat = require('dateformat');
const randomstring = require("randomstring");
const rimraf = require("rimraf");
const docx4js = require('docx4js');
var sppull = require("sppull").sppull;
const storage = require('azure-storage');
///////////////////////////////
// Sequelize database models //
///////////////////////////////
const Sequelize = require('sequelize');
const sequelize = require('../util/database');
const Op = Sequelize.Op;
const ProjectContacts = sequelize.import('../models/db/project_contact');
////////////////////////
// Local dependencies //
////////////////////////
const { parseJsonFile, encrypt, makeDirs, waitForLock, pullFromSharePoint, decrypt, doesFileExistSp } = require('../util/common');
const { getNormalizedFilepath, updateTAndCCleanup, convertDocxToHtml, insertNewTCVersion, waitForFileUpload } = require('../util/update-t-and-c-helper');
const { listContainers, createContainer, uploadString, uploadLocalFile, listBlobs, downloadBlob } = require('../util/blob-helper');
const createError = require('../util/error-management').createErrorFlow;
const { getProjectPath, saveMetadata, copyFileSpToS3Cleanup } = require('../util/copy-to-s3-helper');
const { getTimeTaken, formatLockKey, saveFileToSp, createFolderIfNotExists, createFolderPathRecursively, processExcelFileRequest } = require('../util/common');
const logger = require('../util/logger')(module);
const fileName = req.body.fileName.trim();
const spSite = req.body.spSite;
const spFolder = req.body.spFolder;
const email = req.body.email_address;
const downloadPath = req.body.S3Path;
const spFile = `${spFolder}/${fileName}`;
const before = Date.now();
const uploadFolderName = 'upload';
const siteUrl = `${process.env.SP_URL}/sites/${spSite}/`;
const creds = {
 username: process.env.SP_USER,
 password: decrypt(process.env.SP_PASSWORD)
};
ProjectContacts.findAll({ where: { can_upload_files: 1, email_address: email }, attributes: ['email_address', 'project_id', 'can_upload_files'] })
 .then(projectContacts => {
 if (projectContacts.length > 0) { //If email can upload, proceed
 doesFileExistSp(creds, spSite, siteUrl, spFile) //Check if file exists in SharePoint
 .then(exists => {
 if (exists) {
 logger.info(`DOWNLOAD PATH: ${downloadPath}`);
 logger.info(`FILENAME: ${fileName}`);
 const sppullContext = {
 siteUrl: siteUrl, //SharePoint URL
 creds: {
 username: process.env.SP_USER,
 password: decrypt(process.env.SP_PASSWORD)
 }
 };
 const sppullOptions = {
 spRootFolder: spFolder, // The folder path for the file in SharePoint
 dlRootFolder: downloadPath, // Where the file is saved locally
 strictObjects: [fileName], // Only download the fileName specified as a query parameter
 muteConsole: true
 };
 pullFromSharePoint(sppullContext, sppullOptions)
 .then(filepath => { //Pull file with fileName from SharePoint
 logger.info(`FILE NOW IN PATH: ${filepath}`);
 // Create the upload directory within the project directory.
 const s3UploadFolder = path.join(downloadPath, uploadFolderName);
 makeDirs(s3UploadFolder)
 .then(() => { //creates upload folder in s3
 function saveMetadataCallback(errorObj) { //callback for saveMetadata which checks for errors, semaphore/locks not being used
 if (errorObj) {
 const filepath = path.join(downloadPath, fileName);
 copyFileSpToS3Cleanup(filepath, semaphore, lockKey).then(() => {
 const error = createError(errorObj.errorMsg, errorObj.statusCode, errorObj.origErr);
 return next(errorObj);
 }).catch(errorObj => {
 const error = createError(errorObj.errorMsg, errorObj.statusCode, errorObj.origErr);
 return next(error);
 });
 }
 }
 saveMetadata(saveMetadataCallback); // Save the metadata info.json files.
 }).catch(err => {
 const filepath = path.join(downloadPath, fileName);
 copyFileSpToS3Cleanup(filepath, semaphore, lockKey)
 .then(() => {
 const error = createError('Unable to create upload directory', 500, err);
 return next(error);
 }).catch(errorObj => {
 const error = createError(errorObj.errorMsg, errorObj.statusCode, errorObj.origErr);
 return next(error);
 });
 });
 return res.status(200).json({
 message: `${fileName} has been uploaded to ${filepath}`
 })
 }).catch(errorObj => {
 const filepath = path.join(downloadPath, fileName);
 copyFileSpToS3Cleanup(filepath, semaphore, lockKey)
 .then(() => {
 const error = createError(errorObj.errorMsg, errorObj.statusCode, errorObj.origErr);
 return next(error);
 }).catch(errorObj => {
 const error = createError(errorObj.errorMsg, errorObj.statusCode, errorObj.origErr);
 return next(error);
 });
 });
 } else {
 const error = createError('File does not exist!');
 return next(error);
 }
 }).catch(err => {
 const error = createError('File does not exist!');
 return next(error);
 })
 } else {
 logger.error(`${email} does not have permission to upload`);
 return res.status(401).json({
 message: `${email} does not have permission to upload`
 });
 }
 });
asked Oct 31, 2019 at 19:50
\$\endgroup\$
5
  • \$\begingroup\$ Can you add your requires in there? Otherwise it will be hard to know what functions you wrote, and what functions you call from 3rd party libraries. \$\endgroup\$ Commented Oct 31, 2019 at 22:59
  • \$\begingroup\$ Show the whole module file. The code context is important here. \$\endgroup\$ Commented Nov 1, 2019 at 2:14
  • 1
    \$\begingroup\$ Added. Let me know if I should add some of the local dependencies code, to clarify it even more. \$\endgroup\$ Commented Nov 1, 2019 at 13:16
  • \$\begingroup\$ Almost spit out my coffee when I saw creds.password, then I saw it was fine \$\endgroup\$ Commented Nov 1, 2019 at 13:24
  • \$\begingroup\$ lol! I'm being extra careful to not post the credentials. \$\endgroup\$ Commented Nov 1, 2019 at 13:25

1 Answer 1

1
\$\begingroup\$

Got it using promises:

//Finds if project_contact email has permission to upload
 function findProjectContacts() {
 return new Promise((resolve, reject) => {
 ProjectContacts.findAll({ where: { can_upload_files: 1, email_address: email }, attributes: ['email_address', 'project_id', 'can_upload_files'] })
 .then(projectContacts => {
 if (projectContacts.length > 0) {
 return resolve(true);
 }
 else {
 const error = createError(`${email} does not have permission to upload!`, 401);
 return reject(error);
 }
 })
 .catch(err => {
 const error = createError(`${email} does not have permission to upload!`, 401, err);
 return reject(error)
 })
 })
 }
 //Checks if file exists in SharePoint
 function findFile() {
 return new Promise((resolve, reject) => {
 doesFileExistSp(creds, spSite, siteUrl, spFile).then(exists => {
 if (!exists) {
 const error = createError(`${filename} does not exist in ${spFolder}`, 404);
 return reject(error);
 } else {
 return resolve(true);
 }
 }).catch(err => {
 const error = createError(`${filename} does not exist in ${spFolder} `, 404, err);
 return reject(error);
 });
 });
 }
 //Pulls file from SharePoint to download into specified filepath
 function pullFile() {
 return new Promise((resolve, reject) => {
 const sppullContext = {
 siteUrl: siteUrl, //SharePoint URL
 creds: creds
 };
 const sppullOptions = {
 spRootFolder: spFolder, // The folder path for the file in SharePoint
 dlRootFolder: downloadPath, // Where the file is saved locally
 strictObjects: [filename], // Only download the filename specified as a query parameter
 muteConsole: true
 };
 pullFromSharePoint(sppullContext, sppullOptions) //Pull file with filename from SharePoint
 .then(filepath => {
 if (!fs.existsSync(filepath)) {
 const error = createError(`${filepath} does not exist`, 404);
 return reject(error);
 }
 else {
 logger.info(`FILE NOW IN PATH: ${filepath}`);
 const s3UploadFolder = path.join(downloadPath, uploadFolderName);
 makeDirs(s3UploadFolder);
 }
 return resolve(true);
 });
 });
 }
 findProjectContacts()
 .then(permission => {
 if (permission === true)
 return findFile();
 })
 .then(fileFound => {
 if (fileFound === true)
 return pullFile();
 }).then(fileCopied => {
 if (fileCopied === true)
 logger.info(`${filename} has been uploaded`);
 return res.status(200).json({
 message: `${filename} has been uploaded`
 });
 }).catch(errorObj => {
 return next(errorObj);
 })
}
answered Nov 27, 2019 at 16:25
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.