diff --git a/createUser.js b/createUser.js new file mode 100644 index 0000000..fe4ccf6 --- /dev/null +++ b/createUser.js @@ -0,0 +1,31 @@ +var User = require('./models/user'); +var mongoose = require('mongoose'); + +mongoose.connect(process.env.MONGODB_URL); + +var db = mongoose.connection; +db.on('error', console.error.bind(console, 'MongoDB connection error:')); + +const readline = require('readline'); + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +rl.question('Please enter the username : ', (username) => { + rl.question('Please enter the password : ', (password) => { + var newUser = User({ + user : username, + password : password + }); + + User.createUser(newUser, function(error){ + if(error) + throw error; + else + console.log("User with username " + newUser.user + " created.."); + rl.close(process.exit(1)); + }); + }); +}); \ No newline at end of file diff --git a/initRegistry.js b/initRegistry.js index ab8e7fc..85a64ad 100644 --- a/initRegistry.js +++ b/initRegistry.js @@ -60,7 +60,8 @@ asyncLoop(mines, function(mine, next){ "pass": password }, }, function(err, res, body){ - console.log(mineName + " Added") + console.log(mineName + " ==> " + body.friendlyMessage); next(); }); }) + diff --git a/models/instance.js b/models/instance.js index fb6ebbb..68c3d29 100644 --- a/models/instance.js +++ b/models/instance.js @@ -47,11 +47,13 @@ var schema = new Schema({ main: String, logo: String }, - twitter: String, + twitter: String, status: String, isProduction: Boolean, maintainerOrgName: String, - maintainerUrl: String + maintainerUrl: String, + maintainerEmail: String, + maintainerGithubUrl: String }, { collection: 'instances' diff --git a/models/instance_validate_schema.js b/models/instance_validate_schema.js index 69ad2f5..bde341c 100644 --- a/models/instance_validate_schema.js +++ b/models/instance_validate_schema.js @@ -10,6 +10,14 @@ var InstanceSchema = { id: "/properties/description", type: "string" }, + maintainerEmail: { + id: "/properties/maintainerEmail", + type: "string" + }, + maintainerGithubUrl: { + id: "/properties/maintainerGithubUrl", + type: "string" + }, maintainerOrgName: { id: "/properties/maintainerOrgName", type: "string" @@ -136,6 +144,14 @@ var InstancePutSchema = { id: "/properties/maintainerUrl", type: "string" }, + maintainerEmail: { + id: "/properties/maintainerEmail", + type: "string" + }, + maintainerGithubUrl: { + id: "/properties/maintainerGithubUrl", + type: "string" + }, images: { id: "/properties/images", properties: { diff --git a/models/user.js b/models/user.js index 8fd02f0..9e3b509 100644 --- a/models/user.js +++ b/models/user.js @@ -1,18 +1,44 @@ /** * User Model */ +var bcrypt = require("bcrypt"); +var SALT_WORK_FACTOR = 10; var mongoose = require('mongoose'); // Schema Modeling var Schema = mongoose.Schema; var schema = new Schema({ - user: String, + user: { + type : String, + required : true, + unique: true + }, password: String }, { collection: 'users' }); -var User = mongoose.model("User", schema); -module.exports = User; +var User = module.exports = mongoose.model("User", schema); + +module.exports.createUser = function(newUser, callback) { + bcrypt.hash(newUser.password, SALT_WORK_FACTOR, function(err, hash) { + if (err) return err; + // override the cleartext password with the hashed one + newUser.password = hash; + newUser.save(callback); + }); +} + + +module.exports.comparePassword = function(candidatePassowrd, hash, callback){ + bcrypt.compare(candidatePassowrd, hash, function(err, isMatch){ + if(err) return callback(err); + callback(null, isMatch); + }); +} + +module.exports.getUserByUsername = function(username, callback){ + User.findOne({user:username}, callback); +} \ No newline at end of file diff --git a/package.json b/package.json index aaa7983..f5061cd 100644 --- a/package.json +++ b/package.json @@ -7,29 +7,30 @@ }, "dependencies": { "async": "^2.4.1", - "body-parser": "~1.15.2", + "body-parser": "^1.18.3", "bootstrap": "~3.3.7", "bootstrap-material-design": "^0.5.10", "connect-slashes": "^1.3.1", "cookie-parser": "~1.4.3", "debug": "~2.2.0", "ejs": "~2.5.2", - "express": "~4.14.0", + "express": "^4.16.4", "express-jsonschema": "~1.1.6", "express-session": "^1.15.4", "forever": "^0.15.3", "jquery": "~3.2.1", "leaflet-search": "^2.3.2", "mongoose": "~4.10.3", - "morgan": "~1.7.0", + "morgan": "^1.9.1", "node-async-loop": "^1.2.2", "node-cron": "^1.2.0", "passport": "^0.3.2", "passport-http": "^0.3.0", "passport-local": "^1.0.0", "request": "^2.81.0", - "serve-favicon": "~2.3.0", + "serve-favicon": "^2.5.0", "swagger-express": "~1.0.5", - "swagger-ui-express": "~2.0.0" + "swagger-ui-express": "~2.0.0", + "bcrypt": "~3.0.0" } } diff --git a/public/javascripts/index.js b/public/javascripts/index.js index a9b8d03..c272f47 100644 --- a/public/javascripts/index.js +++ b/public/javascripts/index.js @@ -18,12 +18,12 @@ $(document).ready(function() { $.ajax({ url: 'service/synchronize/', type: 'PUT', + beforeSend: function(xhr) { + xhr.setRequestHeader("Authorization", "Basic " + btoa(user.user + ":" + user.password)); + }, success: function(result) { localStorage.setItem("message", "All instances were updated successfully."); window.location = window.location.pathname; - }, - beforeSend: function(xhr) { - xhr.setRequestHeader("Authorization", "Basic " + btoa(user.user + ":" + user.password)); } }); } @@ -313,12 +313,12 @@ function getInstances(search) { $.ajax({ url: 'service/instances/' + instance.id, type: 'DELETE', + beforeSend: function(xhr) { + xhr.setRequestHeader("Authorization", "Basic " + btoa(user.user + ":" + user.password)); + }, success: function(result) { localStorage.setItem("message", "Instance " + instance.name + " was deleted successfully."); window.location = window.location.pathname; - }, - beforeSend: function(xhr) { - xhr.setRequestHeader("Authorization", "Basic " + btoa(user.user + ":" + user.password)); } }); } @@ -330,12 +330,12 @@ function getInstances(search) { $.ajax({ url: 'service/synchronize/' + instance.id, type: 'PUT', + beforeSend: function(xhr) { + xhr.setRequestHeader("Authorization", "Basic " + btoa(user.user + ":" + user.password)); + }, success: function(result) { localStorage.setItem("message", "Instance " + instance.name + " was updated successfully."); window.location = window.location.pathname; - }, - beforeSend: function(xhr) { - xhr.setRequestHeader("Authorization", "Basic " + btoa(user.user + ":" + user.password)); } }); } @@ -369,6 +369,12 @@ function getInstances(search) { if (instance.maintainerUrl !== undefined) { $("#mine-modal-body").append(' Maintainer URL: ' + instance.maintainerUrl + '
'); } + if (instance.maintainerEmail !== undefined) { + $("#mine-modal-body").append(' Maintainer Email: ' + instance.maintainerEmail + '
'); + } + if (instance.maintainerGithubUrl !== undefined) { + $("#mine-modal-body").append(' Maintainer Github URL: ' + instance.maintainerGithubUrl + '
'); + } $("#mine-modal-body").append(' API Version: ' + instance.api_version + '') if (instance.release_version !== "") { $("#mine-modal-body").append( diff --git a/routes/auth.js b/routes/auth.js index 2a76452..a4ec7ce 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -16,20 +16,27 @@ var User = require('../models/user'); * will be set at `req.user` in route handlers after authentication. */ passport.use(new Strategy( - function(username, password, done) { - User.findOne({ 'user': username }, function(err, user) { - if (err) { return done(err); } - if (!user) { - return done(null, false, { message: 'Incorrect Username.' }); - } - if (user.password != password) { - return done(null, false, { message: 'Incorrect Password.' }); - } - return done(null, user); - }); - } + function(username, password, done){ + User.getUserByUsername(username, function(err, user){ + if(err) throw err; + else if(!user){ + return done(null, false, {message: "Incorrect Username"}); + } + else{ + User.comparePassword(password, user.password, function(err, isMatch){ + if(err) throw err; + if(isMatch){ + return done(null, user); + } else { + return done(null, false, {message: "Incorrect Password"}); + } + }); + } + }); + } )); + /** * FRONT END: Sessions Persistence * In order to restore authentication state across HTTP requests, Passport needs @@ -55,13 +62,22 @@ passport.use(new BasicStrategy( function(username, password, done) { User.findOne({ 'user': username }, function(err, user) { if (err) { return done(err); } - if (!user) { + else if (!user) { return done(null, false, { message: 'Incorrect Username.' }); } - if (user.password != password) { - return done(null, false, { message: 'Incorrect Password.' }); + else if (user.password != password) { + User.comparePassword(password, user.password, function(err, isMatch){ + if(err) throw err; + if(isMatch){ + return done(null, user); + } else { + return done(null, false, {message: "Incorrect Password"}); + } + }); + } + else{ + return done(null, user); } - return done(null, user); }); } -)); +)); \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index fbca96d..5fce9a4 100644 --- a/routes/index.js +++ b/routes/index.js @@ -110,6 +110,8 @@ function updateInstance(req, res, next){ "description": req.body.newDesc, "maintainerOrgName": req.body.maintainerOrgName.trim(), "maintainerUrl": req.body.maintainerUrl.trim(), + "maintainerEmail": req.body.maintainerEmail.trim(), + "maintainerGithubUrl": req.body.maintainerGithubUrl.trim(), "twitter": req.body.newTwitter.trim(), "location": { "latitude": req.body.newLatitude, @@ -139,6 +141,8 @@ function updateInstance(req, res, next){ desc: req.body.newDesc, maintainerOrgName: req.body.maintainerOrgName, maintainerUrl: req.body.maintainerUrl, + maintainerEmail: req.body.maintainerEmail, + maintainerGithubUrl: req.body.maintainerGithubUrl, twitter: req.body.newTwitter, lat: req.body.newLatitude, lon: req.body.newLongitude, @@ -189,6 +193,8 @@ router.post('/instance', function(req, res, next) { "description": req.body.newDesc.trim(), "maintainerOrgName": req.body.maintainerOrgName.trim(), "maintainerUrl": req.body.maintainerUrl.trim(), + "maintainerEmail": req.body.maintainerEmail.trim(), + "maintainerGithubUrl": req.body.maintainerGithubUrl.trim(), "twitter": req.body.newTwitter.trim(), "location": { "latitude": req.body.newLatitude, @@ -218,6 +224,8 @@ router.post('/instance', function(req, res, next) { desc: req.body.newDesc, maintainerOrgName: req.body.maintainerOrgName, maintainerUrl: req.body.maintainerUrl, + maintainerEmail: req.body.maintainerEmail, + maintainerGithubUrl: req.body.maintainerGithubUrl, twitter: req.body.newTwitter, lat: req.body.newLatitude, lon: req.body.newLongitude, diff --git a/routes/instances.js b/routes/instances.js index 3cb53de..69c1a21 100644 --- a/routes/instances.js +++ b/routes/instances.js @@ -198,6 +198,8 @@ router.post('/', passport.authenticate('basic', {session: false}), validate({bod newInstanceObject.location = typeof(req.body.location) !== 'undefined' ? req.body.location : {"latitude": "", "longitude": ""}; newInstanceObject.maintainerOrgName = typeof(req.body.maintainerOrgName) !== 'undefined' ? req.body.maintainerOrgName : ""; newInstanceObject.maintainerUrl = typeof(req.body.maintainerUrl) !== 'undefined' ? req.body.maintainerUrl : ""; + newInstanceObject.maintainerEmail = typeof(req.body.maintainerEmail) !== 'undefined' ? req.body.maintainerEmail : ""; + newInstanceObject.maintainerGithubUrl = typeof(req.body.maintainerGithubUrl) !== 'undefined' ? req.body.maintainerGithubUrl : ""; // Get the instance Versions & Branding information var intermine_endpoint = req.body.url + "/service/version/intermine"; @@ -353,6 +355,8 @@ router.put('/:id', passport.authenticate('basic', {session: false}), validate({b instance.description = typeof(req.body.description) !== 'undefined' ? req.body.description : instance.description; instance.maintainerOrgName = typeof(req.body.maintainerOrgName) !== 'undefined' ? req.body.maintainerOrgName : instance.maintainerOrgName; instance.maintainerUrl = typeof(req.body.maintainerUrl) !== 'undefined' ? req.body.maintainerUrl : instance.maintainerUrl; + instance.maintainerEmail = typeof(req.body.maintainerEmail) !== 'undefined' ? req.body.maintainerEmail : instance.maintainerEmail; + instance.maintainerGithubUrl = typeof(req.body.maintainerGithubUrl) !== 'undefined' ? req.body.maintainerGithubUrl : instance.maintainerGithubUrl; instance.last_time_updated = new Date(); instance.api_version = typeof(req.body.api_version) !== 'undefined' ? req.body.api_version : instance.api_version; instance.release_version = typeof(req.body.release_version) !== 'undefined' ? req.body.release_version : instance.release_version; diff --git a/views/addInstance.ejs b/views/addInstance.ejs index c10c76a..edcec91 100644 --- a/views/addInstance.ejs +++ b/views/addInstance.ejs @@ -52,6 +52,20 @@ +
+ +
+ +
+
+ +
+ +
+ +
+
+
@@ -161,8 +175,10 @@ $("#newName").val("<%= name %>"); $("#newUrl").val("<%= url %>"); $("#newDesc").val("<%= desc %>"); - $("#maintainerOrgName").val("<%= maintainerOrgName %>"); - $("#maintainerUrl").val("<%= maintainerUrl %>"); + $("#maintainerOrgName").val("<%= maintainerOrgName %>"); + $("#maintainerUrl").val("<%= maintainerUrl %>"); + $("#maintainerEmail").val("<%= maintainerEmail %>"); + $("#maintainerGithubUrl").val("<%= maintainerGithubUrl %>"); $("#newTwitter").val("<%= twitter %>"); $("#newLatitude").val(<%= lat %> ); $("#newLongitude").val(<%= lon %> ); @@ -238,8 +254,10 @@ $("#newName").val(instance.name); $("#newUrl").val(instance.url); $("#newDesc").val(instance.description); - $("#maintainerOrgName").val(instance.maintainerOrgName); - $("#maintainerUrl").val(instance.maintainerUrl); + $("#maintainerOrgName").val(instance.maintainerOrgName); + $("#maintainerUrl").val(instance.maintainerUrl); + $("#maintainerEmail").val(instance.maintainerEmail); + $("#maintainerGithubUrl").val(instance.maintainerGithubUrl); $("#newTwitter").val(instance.twitter); $("#newLatitude").val(instance.location.latitude); $("#newLongitude").val(instance.location.longitude);