I am new to express and I was able to get most of it to work until I wanted to create a delete button.
I am having difficulty getting my delete button to work all the time. It works at random moment and other times it does not work and when it does not work the following error appears:
{ CastError: Cast to ObjectId failed for value "undefined" at path "_id" for model "User"
Code below:
Both index.js and users.js files are in routes directory
//user - file in module directory
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String
},
email: {
type: String
},
name: {
type: String
},
isAdmin: {
type: Boolean,
default: false
}
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.createUser = function(newUser, callback){
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(newUser.password, salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
}
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch){
if(err) throw err;
callback(null, isMatch);
});
}
<!--page with delete button-->
<section class="jumbotron">
<div class="container">
<h1 class="jumbotron-heading text-center">Users Page</h1>
</div>
<div>
<ul class="list-group">
{{#each users}}
<li class="list-group-item">{{this.name}}</li>
{{/each}}
</ul>
</div>
</secion>
//main.js - file in the javascript directory
$(document).ready(function(){
$('.delete-user').on('click', function(e) {
$target = $(e.target);
const id = $target.attr('data-id');
$.ajax({
type: 'DELETE',
url: '/users/user/'+id,
success: function(response){
alert('Deleting User');
window.location.href='/users/users';
},
error: function(err){
console.log(err);
}
});
});
});
//users.js - file
var express = require('express');
var router = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('../modules/user');
// Admin Page
router.get('/admin', function(req, res){
res.render('admin');
});
// Login Page
router.get('/login', function(req, res){
res.render('login');
});
// Registeration Page
router.get('/register', function(req, res){
res.render('register');
});
// Users
router.get('/users', function(req, res) {
User.find({}, function(err, users) {
if(err) {
console.log(err);
} else {
res.render('users', {
users: users
});
}
});
});
// Individual Users
router.get('/user/:id', function(req, res) {
User.findById(req.params.id, function(err, users) {
res.render('user', {
users: users
});
});
});
// Delete Users
router.delete('/user/:id', function(req, res) {
let query = {_id:req.params.id};
User.remove(query, function(err){
if(err){
console.log(err);
}
res.send('Success');
});
});
// Create post request from form to server
router.post('/register', function(req, res){
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
var adminCode = req.body.adminCode;
//Validation
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('email', 'Email is Required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('username', 'Username is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('password2', 'Passwords do not match').equals(req.body.password);
var errors = req.validationErrors();
if(errors){
res.render('register',{
errors:errors
});
} else {
var newUser = new User({
name: name,
email: email,
username: username,
password: password
});
if(adminCode === 'secretcode123') {
newUser.isAdmin = true;
}
User.createUser(newUser, function(err, user){
if(err) throw err;
console.log(user);
});
req.flash('success_msg', 'You are registered and can now login');
res.redirect('/users/register');
}
});
passport.use(new LocalStrategy(
function(username, password, done) {
User.getUserByUsername(username, function(err, user) {
if (err) throw err;
if (!user) {
return done(null, false, { message: 'Unknown User' });
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch) {
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password'});
}
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
router.post('/login',
passport.authenticate('local', {successRedirect: '/', failureRedirect: '/users/login', failureFlash: true }),
function(req, res) {
res.redirect('/');
});
router.get('/logout', function(req, res){
req.logout();
req.flash('success_msg', 'You are logged out');
res.redirect('/users/login');
});
module.exports = router;
//indexjs - file
var express = require('express');
var router = express.Router();
// Home Page
router.get('/', ensureAuthenticated, function(req, res){
res.render('index');
});
function ensureAuthenticated(req, res,next){
if(req.isAuthenticated()){
return next();
} else {
//req.flash('error_msg', 'You are not logged in');
res.redirect('/users/login');
}
}
module.exports = router;
code here
can someone please advise what i am doing wrong.
It seems like i was able to correct the error. I had to move my data-id element from from my div tag to my anchor tag: see code below:
<section class="jumbotron">
<div class="container">
<h1 class="jumbotron-heading text-center">User Page</h1>
<h1 class="text-center">{{users.name}}</h1>
</div>
<div class="button">
<button class="btn btn-danger delete-user"/*it was here first*/><a href="#" /*now it is here*/data-id={{users._id}}>Delete</a></button>
</div>
</secion>
Related
I'm following a Udemy MERN stack course and I am quite a beginner ,I've got stuck in middle of a problem. There is no point in completing it before solving this problem. The problem is with the concept of authorization and concept of protected roles, so when the user is logged in to the interface we have to check whether is user is authorized or not. I followed the instructer end to end exactly according to the instruction and his code.
Using jsonwebtoken, verifiationn is conducted on the basis of encrypted token. whos key is stored in .env file
The output of the network dev tool in the browser :
enter image description here
I have no idea what causes this.
server.js
const express = require("express");
const app = express();
require("dotenv").config();
const dbConfig = require("./config/dbConfig.js");
app.use(express.json());
const userRoute = require("./routes/userRoute");
app.use("/api/user", userRoute);
const port = process.env.PORT || 5000;
console.log(process.env.MONGO_URL);
app.listen(port, () => console.log(`Node server started at port ${port}`));
.env
MONGO_URL = 'mongodb+srv://users:root#cluster0.vnoq4f8.mongodb.net/ngodatabase';
JWT_SECRET = 'ngo_project';
Home.js
import React, { useEffect } from "react";
import axios from "axios";
function Home() {
const getData = async () => {
try {
const response = await axios.post(
"/api/user/get-user-info-by-id",
{},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("token"),
}, // headers
}
);
console.log(response.data);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getData();
}, []);
return <div>Home</div>;
}
export default Home;
authmiddleware.js
const jwt = require("jsonwebtoken");
module.exports = async (req, res, next) => {
try {
const token = req.headers["authorization"].split(" ")[1];
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
return res.status(401).send({
message: "Auth failed",
success: false,
});
} else {
req.body.userId = decoded.id;
next();
}
});
} catch (error) {
return res.status(401).send({
message: "Auth failed",
success: false,
});
}
};
userRoute.js
const express = require("express");
const router = express.Router();
const User = require("../models/userModel");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const authmiddleware = require("../middlewares/authmiddleware");
router.post("/register", async (req, res) => {
try {
const userExist = await User.findOne({ email: req.body.email });
if (userExist) {
return res
.status(200)
.send({ message: "User already exists", success: false });
}
const password = req.body.password;
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
req.body.password = hashedPassword;
const newuser = new User(req.body);
await newuser.save();
res
.status(200)
.send({ message: "User created successfully", success: true });
} catch (error) {
console.log(error);
res
.status(500)
.send({ message: "Error creating user", success: false, error });
}
});
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
if (!user) {
return res
.status(200)
.send({ message: "User does not exist", success: false });
}
const isMatch = await bcrypt.compare(req.body.password, user.password);
if (!isMatch) {
return res
.status(200)
.send({ message: "Password is incorrect", success: false });
} else {
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, {
expiresIn: "1d",
});
res
.status(200)
.send({ message: "login successful", success: true, data: token });
}
} catch (error) {
console.log(error);
res
.status(500)
.send({ message: "Error logging in", success: false, error });
}
});
router.post("/get-user-info-by-id", authmiddleware, async (req, res) => {
try {
const user = await User.findOne({ _id: req.body.userId });
if (!user) {
return res
.status(200)
.send({ message: "User does not exist", success: false });
} else {
res.status(200).send({
success: true,
data: {
name: user.name,
email: user.email,
},
});
}
} catch (error) {
res.status(500).send({
message: "Error getting user information",
success: false,
error,
});
}
});
module.exports = router;
package.json
jsonwebtoken in package
Login.js
import { Button, Form, Input } from "antd";
import React from "react";
import toast from "react-hot-toast";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";
function Login() {
const navigate = useNavigate();
const onFinish = async (values) => {
try {
const response = await axios.post("/api/user/login", values);
if (response.data.success) {
toast.success(response.data.message);
toast("Redirecting to home page");
localStorage.setItem("token", response.data.data);
navigate("/");
} else {
toast.error(response.data.message);
}
} catch (error) {
toast.error("Something went wrong");
}
};
return (
<div className="authentication">
<div className="authentication-form card p-4">
<h1 className="card-title">Welcome Back</h1>
<Form layout="vertical" onFinish={onFinish}>
<Form.Item label="Email" name="email">
<Input placeholder="Email"></Input>
</Form.Item>
<Form.Item label="Password" name="password">
<Input placeholder="Password" type="password"></Input>
</Form.Item>
<Button className="primary-button my-2" htmlType="submit">
LOGIN
</Button>
<Link to="/register" className="anchor mt-2">
CLICK HERE TO REGISTER
</Link>
</Form>
</div>
</div>
);
}
export default Login;
Register.js
import { Button, Form, Input } from "antd";
import React from "react";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";
import toast from "react-hot-toast";
function Register() {
const navigate = useNavigate();
const onFinish = async (values) => {
try {
const response = await axios.post("/api/user/register", values);
if (response.data.success) {
toast.success(response.data.message);
toast("Redirecting to login page");
navigate("/login");
} else {
toast.error(response.data.message);
}
} catch (error) {
toast.error("Something went wrong");
}
};
return (
<div className="authentication">
<div className="authentication-form card p-4">
<h1 className="card-title">Nice to meet you</h1>
<Form layout="vertical" onFinish={onFinish}>
<Form.Item label="Name" name="name">
<Input type="text" placeholder="Name" name="name"></Input>
</Form.Item>
<Form.Item label="Email" name="email">
<Input type="email" placeholder="Email" name="email"></Input>
</Form.Item>
<Form.Item label="Password" name="password">
<Input
placeholder="Password"
name="password"
type="password"
></Input>
</Form.Item>
<Button
className="primary-button my-2"
htmlType="submit"
name="submit"
>
REGISTER
</Button>
<Link to="/Login" className="anchor mt-2">
CLICK HERE TO LOGIN
</Link>
</Form>
</div>
</div>
);
}
export default Register;
did you check if you already have the token in your storage ?
check using inspectElement, or try to print the token in authmiddleware.js
like:
const jwt = require("jsonwebtoken");
module.exports = async (req, res, next) => {
try {
const token = req.headers["authorization"].split(" ")[1];
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
console.log(token); //this line will print the token that given in your request
return res.status(401).send({
message: "Auth failed",
success: false,
});
} else {
req.body.userId = decoded.id;
next();
}
});
} catch (error) {
return res.status(401).send({
message: "Auth failed",
success: false,
});
}
};
I am new to JWT and Passport so I started following a MERN tutorial on Youtube by NoobCoder that deals with authentication and authorization using JWT. I reached the part where the route deals with '/logout' and I get Unauthorized as a reply from Postman. The code so far is exactly the same by the looks of it. Can someone help me understand what is wrong here?
I have attached the code in the bottom. Please let me know if more information is required.
Here is the code:
app.js
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
app.use(cookieParser());
app.use(express.json());
mongoose.connect('mongodb://localhost:27017/mernauth', {useNewUrlParser: true, useUnifiedTopology: true}, () => {
console.log('Successfully connected to DB');
});
const userRouter = require('./routes/User');
app.use('/user', userRouter);
app.listen(5000, () => {
console.log('express server started');
});
passport.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const JwtStrategy = require('passport-jwt').Strategy;
const User = require('./models/User');
const cookieExtractor = req => {
let token = null;
if(req && req.cookies) {
token = req.cookies['access_token'];
}
return token;
}
// Authorization
passport.use(new JwtStrategy({
jwtFromRequest: cookieExtractor,
secretOrKey: 'NoobCoder'
}, (payload, done) => {
User.findById({_id: payload.sub}, (err, user) => {
if(err) {
return done(err, false);
}
if(user) {
return done(null, user);
}
else {
return done(null, false);
}
})
}));
// Authenticated local strategy using username and password
passport.use(new LocalStrategy((username, password, done) => {
User.findOne({username}, (err, user) => {
// Something went wrong with DB
if(err) {
return done(err);
}
// If no user exists; null = no error; false = user does not exist
if(!user) {
return done(null, false);
}
// Check if password is correct; callback cb = done
user.comparePassword(password, done);
});
}));
User.js (route)
const express = require('express');
const userRouter = express.Router();
const passport = require('passport');
const passportConfig = require('../passport');
const JWT = require('jsonwebtoken');
const User = require('../models/User');
const Todo = require('../models/Todo');
const signToken = userID => {
return JWT.sign({
iss: "NoobCoder",
sub: userID
}, "NoobCoder", {expiresIn: "1h"});
}
userRouter.post('/register', (req, res) => {
const {username, password, role} = req.body;
User.findOne({username}, (err, user) => {
if(err) {
res.status(500).json({message: {msgBody: "Error has occured", msgError: true}})
}
if(user) {
res.status(400).json({message: {msgBody: "Username is already taken", msgError: true}})
}
else {
const newUser = new User({username, password, role});
newUser.save(err => {
if(err) {
res.status(500).json({message: {msgBody: "Error has occured", msgError: true}})
}
else {
res.status(201).json({message: {msgBody: "Account Successfully Created", msgError: false}})
}
})
}
})
});
userRouter.post('/login', passport.authenticate('local', {session: false}), (req, res) => {
if(req.isAuthenticated()) {
const {_id, username, role} = req.user;
const token = signToken(_id);
res.cookie('access_token', token, {httpOnly: true, sameSite: true});
res.status(200).json({isAuthenticated: true, user: {username, role}})
}
});
userRouter.get('/logout', passport.authenticate('jwt', {session: false}), (req, res) => {
res.clearCookie('access_token');
res.json({user: {username: '', role: ''}, success: true});
});
module.exports = userRouter;
User.js (model)
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
min: 6,
max: 15
},
password: {
type: String,
required: true,
},
role: {
type: String,
enum: ['user', 'admin'],
required: true
},
todos: [{type: mongoose.Schema.Types.ObjectId, ref: 'Todo'}]
});
UserSchema.pre('save', function(next) {
if(!this.isModified('password')) {
return next()
}
bcrypt.hash(this.password, 10, (err, passwordHash) => {
if(err) {
return next(err);
}
this.password = passwordHash;
next();
});
});
UserSchema.methods.comparePassword = function(password, cb) {
bcrypt.compare(password, this.password, (err, isMatch) => {
if(err) {
return cb(err);
}
else {
if(!isMatch) {
return cb(null, isMatch)
}
return cb(null, this);
}
})
};
module.exports = mongoose.model('User', UserSchema);
Perhaps the /logout route is unauthorised because the JWT token is not present?
JWT token presence can be verified by ensuring that the cookieExtractor function is returning a token
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
Source
I have an Express server on the backend that uses Passport.js for authentication. Even when successfully authenticated, a 404 error is shown in the webbrowser, when redirecting to '/about', '/login', or any other path (all those paths exists on the frontend), or even when not redirecting. The only time a 404 is not shown is if a redirect to '/' is made. I will include the relevant code snippets below.
users.js
router.post('/api/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
// res.statusCode is still 200 here!!!!!!!!
return res.redirect('/about');
});
})(req, res, next);
})
Alternative users.js (has same issue)
router.post('/api/login',
passport.authenticate('local', { successRedirect: '/about',
failureRedirect: '/login' }))
passportLocalStrategy.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const init = require('./passportSessionConfig');
const knex = require('../db/connection');
const authUtils = require('./utils')
init();
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
},
function (username, password, done) {
// check to see if the username exists
knex('users')
.where({ 'email': username })
.orWhere({ username })
.first()
.then((results) => {
if (!results) return done(null, false);
if (!authUtils.comparePass(password, results.password)) {
return done(null, false);
} else return done(null, results);
})
.catch((err) => { return done(err); });
}));
module.exports = passport;
This is the frontend javascript code that made the request (Vue.js)
methods: {
login: function(e) {
e.preventDefault();
let data = {
email: this.email,
password: this.password,
returnTo: window.location.pathname
};
this.axios
.post("/api/login", data)
.then(response => {
console.log("Logged in");
this.$router.push("/about");
})
.catch(errors => {
console.log("Cannot log in");
console.log(errors);
});
}
}
This is the 404 error from the webbrowser
I want to make sure that a particular link ('New Blog') is only available to myself (username = "admin") and not to the general public. I've written the following if statement but it's throwing an error:
<% if(currentUser.username = "admin") { %>
<ul class="nav navbar-nav">
<li class="active"><i class="fa fa-plus" aria-hidden="true"></i> New Blog <span class="sr-only">(current)</span></li>
</ul>
<% } %>
What is wrong with my logic here??
Routes are as follows:
router.get("/blogs", function(req, res){
Blog.find({}, function(err, blogs){
if(err) {
console.log(err);
} else {
res.render("index", {blogs: blogs});
}
});
});
router.get("/new", function(req, res){
res.render("new");
});
router.get("/blogs/:id", function(req, res){
Blog.findById(req.params.id, function(err, foundBlog){
if(err){
res.redirect("/blogs");
} else {
res.render("show", {blog:foundBlog});
}
});
});
// create route
router.post("/blogs", function(req, res){
req.body.blog.body = req.sanitize(req.body.blog.body);
Blog.create(req.body.blog, function(err, newBlog){
if(err) {
res.render("new");
} else {
res.redirect("/blogs");
}
});
});
// edit route
router.get("/blogs/:id/edit", function(req, res){
// find blog
Blog.findById(req.params.id, function(err, foundBlog){
if(err){
res.redirect("/blogs");
} else {
res.render("edit", {blog: foundBlog});
}
});
});
// update route
router.put("/blogs/:id", function(req,res){
req.body.blog.body = req.sanitize(req.body.blog.body);
Blog.findByIdAndUpdate(req.params.id, req.body.blog, function(err, updatedBlog) {
if(err) {
res.redirect("/");
} else {
res.redirect("/blogs/" + req.params.id);
}
});
});
// delete route
router.delete("/blogs/:id", function(req, res){
Blog.findByIdAndRemove(req.params.id, req.body.blog, function(err, deleteBlog){
if(err) {
res.redirect("/blogs");
} else {
res.redirect("/blogs");
}
});
});
router.get("/", function(req, res){
res.redirect("/blogs");
})
// reg
router.get("/register", function(req, res){
res.render("register");
});
// signup logic
router.post("/register", function(req, res){
var newUser = new User({username: req.body.username, image: req.body.image});
User.register(newUser, req.body.password, function(err, user){
if(err){
res.redirect("/blogs");
}
passport.authenticate("local")(req, res, function(){
res.redirect("/blogs");
});
});
});
// login form
router.get("/login", function(req, res){
res.render("login");
});
// login logic
router.post("/login", passport.authenticate("local", {
successRedirect: "/blogs",
failureRedirect: "/login",
}));
// logout logic
router.get("/logout", function(req, res){
req.logout();
req.flash("success", "You are now logged out");
res.redirect("/blogs");
});
When authentication is successful, Passport attaches the user object to the request object of the express router(req.user). This is achieved via the done(null, user) in your local authentication strategy. You can make the user object to check whether the corresponding user is indeed the admin.
router.post("/blogs", function(req, res){
req.body.blog.body = req.sanitize(req.body.blog.body);
Blog.create(req.body.blog, function(err, newBlog){
if(err) {
res.render("new", {
// Ternary operator which checks if the user object is empty or not
currentUser: req.user ? req.user.currentUser: '',
// I hope currentUser is present in your Schema object
});
} else {
res.redirect("/blogs");
}
});
And then you can check in your view whether it is the correct user or not:
<% if(currentUser === "admin") { %>
<ul class="nav navbar-nav">
<li class="active"><i class="fa fa-plus" aria-hidden="true"></i> New Blog <span class="sr-only">(current)</span> </li>
</ul>
<% } %>
I'm trying to figure out where the error lies in my authentication code that is creating an endless loop every time I try to login. I think it is within the local strategy passport.use('local', new LocalStrategy section of my code because my console.log(req.body.email); passes back the correct value that was inputted in the field and a query is logged that uses the findOne value, but none of the other console.log are being triggered (one for a email error, another for password error and one for success).
Example: trying to login with test#test.com email address
test#test.com
Executing (default): SELECT `user_id`, `first_name` AS `firstName`, `last_name` AS `lastName`, `email`, `password`, `createdAt`, `updatedAt` FROM `user` AS `user` LIMIT 1;
user.js:
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('user', {
user_id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
firstName: {
type: DataTypes.STRING,
field: 'first_name'
},
lastName: {
type: DataTypes.STRING,
field: 'last_name'
},
email: DataTypes.STRING,
password: DataTypes.STRING,
}, {
freezeTableName: true
});
return User;
}
db-index.js:
var Sequelize = require('sequelize');
var path = require('path');
var config = require(path.resolve(__dirname, '..', '..','./config/config.js'));
var sequelize = new Sequelize(config.database, config.username, config.password, {
host:'localhost',
port:'3306',
dialect: 'mysql'
});
sequelize.authenticate().then(function(err) {
if (!!err) {
console.log('Unable to connect to the database:', err)
} else {
console.log('Connection has been established successfully.')
}
});
var db = {}
db.User = sequelize.import(__dirname + "/user");
db.sequelize = sequelize;
db.Sequelize = Sequelize;
sequelize.sync();
module.exports = db;
site-routes.js:
var express = require('express');
var siteRoutes = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var models = require('../models/db-index');
/*==== Passport Configuration ====*/
// Serialize sessions
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
model.User.find({where: {id: id}}).success(function(user){
done(null, user);
}).error(function(err){
done(err, null);
});
});
passport.use('local', new LocalStrategy({
passReqToCallback : true,
usernameField: 'email'
},
function(req, email, password, done) {
console.log(req.body.email);
//Find user by email
models.User.findOne({ email: req.body.email }, function(err, user) {
//If there is an error, return done
if (err) { return done(err); }
//If user does not exist, log error and redirect
if (!user) {
console.log('No email')
return done(null, false, req.flash('message', 'Email not found.'));
}
//If user exists, but wrong password
if (!user.validPassword(password)) {
console.log('Password fail');
return done(null, false, { message: 'Incorrect password.' });
}
//If all credentials match, return user
console.log('Attempting login');
return done(null, user);
console.log('Successful login');
});
}
));
/*==== Index ====*/
siteRoutes.get('/', function(req, res){
res.render('pages/index.hbs');
});
/*==== Login ====*/
siteRoutes.route('/login')
.get(function(req, res){
res.render('pages/login.hbs');
})
.post(passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/sign-up',
failureFlash: true
}));
siteRoutes.route('/sign-up')
.get(function(req, res){
res.render('pages/sign-up.hbs');
})
.post(function(req, res){
models.User.create({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password
}).then(function() {
res.redirect('/');
}).catch(function(error){
res.send(error);
})
});
module.exports = siteRoutes;
login.hbs:
<!DOCTYPE html>
<head>
{{> head}}
</head>
<body>
{{> navigation}}
<div class="container">
<div class="col-md-6 col-md-offset-3">
<form action="/login" method="post">
<label for="login-username">Username</label>
<input type="text" class="form-control" id="login-username" name="email" placeholder="username or email">
<br />
<label for="login-password">Password</label>
<input type="password" class="form-control" id="login-password" name="password">
<div class="login-buttons">
<button type="submit">Login</button>
</div>
</form>
Don't have an account? Then register here!
<br />
Forgot your password?
</div>
</div>
</body>
You are passing a callback function as a second argument to models.User.findOne, but Sequelize functions don't take callbacks. Instead they return a promise. Your code in site-routes.js should look something like this:
passport.use('local', new LocalStrategy({
passReqToCallback: true,
usernameField: 'email'
},
function(req, email, password, done) {
console.log(req.body.email);
//Find user by email
models.User.findOne({
email: req.body.email
})
.then(function(user) {
// handle login here, user will be falsey if no user found with that email
})
.catch(function(err) {
// either findOne threw an exception or it returned a rejected promise
});
}
));
For a full-fledged example of local authentication using passport.js and Sequelize you can see my login-fiddle. Here is a perma-link to the passport local authentication strategy.