From 73a780230424204f33e722fc568997dcdafc320b Mon Sep 17 00:00:00 2001
From: Markus Grigull <web@grigull.me>
Date: Sun, 2 Oct 2016 20:12:24 +0200
Subject: [PATCH] Add simulator model and fix routes

---
 README.md                  |  7 +--
 docker-compose.yml         |  2 +
 models/project.js          |  2 +-
 models/simulation.js       |  2 +-
 models/simulator.js        | 23 +++++++++
 routes/projects.js         | 95 ++++++++++++++++++------------------
 routes/simulationModels.js | 54 ++++++++++-----------
 routes/simulations.js      | 52 ++++++++++----------
 routes/simulators.js       | 98 ++++++++++++++++++++++++++++++++++++++
 server.js                  |  6 ++-
 10 files changed, 236 insertions(+), 105 deletions(-)
 create mode 100644 models/simulator.js
 create mode 100644 routes/simulators.js

diff --git a/README.md b/README.md
index d376a0c..0aa3fec 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ This is the backend for the VILLASweb frontend. It is build upon NodeJS, Express
 
 ## To-Do
  - Don't send user password (select: false)
- - Only get projects which are accessible by the user
+ - Only get objects which are accessible by the user
  - Add support for config.js with docker volumes
  - Add support for key-secret for bcrypt
  - Let user change own properties if not admin
@@ -13,5 +13,6 @@ This is the backend for the VILLASweb frontend. It is build upon NodeJS, Express
  - Add proper 404 to all routes
  - Add proper error messages to all routes
  - Handle missing objects (e.g. visualization is removed and belonging project does not exist anymore)
- - Save model creation date
- - Add project/visualization sharing
+ - Save objects creation date
+ - Add object sharing
+ - Add project to simulation when updating
diff --git a/docker-compose.yml b/docker-compose.yml
index b189c0c..b7a6f8d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -4,6 +4,8 @@ node:
     - "3000:3000"
   links:
     - mongo
+  environment:
+    - NODE_ENV=development
 
 mongo:
   image: mongo
