diff --git a/app/controllers/users/users.authentication.server.controller.js b/app/controllers/users/users.authentication.server.controller.js index ccdc68fa..dbdca627 100755 --- a/app/controllers/users/users.authentication.server.controller.js +++ b/app/controllers/users/users.authentication.server.controller.js @@ -11,7 +11,9 @@ var _ = require('lodash'), config = require('../../../config/config'), nodemailer = require('nodemailer'), crypto = require('crypto'), - User = mongoose.model('User'); + User = mongoose.model('User'), + tokgen = require("../../libs/tokenGenerator"); + var nev = require('email-verification')(mongoose); @@ -304,3 +306,43 @@ exports.removeOAuthProvider = function(req, res, next) { }); } }; + +/* Generate API Key for User */ +exports.generateAPIKey = function(req, res) { + if (!req.isAuthenticated()){ + return res.status(400).send({ + message: 'User is not Authorized' + }); + } + + User.findById(req.user.id) + .exec( function(err, user) { + if (err) return res.status(400).send(err); + + if (!user) { + return res.status(400).send({ + message: 'User does not Exist' + }); + } + + user.apiKey = tokgen(); + + user.save(function(err, _user) { + if (err) { + return res.status(400).send({ + message: errorHandler.getErrorMessage(err) + }); + } + + var newUser = _user.toObject(); + delete newUser.salt; + delete newUser.__v; + delete newUser.passwordHash; + delete newUser.provider; + + console.log(newUser); + return res.json(newUser); + }); + + }); +}; diff --git a/app/libs/tokenGenerator.js b/app/libs/tokenGenerator.js new file mode 100644 index 00000000..5281adaf --- /dev/null +++ b/app/libs/tokenGenerator.js @@ -0,0 +1,8 @@ +"use strict"; + +let TokenGenerator = require("uuid-token-generator"); +let tokgen = new TokenGenerator(256, TokenGenerator.BASE62); + +module.exports = function() { + return tokgen.generate(); +}; diff --git a/app/models/user.server.model.js b/app/models/user.server.model.js index a39a40ab..22edcff5 100755 --- a/app/models/user.server.model.js +++ b/app/models/user.server.model.js @@ -119,7 +119,13 @@ var UserSchema = new Schema({ resetPasswordExpires: { type: Date }, - token: String + token: String, + apiKey: { + type: String, + unique: true, + index: true, + sparse: true + }, }); UserSchema.virtual('displayName').get(function () { diff --git a/app/routes/forms.server.routes.js b/app/routes/forms.server.routes.js index 2bcb6332..7726d32b 100644 --- a/app/routes/forms.server.routes.js +++ b/app/routes/forms.server.routes.js @@ -6,7 +6,8 @@ var users = require('../../app/controllers/users.server.controller'), forms = require('../../app/controllers/forms.server.controller'), multer = require('multer'), - config = require('../../config/config'); + config = require('../../config/config'), + auth = require('../../config/passport_helpers'); // Setting the pdf upload route and folder var storage = multer.diskStorage({ @@ -27,21 +28,21 @@ var upload = multer({ module.exports = function(app) { // Form Routes app.route('/upload/pdf') - .post(users.requiresLogin, upload.single('file'), forms.uploadPDF); + .post(auth.isAuthenticatedOrApiKey, upload.single('file'), forms.uploadPDF); app.route('/forms') - .get(users.requiresLogin, forms.list) - .post(users.requiresLogin, forms.create); + .get(auth.isAuthenticatedOrApiKey, forms.list) + .post(auth.isAuthenticatedOrApiKey, forms.create); app.route('/forms/:formId([a-zA-Z0-9]+)') .get(forms.read) .post(forms.createSubmission) - .put(users.requiresLogin, forms.hasAuthorization, forms.update) - .delete(users.requiresLogin, forms.hasAuthorization, forms.delete); + .put(auth.isAuthenticatedOrApiKey, forms.hasAuthorization, forms.update) + .delete(auth.isAuthenticatedOrApiKey, forms.hasAuthorization, forms.delete); app.route('/forms/:formId([a-zA-Z0-9]+)/submissions') - .get(users.requiresLogin, forms.hasAuthorization, forms.listSubmissions) - .delete(users.requiresLogin, forms.hasAuthorization, forms.deleteSubmissions); + .get(auth.isAuthenticatedOrApiKey, forms.hasAuthorization, forms.listSubmissions) + .delete(auth.isAuthenticatedOrApiKey, forms.hasAuthorization, forms.deleteSubmissions); // Finish by binding the form middleware app.param('formId', forms.formByID); diff --git a/app/routes/users.server.routes.js b/app/routes/users.server.routes.js index b8b0eed2..7b853122 100755 --- a/app/routes/users.server.routes.js +++ b/app/routes/users.server.routes.js @@ -3,24 +3,25 @@ /** * Module dependencies. */ -var passport = require('passport'); -var config = require('../../config/config'); +var passport = require('passport'), + config = require('../../config/config'), + auth = require('../../config/passport_helpers'); module.exports = function(app) { // User Routes var users = require('../../app/controllers/users.server.controller'); // Setting up the users profile api - app.route('/users/me').get(users.requiresLogin, users.getUser); - app.route('/users').put(users.requiresLogin, users.update); - app.route('/users/accounts').delete(users.requiresLogin, users.removeOAuthProvider); + app.route('/users/me').get(auth.isAuthenticatedOrApiKey, users.getUser); + app.route('/users').put(auth.isAuthenticatedOrApiKey, users.update); + app.route('/users/accounts').delete(auth.isAuthenticatedOrApiKey, users.removeOAuthProvider); // Setting up the users account verification api app.route('/auth/verify/:token').get(users.validateVerificationToken); app.route('/auth/verify').post(users.resendVerificationEmail); // Setting up the users password api - app.route('/users/password').post(users.requiresLogin, users.changePassword); + app.route('/users/password').post(auth.isAuthenticatedOrApiKey, users.changePassword); app.route('/auth/forgot').post(users.forgot); app.route('/auth/reset/:token').get(users.validateResetToken); app.route('/auth/reset/:token').post(users.reset); @@ -32,6 +33,8 @@ module.exports = function(app) { app.route('/auth/signin').post(users.signin); app.route('/auth/signout').get(users.signout); + app.route('/auth/genkey').get(users.requiresLogin, users.generateAPIKey); + // // Setting the facebook oauth routes // app.route('/auth/facebook').get(passport.authenticate('facebook', { // scope: ['email'] diff --git a/config/passport_helpers.js b/config/passport_helpers.js new file mode 100644 index 00000000..6ee77de6 --- /dev/null +++ b/config/passport_helpers.js @@ -0,0 +1,54 @@ +"use strict"; + +var config = require("./config"); +var passport = require("passport"); + +var User = require('mongoose').model('User'); + +module.exports.isAuthenticatedOrApiKey = function isAuthenticated(req, res, next) { + debugger; + if (req.isAuthenticated()) { + return next(); + } else { + // Try authenticate with API KEY + if (req.headers.apikey || req.query.apikey || req.body.apikey) { + passport.authenticate("localapikey", function (err, user, info) { + if (err) + return res.sendStatus(500); + + if (!user) + return res.status(401).send(info.message || ""); + + req.login(user, function(err) { + if (err) return res.sendStatus(500); + + req.user = user; + return next(); + }); + + })(req, res, next); + } else { + return res.sendStatus(401); + } + } +}; + + +module.exports.hasRole = function hasRole(roleRequired) { + if (!roleRequired) + throw new Error("Required role needs to be set"); + + return function(req, res, next) { + return module.exports.isAuthenticated(req, res, function() { + if (req.user && req.user.roles && req.user.roles.indexOf(roleRequired) !== -1) + next(); + else + res.sendStatus(403); + }); + }; +}; + +module.exports.hasAdminRole = function hasAdminRole() { + return module.exports.hasRole("admin"); +}; + diff --git a/config/strategies/apikey.js b/config/strategies/apikey.js new file mode 100644 index 00000000..d9dc6e0c --- /dev/null +++ b/config/strategies/apikey.js @@ -0,0 +1,25 @@ +"use strict"; + +var passport = require("passport"); +var LocalAPIKeyStrategy = require("passport-localapikey-update").Strategy; +var User = require('mongoose').model('User'); + +module.exports = function() { + passport.use(new LocalAPIKeyStrategy({ + passReqToCallback : true + }, function(req, apiKey, done) { + return User.findOne({ + "apiKey": apiKey + }, function(err, user) { + if (err) + return done(err); + + if (!user) + return done(null, false, { + message: "Unknown API Key" + }); + + return done(null, user); + }); + })); +}; diff --git a/package.json b/package.json index a9061648..bf6544ae 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "passport-google-oauth": "~0.2.0", "passport-linkedin": "~1.0.0", "passport-local": "~1.0.0", + "passport-localapikey-update": "^0.5.0", "passport-twitter": "~1.0.2", "path-exists": "^2.1.0", "pdffiller": "~0.1.1", @@ -90,6 +91,7 @@ "socket.io": "^1.4.6", "socket.io-redis": "^1.0.0", "swig": "~1.4.1", + "uuid-token-generator": "^0.5.0", "wildcard-subdomains": "github:whitef0x0/wildcard-subdomains" }, "devDependencies": {