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
23 changes: 9 additions & 14 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,29 @@
// ℹ️ Gets access to environment variables/settings
// https://www.npmjs.com/package/dotenv
require('dotenv/config');

// ℹ️ Connects to the database
require('dotenv/config');
require('./db');
require("./config/hbs.config");
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 express = require('express');
const hbs = require('hbs');

const app = express();

// ℹ️ This function is getting exported from the config folder. It runs most middlewares

require('./config')(app);

// default value for title local

const projectName = 'lab-express-basic-auth';
const capitalized = string => string[0].toUpperCase() + string.slice(1).toLowerCase();

app.locals.title = `${capitalized(projectName)}- Generated with Ironlauncher`;

// 👇 Start handling routes here
app.use(sessionConfig);
app.use(loggedUser);

const index = require('./routes/index');
app.use('/', index);

// ❗ To handle errors. Routes that don't exist or errors that you handle in specific routes
require('./error-handling')(app);

module.exports = app;
Expand Down
1 change: 1 addition & 0 deletions config/api.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let url = "https://dog.ceo/dog-api/documentation/random";
12 changes: 12 additions & 0 deletions config/hbs.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const hbs = require("hbs");

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

hbs.registerHelper("isSelected", function (id, cast, options) {
// Verifica si el id está en el array cast
if (cast.includes(id)) {
return "selected";
}

return "";
});
42 changes: 42 additions & 0 deletions config/session.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
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-cookies",
secret: "super-secret",
resave: true,
saveUninitialized: false,
cookie: {
secure: false, // mandamos la cookie en protocolos HTTP/HTTPS si es true solo HTTPS
httpOnly: true, // no es accesible por el Javascript del client-browser
maxAge: 24 * 3600 * 1000 * MAX_AGE, // una semana de vida
},
store: new MongoStore({
mongoUrl: mongoose.connection._connectionString, //monngoose.connection.db
ttl: 24 * 3600 * MAX_AGE,
}),
});

module.exports.loggedUser = (req,res,next) => {
const userId = req.session.userId;

if (userId) {
User.findById(userId)
.then((userFromDB) => {
if (userFromDB) {
req.currentUser = userFromDB; // todos los middlewares ya tienen acceso a currentUser
res.locals.currentUser = userFromDB; // res.locals es el objeto donde se manda informacion a todas las vistas (hbs)
next();
} else {
next();
}
})
.catch((err) => next(err));
} else {
next();
}
}
82 changes: 82 additions & 0 deletions controllers/auth.controllers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const mongoose = require("mongoose");
const User = require("../models/User.model");

module.exports.register = (req, res, next) => {
res.render("register");
};

module.exports.doRegister = (req, res, next) => {
User.create(req.body)
.then((user) => {
console.log(user);
user.checkPassword(req.body.password);
res.redirect("/login");
})
.catch((err) => {
if (err instanceof mongoose.Error.ValidationError) {
res.render("register", {
user: {
email: req.body.email,
},
errors: err.errors,
});
} else if (err.code === 11000) {
// Handle MongoDB Duplicate Key Errors
// Customize the error message based on the field causing the issue
const field = Object.keys(err.keyValue)[0]; // Extract the field causing the conflict
const value = err.keyValue[field]; // Extract the conflicting value
res.render("register", {
user: {
email: req.body.email,
},
errors: {
password: "Email or password incorrect"
},
});
} else {
console.log("***Register error2*** -->>>");
next(err);
}
});
};

module.exports.login = (req, res, next) => {
res.render("login");
};

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

const renderWithErrors = () => {
res.render("auth/login", {
email,
error: "Email o contraseña incorrectos",
});
};

User.findOne({ email })
.then((user) => {
if (user) {
return user.checkPassword(password).then((match) => {
if (match) {
req.session.userId = user.id; // genero cookie y session
res.redirect("/profile");
} else {
console.log("Email o contraseña incorrectos"); // contraseña incorrecta
renderWithErrors();
}
});
}
})
.catch((err) => next(err));
};

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

module.exports.logout = (req, res, next) => {
req.session.destroy();
res.clearCookie("express-cookie");
res.redirect("/login");
};
27 changes: 27 additions & 0 deletions controllers/main.routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
let url = "https://dog.ceo/api/breeds/image/random/6";
let gifUrl = "https://api.giphy.com/v1/gifs/random?api_key=JW0vWwVJ0uKi7MktTad2ZUTneYEuOpOY&tag=&rating=g";

module.exports.homeDisplay = (req,res,next) => {
res.render("home");
}

module.exports.mainDisplay = (req, res, next) => {
fetch(url)
.then(data => data.json())
.then(data=>{

res.render("main" , { image: data.message})
})
.catch(err => console.log(err))
}

module.exports.privateDisplay = (req, res, next) => {
fetch(gifUrl)
.then(data => data.json())
.then(data => {
console.log("***GIF API*** --->>>", data.data.images.original.url);
res.render("private",{image: data.data.images.original.url});
})
.catch(err => console.log(err))

}
9 changes: 9 additions & 0 deletions middleware/admin.middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports.isAdmin = (req, res, next) => {
if (req.currentUser.isAdmin) {
next();
} else {
res.render("error", {
error: "No eres admin",
});
}
};
15 changes: 15 additions & 0 deletions middleware/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");
}
};
43 changes: 39 additions & 4 deletions models/User.model.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,49 @@
const { Schema, model } = require("mongoose");
const bcrypt = require("bcrypt");

const EMAIL_PATTERN =
/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;

// TODO: Please make sure you edit the user model to whatever makes sense in this case
const userSchema = new Schema({
const UserSchema = new Schema({
username: {
type: String,
unique: true
required: [true, "username is requiured"],
trim: true,
},
email: {
type: String,
required: [true, "email is required"],
unique: true,
match: [EMAIL_PATTERN, "Email is invalid"],
trim: true,
lowercase: true,
},
password: {
type: String,
required: true,
minLength: [8, "Password must be 8 characters or longer"],
},
password: String
});

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

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

UserSchema.methods.checkPassword = function(password){
return bcrypt.compare(password, this.password)
}


const User = model("User", UserSchema);

module.exports = User;
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
"dev": "nodemon server.js"
},
"dependencies": {
"bcrypt": "^5.1.1",
"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
19 changes: 16 additions & 3 deletions routes/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
const router = require("express").Router();
const authControllers = require('../controllers/auth.controllers');
const authMiddleware = require('../middleware/auth.middleware');
const mainController = require('../controllers/main.routes')

/* GET home page */
router.get("/", (req, res, next) => {
res.render("index");
});
router.get("/register", authControllers.register);
router.post("/register", authControllers.doRegister);

router.get("/login", authMiddleware.isNotAuthenticated, authControllers.login);
router.post("/login",authMiddleware.isNotAuthenticated, authControllers.doLogin );

router.get("/profile", authControllers.loggedIn);

router.get("/logout", authControllers.logout);

router.get("/home", mainController.homeDisplay);
router.get("/private", mainController.privateDisplay);
router.get("/main", mainController.mainDisplay);

module.exports = router;
1 change: 1 addition & 0 deletions views/home.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1 class="p-3">This is the main home page, click up to log-in or sign-in</h1>
2 changes: 0 additions & 2 deletions views/index.hbs

This file was deleted.

4 changes: 3 additions & 1 deletion views/layout.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{title}}</title>
<link rel="stylesheet" href="/stylesheets/style.css" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>

<body>

{{> nav}}
{{{body}}}

<script src="/js/script.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>

</html>
Loading