diff --git a/app.js b/app.js index 2ecc9f2220..b6ceabaf50 100644 --- a/app.js +++ b/app.js @@ -12,9 +12,25 @@ const express = require('express'); // Handles the handlebars // https://www.npmjs.com/package/hbs const hbs = require('hbs'); +const MongoStore = require('connect-mongo')(session); +const mongoose = require('mongoose'); const app = express(); +app.use(express.static('public')); + +const authMiddleware = require('./routes/middleware'); + +// Import routes and other setup code + +app.get('/main', authMiddleware, (req, res) => { + res.render('main'); // Render the main view +}); + +app.get('/private', authMiddleware, (req, res) => { + res.render('private'); // Render the private view +}); + // ℹ️ This function is getting exported from the config folder. It runs most middlewares require('./config')(app); @@ -31,5 +47,12 @@ app.use('/', index); // ❗ To handle errors. Routes that don't exist or errors that you handle in specific routes require('./error-handling')(app); +app.use(session({ + secret: 'your-secret-key', + resave: false, + saveUninitialized: true, + store: new MongoStore({ mongooseConnection: mongoose.connection }) + })); + module.exports = app; diff --git a/models/User.model.js b/models/User.model.js index 9cdd3a3ce4..9947ff29ba 100644 --- a/models/User.model.js +++ b/models/User.model.js @@ -2,11 +2,21 @@ 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: { + + email: { type: String, - unique: true + required: [true, 'Email is required.'], + // this match will disqualify all the emails with accidental empty spaces, missing dots in front of (.)com and the ones with no domain at all + match: [/^\S+@\S+\.\S+$/, 'Please use a valid email address.'], + unique: true, + lowercase: true, + trim: true }, - password: String + passwordHash: { + type: String, + required: [true, 'Password is required.'] + } + }); const User = model("User", userSchema); diff --git a/package.json b/package.json index 19489d9695..9e2c55c516 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,11 @@ "dev": "nodemon server.js" }, "dependencies": { + "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..eb8c2f8176 --- /dev/null +++ b/routes/auth.routes.js @@ -0,0 +1,114 @@ +// routes/auth.routes.js + +const { Router } = require('express'); +const router = new Router(); + + + + +const User = require('../models/User.model'); + + +// auth.routes.js +const mongoose = require('mongoose'); // <== has to be added +// ... other imports and get route stay untouched + + + +// GET route ==> to display the signup form to users +router.get('/signup', (req, res) => res.render('auth/signup')); + +// POST route ==> to process form data +//router.post('/signup', (req, res, next) => { + // console.log('The form data: ', req.body); + //}); + + + +// the get route skipped +const bcryptjs = require('bcryptjs'); +const saltRounds = 10; +// POST route ==> to process form data +router.post('/signup', (req, res, next) => { + // console.log("The form data: ", req.body); + + const { username, email, password } = req.body; + + const regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/; + + if (!regex.test(password)) { + res + .status(500) + .render('auth/signup', { errorMessage: 'Password needs to have at least 6 chars and must contain at least one number, one lowercase and one uppercase letter.' }); + return; + } + + bcryptjs + .genSalt(saltRounds) + .then(salt => bcryptjs.hash(password, salt)) + .then(hashedPassword => { + return User.create({ + // username: username + username, + email, + // passwordHash => this is the key from the User model + // ^ + // | |--> this is placeholder (how we named returning value from the previous method (.hash())) + passwordHash: hashedPassword + }); + }) + .then(userFromDB => { + console.log('Newly created user is: ', userFromDB); + }) + .then(userFromDB => { + // console.log('Newly created user is: ', userFromDB); + res.redirect('/userProfile'); + }) + + .catch(error => { + if (error instanceof mongoose.Error.ValidationError) { + res.status(500).render('auth/signup', { errorMessage: error.message }); + } else if (error.code === 11000) { + + console.log(" Username and email need to be unique. Either username or email is already used. "); + + res.status(500).render('auth/signup', { + errorMessage: 'User not found and/or incorrect password.' + }); + } else { + next(error); + } + }); + }); + +// routes/auth.routes.js +// ... imports and get route stay untouched + +// POST route ==> to process form data +router.post('/signup', (req, res, next) => { + const { username, email, password } = req.body; + + // make sure users fill all mandatory fields: + if (!username || !email || !password) { + res.render('auth/signup', { errorMessage: 'All fields are mandatory. Please provide your username, email and password.' }); + return; + } + + // ... the rest of the code stays unchanged +}); + + +app.get('/login', (req, res) => { + res.render('login'); // Render your login form view + }); + + // Handle login form submission + app.post('/login', async (req, res) => { + const { email, password } = req.body; + // Check credentials and authenticate user + // If authentication successful, store user information in session + req.session.user = { email }; // Example: Storing email in session + res.redirect('/dashboard'); // Redirect to dashboard or any other authenticated route + }); + +module.exports = router; \ No newline at end of file diff --git a/routes/middleware.js b/routes/middleware.js new file mode 100644 index 0000000000..e17ea8e5de --- /dev/null +++ b/routes/middleware.js @@ -0,0 +1,11 @@ +const authMiddleware = (req, res, next) => { + if (req.session.user) { + // User is authenticated, allow access to the next middleware + next(); + } else { + // User is not authenticated, redirect to login page + res.redirect('/login'); + } + }; + + module.exports = authMiddleware; \ No newline at end of file diff --git a/views/login.hbs b/views/login.hbs new file mode 100644 index 0000000000..23c15d7971 --- /dev/null +++ b/views/login.hbs @@ -0,0 +1,7 @@ +
+ + + + + +
\ No newline at end of file diff --git a/views/main.hbs b/views/main.hbs new file mode 100644 index 0000000000..b6b2d0e98e --- /dev/null +++ b/views/main.hbs @@ -0,0 +1,3 @@ +

Main Page

+Funny Cat Picture +Back to Home \ No newline at end of file diff --git a/views/private.hbs b/views/private.hbs new file mode 100644 index 0000000000..9802675af5 --- /dev/null +++ b/views/private.hbs @@ -0,0 +1,2 @@ +

Private Page

+Favorite Gif \ No newline at end of file