diff --git a/models/project.js b/models/project.js
index ae3a922..6b4facc 100644
--- a/models/project.js
+++ b/models/project.js
@@ -19,7 +19,7 @@ var projectSchema = new Schema({
   name: { type: String, required: true },
   owner: { type: Schema.Types.ObjectId, ref: 'User', required: true },
   visualizations: [{ type: Schema.Types.ObjectId, ref: 'Visualization', default: [] }],
-  simulation: [{ type: Schema.Types.ObjectId, ref: 'Simulation' }]
+  simulation: { type: Schema.Types.ObjectId, ref: 'Simulation', required: true }
 });
 
 projectSchema.pre('remove', function(callback) {
diff --git a/models/simulation.js b/models/simulation.js
index 7957cc2..7315872 100644
--- a/models/simulation.js
+++ b/models/simulation.js
@@ -18,7 +18,7 @@
  var simulationSchema = new Schema({
    name: { type: String, required: true },
    running: { type: Boolean, default: false },
-   owner: { type: Schema.Types.ObjectId, ref: 'User' },
+   owner: { type: Schema.Types.ObjectId, ref: 'User', required: true },
    models: [{ type: Schema.Types.ObjectId, ref: 'SimulationModel', default: [] }],
    projects: [{ type: Schema.Types.ObjectId, ref: 'Project', default: [] }]
  });
diff --git a/models/simulator.js b/models/simulator.js
new file mode 100644
index 0000000..c1cb517
--- /dev/null
+++ b/models/simulator.js
@@ -0,0 +1,23 @@
+/**
+ * File: simulation.js
+ * Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
+ * Date: 28.09.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 mongoose = require('mongoose');
+
+ var Schema = mongoose.Schema;
+
+ // simulator model
+ var simulatorSchema = new Schema({
+   name: { type: String, required: true },
+   running: { type: Boolean, default: false },
+   simulatorid: { type: Number, required: true },
+   endpoint: { type: String, required: true }
+ });
+
+ module.exports = mongoose.model('Simulator', simulatorSchema);
diff --git a/routes/projects.js b/routes/projects.js
index 03e4d1f..c59dbb7 100644
--- a/routes/projects.js
+++ b/routes/projects.js
@@ -15,6 +15,7 @@ var auth = require('../auth');
 // models
 var Project = require('../models/project');
 var User = require('../models/user');
+var Simulation = require('../models/simulation');
 
 // create router
 var router = express.Router();
@@ -22,66 +23,67 @@ var router = express.Router();
 // all project routes need authentication
 router.use('/projects', auth.validateToken);
 
-// authorize user function
-function authorizeUser(req, project) {
-  // get logged-in user id
-  var userId = req.decoded._doc._id;
-  var userAdminLevel = req.decoded._doc.adminLevel;
-
-  if (project.owner == userId) {
-    return true;
-  } else if (userAdminLevel >= 1) {
-    return true;
-  }
-
-  return false;
-}
-
 // routes
 router.get('/projects', function(req, res) {
   // get all projects
   Project.find(function(err, projects) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     res.send({ projects: projects });
   });
 });
 
-router.route('/projects').post(function(req, res) {
+router.post('/projects', function(req, res) {
   // create new project
   var project = new Project(req.body.project);
 
+  // save project
   project.save(function(err) {
     if (err) {
-      return res.send(err);
+      return res.status(500).send(err);
     }
 
-    res.send({ project: project });
-  });
+    // add project to user
+    User.findOne({ _id: project.owner }, function(err, user) {
+      if (err) {
+        return res.status(400).send(err);
+      }
 
-  // add project to user
-  User.findOne({ _id: project.owner }, function(err, user) {
-    if (err) {
-      return console.log(err);
-    }
+      user.projects.push(project._id);
+
+      user.save(function(err) {
+        if (err) {
+          return res.status(500).send(err);
+        }
 
-    user.projects.push(project._id);
+        // add project to simulation
+        Simulation.findOne({ _id: project.simulation }, function(err, simulation) {
+          if (err) {
+            return res.status(400).send(err);
+          }
 
-    user.save(function(err) {
-      if (err) {
-        console.log(err);
-      }
+          simulation.projects.push(project._id);
+
+          simulation.save(function(err) {
+            if (err) {
+              return res.status(500).send(err);
+            }
+
+            res.send({ project: project });
+          });
+        });
+      });
     });
   });
 });
 
-router.route('/projects/:id').put(function(req, res) {
+router.put('/projects/:id', function(req, res) {
   // get project
   Project.findOne({ _id: req.params.id }, function(err, project) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     // update all properties
@@ -92,7 +94,7 @@ router.route('/projects/:id').put(function(req, res) {
     // save the changes
     project.save(function(err) {
       if (err) {
-        return res.send(err);
+        return res.status(500).send(err);
       }
 
       res.send({ project: project });
@@ -100,26 +102,26 @@ router.route('/projects/:id').put(function(req, res) {
   });
 });
 
-router.route('/projects/:id').get(function(req, res) {
+router.get('/projects/:id', function(req, res) {
   Project.findOne({ _id: req.params.id }, function(err, project) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     res.send({ project: project });
   });
 });
 
-router.route('/projects/:id').delete(function(req, res) {
+router.delete('/projects/:id', function(req, res) {
   Project.findOne({ _id: req.params.id }, function(err, project) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     // remove from owner's list
     User.findOne({ _id: project.owner }, function(err, user) {
       if (err) {
-        return console.log(err);
+        return res.status(400).send(err);
       }
 
       for (var i = 0; user.projects.length; i++) {
@@ -131,17 +133,18 @@ router.route('/projects/:id').delete(function(req, res) {
 
       user.save(function(err) {
         if (err) {
-          return console.log(err);
+          return res.status(500).send(err);
         }
-      });
-    });
 
-    project.remove(function(err) {
-      if (err) {
-        return res.send(err);
-      }
+        // remove the project
+        project.remove(function(err) {
+          if (err) {
+            return res.status(500).send(err);
+          }
 
-      res.send({});
+          res.send({});
+        });
+      });
     });
   });
 });
diff --git a/routes/simulationModels.js b/routes/simulationModels.js
index d55f916..ed13cbf 100644
--- a/routes/simulationModels.js
+++ b/routes/simulationModels.js
@@ -27,7 +27,7 @@ router.get('/simulationModels', function(req, res) {
   // get all models
   SimulationModel.find(function(err, models) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     res.send({ simulationModel: models });
@@ -40,24 +40,24 @@ router.post('/simulationModels', function(req, res) {
 
   model.save(function(err) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
-    res.send({ simulationModel: model });
-  });
+    // add model to simulation
+    Simulation.findOne({ _id: model.simulation }, function(err, simulation) {
+      if (err) {
+        return res.status(500).send(err);
+      }
 
-  // add model to simulation
-  Simulation.findOne({ _id: model.simulation }, function(err, simulation) {
-    if (err) {
-      return console.log(err);
-    }
+      simulation.models.push(model._id);
 
-    simulation.models.push(model._id);
+      simulation.save(function(err) {
+        if (err) {
+          return res.status(500).send(err);
+        }
 
-    simulation.save(function(err) {
-      if (err) {
-        console.log(err);
-      }
+        res.send({ simulationModel: model });
+      });
     });
   });
 });
@@ -66,7 +66,7 @@ router.put('/simulationModels/:id', function(req, res) {
   // get model
   SimulationModel.findOne({ _id: req.params.id }, function(err, model) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     // update all properties
@@ -77,7 +77,7 @@ router.put('/simulationModels/:id', function(req, res) {
     // save the changes
     model.save(function(err) {
       if (err) {
-        return res.send(err);
+        return res.status(500).send(err);
       }
 
       res.send({ simulationModel: model });
@@ -88,7 +88,7 @@ router.put('/simulationModels/:id', function(req, res) {
 router.get('/simulationModels/:id', function(req, res) {
   SimulationModel.findOne({ _id: req.params.id }, function(err, model) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     res.send({ simulationModel: model });
@@ -98,13 +98,13 @@ router.get('/simulationModels/:id', function(req, res) {
 router.delete('/simulationModels/:id', function(req, res) {
   SimulationModel.findOne({ _id: req.params.id }, function(err, model) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     // remove from simulation's list
     Simulation.findOne({ _id: model.simulation }, function(err, simulation) {
       if (err) {
-        return console.log(err);
+        return res.status(500).send(err);
       }
 
       for (var i = 0; simulation.models.length; i++) {
@@ -116,17 +116,17 @@ router.delete('/simulationModels/:id', function(req, res) {
 
       simulation.save(function(err) {
         if (err) {
-          return console.log(err);
+          return res.status(500).send(err);
         }
-      });
-    });
 
-    model.remove(function(err) {
-      if (err) {
-        return res.send(err);
-      }
+        model.remove(function(err) {
+          if (err) {
+            return res.status(500).send(err);
+          }
 
-      res.send({});
+          res.send({});
+        });
+      });
     });
   });
 });
diff --git a/routes/simulations.js b/routes/simulations.js
index 911cfa4..2ca5a06 100644
--- a/routes/simulations.js
+++ b/routes/simulations.js
@@ -40,24 +40,25 @@ router.post('/simulations', function(req, res) {
 
   simulation.save(function(err) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
-    res.send({ simulation: simulation });
-  });
+    // add simulation to user
+    User.findOne({ _id: simulation.owner }, function(err, user) {
+      if (err) {
+        return res.status(400).send(err);
+      }
 
-  // add simulation to user
-  User.findOne({ _id: simulation.owner }, function(err, user) {
-    if (err) {
-      return console.log(err);
-    }
+      user.simulations.push(simulation._id);
 
-    user.simulations.push(simulation._id);
+      user.save(function(err) {
+        if (err) {
+          res.status(500).send(err);
+        }
 
-    user.save(function(err) {
-      if (err) {
-        console.log(err);
-      }
+        // send response
+        res.send({ simulation: simulation });
+      });
     });
   });
 });
@@ -66,7 +67,7 @@ router.put('/simulations/:id', function(req, res) {
   // get simulation
   Simulation.findOne({ _id: req.params.id }, function(err, simulation) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     // update all properties
@@ -77,7 +78,7 @@ router.put('/simulations/:id', function(req, res) {
     // save the changes
     simulation.save(function(err) {
       if (err) {
-        return res.send(err);
+        return res.status(400).send(err);
       }
 
       res.send({ simulation: simulation });
@@ -98,13 +99,13 @@ router.get('/simulations/:id', function(req, res) {
 router.delete('/simulations/:id', function(req, res) {
   Simulation.findOne({ _id: req.params.id }, function(err, simulation) {
     if (err) {
-      return res.send(err);
+      return res.status(400).send(err);
     }
 
     // remove from owner's list
     User.findOne({ _id: simulation.owner }, function(err, user) {
       if (err) {
-        return console.log(err);
+        return res.status(500).send(err);
       }
 
       for (var i = 0; user.simulations.length; i++) {
@@ -116,17 +117,18 @@ router.delete('/simulations/:id', function(req, res) {
 
       user.save(function(err) {
         if (err) {
-          return console.log(err);
+          return res.status(500).send(err);
         }
-      });
-    });
 
-    simulation.remove(function(err) {
-      if (err) {
-        return res.send(err);
-      }
+        // remove simulation itself
+        simulation.remove(function(err) {
+          if (err) {
+            return res.status(500).send(err);
+          }
 
-      res.send({});
+          res.send({});
+        });
+      });
     });
   });
 });
diff --git a/routes/simulators.js b/routes/simulators.js
new file mode 100644
index 0000000..4057285
--- /dev/null
+++ b/routes/simulators.js
@@ -0,0 +1,98 @@
+/**
+ * File: simulators.js
+ * Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
+ * Date: 28.09.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 auth = require('../auth');
+
+// models
+var Simulator = require('../models/simulator');
+
+// create router
+var router = express.Router();
+
+// all model routes need authentication
+router.use('/simulators', auth.validateToken);
+
+// routes
+router.get('/simulators', function(req, res) {
+  // get all simulators
+  Simulator.find(function(err, simulators) {
+    if (err) {
+      return res.status(400).send(err);
+    }
+
+    res.send({ simulators: simulators });
+  });
+});
+
+router.post('/simulators', function(req, res) {
+  // create new simulator
+  var simulator = new Simulator(req.body.simulator);
+
+  simulator.save(function(err) {
+    if (err) {
+      return res.status(400).send(err);
+    }
+
+    res.send({ simulator: simulator });
+  });
+});
+
+router.put('/simulators/:id', function(req, res) {
+  // get simulator
+  Simulator.findOne({ _id: req.params.id }, function(err, simulator) {
+    if (err) {
+      return res.status(400).send(err);
+    }
+
+    // update all properties
+    for (property in req.body.simulator) {
+      simulator[property] = req.body.simulator[property];
+    }
+
+    // save the changes
+    simulator.save(function(err) {
+      if (err) {
+        return res.status(500).send(err);
+      }
+
+      res.send({ simulator: simulator });
+    });
+  });
+});
+
+router.get('/simulators/:id', function(req, res) {
+  Simulator.findOne({ _id: req.params.id }, function(err, simulator) {
+    if (err) {
+      return res.status(400).send(err);
+    }
+
+    res.send({ simulator: simulator });
+  });
+});
+
+router.delete('/simulators/:id', function(req, res) {
+  Simulator.findOne({ _id: req.params.id }, function(err, simulator) {
+    if (err) {
+      return res.status(400).send(err);
+    }
+
+    simulator.remove(function(err) {
+      if (err) {
+        return res.status(500).send(err);
+      }
+
+      res.send({});
+    });
+  });
+});
+
+module.exports = router;
diff --git a/server.js b/server.js
index b2a2998..009969c 100644
--- a/server.js
+++ b/server.js
@@ -23,6 +23,7 @@ var visualizations = require('./routes/visualizations');
 var plots = require('./routes/plots');
 var simulations = require('./routes/simulations');
 var simulationModels = require('./routes/simulationModels');
+var simulators = require('./routes/simulators');
 
 var User = require('./models/user');
 
@@ -45,6 +46,7 @@ app.use('/api/v1', visualizations);
 app.use('/api/v1', plots);
 app.use('/api/v1', simulations);
 app.use('/api/v1', simulationModels);
+app.use('/api/v1', simulators);
 
 // catch 404 and forward to error handler
 app.use(function(req, res, next) {
@@ -57,14 +59,14 @@ app.use(function(req, res, next) {
 if (app.get('env') === 'development') {
   app.use(function(err, req, res, next) {
     res.status(err.status || 500);
-    res.render('error', { message: err.message, error: err });
+    res.send({ error: err, message: err.message });
   });
 }
 
 // production error handler
 app.use(function(err, req, res, next) {
   res.status(err.status || 500);
-  res.render('error', { message: err.message, error: {} });
+  res.send({ error: {}, message: err.message });
 });
 
 // start the app
-- 
GitLab