From e475a571faefe3ca769cefa523e9f031c68b5cb2 Mon Sep 17 00:00:00 2001
From: Markus Grigull <web@grigull.me>
Date: Sat, 4 Feb 2017 15:34:55 +0100
Subject: [PATCH] Add file upload route and model

Allow empty widget name
---
 .gitignore       |  1 +
 models/file.js   | 24 ++++++++++++++++
 models/user.js   |  3 +-
 models/widget.js |  2 +-
 package.json     |  3 +-
 routes/files.js  | 36 +++++++++++++++++++++++
 routes/upload.js | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
 server.js        |  6 ++++
 8 files changed, 146 insertions(+), 3 deletions(-)
 create mode 100644 models/file.js
 create mode 100644 routes/files.js
 create mode 100644 routes/upload.js

diff --git a/.gitignore b/.gitignore
index adac2d0..b9ec202 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 # NodeJS
 node_modules/
 npm-debug.log
+public/*
 
 # OS X
 .DS_Store
diff --git a/models/file.js b/models/file.js
new file mode 100644
index 0000000..aaeaf6f
--- /dev/null
+++ b/models/file.js
@@ -0,0 +1,24 @@
+/**
+ * File: file.js
+ * Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
+ * Date: 25.01.2017
+ * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC
+ *   This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
+ *   Unauthorized copying of this file, via any medium is strictly prohibited.
+ **********************************************************************************/
+
+// include
+var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+// file model
+var fileSchema = new Schema({
+  name: { type: String },
+  path: { type: String, required: true },
+  type: { type: String },
+  user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
+  date: { type: Date, default: Date.now }
+});
+
+module.exports = mongoose.model('File', fileSchema);
diff --git a/models/user.js b/models/user.js
index f4abbbf..70b646a 100644
--- a/models/user.js
+++ b/models/user.js
@@ -23,7 +23,8 @@ var userSchema = new Schema({
   role: { type: String, required: true, default: 'user' },
   projects: [{ type: Schema.Types.ObjectId, ref: 'Project', default: [] }],
   mail: { type: String, default: "" },
-  simulations: [{ type: Schema.Types.ObjectId, ref: 'Simulation', default: [] }]
+  simulations: [{ type: Schema.Types.ObjectId, ref: 'Simulation', default: [] }],
+  files: [{type: Schema.Types.ObjectId, ref: 'File', default: [] }]
 });
 
 userSchema.methods.verifyPassword = function(password, callback) {
diff --git a/models/widget.js b/models/widget.js
index 3ee75fe..a6857f8 100644
--- a/models/widget.js
+++ b/models/widget.js
@@ -14,7 +14,7 @@ var Schema = mongoose.Schema;
 
 // widget model
 var widgetSchema = new Schema({
-  name: { type: String, required: true },
+  name: { type: String },
   widgetData: { type: Schema.Types.Mixed, default: {} },
   width: { type: Number, required: true },
   height: { type: Number, required: true },
diff --git a/package.json b/package.json
index 43afcca..4fd505f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "VILLASweb-backend",
-  "version": "0.1.0",
+  "version": "0.1.1",
   "private": true,
   "main": "server.js",
   "dependencies": {
@@ -8,6 +8,7 @@
     "body-parser": "^1.15.2",
     "cors": "^2.7.1",
     "express": "^4.14.0",
+    "formidable": "^1.0.17",
     "jsonwebtoken": "^7.0.1",
     "mongoose": "^4.5.1",
     "morgan": "^1.7.0"
diff --git a/routes/files.js b/routes/files.js
new file mode 100644
index 0000000..c4aea8c
--- /dev/null
+++ b/routes/files.js
@@ -0,0 +1,36 @@
+/**
+ * File: files.js
+ * Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
+ * Date: 25.01.2017
+ * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC
+ *   This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
+ *   Unauthorized copying of this file, via any medium is strictly prohibited.
+ **********************************************************************************/
+
+// include
+var express = require('express');
+
+var auth = require('../auth');
+
+// models
+var File = require('../models/file');
+var User = require('../models/user');
+
+// create router
+var router = express.Router();
+
+// all file routes need authentication
+router.use('/files', auth.validateToken);
+
+// routes
+router.get('/files/:id', function(req, res) {
+  File.findOne({ _id: req.params.id }, function(err, file) {
+    if (err) {
+      return res.status(400).send(err);
+    }
+
+    res.send({ file: file });
+  });
+});
+
+module.exports = router;
diff --git a/routes/upload.js b/routes/upload.js
new file mode 100644
index 0000000..8492212
--- /dev/null
+++ b/routes/upload.js
@@ -0,0 +1,74 @@
+/**
+ * File: upload.js
+ * Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
+ * Date: 05.12.2016
+ * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC
+ *   This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
+ *   Unauthorized copying of this file, via any medium is strictly prohibited.
+ **********************************************************************************/
+
+// include
+var express = require('express');
+var path = require('path');
+var formidable = require('formidable');
+var fs = require('fs');
+
+var auth = require('../auth');
+
+var User = require('../models/user');
+var File = require('../models/file');
+
+// create router
+var router = express.Router();
+
+// serve public files
+router.use(express.static(path.join(__dirname, '../public')));
+
+// 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) {
+    fs.rename(file.path, path.join(form.uploadDir, req.decoded._doc._id + '_' + file.name));
+
+    // find user
+    User.findOne({ _id: req.decoded._doc._id }, function(err, user) {
+      if (err) {
+        console.log(err);
+      }
+
+      // create file object
+      var fileObj = new File({ name: file.name, path: 'public/' + user._id + '_' + file.name, user: user._id });
+      fileObj.save(function(err) {
+        if (err) {
+          console.log(err);
+        }
+
+        user.files.push(fileObj._id);
+
+        user.save(function(err) {
+          if (err) {
+            console.log(err);
+          }
+        });
+      });
+    });
+  });
+
+  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' });
+  });
+
+  // handle the request
+  form.parse(req);
+});
+
+module.exports = router;
diff --git a/server.js b/server.js
index bb6d838..5d66b8d 100644
--- a/server.js
+++ b/server.js
@@ -24,6 +24,8 @@ var widgets = require('./routes/widgets');
 var simulations = require('./routes/simulations');
 var simulationModels = require('./routes/simulationModels');
 var simulators = require('./routes/simulators');
+var upload = require('./routes/upload');
+var files = require('./routes/files');
 
 var User = require('./models/user');
 
@@ -47,6 +49,10 @@ app.use('/api/v1', widgets);
 app.use('/api/v1', simulations);
 app.use('/api/v1', simulationModels);
 app.use('/api/v1', simulators);
+app.use('/api/v1', upload);
+app.use('/api/v1', files);
+
+app.use('/public', express.static(__dirname + '/public'));
 
 // catch 404 and forward to error handler
 app.use(function(req, res, next) {
-- 
GitLab