From 8d1fb37a3d0ca26d226f90e8d89489c2e714b9bf Mon Sep 17 00:00:00 2001
From: Ricardo Hernandez-Montoya <rhernandez@gridhound.de>
Date: Mon, 8 May 2017 12:55:55 +0200
Subject: [PATCH] ensure public folder exists in docker image. Files
 directories per user, authenticated upload

---
 Dockerfile       | 14 ++++++--
 config.js        |  1 +
 routes/upload.js | 86 +++++++++++++++++++++++++++++-------------------
 3 files changed, 64 insertions(+), 37 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index 8a80a1c..86f2927 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,11 +1,19 @@
 FROM node:latest
 
-# Bundle app source
-COPY . .
+# Create app directory
+RUN mkdir -p /usr/src/app
+WORKDIR /usr/src/app
 
-# Install dependencies
+# Install app dependencies
+COPY package.json /usr/src/app/
 RUN npm install
 
+# Create public directory
+RUN mkdir -p /usr/src/app/public
+
+# Bundle app source
+COPY . /usr/src/app
+
 # Run the app
 EXPOSE 4000
 CMD [ "npm", "start" ]
diff --git a/config.js b/config.js
index 658bda8..1eac72e 100644
--- a/config.js
+++ b/config.js
@@ -20,6 +20,7 @@
  ******************************************************************************/
 
 module.exports = {
+  publicDir: '../public',
   development: {
     databaseName: 'VILLAS',
     databaseURL: 'mongodb://localhost:27017/',
diff --git a/routes/upload.js b/routes/upload.js
index ffcd549..04430d7 100644
--- a/routes/upload.js
+++ b/routes/upload.js
@@ -25,64 +25,82 @@ var path = require('path');
 var formidable = require('formidable');
 var fs = require('fs');
 
-//var auth = require('../auth');
+// load configuration
+var config = require('../config');
+var auth = require('../auth');
 
-//var User = require('../models/user');
+var User = require('../models/user');
 var File = require('../models/file');
 
 // create router
 var router = express.Router();
 
+// all user routes need authentication
+router.use('/upload', auth.validateToken);
+
 // serve public files
-router.use(express.static(path.join(__dirname, '../public')));
+let publicDir = path.join(__dirname, config.publicDir);
+router.use(express.static(publicDir));
 
 // routes
-router.post('/upload', /*auth.validateToken,*/ function(req, res) {
-  // create form object
-  var form = new formidable.IncomingForm();
-  form.uploadDir = path.join(__dirname, '../public');
-
-  // register events
-  form.on('file', function(field, file) {
-    console.log(file);
-
-    //fs.rename(file.path, path.join(form.uploadDir, /*req.decoded._doc._id + '_' +*/ file.name));
+router.post('/upload', auth.validateRole('visualization', 'update'), function(req, res) {
+  
+  // find upload author
+  User.findOne({ _id: req.decoded._doc._id }, function(err, user) {
+    if (err) {
+      console.error('Could find author while uploading', err);
+      res.status(500).send({ success: false, message: 'File could not be uploaded.' });
+    }
+
+    // create form object with the upload dir corresponding to user's
+    var form = new formidable.IncomingForm();
+    let userFolder = path.join(publicDir,user._id + ''); // ensure is a string
+    form.uploadDir = userFolder;
+
+    form.on('error', function(error) {
+      console.error('Error while processing incoming form',error);
+      res.status(400).send({ success: false, message: 'File could not be uploaded.' });
+    });
 
-    // find user
-    /*User.findOne({ _id: req.decoded._doc._id }, function(err, user) {
-      if (err) {
-        console.log(err);
-      }*/
+    form.on('file', function(field, file) {
 
-      // create file object
-      var fileObj = new File({ name: file.name, path: 'public/' + /*user._id + '_' +*/ file.name/*, user: user._id*/ });
+      // create file object, assigning path to userID + formidable's created name
+      let filePath = path.join(user._id + '', path.basename(file.path));
+      var fileObj = new File({ name: file.name, path: filePath });
       fileObj.save(function(err) {
         if (err) {
-          console.log(err);
+          console.error('Error while storing reference to uploaded file', err);
+          res.status(500).send({ success: false, message: 'File could not be uploaded.' });
         }
 
-        /*user.files.push(fileObj._id);
+        user.files.push(fileObj._id);
 
         user.save(function(err) {
           if (err) {
-            console.log(err);
+            console.error('Error while updating user\'s files references', err);
+            res.status(500).send({ success: false, message: 'File could not be uploaded.' });
           }
         });
-      });*/
+      });
     });
-  });
 
-  form.on('error', function(error) {
-    console.log('Error uploading file: ' + error);
-    res.status(403).send({ success: false, message: 'Error uploading file: ' + error });
-  });
+    form.on('end', function() {
+      res.send({ success: true, message: 'File uploaded' });
+    });
 
-  form.on('end', function() {
-    res.send({ success: true, message: 'File uploaded' });
-  });
+    // Make sure user's folder exists
+    fs.mkdir(userFolder, function(err) {
+      // error occurred (ignore already existing) 
+      if (err && err.code != 'EEXIST') {
+        res.status(500).send({ success: false, message: 'File could not be uploaded.'});
+        return;
+      }
+      
+      // handle the request
+      form.parse(req);
 
-  // handle the request
-  form.parse(req);
+    });
+  });
 });
 
 module.exports = router;
-- 
GitLab