diff --git a/config/passport/passport.js b/config/passport/passport.js new file mode 100644 index 0000000..56a086a --- /dev/null +++ b/config/passport/passport.js @@ -0,0 +1,114 @@ +// load bcrypt +var bCrypt = require("bcrypt-nodejs"); + +module.exports = function(passport, user) { + let User = user; + let LocalStrategy = require("passport-local").Strategy; + + passport.use( + "local-signup", + new LocalStrategy( + { + usernameField: "userName", + passwordField: "password", + passReqToCallback: true // allows us to pass back the entire request to the callback + }, + + function(req, userName, password, done) { + var generateHash = function(password) { + return bCrypt.hashSync(password, bCrypt.genSaltSync(8), null); + }; + User.findOne({ + where: { + userName: userName + } + }).then(function(user) { + if (user) { + return done(null, false, { + message: "That useranme is already taken" + }); + } else { + var userPassword = generateHash(password); + var data = { + userName: userName, + password: userPassword + }; + + User.create(data).then(function(newUser) { + if (!newUser) { + return done(null, false); + } + if (newUser) { + return done(null, newUser); + } + }); + } + }); + } + ) + ); + + passport.use( + "local-login", + new LocalStrategy( + { + // by default, local strategy uses username and password, we will override with userName + usernameField: "userName", + passwordField: "password", + passReqToCallback: true // allows us to pass back the entire request to the callback + }, + + function(req, userName, password, done) { + var User = user; + var isValidPassword = function(userpass, password) { + return bCrypt.compareSync(password, userpass); + }; + + User.findOne({ + where: { + userName: userName + } + }) + .then(function(user) { + if (!user) { + return done(null, false, { + message: "Username does not exist" + }); + } + + if (!isValidPassword(user.password, password)) { + return done(null, false, { + message: "Incorrect password." + }); + } + + var userinfo = user.get(); + return done(null, userinfo); + }) + .catch(function(err) { + console.log("Error:", err); + + return done(null, false, { + message: "Something went wrong with your Signin" + }); + }); + } + ) + ); + + // serialize + passport.serializeUser(function(user, done) { + done(null, user.id); + }); + + // deserialize user + passport.deserializeUser(function(id, done) { + User.findByPk(id).then(function(user) { + if (user) { + done(null, user.get()); + } else { + done(user.errors, null); + } + }); + }); +}; diff --git a/models/user.js b/models/user.js index dcb3bf0..0d2058a 100644 --- a/models/user.js +++ b/models/user.js @@ -3,7 +3,7 @@ module.exports = function(sequelize, DataTypes) { userName: { type: DataTypes.STRING, allowNull: false, - validate: { len: [4, 16] } + validate: { len: [3, 16] } }, email: { type: DataTypes.STRING, @@ -12,8 +12,8 @@ module.exports = function(sequelize, DataTypes) { }, password: { type: DataTypes.STRING, - allowNull: false, - validate: { len: [4, 16] } + allowNull: false + // validate: { len: [4, 16] } } }); diff --git a/package-lock.json b/package-lock.json index 1f32afb..e0f0749 100644 --- a/package-lock.json +++ b/package-lock.json @@ -192,6 +192,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "bcrypt-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", + "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -934,6 +939,33 @@ "promise": "^8.0.2" } }, + "express-session": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.2.tgz", + "integrity": "sha512-oy0sRsdw6n93E9wpCNWKRnSsxYnSDX9Dnr9mhZgqUEEorzcq5nshGYSZ4ZReHFhKQ80WI5iVUUSPW7u3GaKauw==", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.1.2", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -1933,6 +1965,11 @@ "ee-first": "1.1.1" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2059,6 +2096,28 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "passport": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", + "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + } + }, + "passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2093,6 +2152,11 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -2206,6 +2270,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "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.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2793,6 +2862,14 @@ "source-map": "~0.6.1" } }, + "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" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index aca4348..f00e1cb 100644 --- a/package.json +++ b/package.json @@ -15,12 +15,16 @@ }, "license": "ISC", "dependencies": { + "bcrypt-nodejs": "0.0.3", "cron": "^1.7.1", "dotenv": "^8.0.0", "express": "^4.17.1", "express-handlebars": "^3.1.0", + "express-session": "^1.16.2", "mysql": "^2.17.1", "mysql2": "^1.6.5", + "passport": "^0.4.0", + "passport-local": "^1.0.0", "public-ip": "^3.1.0", "request": "^2.88.0", "request-json": "^0.6.4", diff --git a/public/js/login.js b/public/js/login.js deleted file mode 100644 index c8259da..0000000 --- a/public/js/login.js +++ /dev/null @@ -1,25 +0,0 @@ -$("#loginButton").on("click", function(event) { - event.preventDefault(); - var userName = $("#user") - .val() - .trim(); - var password = $("#password") - .val() - .trim(); - var data = { - userName: userName, - password: password - }; - - $.get("/api/users/" + userName) - .then(function(user) { - // redirect for demo - window.location.href = "/users/" + user.userName; - }) - .catch(function() { - $.post("/api/users", data).then(function(newUser) { - // redirect for demo - window.location.href = "/users/" + newUser.userName; - }); - }); -}); diff --git a/routes/authRoutes.js b/routes/authRoutes.js new file mode 100644 index 0000000..d50c4a9 --- /dev/null +++ b/routes/authRoutes.js @@ -0,0 +1,33 @@ +module.exports = function(app, passport) { + app.post( + "/signup", + passport.authenticate("local-signup", { + failureRedirect: "/signup" + }), + (request, response) => { + let redirect = `/users/${request.user.userName}`; + response.redirect(redirect); + } + ); + + app.post( + "/login", + passport.authenticate("local-login", { + failureRedirect: "/login" + }), + (request, response) => { + let redirect = `/users/${request.user.userName}`; + response.redirect(redirect); + } + ); + + app.get("/logout", function(request, response) { + request.session.destroy(error => { + if (error) { + throw error; + } + let redirect = "/"; + response.redirect(redirect); + }); + }); +}; diff --git a/scripts/seedData.js b/scripts/seedData.js index 2a4b621..fc28097 100644 --- a/scripts/seedData.js +++ b/scripts/seedData.js @@ -1,4 +1,5 @@ var csv = require("csvtojson"); +const bCrypt = require("bcrypt-nodejs"); var db = require("../models"); @@ -15,9 +16,9 @@ db.sequelize }).then(function(dbPlant) { console.log("Creating fake user."); db.User.create({ - userName: "user", + userName: "jan", email: "mail@mail.com", - password: "password" + password: bCrypt.hashSync("password", bCrypt.genSaltSync(8), null) }).then(function(dbUser) { console.log("Creating fake device."); db.Device.create({ diff --git a/server.js b/server.js index fd1037f..23135cf 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,7 @@ var express = require("express"); var exphbs = require("express-handlebars"); +const passport = require("passport"); +const session = require("express-session"); var db = require("./models"); @@ -11,6 +13,18 @@ app.use(express.urlencoded({ extended: false })); app.use(express.json()); app.use(express.static("public")); app.use(express.static("device")); + +// For Passport +app.use( + session({ + secret: process.env.PASSPORT_SECRET, + resave: true, + saveUninitialized: true + }) +); // session secret +app.use(passport.initialize()); +app.use(passport.session()); // persistent login sessions + // Handlebars app.engine( "handlebars", @@ -25,6 +39,11 @@ app.set("view engine", "handlebars"); require("./routes/apiRoutes")(app); require("./routes/htmlRoutes")(app); require("./device-routes/apiRoutes")(app); +require("./routes/authRoutes")(app, passport); + +// Load passport strategies +require("./config/passport/passport")(passport, db.User); + var syncOptions = { force: false }; // If running a test, set syncOptions.force to true diff --git a/views/login.handlebars b/views/login.handlebars index bd2212e..5e61531 100644 --- a/views/login.handlebars +++ b/views/login.handlebars @@ -1,4 +1,3 @@ -
@@ -11,25 +10,24 @@