diff --git a/.env b/.env index c0c68b1ca0..6ed643f4b8 100644 --- a/.env +++ b/.env @@ -1 +1,2 @@ -PORT=3000 \ No newline at end of file +PORT=3000 +SESS_SECRET=supersecreto diff --git a/app.js b/app.js index 2ecc9f2220..9ef398f455 100644 --- a/app.js +++ b/app.js @@ -17,6 +17,7 @@ const app = express(); // ℹ️ This function is getting exported from the config folder. It runs most middlewares require('./config')(app); +require('./config/session.config')(app) // default value for title local const projectName = 'lab-express-basic-auth'; @@ -28,6 +29,12 @@ app.locals.title = `${capitalized(projectName)}- Generated with Ironlauncher`; const index = require('./routes/index'); app.use('/', index); +const authRoutes = require('./routes/auth.routes') +app.use('/', authRoutes) + +const userRoutes = require("./routes/user.routes") +app.use("/", userRoutes) + // ❗ To handle errors. Routes that don't exist or errors that you handle in specific routes require('./error-handling')(app); diff --git a/config/session.config.js b/config/session.config.js new file mode 100644 index 0000000000..8f55440304 --- /dev/null +++ b/config/session.config.js @@ -0,0 +1,25 @@ +const session = require('express-session'); +const MongoStore = require('connect-mongo'); +const mongoose = require('mongoose'); + +module.exports = app => { + + app.set('trust proxy', 1); + + app.use( + session({ + secret: process.env.SESS_SECRET, + resave: true, + saveUninitialized: false, + cookie: { + sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax', + secure: process.env.NODE_ENV === 'production', + httpOnly: true, + maxAge: 1000 + }, + store: MongoStore.create({ + mongoUrl: process.env.MONGODB_URI || "mongodb://127.0.0.1:27017/lab-express-basic-auth" + }) + }) + ); +}; \ No newline at end of file diff --git a/db/index.js b/db/index.js index 5da532b6ee..89b32ae466 100644 --- a/db/index.js +++ b/db/index.js @@ -6,7 +6,7 @@ const mongoose = require("mongoose"); // If no env has been set, we dynamically set it to whatever the folder name was upon the creation of the app const MONGO_URI = process.env.MONGODB_URI || "mongodb://127.0.0.1:27017/lab-express-basic-auth"; - +// mongodb://0.0.0.0:27017 mongoose .connect(MONGO_URI) .then((x) => { diff --git a/middleware/route-guard.js b/middleware/route-guard.js new file mode 100644 index 0000000000..be21834a9c --- /dev/null +++ b/middleware/route-guard.js @@ -0,0 +1,25 @@ +const { models } = require("mongoose") + +const isLoggedIn = (req, res, next) => { + if (req.session.currentUser) { + next() + } + else { + res.redirect('/login') + } +} + + +const isLoggedOut = (req, res, next) => { + if (!req.session.currentUser) { + next() + } + else { + res.redirect('/') + } +} + +module.exports = { + isLoggedIn, + isLoggedOut +} \ No newline at end of file diff --git a/models/User.model.js b/models/User.model.js index 9cdd3a3ce4..fc4f279fe3 100644 --- a/models/User.model.js +++ b/models/User.model.js @@ -1,12 +1,18 @@ const { Schema, model } = require("mongoose"); + // TODO: Please make sure you edit the user model to whatever makes sense in this case const userSchema = new Schema({ username: { type: String, + trim: true, + required: [true, 'Username Required'], unique: true }, - password: String + password: { + type: String, + required: [true, 'No password inserted'] + } }); const User = model("User", userSchema); diff --git a/package.json b/package.json index 19489d9695..c518562335 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,15 @@ "private": true, "scripts": { "start": "node server.js", - "dev": "nodemon server.js" + "dev": "nodemon server.js -e js, hbs" }, "dependencies": { + "bcryptjs": "^2.4.3", + "connect-mongo": "^5.1.0", "cookie-parser": "^1.4.5", "dotenv": "^8.2.0", "express": "^4.17.1", + "express-session": "^1.18.0", "hbs": "^4.1.1", "mongoose": "^6.1.2", "morgan": "^1.10.0", diff --git a/routes/auth.routes.js b/routes/auth.routes.js new file mode 100644 index 0000000000..e22381879c --- /dev/null +++ b/routes/auth.routes.js @@ -0,0 +1,62 @@ +const express = require('express'); +const router = express.Router(); +const bcrypt = require('bcryptjs'); +const User = require('./../models/User.model'); +const saltRounds = 10; +const { isLoggedOut } = require('../middleware/route-guard'); + +router.get('/register', isLoggedOut, (req, res) => { + res.render('auth/signup'); +}); + +router.post('/register', isLoggedOut, (req, res, next) => { + const { username, plainPassword } = req.body; + + bcrypt.genSalt(saltRounds) + .then(salt => bcrypt.hash(plainPassword, salt)) + .then(passwordHash => User.create({ username, password: passwordHash })) + .then(() => res.redirect('/login')) + .catch(err => next(err)); +}); + +router.get('/login', isLoggedOut, (req, res, next) => { + res.render('auth/login'); +}); + +router.post('/login', isLoggedOut, (req, res, next) => { + const { username, password } = req.body; + + if (!username || !password) { + res.render('auth/login', { errorMessage: 'Username and password are required' }); + return; + } + + User + .findOne({ username }) + .then(foundUser => { + if (!foundUser) { + res.render('auth/login', { errorMessage: 'Username not registered' }); + return; + } + + bcrypt.compare(password, foundUser.password) + .then(isPasswordValid => { + if (!isPasswordValid) { + res.render('auth/login', { errorMessage: 'Invalid password' }); + return; + } + + req.session.currentUser = foundUser; + res.redirect('/'); + }); + }) + .catch(err => next(err)); +}); + +router.get('/logout', (req, res) => { + req.session.destroy(() => { + res.redirect('/'); + }); +}); + +module.exports = router; diff --git a/routes/user.routes.js b/routes/user.routes.js new file mode 100644 index 0000000000..9f06b09610 --- /dev/null +++ b/routes/user.routes.js @@ -0,0 +1,11 @@ +const express = require('express') +const router = express.Router() + +const { isLoggedIn } = require('../middleware/route-guard') + +router.get('/profile', isLoggedIn, (req, res) =>{ + res.render('user/profile', { user: req.session.currentUser}) + +}) + +module.exports = router \ No newline at end of file diff --git a/views/auth/login.hbs b/views/auth/login.hbs new file mode 100644 index 0000000000..2d6544c90c --- /dev/null +++ b/views/auth/login.hbs @@ -0,0 +1,26 @@ +