diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f843834 --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless + +# FuseBox cache +.fusebox/ + +#built folder +built/ +#package-lock.json file +package-lock.json + +#vscode file +.vscode/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..84552eb --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +## Backend-mongoDB + +Backend microservices api demo. +Essential features of login panel: User Registration , User Login, Forgot Password, Update Password; all done in Node.js with Express and MongoDB. + +**User Authentication** enabled using [Passport](http://www.passportjs.org/) + +**Role Based Access Control** on the routes and can be configured accroding to need to provide limited access based on the role of user. + +## Run +1. Install dependencies ``` npm install ``` +2. Configure MongoDB uri in ``` config/development.ts ``` +3. Get SendGrid API Key from [SendGrid](https://sendgrid.com) and set it in ``` .env ``` file +4. *(Optional)* Default role is user and you can customize acl in ``` src/app/config/nacl.json ``` +5. Run ``` tsc ``` in your terminal to compile the code +6. Run ``` node built/app.js ``` to run the project + +[Postman](https://www.getpostman.com/) is recommended to send various requests e.g. GET, POST, etc. + +* Register user by ``` http:localhost:9000/api/user/register ``` and you will see the user stored in MongoDB + +* Now, you can try various other methods such as Forgot Password, Update Password and play around with other custom routes. + +* You can perform authentication using ``` auth/ ``` routes. + +* You can also query the stored data in database using ``` api/query/ ``` routes. + +### References +* For learning more about ACL library used here: [express-acl](https://www.npmjs.com/package/express-acl) +* Library used for [pagination](https://www.npmjs.com/package/mongoose-paginate) + + diff --git a/built/api/user/index.js b/built/api/user/index.js index 4cbfbd9..7f1e602 100644 --- a/built/api/user/index.js +++ b/built/api/user/index.js @@ -1,5 +1,4 @@ 'use strict'; -Object.defineProperty(exports, "__esModule", { value: true }); var express = require("express"); var controller = require("./user.controller"); var auth = require("../../auth/auth.service"); @@ -15,5 +14,4 @@ router.post('/verifytoken', controller.verifytoken); router.post('/updatepassword', auth.isAuthenticated(), controller.updatePassword); /* For mobile side */ router.post('/upload/avatar', auth.isAuthenticated(), upload.single('file'), controller.uploadpic); -/* END */ module.exports = router; diff --git a/built/api/user/user.controller.js b/built/api/user/user.controller.js index 4e57a6e..8dc4b46 100644 --- a/built/api/user/user.controller.js +++ b/built/api/user/user.controller.js @@ -2,83 +2,123 @@ Object.defineProperty(exports, "__esModule", { value: true }); var mongoose = require("mongoose"); var crypto = require("crypto"); +var sgMail = require("@sendgrid/mail"); +var auth = require("../../auth/auth.service"); var local_env_1 = require("../../config/local.env"); var common_1 = require("../../common/common"); +var dotenv = require("dotenv"); +dotenv.config(); +//sendGrid api key +sgMail.setApiKey(process.env.SENDGRID_API_KEY); /* Update password from admin panel */ function updatePassword(req, res) { - var User = mongoose.model('User'); + var User = mongoose.model("User"); + console.log('user: ' + User); User.findOne({ _id: req.user._id }, function (err, user) { if (err) { res.send(common_1.send_response(null, true, "User not found!")); } else { - var isAuth = user.authenticate(req.body.old_password); - if (isAuth === true) { - user.password = req.body.new_password; - user.save(function (err, saved) { - if (err) { - res.send(common_1.send_response(null, true, common_1.parse_error(err))); + if (!req.body.old_password || !req.body.new_password || !req.body.confirm_password) { + res.send(common_1.send_response(null, true, "Please enter your old password and new password")); + } + else { + var isAuth = user.authenticate(req.body.old_password); + if (isAuth === true) { + if (req.body.new_password !== req.body.confirm_password) { + res.send(common_1.send_response(null, true, " New password and Confirm password do not match, try again!")); } else { - res.send(common_1.send_response(null, false, saved)); + user.password = req.body.new_password; + user.save(function (err, saved) { + if (err) { + res.send(common_1.send_response(null, true, common_1.parse_error(err))); + } + else { + res.send(common_1.send_response(null, false, "password updated!")); + } + }); } - }); - } - else { - res.send(common_1.send_response(null, true, "Old password is wrong!")); + } + else { + res.send(common_1.send_response(null, true, "Old password is wrong!")); + } } } }); } exports.updatePassword = updatePassword; -; /* Verify token whether token exist in forgot password model or changed */ function verifytoken(req, res) { - var ForgotPassword = mongoose.model('Forgotpassword'); + var ForgotPassword = mongoose.model("Forgotpassword"); var data = req.body; ForgotPassword.findOne({ token: data.token }, function (err, user) { if (user == null) { - res.json({ data: null, is_error: true, message: 'Token invalid!' }); + res.json({ data: null, is_error: true, message: "Token invalid!" }); } else if (user.is_changed == true) { - res.json({ data: user, is_error: true, message: 'This link is no longer available.Please request a new link!' }); + res.json({ + data: user, + is_error: true, + message: "This link is no longer available.Please request a new link!" + }); } else { - res.json({ data: user, is_error: false, message: 'Valid token!' }); + res.json({ data: user, is_error: false, message: "Valid token!" }); } }); } exports.verifytoken = verifytoken; /* Forgot password api for sending mail with link */ function forgotpassword(req, res) { - var User = mongoose.model('User'); - var ForgotPassword = mongoose.model('Forgotpassword'); + var User = mongoose.model("User"); + var ForgotPassword = mongoose.model("Forgotpassword"); var data = req.body; User.findOne({ email: data.email }, function (err, user) { if (user == null) { - res.json({ data: null, is_error: true, message: 'User not found!' }); + res.json({ data: null, is_error: true, message: "User not found!" }); } else { var today = new Date(); //Generate Hash - var secret = 'a3s5d46a5sd684asdaasdkn!@312'; - var hash = crypto.createHmac('sha256', secret) + var secret = "a3s5d46a5sd684asdaasdkn!@312"; + var hash = crypto + .createHmac("sha256", secret) .update(user._id + user.email + user._id + today) - .digest('hex'); + .digest("hex"); var email_data = { - user: usersetup._id, - token: hash, + user: user._id, + token: hash }; - var email_data = new ForgotPassword(email_data); + var email_data = new ForgotPassword(email_data, function (err) { + if (err) { + console.log('data not pushed in database'); + } + else + res.send(common_1.send_response(null, false, "Data pushed in database!")); + }); ForgotPassword.create(email_data, function (error, data) { var mail_data = { - 'replace_var': { - username: user.first_name, - link: local_env_1.default.CLIENT_URL + '/reset_password.html?token=' + hash - }, - 'send_to': user.email, - 'subject': 'Forgot Password' + to: user.email, + from: process.env.EMAIL_ID, + subject: "Forgot Password", + text: "Click the following link to reset the password: " + + local_env_1.default.CLIENT_URL + + "/resetPassword?token=" + + hash }; + sgMail.send(mail_data).then(function (sent) { + if (sent) { + res.json({ data: null, is_error: false, message: "Mail sent!" }); + } + else { + res.json({ + data: null, + is_error: true, + message: "Mail sending failed!" + }); + } + }); res.json({ data: user, is_error: false }); }); } @@ -87,60 +127,67 @@ function forgotpassword(req, res) { exports.forgotpassword = forgotpassword; /** Reset Password **/ function resetPassword(req, res) { - var User = mongoose.model('User'); - var Forgotpassword = mongoose.model('Forgotpassword'); + var User = mongoose.model("User"); + var Forgotpassword = mongoose.model("Forgotpassword"); var params = req.body; - if (!params - || !params.token - || !params.new_password) { - res.send(common_1.send_response(null, true, 'Validation error!')); + console.log("params: " + params); + if (!params || !params.token || !params.new_password) { + res.send(common_1.send_response(null, true, "Validation error!")); } else { if (params.new_password.length <= 5) { res.send(common_1.send_response(null, true, "Password must be of minimum 6 characters!")); } else { - Forgotpassword - .findOne({ token: params.token }) - .exec(function (err, forgot) { + Forgotpassword.findOne({ token: params.token }).exec(function (err, forgot) { if (err) { res.send(common_1.send_response(null, true, err.message)); } else { - console.log(forgot.user); - User.findOne({ _id: forgot.user }) - .exec(function (err, user) { - console.log(user); + console.log("forgot: " + forgot.user); + User.findOne({ _id: forgot.user }).exec(function (err, user) { if (err) { res.send(common_1.send_response(null, true, err.message)); } else { if (user) { - user.password = params.new_password; - user.save(function (err, user) { - if (err) { - res.send(common_1.send_response(null, true, err.message)); + if (!params.new_password || !params.confirm_password) { + res.send(common_1.send_response(null, true, "Please enter new_password and/or confirm_password")); + } + else { + if (params.new_password !== params.confirm_password) { + res.send(common_1.send_response(null, true, 'Password do not match. Try again!')); } else { - forgot.is_changed = true; - forgot.save(function (err, user) { + user.password = params.new_password; + console.log('user.password is(changed):' + user.password); + user.save(function (err, user) { if (err) { res.send(common_1.send_response(null, true, err.message)); } else { - // remove model object from user - user = user.toJSON(); - // delete password key - delete user.password; - res.send(common_1.send_response(user, false, 'Your password is changed successfully now you can login with new password from the app.')); - //res.send(send_response(user)); + forgot.is_changed = true; + forgot.save(function (err, user) { + if (err) { + res.send(common_1.send_response(null, true, err.message)); + } + else { + // remove model object from user + user = user.toJSON(); + // delete password key + delete user.password; + res.send(common_1.send_response(null, false, "Your password is changed successfully now you can login with new password from the app.")); + // res.send(send_response(user, false, "password changed!")); + console.log('Password successfully changed!!'); + } + }); } }); } - }); + } } else { - res.send(common_1.send_response(null, true, 'User not found!')); + res.send(common_1.send_response(null, true, "User not found!")); } } }); @@ -150,41 +197,51 @@ function resetPassword(req, res) { } } exports.resetPassword = resetPassword; -; /* Verification api after user register from website */ function register_verify(req, res) { - var User = mongoose.model('User'); + var User = mongoose.model("User"); var data = req.body; User.findOne({ email: data.email }, function (err, user) { if (user == null) { - res.json({ data: null, is_error: true, message: 'Invalid user detail!' }); + res.json({ data: null, is_error: true, message: "Invalid user detail!" }); } else { var today = new Date(); //Generate Hash - var secret = 'a3s5d46a5sd684asdaasdkn!@312'; - var hash = crypto.createHmac('sha256', secret) + var secret = "a3s5d46a5sd684asdaasdkn!@312"; + var hash = crypto + .createHmac("sha256", secret) .update(user._id + user.email + user._id + today) - .digest('hex'); + .digest("hex"); var mail_data = { - 'replace_var': { - username: user.first_name, - link: local_env_1.default.CLIENT_URL + '/#/register_verify/' + user._id - }, - 'send_to': user.email, - 'subject': 'Register Verify' + to: user.email, + from: process.env.EMAIL_ID, + subject: "Register Verify", + text: "Your email is verified" }; + sgMail.send(mail_data).then(function (sent) { + if (sent) { + res.json({ data: null, is_error: false, message: "Mail sent!" }); + } + else { + res.json({ + data: null, + is_error: true, + message: "Mail sending failed!" + }); + } + }); } }); } exports.register_verify = register_verify; /* Mail to user for welcoming after registration */ function welcome_user(req, res) { - var User = mongoose.model('User'); + var User = mongoose.model("User"); var data = req.body; User.findOne({ email: data.email }, function (err, user) { if (user == null) { - res.json({ data: null, is_error: true, message: 'Invalid user!' }); + res.json({ data: null, is_error: true, message: "Invalid user!" }); } else { user.is_verify = true; @@ -195,23 +252,27 @@ function welcome_user(req, res) { else { var today = new Date(); //Generate Hash - var secret = 'a3s5d46a5sd684asdaasdkn!@312'; - var hash = crypto.createHmac('sha256', secret) + var secret = "a3s5d46a5sd684asdaasdkn!@312"; + var hash = crypto + .createHmac("sha256", secret) .update(user._id + user.email + user._id + today) - .digest('hex'); + .digest("hex"); var mail_data = { - 'replace_var': { - username: user.first_name - }, - 'send_to': user.email, - 'subject': 'Welcome!' + to: user.email, + from: process.env.EMAIL_ID, + subject: "Welcome!", + text: "Welcome " + user.first_name }; - mailsender.send_mail('/welcome_user.html', mail_data, function (response) { - if (response.is_error) { - res.json({ data: null, is_error: true, message: 'Mail sending failed!' }); + sgMail.send(mail_data).then(function (sent) { + if (sent) { + res.json({ data: null, is_error: false, message: "Mail sent!" }); } else { - res.json({ data: null, is_error: false, message: 'Mail sent!' }); + res.json({ + data: null, + is_error: true, + message: "Mail sending failed!" + }); } }); } @@ -222,43 +283,65 @@ function welcome_user(req, res) { exports.welcome_user = welcome_user; /* Register user api from app */ function register_user(req, res) { - var Model = mongoose.model('User'); + var Model = mongoose.model("User"); var data = req.body; - Model.create(data, function (err, user) { - if (err) { - console.log("asaaaa"); - res.send(common_1.send_response(null, true, common_1.parse_error(err))); + console.log('password: ' + data.password); + if (!data.email || !data.password || !data.confirm_password) { + res.send(common_1.send_response(null, true, "Please enter email and password")); + } + else { + if (data.password !== data.confirm_password) { + res.send(common_1.send_response(null, true, "passwords do not match!")); } else { - console.log("Asda"); - var today = new Date(); - //Generate Hash - var secret = 'a3s5d46a5sd684asdaasdkn!@312'; - var hash = crypto.createHmac('sha256', secret) - .update(user._id + user.email + user._id + today) - .digest('hex'); - var mail_data = { - 'replace_var': { - username: user.first_name - }, - 'send_to': user.email, - 'subject': 'Welcome!' - }; - // var token = auth.signToken(user._id, user.role); - var data = { user: user }; - res.send(common_1.send_response(null, true, "Register success. please check your inbox")); + Model.create(data, function (err, user) { + if (err) { + console.log("asaaaa"); + res.send(common_1.send_response(null, true, common_1.parse_error(err))); + } + else { + console.log("Asda"); + var today = new Date(); + //Generate Hash + var secret = "a3s5d46a5sd684asdaasdkn!@312"; + var hash = crypto + .createHmac("sha256", secret) + .update(user._id + user.email + user._id + today) + .digest("hex"); + var mail_data = { + to: user.email, + from: process.env.EMAIL_ID, + subject: "Welcome " + user.first_name + "!", + text: "Welcome to our website!" + }; + sgMail.send(mail_data).then(function (sent) { + if (sent) { + res.json({ data: null, is_error: false, message: "Mail sent!" }); + } + else { + res.json({ + data: null, + is_error: true, + message: "Mail sending failed!" + }); + } + }); + var token = auth.signToken(user._id, user.role); + var data = { user: user }; + res.send(common_1.send_response(null, true, "Register success. please check your inbox")); + } + }); } - }); + } } exports.register_user = register_user; -; /** * User profile pic change API * @param req * @param res */ function uploadpic(req, res) { - var Model = mongoose.model('User'); + var Model = mongoose.model("User"); Model.findOne({ _id: req.user._id }, function (err, mod) { if (err) { res.send(common_1.send_response(null, true, "Could not find User")); @@ -282,4 +365,3 @@ function uploadpic(req, res) { }); } exports.uploadpic = uploadpic; -; diff --git a/built/auth/auth.service.js b/built/auth/auth.service.js index 928e6fc..55191cb 100644 --- a/built/auth/auth.service.js +++ b/built/auth/auth.service.js @@ -4,6 +4,7 @@ var environment_1 = require("../config/environment"); var jwt = require("jsonwebtoken"); var expressJwt = require("express-jwt"); var compose = require("composable-middleware"); +// import { default as User } from '../models/user.model'; var user_model_1 = require("../models/user.model"); var validateJwt = expressJwt({ secret: environment_1.default.secrets.session }); /** @@ -22,7 +23,7 @@ function isAuthenticated() { }) // Attach user to request .use(function (req, res, next) { - user_model_1.default.findById(req.user._id, function (err, user) { + user_model_1.default.User.findById(req.user._id, function (err, user) { if (err) return next(err); if (!user) diff --git a/built/auth/facebook/passport.js b/built/auth/facebook/passport.js index 7da6e81..e6bc969 100644 --- a/built/auth/facebook/passport.js +++ b/built/auth/facebook/passport.js @@ -4,6 +4,7 @@ var passport = require("passport"); var facebook = require("passport-facebook"); var FacebookStrategy = facebook.Strategy; function setup(User, config) { + config = config.default; passport.use(new FacebookStrategy({ clientID: config.facebook.clientID, clientSecret: config.facebook.clientSecret, diff --git a/built/auth/google/passport.js b/built/auth/google/passport.js index 722b318..474e5cd 100644 --- a/built/auth/google/passport.js +++ b/built/auth/google/passport.js @@ -5,6 +5,7 @@ var passport = require("passport"); var google = require("passport-google-oauth"); var GoogleStrategy = google.OAuth2Strategy; function setup(User, config) { + config = config.default; passport.use(new GoogleStrategy({ clientID: config.google.clientID, clientSecret: config.google.clientSecret, diff --git a/built/auth/local/passport.js b/built/auth/local/passport.js index 56aff4e..cd0610f 100644 --- a/built/auth/local/passport.js +++ b/built/auth/local/passport.js @@ -3,12 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true }); var passport = require("passport"); var local = require("passport-local"); var LocalStrategy = local.Strategy; +var user_model_1 = require("../../models/user.model"); function setup(User, config) { passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' // this is the virtual field on the model }, function (email, password, done) { - User.findOne({ + user_model_1.default.User.findOne({ email: email }, function (err, user) { if (err) diff --git a/built/auth/twitter/passport.js b/built/auth/twitter/passport.js index 8810477..18018fb 100644 --- a/built/auth/twitter/passport.js +++ b/built/auth/twitter/passport.js @@ -1,9 +1,10 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +var passport = require('passport'); +var twitter = require('passport-twitter'); +var TwitterStrategy = twitter.Strategy; function setup(User, config) { - var passport = require('passport'); - var twitter = require('passport-twitter'); - var TwitterStrategy = twitter.Strategy; + config = config.default; passport.use(new TwitterStrategy({ consumerKey: config.twitter.clientID, consumerSecret: config.twitter.clientSecret, diff --git a/built/config/environment/production.js b/built/config/environment/production.js index bb0d5eb..c743a08 100644 --- a/built/config/environment/production.js +++ b/built/config/environment/production.js @@ -14,5 +14,5 @@ module.exports = { // MongoDB connection options mongo: { uri: 'mongodb://now:samcom84@162.250.121.171:27777/now' - } + }, }; diff --git a/built/config/local.env.js b/built/config/local.env.js index fe33f5a..863b051 100644 --- a/built/config/local.env.js +++ b/built/config/local.env.js @@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); // You will need to set these on the server you deploy to. exports.default = { DOMAIN: 'http://anydomainhere.com/', - CLIENT_URL: 'http://anydomainhere.com/', + CLIENT_URL: 'http://localhost:9000', SESSION_SECRET: "dotwhitelable-secret", FACEBOOK_ID: 'app-id', FACEBOOK_SECRET: 'secret', diff --git a/built/config/seed.js b/built/config/seed.js index 8302ad3..b544020 100644 --- a/built/config/seed.js +++ b/built/config/seed.js @@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); // Insert seed models below var user_model_1 = require("../models/user.model"); // Create Default Admin -var admin = new user_model_1.default({ +var admin = new user_model_1.default.User({ first_name: 'Admin', last_name: 'now', user_name: "admin", @@ -18,7 +18,7 @@ var admin = new user_model_1.default({ phone_number: '9898245452', is_verify: true }); -user_model_1.default.create(admin, function (err, user) { +user_model_1.default.User.create(admin, function (err, user) { if (err) { console.log("Error creating default admin : " + err); } diff --git a/built/models/user.model.js b/built/models/user.model.js index 16d3482..5eecdbd 100644 --- a/built/models/user.model.js +++ b/built/models/user.model.js @@ -32,6 +32,10 @@ var UserSchema = new Schema({ last_updated: { type: Date, default: null }, last_login: { type: Date, default: null }, }, schemaOptions); +var ForgotPasswordSchema = new Schema({ + user: String, + token: String +}, schemaOptions); UserSchema.plugin(autopopulate); UserSchema.plugin(mongooseHidden); /** @@ -177,4 +181,9 @@ UserSchema.methods = { return pwd; } }; -exports.default = mongoose.model('User', UserSchema); +// export = mongoose.model('User', UserSchema); +// export = mongoose.model('Forgotpassword', ForgotPasswordSchema); +exports.default = { + User: mongoose.model('User', UserSchema), + Forgotpassword: mongoose.model('Forgotpassword', ForgotPasswordSchema) +}; diff --git a/package.json b/package.json index f486283..a32ec58 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "author": "ankit", "license": "ISC", "dependencies": { + "@sendgrid/mail": "^6.3.1", "body-parser": "^1.18.3", "composable-middleware": "^0.3.0", "compression": "^1.7.3", @@ -17,6 +18,7 @@ "cors": "^2.8.4", "crypto": "^1.0.1", "dedupe": "^2.1.0", + "dotenv": "^6.1.0", "errorhandler": "^1.5.0", "express": "^4.16.3", "express-jwt": "^5.3.1", @@ -27,7 +29,7 @@ "jsonwebtoken": "^8.3.0", "lodash": "^4.17.11", "method-override": "^3.0.0", - "mongoose": "^4.8.5", + "mongoose": "^4.13.17", "mongoose-autopopulate": "^0.8.1", "mongoose-hidden": "^1.6.0", "morgan": "^1.9.1", diff --git a/src/app/api/user/index.ts b/src/app/api/user/index.ts index 7d985bb..346661f 100644 --- a/src/app/api/user/index.ts +++ b/src/app/api/user/index.ts @@ -21,4 +21,4 @@ router.post('/updatepassword', auth.isAuthenticated(), controller.updatePassword router.post('/upload/avatar', auth.isAuthenticated(), upload.single('file'), controller.uploadpic); /* END */ -module.exports = router; \ No newline at end of file +export = router; \ No newline at end of file diff --git a/src/app/api/user/user.controller.ts b/src/app/api/user/user.controller.ts index 07b2241..9b5263c 100644 --- a/src/app/api/user/user.controller.ts +++ b/src/app/api/user/user.controller.ts @@ -1,279 +1,401 @@ -import * as _ from 'lodash'; -import * as async from 'async'; -import * as passport from 'passport'; +import * as _ from "lodash"; +import * as async from "async"; +import * as passport from "passport"; import * as mongoose from "mongoose"; -import * as crypto from 'crypto'; -import * as auth from '../../auth/auth.service'; -import { default as config } from '../../config/local.env'; -import { send_response , parse_error } from '../../common/common' +import * as crypto from "crypto"; +import * as sgMail from "@sendgrid/mail"; +import * as auth from "../../auth/auth.service"; +import { default as config } from "../../config/local.env"; +import { send_response, parse_error } from "../../common/common"; +import * as dotenv from "dotenv"; +dotenv.config(); + +//sendGrid api key + +sgMail.setApiKey(process.env.SENDGRID_API_KEY); /* Update password from admin panel */ -export function updatePassword (req, res) { - var User = mongoose.model('User'); - User.findOne({_id: req.user._id}, function (err, user) { - if (err) { - res.send(send_response(null, true, "User not found!")); +export function updatePassword(req, res) { + var User = mongoose.model("User"); + console.log("user: " + User); + User.findOne({ _id: req.user._id }, function(err, user) { + if (err) { + res.send(send_response(null, true, "User not found!")); + } else { + if ( + !req.body.old_password || + !req.body.new_password || + !req.body.confirm_password + ) { + res.send( + send_response( + null, + true, + "Please enter your old password and new password" + ) + ); } else { - var isAuth = user.authenticate(req.body.old_password); - if (isAuth === true) { + var isAuth = user.authenticate(req.body.old_password); + if (isAuth === true) { + if (req.body.new_password !== req.body.confirm_password) { + res.send( + send_response( + null, + true, + " New password and Confirm password do not match, try again!" + ) + ); + } else { user.password = req.body.new_password; - user.save(function (err, saved) { - if (err) { - res.send(send_response(null, true, parse_error(err))); - } else { - res.send(send_response(null, false ,saved)); - } + user.save(function(err, saved) { + if (err) { + res.send(send_response(null, true, parse_error(err))); + } else { + res.send(send_response(null, false, "password updated!")); + } }); - } else { - res.send(send_response(null, true, "Old password is wrong!")); - } + } + } else { + res.send(send_response(null, true, "Old password is wrong!")); + } } - }); -}; + } + }); +} /* Verify token whether token exist in forgot password model or changed */ -export function verifytoken (req, res) { - var ForgotPassword = mongoose.model('Forgotpassword'); - var data = req.body; - ForgotPassword.findOne({token: data.token}, function (err, user) { - if (user == null) { - res.json({data: null, is_error: true, message: 'Token invalid!'}); - } else if (user.is_changed == true) { - res.json({data: user, is_error: true, message: 'This link is no longer available.Please request a new link!'}); - } else { - res.json({data: user, is_error: false, message: 'Valid token!'}); - } - }); +export function verifytoken(req, res) { + var ForgotPassword = mongoose.model("Forgotpassword"); + var data = req.body; + ForgotPassword.findOne({ token: data.token }, function(err, user) { + if (user == null) { + res.json({ data: null, is_error: true, message: "Token invalid!" }); + } else if (user.is_changed == true) { + res.json({ + data: user, + is_error: true, + message: "This link is no longer available.Please request a new link!" + }); + } else { + res.json({ data: user, is_error: false, message: "Valid token!" }); + } + }); } /* Forgot password api for sending mail with link */ -export function forgotpassword (req, res) { - var User = mongoose.model('User'); - var ForgotPassword = mongoose.model('Forgotpassword'); - var data = req.body; - User.findOne({email: data.email}, function (err, user) { - if (user == null) { - res.json({data: null, is_error: true, message: 'User not found!'}); - } else { - var today = new Date(); - //Generate Hash - var secret = 'a3s5d46a5sd684asdaasdkn!@312'; - var hash = crypto.createHmac('sha256', secret) - .update(user._id + user.email + user._id + today) - .digest('hex'); - - var email_data = { - user: usersetup._id, - token: hash, - }; +export function forgotpassword(req, res) { + var User = mongoose.model("User"); + var ForgotPassword = mongoose.model("Forgotpassword"); + var data = req.body; - var email_data = new ForgotPassword(email_data); + User.findOne({ email: data.email }, function(err, user) { + if (user == null) { + res.json({ data: null, is_error: true, message: "User not found!" }); + } else { + var today = new Date(); + //Generate Hash + var secret = "a3s5d46a5sd684asdaasdkn!@312"; + var hash = crypto + .createHmac("sha256", secret) + .update(user._id + user.email + user._id + today) + .digest("hex"); - ForgotPassword.create(email_data, function (error, data) { + var email_data = { + user: user._id, + token: hash + }; - var mail_data = { - 'replace_var': { - username: user.first_name, - link: config.CLIENT_URL + '/reset_password.html?token=' + hash - }, - 'send_to': user.email, - 'subject': 'Forgot Password' - }; + var email_data = new ForgotPassword(email_data, function(err) { + if (err) { + console.log("data not pushed in database"); + } else res.send(send_response(null, false, "Data pushed in database!")); + }); + ForgotPassword.create(email_data, function(error, data) { + var mail_data = { + to: user.email, + from: process.env.EMAIL_ID, + subject: "Forgot Password", + text: + "Click the following link to reset the password: " + + config.CLIENT_URL + + "/resetPassword?token=" + + hash + }; + sgMail.send(mail_data).then(sent => { + if (sent) { + res.json({ data: null, is_error: false, message: "Mail sent!" }); + } else { + res.json({ + data: null, + is_error: true, + message: "Mail sending failed!" + }); + } + }); - res.json({data: user, is_error: false}); - }); - } - }); + res.json({ data: user, is_error: false }); + }); + } + }); } /** Reset Password **/ -export function resetPassword (req, res) { - var User = mongoose.model('User'); - var Forgotpassword = mongoose.model('Forgotpassword'); - var params = req.body; - - if (!params - || !params.token - || !params.new_password) { - res.send(send_response(null, true, 'Validation error!')) - } else { - if (params.new_password.length <= 5) { - res.send(send_response(null, true, "Password must be of minimum 6 characters!")); - } else { - Forgotpassword - .findOne({token: params.token}) - .exec(function (err, forgot) { - if (err) { - res.send(send_response(null, true, err.message)); - } else { - console.log(forgot.user); - User.findOne({_id: forgot.user}) - .exec(function (err, user) { - console.log(user); - if (err) { - res.send(send_response(null, true, err.message)); - } else { - - if (user) { +export function resetPassword(req, res) { + var User = mongoose.model("User"); + var Forgotpassword = mongoose.model("Forgotpassword"); + var params = req.body; - user.password = params.new_password; - user.save(function (err, user) { - if (err) { - res.send(send_response(null, true, err.message)); - } else { - forgot.is_changed = true; - forgot.save(function (err, user) { - if (err) { - res.send(send_response(null, true, err.message)); - } else { - // remove model object from user - user = user.toJSON(); - // delete password key - delete user.password; - res.send(send_response(user, false, 'Your password is changed successfully now you can login with new password from the app.')); - //res.send(send_response(user)); - } - }); - } - }); - } else { - res.send(send_response(null, true, 'User not found!')); - } - } - }) - } - }) - } - } -}; + console.log("params: " + params); + if (!params || !params.token || !params.new_password) { + res.send(send_response(null, true, "Validation error!")); + } else { + if (params.new_password.length <= 5) { + res.send( + send_response(null, true, "Password must be of minimum 6 characters!") + ); + } else { + Forgotpassword.findOne({ token: params.token }).exec(function( + err, + forgot + ) { + if (err) { + res.send(send_response(null, true, err.message)); + } else { + console.log("forgot: " + forgot.user); + User.findOne({ _id: forgot.user }).exec(function(err, user) { + if (err) { + res.send(send_response(null, true, err.message)); + } else { + if (user) { + if (!params.new_password || !params.confirm_password) { + res.send( + send_response( + null, + true, + "Please enter new_password and/or confirm_password" + ) + ); + } else { + if (params.new_password !== params.confirm_password) { + res.send( + send_response( + null, + true, + "Password do not match. Try again!" + ) + ); + } else { + user.password = params.new_password; + console.log("user.password is(changed):" + user.password); + user.save(function(err, user) { + if (err) { + res.send(send_response(null, true, err.message)); + } else { + forgot.is_changed = true; + forgot.save(function(err, user) { + if (err) { + res.send(send_response(null, true, err.message)); + } else { + // remove model object from user + user = user.toJSON(); + // delete password key + delete user.password; + res.send( + send_response( + null, + false, + "Your password is changed successfully now you can login with new password from the app." + ) + ); + // res.send(send_response(user, false, "password changed!")); + console.log("Password successfully changed!!"); + } + }); + } + }); + } + } + } else { + res.send(send_response(null, true, "User not found!")); + } + } + }); + } + }); + } + } +} /* Verification api after user register from website */ -export function register_verify (req, res) { - var User = mongoose.model('User'); - var data = req.body; - User.findOne({email: data.email}, function (err, user) { - if (user == null) { - res.json({data: null, is_error: true, message: 'Invalid user detail!'}); - } else { - var today = new Date(); - //Generate Hash - var secret = 'a3s5d46a5sd684asdaasdkn!@312'; - var hash = crypto.createHmac('sha256', secret) - .update(user._id + user.email + user._id + today) - .digest('hex'); +export function register_verify(req, res) { + var User = mongoose.model("User"); + var data = req.body; + User.findOne({ email: data.email }, function(err, user) { + if (user == null) { + res.json({ data: null, is_error: true, message: "Invalid user detail!" }); + } else { + var today = new Date(); + //Generate Hash + var secret = "a3s5d46a5sd684asdaasdkn!@312"; + var hash = crypto + .createHmac("sha256", secret) + .update(user._id + user.email + user._id + today) + .digest("hex"); - var mail_data = { - 'replace_var': { - username: user.first_name, - link: config.CLIENT_URL + '/#/register_verify/' + user._id - }, - 'send_to': user.email, - 'subject': 'Register Verify' - }; - - - } - }) + var mail_data = { + to: user.email, + from: process.env.EMAIL_ID, + subject: "Register Verify", + text: "Your email is verified" + }; + sgMail.send(mail_data).then(sent => { + if (sent) { + res.json({ data: null, is_error: false, message: "Mail sent!" }); + } else { + res.json({ + data: null, + is_error: true, + message: "Mail sending failed!" + }); + } + }); + } + }); } /* Mail to user for welcoming after registration */ -export function welcome_user (req, res) { - var User = mongoose.model('User'); - var data = req.body; - User.findOne({email: data.email}, function (err, user) { - if (user == null) { - res.json({data: null, is_error: true, message: 'Invalid user!'}); - } else { - user.is_verify = true; - user.save(function (err) { - if (err) { - res.send(send_response(null, true, parse_error(err))); - } else { - var today = new Date(); - //Generate Hash - var secret = 'a3s5d46a5sd684asdaasdkn!@312'; - var hash = crypto.createHmac('sha256', secret) - .update(user._id + user.email + user._id + today) - .digest('hex'); +export function welcome_user(req, res) { + var User = mongoose.model("User"); + var data = req.body; + User.findOne({ email: data.email }, function(err, user) { + if (user == null) { + res.json({ data: null, is_error: true, message: "Invalid user!" }); + } else { + user.is_verify = true; + user.save(function(err) { + if (err) { + res.send(send_response(null, true, parse_error(err))); + } else { + var today = new Date(); + //Generate Hash + var secret = "a3s5d46a5sd684asdaasdkn!@312"; + var hash = crypto + .createHmac("sha256", secret) + .update(user._id + user.email + user._id + today) + .digest("hex"); - var mail_data = { - 'replace_var': { - username: user.first_name - }, - 'send_to': user.email, - 'subject': 'Welcome!' - }; - mailsender.send_mail('/welcome_user.html', mail_data, function (response) { - if (response.is_error) { - res.json({data: null, is_error: true, message: 'Mail sending failed!'}); - } else { - res.json({data: null, is_error: false, message: 'Mail sent!'}); - } - }); + var mail_data = { + to: user.email, + from: process.env.EMAIL_ID, + subject: "Welcome!", + text: "Welcome " + user.first_name + }; + sgMail.send(mail_data).then(sent => { + if (sent) { + res.json({ data: null, is_error: false, message: "Mail sent!" }); + } else { + res.json({ + data: null, + is_error: true, + message: "Mail sending failed!" + }); } - }); - } - }) + }); + } + }); + } + }); } /* Register user api from app */ -export function register_user (req, res) { - var Model = mongoose.model('User'); - var data = req.body; - Model.create(data, function (err, user) { - if (err) { - console.log("asaaaa"); - res.send(send_response(null, true, parse_error(err))); - } else { - console.log("Asda"); - var today = new Date(); - //Generate Hash - var secret = 'a3s5d46a5sd684asdaasdkn!@312'; - var hash = crypto.createHmac('sha256', secret) - .update(user._id + user.email + user._id + today) - .digest('hex'); - - var mail_data = { - 'replace_var': { - username: user.first_name - }, - 'send_to': user.email, - 'subject': 'Welcome!' - }; +export function register_user(req, res) { + var Model = mongoose.model("User"); + var data = req.body; + console.log("password: " + data.password); + if (!data.email || !data.password || !data.confirm_password) { + res.send( + send_response( + null, + true, + "Please enter email and password and confirm password" + ) + ); + } else { + if (data.password !== data.confirm_password) { + res.send(send_response(null, true, "passwords do not match!")); + } else { + Model.create(data, function(err, user) { + if (err) { + console.log("asaaaa"); + res.send(send_response(null, true, parse_error(err))); + } else { + console.log("Asda"); + var today = new Date(); + //Generate Hash + var secret = "a3s5d46a5sd684asdaasdkn!@312"; + var hash = crypto + .createHmac("sha256", secret) + .update(user._id + user.email + user._id + today) + .digest("hex"); -// var token = auth.signToken(user._id, user.role); - var data = {user: user}; - res.send(send_response(null,true,"Register success. please check your inbox")) - } - }); -}; + var mail_data = { + to: user.email, + from: process.env.EMAIL_ID, + subject: "Welcome " + user.first_name + "!", + text: "Welcome to our website!" + }; + sgMail.send(mail_data).then(sent => { + if (sent) { + res.json({ data: null, is_error: false, message: "Mail sent!" }); + } else { + res.json({ + data: null, + is_error: true, + message: "Mail sending failed!" + }); + } + }); + var token = auth.signToken(user._id, user.role); + var data = { user: user }; + res.send( + send_response( + null, + true, + "Register success. please check your inbox" + ) + ); + } + }); + } + } +} /** * User profile pic change API * @param req * @param res */ -export function uploadpic (req, res) { - var Model = mongoose.model('User'); - Model.findOne({_id: req.user._id}, function (err, mod) { - if (err) { - res.send(send_response(null, true, "Could not find User")); - } else { - if (req.file) { - mod.avatar = req.file.filename; +export function uploadpic(req, res) { + var Model = mongoose.model("User"); + Model.findOne({ _id: req.user._id }, function(err, mod) { + if (err) { + res.send(send_response(null, true, "Could not find User")); + } else { + if (req.file) { + mod.avatar = req.file.filename; - mod.save(function (err, obj) { - if (err) { - res.send(send_response(null, true, "Could not save file")); - } else { - res.send(send_response(null, false, obj)); - } - }); - } else { - res.send(send_response(null, true, "Please select the file!")); - } + mod.save(function(err, obj) { + if (err) { + res.send(send_response(null, true, "Could not save file")); + } else { + res.send(send_response(null, false, obj)); + } + }); + } else { + res.send(send_response(null, true, "Please select the file!")); } - }); -}; \ No newline at end of file + } + }); +} diff --git a/src/app/app.ts b/src/app/app.ts index d771ed9..c24feec 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -11,7 +11,7 @@ process.env.TZ = 'Asia/Kolkata'; import * as express from 'express'; import * as mongoose from 'mongoose'; -import { default as config } from './config/environment'; +import config from './config/environment'; import * as cors from 'cors'; import * as http_mod from 'http'; import * as socketIo_mod from 'socket.io'; diff --git a/src/app/auth/auth.service.ts b/src/app/auth/auth.service.ts index 425a891..fe6ef7b 100644 --- a/src/app/auth/auth.service.ts +++ b/src/app/auth/auth.service.ts @@ -6,7 +6,9 @@ import { default as config } from '../config/environment'; import * as jwt from 'jsonwebtoken'; import * as expressJwt from 'express-jwt'; import * as compose from 'composable-middleware'; -import { default as User } from '../models/user.model'; +// import { default as User } from '../models/user.model'; +import models from '../models/user.model'; + var validateJwt = expressJwt({ secret: config.secrets.session }); /** @@ -26,7 +28,7 @@ export function isAuthenticated() { }) // Attach user to request .use(function (req, res, next) { - User.findById(req.user._id, function (err, user) { + models.User.findById(req.user._id, function (err, user) { if (err) return next(err); if (!user) @@ -74,7 +76,3 @@ export function setTokenCookie(req, res) { res.redirect('/'); } -// exports.isAuthenticated = isAuthenticated; -// exports.hasRole = hasRole; -// exports.signToken = signToken; -// exports.setTokenCookie = setTokenCookie; diff --git a/src/app/auth/facebook/passport.ts b/src/app/auth/facebook/passport.ts index bc849a3..4e8c62d 100644 --- a/src/app/auth/facebook/passport.ts +++ b/src/app/auth/facebook/passport.ts @@ -2,37 +2,40 @@ import * as passport from 'passport'; import * as facebook from 'passport-facebook'; let FacebookStrategy = facebook.Strategy; -export function setup (User, config) { +export function setup(User, config) { + + config = config.default; + passport.use(new FacebookStrategy({ - clientID: config.facebook.clientID, - clientSecret: config.facebook.clientSecret, - callbackURL: config.facebook.callbackURL - }, - function(accessToken, refreshToken, profile, done) { + clientID: config.facebook.clientID, + clientSecret: config.facebook.clientSecret, + callbackURL: config.facebook.callbackURL + }, + function (accessToken, refreshToken, profile, done) { User.findOne({ 'facebook.id': profile.id }, - function(err, user) { - if (err) { - return done(err); - } - if (!user) { - user = new User({ - name: profile.displayName, - email: profile.emails[0].value, - role: 'user', - username: profile.username, - provider: 'facebook', - facebook: profile._json - }); - user.save(function(err) { - if (err) return done(err); - done(err, user); - }); - } else { - return done(err, user); - } - }) + function (err, user) { + if (err) { + return done(err); + } + if (!user) { + user = new User({ + name: profile.displayName, + email: profile.emails[0].value, + role: 'user', + username: profile.username, + provider: 'facebook', + facebook: profile._json + }); + user.save(function (err) { + if (err) return done(err); + done(err, user); + }); + } else { + return done(err, user); + } + }) } )); }; diff --git a/src/app/auth/google/passport.ts b/src/app/auth/google/passport.ts index a6531bd..e3c1636 100644 --- a/src/app/auth/google/passport.ts +++ b/src/app/auth/google/passport.ts @@ -5,6 +5,8 @@ var google = require("passport-google-oauth"); var GoogleStrategy = google.OAuth2Strategy; export function setup (User, config) { + config = config.default; + passport.use(new GoogleStrategy({ clientID: config.google.clientID, clientSecret: config.google.clientSecret, diff --git a/src/app/auth/local/passport.ts b/src/app/auth/local/passport.ts index 0ff87d0..03fedad 100644 --- a/src/app/auth/local/passport.ts +++ b/src/app/auth/local/passport.ts @@ -1,6 +1,7 @@ import * as passport from 'passport'; import * as local from 'passport-local'; let LocalStrategy = local.Strategy; +import models from '../../models/user.model'; export function setup (User, config) { passport.use(new LocalStrategy({ @@ -8,7 +9,7 @@ export function setup (User, config) { passwordField: 'password' // this is the virtual field on the model }, function (email, password, done) { - User.findOne({ + models.User.findOne({ email: email }, function (err, user) { if (err) diff --git a/src/app/auth/twitter/passport.ts b/src/app/auth/twitter/passport.ts index 40aa29f..4431fc8 100644 --- a/src/app/auth/twitter/passport.ts +++ b/src/app/auth/twitter/passport.ts @@ -1,9 +1,13 @@ -export function setup (User, config) { - var passport = require('passport'); - var twitter = require('passport-twitter'); - let TwitterStrategy = twitter.Strategy; +var passport = require('passport'); +var twitter = require('passport-twitter'); +let TwitterStrategy = twitter.Strategy; +export function setup (User, config) { + + config = config.default; + passport.use(new TwitterStrategy({ + consumerKey: config.twitter.clientID, consumerSecret: config.twitter.clientSecret, callbackURL: config.twitter.callbackURL diff --git a/src/app/config/environment/index.ts b/src/app/config/environment/index.ts index eb4c36d..14a5c88 100644 --- a/src/app/config/environment/index.ts +++ b/src/app/config/environment/index.ts @@ -12,7 +12,7 @@ function requiredProcessEnv(name) { // All configurations will extend these options // ============================================ -var all = { +var all: any = { env: process.env.NODE_ENV, // Root path of server diff --git a/src/app/config/environment/production.ts b/src/app/config/environment/production.ts index da7eb40..81b688b 100644 --- a/src/app/config/environment/production.ts +++ b/src/app/config/environment/production.ts @@ -16,5 +16,6 @@ module.exports = { mongo: { uri: 'mongodb://now:samcom84@162.250.121.171:27777/now' - } + }, + }; \ No newline at end of file diff --git a/src/app/config/local.env.ts b/src/app/config/local.env.ts index 369937d..5c33779 100644 --- a/src/app/config/local.env.ts +++ b/src/app/config/local.env.ts @@ -7,7 +7,7 @@ export default { DOMAIN: 'http://anydomainhere.com/', - CLIENT_URL: 'http://anydomainhere.com/', + CLIENT_URL: 'http://localhost:9000', SESSION_SECRET: "dotwhitelable-secret", FACEBOOK_ID: 'app-id', diff --git a/src/app/config/seed.ts b/src/app/config/seed.ts index 9395bd6..1a4056a 100644 --- a/src/app/config/seed.ts +++ b/src/app/config/seed.ts @@ -5,10 +5,10 @@ 'use strict'; // Insert seed models below -import {default as User} from '../models/user.model'; +import models from '../models/user.model'; // Create Default Admin -var admin = new User({ +var admin = new models.User({ first_name: 'Admin', last_name: 'now', user_name: "admin", @@ -19,10 +19,10 @@ var admin = new User({ phone_number: '9898245452', is_verify: true }); -User.create(admin, function (err, user) { +models.User.create(admin, function (err, user) { if (err) { console.log("Error creating default admin : " + err); } else { console.log("Default Admin Created"); } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/app/models/user.model.ts b/src/app/models/user.model.ts index 793e7a0..4e57cef 100644 --- a/src/app/models/user.model.ts +++ b/src/app/models/user.model.ts @@ -8,6 +8,7 @@ var authTypes = ['github', 'twitter', 'facebook', 'google']; import * as mongoH from 'mongoose-hidden'; let mongooseHidden = (mongoH)({defaultHidden: {password: true}}); import * as _ from 'lodash'; +import { userInfo } from 'os'; var schemaOptions = { toObject: {virtuals: true}, @@ -37,6 +38,12 @@ var UserSchema = new Schema({ }, schemaOptions); +var ForgotPasswordSchema = new Schema({ + + user: String, + token: String +}, schemaOptions); + UserSchema.plugin(autopopulate); UserSchema.plugin(mongooseHidden); @@ -196,4 +203,11 @@ UserSchema.methods = { } }; -export default mongoose.model('User', UserSchema); +// export = mongoose.model('User', UserSchema); + +// export = mongoose.model('Forgotpassword', ForgotPasswordSchema); + +export default { + User: mongoose.model('User', UserSchema), + Forgotpassword: mongoose.model('Forgotpassword', ForgotPasswordSchema) +};