Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,32 @@ require('dotenv/config');
// ℹ️ Connects to the database
require('./db');

const { sessionConfig, loggedUser } = require("./config/session.config")


// Handles http requests (express is node js framework)
// https://www.npmjs.com/package/express
const express = require('express');

// Handles the handlebars
// https://www.npmjs.com/package/hbs
const path = require("path");
const hbs = require('hbs');

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: false }));

// Normalizes the path to the views folder
app.set("views", path.join(__dirname, "views"));
// Sets the view engine to handlebars
app.set("view engine", "hbs");
// Handles access to the public folder
app.use(express.static(path.join(__dirname, "public")));

hbs.registerPartials(__dirname + "/views/partials");

// ℹ️ This function is getting exported from the config folder. It runs most middlewares
require('./config')(app);

Expand All @@ -25,8 +41,10 @@ const capitalized = string => string[0].toUpperCase() + string.slice(1).toLowerC
app.locals.title = `${capitalized(projectName)}- Generated with Ironlauncher`;

// 👇 Start handling routes here
const index = require('./routes/index');
app.use('/', index);
app.use(sessionConfig);
app.use(loggedUser)
const routes = require('./routes/router');
app.use('/', routes);

// ❗ To handle errors. Routes that don't exist or errors that you handle in specific routes
require('./error-handling')(app);
Expand Down
41 changes: 41 additions & 0 deletions config/session.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const User = require("../models/User.model");
const expressSession = require("express-session");
const MongoStore = require("connect-mongo");
const mongoose = require("mongoose");

const MAX_AGE = 7;

module.exports.sessionConfig = expressSession({
name: "express-cookie",
secret: "super-secret",
resave: false,
saveUninitialized: false,
cookie: {
secure: false,
httpOnly: true,
maxAge: 24 * 3600 * 1000 * MAX_AGE,
},
store: new MongoStore({
mongoUrl: mongoose.connection._connectionString,
ttl: 24 * 3600 * MAX_AGE,
}),
});

module.exports.loggedUser = (req, res, next) => {
const userId = req.session.userId;
if (userId) {
User.findById(userId)
.then((userFound) => {
if (userFound) {
req.currentUser = userFound;
res.locals.currentUser = userFound;
next();
} else {
next();
}
})
.catch((err) => next(err));
} else {
next();
}
};
71 changes: 71 additions & 0 deletions controllers/auth.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// routes/auth.routes.js
const { Router } = require('express');
const User = require("../models/User.model")
const { default: mongoose } = require('mongoose');
const router = new Router();

// GET route ==> to display the signup form to users
module.exports.signUp = (req, res, next) => {
res.render('auth/signup')
}


// POST route ==> to process form data

module.exports.doSignUp = (req, res, next) => {
User.create(req.body)
.then((user) => {
user.checkPassword(req.body.passwordHash)
res.redirect("/logIn");
})
.catch((err) => {
if (err instanceof mongoose.Error.ValidationError) {
res.render("signup", {
user: {
email: req.body.email,
},
errors: err.errors,
});
} else {
next(err);
}
})
}

module.exports.logIn = (req, res, next) => {
res.render("auth/logIn")
}

module.exports.doLogIn = (req, res, next) => {
const { email, passwordHash } = req.body;

const renderWithErrors = () => {
res.render("auth/login", {
email,
error: "Email o constraseña incorrectos"
})
}
User.findOne({ email })
.then((user) => {
if(user) {
return user.checkPassword(passwordHash)
.then((match) => {
if(match) {
req.session.userId = user.id;
res.redirect("/profile");
} else {
renderWithErrors();
}
})
} else {
renderWithErrors();
}
})
.catch((err) => next(err))
}

module.exports.logOut = (req, res, next) => {
req.session.destroy();
res.clearCookie("express-cookie");
res.redirect("/login")
}
13 changes: 13 additions & 0 deletions controllers/user.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const User = require("../models/User.model");

