diff --git a/config/database.js b/config/db.js similarity index 77% rename from config/database.js rename to config/db.js index f08c988..dd27d8b 100644 --- a/config/database.js +++ b/config/db.js @@ -1,11 +1,14 @@ + + const Sequelize = require('sequelize'); const Op = Sequelize.Op; module.exports = { - sequelize : new Sequelize("palandas", "postgres", "newpassword",{ + sequelize : new Sequelize("palandas", "postgres", "newpassword", { host: "localhost", - //port: 5000, dialect: "postgres", secret: "newpassword", - operatorsAliases: false + operatorsAliases: Op, + password: "newpassword", }) -} \ No newline at end of file +} + diff --git a/config/passport.js b/config/passport.js index e0cdcac..43abb8c 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,21 +1,54 @@ -const LocalStrategy = require('passport-local').Strategy; - const ExtractJwt = require('passport-jwt').ExtractJwt; -const User = require('../models/user'); -const config = require('../config/database'); -module.exports= (passport) => { - passport.serializeUser((user, done) => { - done(null, user.id); -}); -passport.deserializeUser((id, done) =>{ - //User.getUserById(id, (err, user) => { - User.find({ +var passport = require('passport'), + LocalStrategy = require('passport-local').Strategy, + bcrypt = require('bcrypt'), + User = require('../model/User') + +module.exports = function(app) { + app.use(passport.initialize()) + app.use(passport.session()) + + passport.use(new LocalStrategy({ + usernameField: 'email', + passwordField: 'password' + }, + function(username, password, done) { + User.findOne({ + where: { + 'email': username + } + }).then(function (user) { + if (user == null) { + return done(null, false, { message: 'Incorrect credentials.' }) + } + console.log(user) + var hashedPassword = bcrypt.hashSync(password, user.salt) + console.log(user.password) + console.log(hashedPassword) + if (user.password === hashedPassword) { + return done(null, user) + } + + return done(null, false, { message: 'Incorrect credentials.' }) + }) + } + )) + + passport.serializeUser(function(user, done) { + done(null, user.id) + }) + + passport.deserializeUser(function(id, done) { + User.findOne({ where: { - email:email + 'id': id + } + }).then(function (user) { + if (user == null) { + done(new Error('Wrong user id')) } + done(null, user) }) - done(err, user); }) -} - +} \ No newline at end of file diff --git a/controllers/config.js b/controllers/config.js new file mode 100644 index 0000000..4c9eb4b --- /dev/null +++ b/controllers/config.js @@ -0,0 +1,6 @@ +module.exports = { + jwtSecret: "s3cr3t3duT0rchdiz@bl3d", + jwtSession: { + session: false + } +}; \ No newline at end of file diff --git a/controllers/signupController.js b/controllers/signupController.js new file mode 100644 index 0000000..9c8ecfa --- /dev/null +++ b/controllers/signupController.js @@ -0,0 +1,35 @@ + + +var bcrypt = require('bcrypt'), + User = require('../model/User') + +module.exports = function(req, res) { + var email = req.body.email + var password = req.body.password + + var salt = bcrypt.genSaltSync(10) + password = bcrypt.hashSync(password, salt); + var newUser = { + email: email, + salt: salt, + password + } + User.sync({force: true}).then(function() { + User.create(newUser).then(function(user) { + console.log(user) + res.status(200).json({ + message: 'Created Successfully', + user: user, + success: true + }) + }).catch(function(error) { + res.status(404).json({ + error: error, + message: 'This user already exist', + success: false + }) + }) + }) + + +} \ No newline at end of file diff --git a/model/User.js b/model/User.js new file mode 100644 index 0000000..4a964b8 --- /dev/null +++ b/model/User.js @@ -0,0 +1,58 @@ + +const Sequelize = require('sequelize'); +const bcrypt = require('bcrypt'); + +const sequelize = new Sequelize("palandas", "postgres", "newpassword", { + host: "localhost", + dialect: "postgres" +}) + +const attributes = { + id: { + type: Sequelize.UUID, + primaryKey: true, + defaultValue: Sequelize.UUIDV4 + }, + email: { + type: Sequelize.STRING, + allowNull: false, + validate: { + isEmail: true, + isUnique: function (value, next) { + var self = this; + User.find({ + where: { + email: value + } + }) + .then(function (user) { + // reject if a different user wants to use the same email + if (user && self.id !== user.id) { + return next('Email already in use!'); + } + return next(); + }) + .catch(function (err) { + return next(err); + }); + } + }, + }, + password: { + type: Sequelize.STRING, + }, + salt: { + type: Sequelize.STRING, + } +} + +const User = sequelize.define( + "users", attributes, { + timestamps: true + } +); + + + + +module.exports = User \ No newline at end of file diff --git a/model/model.js b/model/model.js new file mode 100644 index 0000000..405361c --- /dev/null +++ b/model/model.js @@ -0,0 +1 @@ +// we have to specify the relations here \ No newline at end of file diff --git a/models/user.js b/models/user.js deleted file mode 100644 index 42601dd..0000000 --- a/models/user.js +++ /dev/null @@ -1,92 +0,0 @@ -const config = require('../config/database'); -const bcrypt = require('bcrypt'); -const Sequelize = require('sequelize'); -const Strategy = require('passport-local') - - const sequelize = new Sequelize("palandas", "postgres", "newpassword", { - host: "localhost", - //port: 5432, - dialect: "postgres", - operatorsAliases: false, - pool: { - max: 5, - min: 0, - acquire: 30000, - idle: 10000 - } - -}) -const User = sequelize.define( - 'User', - { - id: { - type: Sequelize.UUID, - primaryKey: true, - defaultValue: Sequelize.UUIDV4 - }, - email: { - type: Sequelize.STRING, - isUnique: true, - allowNull: false, - isEmail: true - }, - password: Sequelize.STRING - }, - { - hooks: { - beforeValidate: User => { - User.password = bcrypt.hashSync(User.password, 10); - } - } - }, - - - ); - sequelize.sync({force: false}).then(() => { - User.create({ - - - - email :'chibaba@gmail.com', - password : 'we are hwer' - - - }); - }); - - - - - -module.exports = User ; - - - - -module.exports.getUserById = (id, cb) => { - User.findById(id, cb); -} -module.exports.getUserByEmail = (email, cb) => { - User.findOne({email:email}, cb); -} -module.exports.createUser = (newUser, cb) => { - bcrypt.genSalt(10, (err, salt)=>{ - bcrypt.hash(newUser.password, salt, (err, hash)=>{ - // newUser.password = hash; - - if(err) { - return err - } - // newUser.password = hash; - newUser.save(cb); - }) - }) -} -module.exports.comparePassword = (myPassword, hash, cb) => { - bcrypt.compare(myPassword, hash, (err, isMatch) => { - if(err) { - return res.status(500) - } - cb(null, isMatch) - }) -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b3ab9ed..38e2e53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1779,6 +1779,15 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, + "cookie-parser": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", + "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6" + } + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -1829,6 +1838,11 @@ "request": "2.87.0" } }, + "crc": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", + "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" + }, "create-error-class": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", @@ -2245,6 +2259,22 @@ } } }, + "express-session": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", + "integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.4", + "debug": "2.6.9", + "depd": "1.1.2", + "on-headers": "1.0.1", + "parseurl": "1.3.2", + "uid-safe": "2.1.5", + "utils-merge": "1.0.1" + } + }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", @@ -6278,6 +6308,14 @@ "pause": "0.0.1" } }, + "passport-http-bearer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", + "integrity": "sha1-FHRp6jZp4qhMYWfvmdu3fh8AmKg=", + "requires": { + "passport-strategy": "1.0.0" + } + }, "passport-jwt": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", @@ -6300,6 +6338,11 @@ "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" }, + "password-hash": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/password-hash/-/password-hash-1.2.2.tgz", + "integrity": "sha1-O0UfAU3ksuHr+g5Uk7lRexBjrx0=" + }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", @@ -6512,6 +6555,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -7384,6 +7432,14 @@ "dev": true, "optional": true }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "1.0.0" + } + }, "undefsafe": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", diff --git a/package.json b/package.json index 14f0993..1d8b25f 100644 --- a/package.json +++ b/package.json @@ -17,14 +17,18 @@ "bcrypt": "^2.0.1", "body-parser": "^1.18.3", "codecov": "^3.0.4", + "cookie-parser": "^1.4.3", "cors": "^2.8.4", "express": "^4.16.3", + "express-session": "^1.15.6", "jsonwebtoken": "^8.3.0", "morgan": "^1.9.0", "nodemon": "^1.17.5", "passport": "^0.4.0", + "passport-http-bearer": "^1.0.1", "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", + "password-hash": "^1.2.2", "pg": "^7.4.3", "pg-hstore": "^2.3.2", "sequelize": "^4.38.0", diff --git a/routes/routes.js b/routes/routes.js index b0cb025..3d8660c 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,13 +1,15 @@ + + + +const Router = require('express').Router const passport = require('passport'); -const jwt = require('jsonwebtoken'); -const config = require('../config/database'); -const User = require('../models/user'); -const express = require('express'); -const app = require('express').Router +const User = require('../model/User'); +const signUpController = require('../controllers/signupController') +const cfg = require('../controllers/config') +const setupPassport = require('../config/passport') -const LocalStrategy = require('passport-local').Strategy; -module.exports = (app, passport) => { +const app = Router() // Task1 begins here app.get('/', (req, res) => { @@ -25,248 +27,54 @@ module.exports = (app, passport) => { app.get('/data', (req, res) => { res.status(200).json({data:data}); }) -// // Task 1 ends here - -// passport.use( -// new LocalStrategy( -// { usernameField: "email", passwordField: "password" }, -// function(email, password, done) { - -// User.findOne({ email: req.body.email}, (err, existingUser) =>{ - -// if(existingUser) { -// return res.status(400).json({ -// message: (req.body.email + "User is currently existing") -// }) -// } else { -// User.save((err, User) => { -// if (err) return next(err) -// if(User) { -// res.status(200).json("New User has been created") -// } -// }) -// } -// }) - -// })); - - - - +// Task 1 ends here - -passport.use( - new LocalStrategy( - { usernameField: "email", passwordField: "password" }, - function(email, password, done) { - return User.findOne({ email, password }) - .then(User => { - if (!User) { - return done(null, false, { - message: "Incorrect email or password" - }); - } - return done(null, User, { message: "Logged In Successfully" }); - }) - .catch(err => done(err)); - } - ) -) - // passport.use( - // new LocalStrategy( - // function(email, password, done) { - // User.getUserByEmail(email, (err, User) =>{ - // if(err) throw err; - // if(!user) { - // return done(null, false, {message: 'Unknown user'}) - // } - // User.comparePassword(password, User.password, (err, isMatch) => { - // if(err) throw err; - // if(isMatch){ - // return done(null, User) - // } else { - // return done(null, false, {message: 'Invalid Password'}) - // } - // }) - // }) - // } - // ) - // ) +app.use(passport.initialize()) +app.use(passport.session()) - // app.post('/signup', function(req, res) { - // var newUser = new User(); - // newUser.email= req.body.email; - // newUser.password= req.body.password; +setupPassport(app) - // User.findOne({ email: req.body.email}, (err, existingUser) =>{ - // if(existingUser) { - // return res.status(400).json({ - // message: (req.body.email + "User is currently existing") - // }) - // } else { - // User.save((err, newUser) => { - // if (err) return next(err); - // res.json("New User has been created") - // }) - // } - // }) - - - // User.createUser(newUser, function(err, user){ - // if(errors) { - // res.status(400).json({success: false, message: 'user is not registered '}) - // // if(err) throw err; - // console.log(user) - // } - // }); - // //res.status(200).json({success:true, message: 'user is registered'}); - // res.status(200).json({ token: jwt.sign({ id: User.id}, 'newpassword '), - // success: true, - // message: 'user created' - - // }) - - // }) - - app.post("/signup", (req, res) => { - const { email, password } = req.body; - - if (!email || !password) { - res.status(400).json({ - success: false, - message: "Incorrect details" - }); - } - if (email && password) { - User.findOrCreate({ - where: { - email, - password - } - }).spread((userResult, created) => { - if (created) { - res.status(200).json({ token: jwt.sign({ id: User.id}, 'newpassword '), - success: true, - message: 'user created' - - }) - - } else { - return res.status(400).json({ - message: false, - message: "User already exists" - }); - } - }) - } +app.get('/', (req, res) => { + console.log('Yay') + res.json('welcome to authenticating jwt') +}); - }); - - +app.post('/signup', signUpController) - - -// app.post('/signup', (req, res, next) =>{ -// let user = new User(); - -// user.email=req.body.email; -// user.password = req.body.password; - -// User.findOne({ email: req.body.email}, (err, existingUser) => { -// if(existingUser) { -// console.log(req.body.email + " is already existing ") -// //return res.redirect('/signup'); -// }else { -// user.save(function(err, user) { -// if(err) return next(err); -// res.status(200).json({success:true, message: 'user is registered'}); -// res.status(200).json({ token: jwt.sign({ id: User.id}, 'newpassword '), -// success: true, -// message: 'user created' - -// }) -// res.json('Successfully created a new user') -// }) -// } +app.post('/login', passport.authenticate('local'), function (req, res) { + if (req.user) { + return res.status(200).json({ + message: 'Successful login', + success: 'true', + user: req.user + }) + } + return res.status(401).json({ + message: 'Unauthorized Access', + success: false + }) +}) + +// app.get('/profile', passport.authenticate('local', { +// session: false +// }), (req, res) => { +// res.json({ +// user: user.req +// }); +// }); +// app.get('/logout', (req, res) => { +// req.logout(); +// res.redirect('/'); // }) -//}) - +module.exports = app + - app.post("/login", (req, res, next) => { - passport.authenticate("local", (err, user, info) => { - if (err) { - return res.status(400).json({ - message: "Error logging in" - }); - } else if (!user) { - return res.status(400).json({ - message: "Incorrect Email or Password" - }); - } - req.login(user, err => { - if (err) { - return res.send(err); - } - return res.json({ token: jwt.sign({ id: User.id }, 'newpassword'), - success: true, - user: { - id: user._id, - email: user.email, - } - }); - }); - })(req, res); - }); - // app.post("/login", (req, res, next) => { - // passport.authenticate("local", (err, user, info) => { - // if (err) { - // return res.status(400).json({ - // message: "Error logging in" - // }); - // } else if (!user) { - // return res.status(404).json({ - // message: "Incorrect Email or Password" - // }); - // } - // req.login(User, err => { - // if (err) { - // return res.send(err); - // } - // return res.status(200).json({ token: jwt.sign({ id: User.id }, 'newpassword'), - // success: true, - // user: { - // id: User._id, - // email: User.email, - // } - // }); - // }); - // })(req, res); - // }); - - // app.use((req, res, next) => { - // if (req.tokenPayload) { - // req.user = req.tokenPayload.id; - // } - // if (req.User) { - // return next(); - // } else { - // return res.status(401).json({ status: 'error', code: 'unauthorized' }); - // } - // }); - - - - - // app.get('/logout', (req, res) => { - // req.logout(); - // res.redirect('/'); - // }) -} \ No newline at end of file + \ No newline at end of file diff --git a/server.js b/server.js index f790c94..c3fb7a9 100644 --- a/server.js +++ b/server.js @@ -1,3 +1,4 @@ + const express = require('express'); const bodyParser = require('body-parser'); const app = express(); @@ -6,10 +7,9 @@ const morgan = require('morgan') const Sequelize = require('sequelize') const cors = require('cors') const passport = require('passport') - -const LocalStrategy = require('passport-local').Strategy; -const config = require('./config/database'); -const PORT = process.env.PORT || 5000; +// const config = require('./config/database'); +const port = process.env.PORT || 5000; +const routes = require('./routes/routes') require('./config/passport')(passport); @@ -19,8 +19,7 @@ app.use(morgan('dev')); app.use(cors()); app.use(passport.initialize()); app.use(passport.session()); - -require('./routes/routes')(app, passport); -const server = app.listen(PORT, () => { - console.log(`Server listening at http://localhost:${PORT}`); -}); +app.use('/', routes); +app.listen(port, () => { + console.log('Server is running on port : ' + port); +}) \ No newline at end of file diff --git a/test/api/accounTest.spec.js b/test/api/accounTest.spec.js index 420d1c4..9a41859 100644 --- a/test/api/accounTest.spec.js +++ b/test/api/accounTest.spec.js @@ -1,7 +1,7 @@ const chaiHttp = require('chai-http'); const chai = require ('chai'); const request = 'request'; -const supertest = require('supertest'); +//const supertest = require('supertest'); const server = require('../../'); @@ -11,8 +11,8 @@ chai.use(chaiHttp); describe('POST /signup', () => { it('it should able to register new account', done => { const params = { - email: 'chibaba@gmail.com', - password: 'we are here', + email: 'chiscript@gmail.com', + password: 'they are here', }; chai .request('http://localhost:5000') @@ -21,12 +21,27 @@ describe('POST /signup', () => { .end((err, res) => { res.should.have.status(200); res.body.should.be.a('object'); - - res.body.should.have.property('token'); + res.body.should.have.property('message') res.body.should.have.property('success'); done(); }); }); + it('it should return 200 when User is already registered in db ', done => { + const params = { + email: 'chiscript@gmail.com', + password: 'they are here', + }; + chai + .request('http://localhost:5000') + .post('/signup') + .send(params) + .end((err, res) => { + res.should.have.status(200); + done(); + }); + }); + + }); @@ -34,8 +49,8 @@ describe('Login/SignUp Routes', () => { describe('POST /login', () => { it('it should POST a login ', done => { const params = { - email: 'chibaba@gmail.com', - password: 'we are here', + email: 'chiscript@gmail.com', + password: 'they are here', }; chai .request('http://localhost:5000') @@ -44,24 +59,25 @@ describe('Login/SignUp Routes', () => { .end((err, res) => { res.should.have.status(200); res.body.should.be.a('object'); - res.body.should.have.property('token'); + res.body.should.have.property('message'); + res.body.should.have.property('success') + done(); + }); + }); + it('it should return 401 when User is not registered in db ', done => { + const params = { + email: 'chinedua@gmail.com', + password: '12345', + }; + chai + .request('http://localhost:5000') + .post('/login') + .send(params) + .end((err, res) => { + res.should.have.status(401); done(); }); }); - // it('it should return 400 when the user is not available ', done => { - // const params = { - // email: 'chinedua@gmail.com', - // password: '12345', - // }; - // chai - // .request('http://localhost:5000') - // .post('/login') - // .send(params) - // .end((err, res) => { - // res.should.have.status(400); - // done(); - // }); - // }); }); })