module.exports.profile = (req, res, next) => {
res.render("users/profile")
}

module.exports.funnyCat = (req, res, next) => {
res.render("main")
}

module.exports.private = (req, res, next) => {
res.render("private")
}
15 changes: 15 additions & 0 deletions middlewares/auth.middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports.isAuthenticated = (req, res, next) => {
if(req.currentUser) {
next();
} else {
res.redirect("/logIn")
}
}

module.exports.isNotAuthenticated = (req, res, next) => {
if(!req.currentUser) {
next();
} else {
res.redirect("/profile")
}
}
56 changes: 47 additions & 9 deletions models/User.model.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,52 @@
const { Schema, model } = require("mongoose");
// models/User.model.js
const { Schema, model } = require('mongoose');
const bcrypt = require("bcrypt");

// TODO: Please make sure you edit the user model to whatever makes sense in this case
const userSchema = new Schema({
username: {
type: String,
unique: true
const EMAIL_PATTERN = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;

const userSchema = new Schema(
{
username: {
type: String,
trim: true,
required: [true, 'Username is required.'],
unique: true
},
email: {
type: String,
required: [true, 'Email is required.'],
unique: true,
match: [EMAIL_PATTERN, "Email is invalid"],
lowercase: true,
trim: true,
match: [EMAIL_PATTERN, "Email is invalid"]
},
passwordHash: {
type: String,
required: [true, 'Password is required.']
}
},
password: String
{
timestamps: true
}
);

userSchema.pre("save", function (next) {
const user = this;

if (user.isModified("passwordHash")) {
bcrypt.hash(user.passwordHash, 10)
.then ((hash) => {
user.passwordHash = hash;
next();
});
} else {
next();
}
});

const User = model("User", userSchema);
userSchema.methods.checkPassword = function (password) {
return bcrypt.compare(password, this.passwordHash)
}

module.exports = User;
module.exports = model('User', userSchema);
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
"dev": "nodemon server.js"
},
"dependencies": {
"bcrypt": "^5.1.1",
"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.1",
"hbs": "^4.1.1",
"mongoose": "^6.1.2",
"morgan": "^1.10.0",
Expand Down
104 changes: 102 additions & 2 deletions public/stylesheets/style.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,108 @@
/* public/stylesheets/style.css */
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
font: 14px 'Lucida Grande', Helvetica, Arial, sans-serif;
}

a {
color: #00B7FF;
color: #00b7ff;
text-decoration: none;
font-size: 1.5em;
}

form {
margin: 30px auto;
width: 380px;
}

form label {
color: #666;
display: inline-block;
margin-bottom: 10px;
text-align: center;
width: 100%;
}

form input,
form button {
box-sizing: border-box;
font-size: 14px;
outline: 0;
padding: 4px;
width: 100%;
margin-bottom: 20px;
}

form button {
background: #43a3e6;
border: 1px solid #43a3e6;
border-radius: 4px;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 14px;
padding: 8px 16px;
text-decoration: none;
text-transform: uppercase;
transition: 0.3s ease background;
width: 100%;
}

form button:hover {
background: #fff;
color: #43a3e6;
transition: 0.3s ease background;
}

.error {
background: #f02b63;
box-sizing: border-box;
color: #fff;
margin: 20px auto;
padding: 20px;
width: 100%;
}

ul {
border-bottom: 2px solid #43a3e6;
height: 30px;
padding: 1em 0;
list-style-type: none;
}

ul li {
line-height: 20px;
}

#to-right {
padding: 1em;
float: right;
}

#to-right span {
color: #43a3e6;
font-size: 1.5em;
}

#form h2 {
display: flex;
justify-content: center;
}

#to-left {
float: left;
}

#to-left p a {
color: #000;
font-weight: bold;
font-size: 2em;
}

#logout-form {
display: inline;
}

#logout-form button {
width: 120px;
}
8 changes: 0 additions & 8 deletions routes/index.js

This file was deleted.

Loading