Passport.authenticate() problems, Bad Request and Other Issues - node.js

I am trying to develop a small project where I am using passport js for authentication, I am facing challenges in passport.authenticate method in both login and signup pages, it doesn't goes inside the method and does not redirect or render desired destination.
home.ejs file
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Mitr:wght#500&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/biodata.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<a class="navbar-brand justify-content-around" id="navbar-home" href="/">Home</a>
<div class="ml-auto" id="navbar-joint">
<a class="navbar-brand" href="/signup">Sign Up</a>
<a class="navbar-brand" href="/logout">Logout</a>
</div>
</nav>
<div class="card">
<div class="card-body">
<form action="/bioform" method="POST">
<h2 class="d-flex justify-content-center">LOGIN</h2>
<div class="form-group">
<input type="text" class="form-control form-control-lg" id="username" name="username" placeholder="Username">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="inputPassword" name="inputPassword" placeholder="Password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg btn-block">Submit</button>
</div>
New User
</form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
signup.ejs file
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Mitr:wght#500&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/biodata.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<a class="navbar-brand justify-content-around" id="navbar-home" href="/">Home</a>
<div class="ml-auto" id="navbar-joint">
<a class="navbar-brand" href="/signup">Sign Up</a>
<a class="navbar-brand" href="/logout">Logout</a>
</div>
</nav>
<div class="card" id="signup-card">
<div class="card-body" id="signup-card-body">
<form action="/register" method="POST">
<h3 class="d-flex justify-content-center">SIGN UP</h3>
<div class="form-group">
<input type="text" class="form-control form-control-lg" id="username" name="username" placeholder="Username">
</div>
<div class="form-group">
<input type="email" class="form-control" id="email" name="email" placeholder="Email">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="inputPassword" name="inputPassword" placeholder="Password">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="confirminputPassword" name="confirminputPassword" placeholder="Confirm Password">
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck1" name="exampleCheck1">
<label class="form-check-label" for="exampleCheck1">I agree</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg btn-block">Submit</button>
</div>
</form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
User.js file
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var usersSchema = new mongoose.Schema({
username:String,
password:String,
email:String
});
usersSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User",usersSchema);
app.js file
var express = require("express");
var app = express();
var mongoose = require("mongoose");
var passport = require("passport"),
localStrategy = require("passport-local");
const User = require("./models/User");
var expressSession = require("express-session");
mongoose.connect('mongodb://localhost/users', {useNewUrlParser: true, useUnifiedTopology: true}).catch(function(reason){
console.log('Unable to connect to the mongodb instance. Error: ', reason);
});
app.set('view engine', 'ejs');
var bod = require("body-parser");
app.use(bod.urlencoded({extended:true}));
app.use(passport.initialize());
app.use(passport.session());
app.use(expressSession({
secret:"Test Key",
resave:false,
saveUninitialized:false
}));
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(express.static(__dirname + '/resources'));
app.get("/", function(req, res) {
res.render("home");
});
app.get("/home", function(req, res) {
res.render("home");
});
app.post("/bioform",passport.authenticate("local",{
failureRedirect:"/home"
}),function(req,res){
console.log(req.body);
res.render('bioform', {userName:req.body.username})
});
app.post("/register",function(req,res){
var userName = req.body.username;
var inputPassword = req.body.inputPassword;
var email = req.body.email;
var exampleCheck1 = req.body.exampleCheck1;
var confirminputPassword = req.body.confirminputPassword;
if(exampleCheck1==="on"){
if(inputPassword===confirminputPassword){
User.register( new User({username:userName,email:email}),inputPassword, function(err,user){
console.log("Inside first");
if(err){
console.log(err);
return res.render("signup");
}
passport.authenticate("local",function(err,user,info){
//the control doesn't reach this point.
console.log("Inside second");
if(err){
return console.log(err);
}
if (!user) { return res.redirect('/home'); }
req.logIn(user, function(err) {
if (err) { console.log(err); }
return res.redirect('bioform', {userName:userName});
});
});
/*
//this startegy didn't work either
passport.authenticate("local")(req,res,function(){
console.log("Reached here ");
res.render("bioform",{userName:userName});
});
*/
});
}else{
console.log("Passwords doesn't match!!!");
res.render("signup");
}
}else{
console.log("Agree to Terms!!!");
res.render("signup");
}
});
function isLoggedIn(req,resp,next){
if(req.isAuthenticated()){
return next();
}else{
res.redirect("/home");
}
}
app.get("/signup", function(req, res) {
res.render("signup");
});
app.listen(3000,function(){
console.log("Server started");
});
passport.authenticate() seems to be the problem here, either it will display a Bad Request message or just does nothing and tries to load the requested page without success. Will deeply appreciate your help in this issue. Thanks
Update: Here is what worked for me, I wrote a new post method
app.post("/register",function(req,res){
var username = req.body.username;
var password = req.body.password;
var email = req.body.email;
User.register({username:username,email:email},password,function(err,user){
console.log("post here")
if(err){
return console.log(err);
}
if(!user){
return res.redirect('/signup');
}
req.login(user, function(err){
if(err){
return console.log(err);
}
console.log("post");
res.render("bioform",{currentUser:req.user});
});
});
});

Reverse the order of your middleware - your express sessions should be declared before passport sessions, otherwise passport will be unable to use them:
app.use(expressSession({
secret:"Test Key",
resave:false,
saveUninitialized:false
}));
app.use(passport.initialize());
app.use(passport.session());
You have some other issues as well - passport.authenticate() should not be called in your /register route. You are currently calling req.login() inside of passport.authenticate when it should be called on its own; see this StackOverflow answer as well as Passport Login Docs. You will want to do something like this:
User.register(/* ... */, function(err, user) {
if (err) {
return res.redirect('/signup');
} else {
req.login(user, function(err) {
if (!err) {
return res.redirect('/home');
} else {
// handle error
}
});
}
});
Take a closer look at passport-local-mongoose which has some simplified configuration starting with their 0.2.1 version, passport docs, and this Express LocalStrategy example. Manually register a user in your Mongoose database and test the authentication strategy with that user. Once you have that working you can move on to your /register route, assuming you are attempting to auto-login after registration

Related

Why its not rendering welcome page when I click Sign in button?

app.js
const express = require('express');
const bodyParser = require('body-parser');
const ejs = require('ejs');
const mongoose = require('mongoose');
const app = express();
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', "ejs");
mongoose.set('strictQuery', false);
mongoose.connect("mongodb://localhost:27017/friendDB", { useNewUrlParser: true });
// Create Schema
const friendSchema = new mongoose.Schema({
email: String,
password: Array,
});
// Create Model through Schema
const Friend = new mongoose.model("Friend", friendSchema);
app.get('/', (req, res) => {
res.render("home");
})
app.get('/SignUp', (req, res) => {
res.render('SignUp');
})
app.get('/SignIn', (req, res) => {
res.render('SignIn');
});
app.get('/welcome', (req, res) => {
res.render('welcome');
})
// app.get("/signInFail", (req,res)=>{
// res.render("signInFail");
// });
app.post('/SignUp', (req, res) => {
// console.log(req.body.username);
// console.log(req.body.password);
const newFriend = new Friend({
email: req.body.username,
password: req.body.password,
confirmPassword: req.body.password
});
newFriend.save((err) => {
if (err) {
console.log(err);
} else {
res.render("welcome");
}
})
});
app.post('/SignIn', (req, res) => {
const username = req.body.username;
const password = req.body.password;
Friend.findOne({ email: username }, function (err, foundFriend) {
if (err) {
console.log(err);
} else {
if (foundFriend) {
if (foundFriend.password === password) {
res.render("welcome");
}
}
}
});
});
// app.post("/SignIn", (req,res)=>{
// const username = req.body.username;
// const password = req.body.password;
// Friend.findOne({email:username}, (err, foundFriend)=>{
// if(err){
// console.log(err);
// }else{
// if(foundFriend){
// if(foundFriend.password === password){
// res.render("welcome");
// }
// }
// }
// });
// });
app.listen(3000, () => {
console.log('server listening at port 3000');
})
welcome.ejs
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Welcome</title>
<link rel="stylesheet" href="css/styles.css">
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<body class="text-center" style="margin:5% 35% 0 35%;">
<main class="form-signin w-100 m-auto">
<form>
<img src="./images/haikyyu main logo.png" alt="main_logo" height="150" width="150"
style="padding-bottom: 15px;border-radius: 100px;">
<h1 class="h3 mb-3 fw-normal">Hurray!</h1>
<h2>You've Signed In successfully😉.</h2>
<p class="mt-5 mb-3 text-muted">© 2022</p>
</form>
</main>
</body>
</html>
SignIn.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<title>SignIn</title>
</head>
<body>
<body class="text-center" style="margin:5% 35% 0 35%;">
<main class="form-signin w-100 m-auto">
<form action="/SignIn" method="post">
<img src="./images/haikyyu main logo.png" alt="main_logo" height="150" width="150"
style="padding-bottom: 15px;border-radius: 100px;">
<h1 class="h3 mb-3 fw-normal">Sign-In</h1>
<div class="form-floating">
<input type="email" class="form-control" id="floatingInput" placeholder="name#example.com" name="username">
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating" style="padding-top: 3px;">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password" name="password">
<label for="floatingPassword">Password</label>
</div>
<div class="checkbox mb-3" style="padding-top:15px">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<div class="buttons" style="display: flex; justify-content: space-between;">
Sign Up
<button class="w-50 btn btn-lg" type="submit"
style="margin-left: 15px;background-color: rgb(236, 76, 18);color:aliceblue;">Sign In</button>
</div>
<p class="mt-5 mb-3 text-muted">© 2022</p>
</form>
</main>
</body>
</body>
</html>
It's not showing any error, it was working when I first tried it but after some time, when I tried to sign in with the same username and password the loader is just keep loading not showing the welcome page.
I think there is some problem in this code:
app.post('/SignIn', (req, res) => {
const username = req.body.username;
const password = req.body.password;
Friend.findOne({ email: username }, function (err, foundFriend) {
if (err) {
console.log(err);
} else {
if (foundFriend) {
if (foundFriend.password === password) {
res.render("welcome");
}
}
}
});
});
But I'm unable to figure out what it is.

req flash not showing messages with passport js

using the express-flash package together with passportjs, and I want to flash messages to a user.
App.js
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const sessions = require('express-session');
const passport = require('passport');
const passportInit = require('./config/passport');
const sessionStoreSQL = require('express-mysql-session')(sessions);
const logger = require('morgan');
const flash = require('express-flash');
const favicon = require('serve-favicon');
const app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser('keyboard cat'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(sessions({
genid: (req) => {
return uuid.v1();
},
secret:'-----',
resave:false,
saveUninitialized:false,
store:sessionStore
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
passportInit(passport,userModel);
require('./routes/index')(app,passport);
require('./server/API/get')(app);
I use a custom middle ware function to map my errors to, so I can access all of them in my templates
app.get('*', function(req,res,next){
res.locals.successes = req.flash('success');
res.locals.errors = req.flash('error');
res.locals.warnings = req.flash('warning');
next();
});
Passport.js
passport.use('local-login', new localStategy({passReqToCallback:true},function (req,username,password,done){
const isValidPassword = (userpass,password) => {
return bcrypt.compareSync(password,userpass);
}
Model.findOne({
where:{
'username':username,
},
}).then(function(user){
if(!user) return done(null,false,req.flash('warning','User does not exist'));
if(!isValidPassword(user.password,password)) return done(null,false,req.flash('error','Incorrect password'));
return done(null, user);
}).catch(err => console.log(err));
}))
Here is where I flash messages to the user.
Then I have a EJS component that handles al my alerts
Alerts.ejs
<% if (errors.lenght > 0) { %>
<div class='header alert alert-danger alert-dismissible'>
<strong><i class="fa fa-exclamation-circle"></i> ERROR:</strong> <%- errors.message %>
<i class='fa fa-times'></i>
</div>
<% } %>
<% if (successes.lenght > 0 ) { %>
<div class='header alert alert-success alert-dismissible'>
<strong><i class="fa fa-check-circle"></i> Success!</strong> <%- successes.message %>
<i class='fa fa-times'></i>
</div>
<% } %>
<% if (warnings.lenght > 0) { %>
<div class='header alert alert-warning alert-dismissible'>
<strong><i class="fa fa-check-circle"></i> Warning:</strong> <%- warnings.message %>
<i class='fa fa-times'></i>
</div>
<% } %>
This is then included in my templates e.g login and register like so
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %> </title>
<% include components/header.ejs %>
</head>
<body>
<% include components/navbar.ejs %>
<div class="container-fluid">
<% include components/alerts.ejs %>
<div class="row justify-content-center">
<div class="col-auto">
<form method="POST" action="/login">
<div class="form-group">
<label for="login-username">Username</label>
<input name="username" type="text" class="form-control" id="loginUsername"
aria-describedby="emailHelp" placeholder="Enter Username">
</div>
<div class="form-group">
<label for="login-password">Password</label>
<input name="password" type="password" class="form-control" id="loginPassword"
placeholder="Password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</body>
<% include components/scripts.ejs %>
</html>
Routes.js
/* eslint-disable no-unused-vars */
module.exports = function (app,passport) {
app.get('/', async function (req, res) {
res.render('index', {title:'Home'});
});
app.post('/',function (req,res) {
})
app.get('/cryptofolio/:username',isAuthenticated, function(req,res) {
res.render('cryptofolio', {title:'Cryptofolio'});
})
app.post('/portfolio',function(req,res){
})
app.get('/login',function(req,res){
res.render('login',{title:'Login'});
});
app.post('/login',passport.authenticate('local-login',{successRedirect: '/',failureRedirect:'/login',failureFlash:true}));
app.get('/register',function (req,res){
res.render('register',{title:'Register'});
})
app.post('/register',passport.authenticate('local-register',{successRedirect: '/',failureRedirect:'/register',failureFlash:true}));
app.get('/logout',function (req,res) {
req.logout();
res.redirect('/');
})
function isAuthenticated(req,res,next){
if (req.isAuthenticated()){
return next();
}
res.redirect('/login');
}
};
But when I input wrong information no errors are being flashed like they should.D
i think the check inside the template is returning false, as it needs to be checking for length not lenght

user.findOne is not a function

I am learning to use passport js in my form application and I am using a user object in an application that uses this model to save a user in database but when I return a user object that has been created and try to update that object by using findOne method I run into user.findOne is not a function error Here is my code.
Thanks in advance for helping me out.
user.js looks something like this
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var usersSchema = new mongoose.Schema({
username:String,
password:String,
email:String
});
usersSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User",usersSchema);
my signup page looks like this
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Mitr:wght#500&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/biodata.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<a class="navbar-brand justify-content-around" id="navbar-home" href="/">Home</a>
<div class="ml-auto" id="navbar-joint">
<a class="navbar-brand" href="/signup">Sign Up</a>
<a class="navbar-brand" href="/logout">Logout</a>
</div>
</nav>
<div class="card" id="signup-card">
<div class="card-body" id="signup-card-body">
<form action="/register" method="POST">
<h3 class="d-flex justify-content-center">SIGN UP</h3>
<div class="form-group">
<input type="text" class="form-control form-control-lg" id="username" name="username" placeholder="Username">
</div>
<div class="form-group">
<input type="email" class="form-control" id="email" name="email" placeholder="Email">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="inputPassword" name="inputPassword" placeholder="Password">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="confirminputPassword" name="confirminputPassword" placeholder="Confirm Password">
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck1" name="exampleCheck1">
<label class="form-check-label" for="exampleCheck1">I agree</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg btn-block">Submit</button>
</div>
</form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
my app.js looks like this
var express = require("express");
var app = express();
var mongoose = require("mongoose");
var passport = require("passport"),
localStrategy = require("passport-local");
const User = require("./models/User");
var expressSession = require("express-session");
mongoose.connect('mongodb://localhost/users', {useNewUrlParser: true, useUnifiedTopology: true}).catch(function(reason){
console.log('Unable to connect to the mongodb instance. Error: ', reason);
});
app.set('view engine', 'ejs');
var bod = require("body-parser");
app.use(bod.urlencoded({extended:true}));
app.use(passport.initialize());
app.use(passport.session());
app.use(expressSession({
secret:"the key",
resave:false,
saveUninitialized:false
}));
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(express.static(__dirname + '/resources'));
/*
var usersSchema = new mongoose.Schema({
username:String,
password:String,
email:String
});
var user = mongoose.model("User",usersSchema);
*/
app.get("/", function(req, res) {
res.render("home");
});
app.get("/home", function(req, res) {
res.render("home");
});
//problem method
app.post("/register",function(req,res){
var userName = req.body.username;
var inputPassword = req.body.inputPassword;
var email = req.body.email;
var exampleCheck1 = req.body.exampleCheck1;
var confirminputPassword = req.body.confirminputPassword;
if(exampleCheck1==="on"){
if(inputPassword===confirminputPassword){
User.register( new User({username:userName}),inputPassword, function(err,user){
console.log(user);
// here I tried to cast the returned object into User.js object but it didn't work
// user = new User();
if(err){
console.log(err);
return res.render("signup");
}
//I am trying to update returned object with email, I am not sure if this is the correct way to do it, would welcome suggestions. but at this point the user.findOne is not a function error is thrown.
user.findOne({username:userName},function(err,user){
user.email = email;
user.save();
console.log(user);
});
passport.authenticate("local")(req,res,function(){
res.render("bioform",{userName:userName});
});
});
}else{
console.log("Passwords doesn't match!!!");
res.render("signup");
}
}else{
console.log("Agree to Terms!!!");
res.render("signup");
}
});
//
app.get("/signup", function(req, res) {
res.render("signup");
});
app.listen(3000,function(){
console.log("Server started");
});
You are trying to call findOne in the object returned by the call to register from passport-local-moongoose.
Instead, you should call it through the User model:
const User = require("./models/User");
[...]
User.register(new User({ username: userName }), inputPassword, function(err, user) {
[...]
// Use User model instead of the object returned in User.register.
User.findOne({ username: userName }, function(err, user) {
// Your logic here.
});
});

body-parser: cannot fetch the values from the form

I have created a form for signing up a user. I want to fetch the values from the form using body-parser but I am not able to do so. While prinnting in the console it gives undefined printed. I don't get what am I doing wrong. I even tried using postman but it doesn't work. Here is my code:
var express = require('express'),
app = express(),
mongoose = require('mongoose'),
bodyParser = require('body-parser'),
passport = require('passport'),
LocalStrategy = require('passport-local'),
methodOverride = require('method-override'),
flash = require('flash'),
session = require('express-session');
app.get("/about", function(req, res) {
res.render("about");
});
app.get("/register", function(req, res) {
res.render("register");
});
app.post("/register", function(req, res) {
var firstName = req.body.firstName,
lastName = req.body.lastName,
username = req.body.username,
email = req.body.email;
var newUser = new User({
firstName: firstName,
lastName: lastName,
username: username,
email: email
});
console.log(firstName + " " + req.body.password + " " + req.body.c_password);
User.register(newUser, req.body.password, function(err, user) {
if(err) {
return res.render("register", {'error': err.message});
}
passport.authenticate('local')(req, res, function() {
req.flash('success', 'Welcome ' + user.username);
res.redirect('/home');
})
})
});
var port = process.env.PORT || 3000;
app.listen(port, function() {
console.log("Service Running");
});
And here is my form
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hotel Site</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.0/css/all.css" integrity="sha384-REHJTs1r2ErKBuJB0fCK99gCYsVjwxHrSU0N7I1zl9vZbggVJXRMsv/sLlOAGb4M" crossorigin="anonymous">
<link rel="icon" href="https://www.svgrepo.com/show/12002/hotel.svg" type="image/x-icon">
<link rel="stylesheet" href="/stylesheets/style.css">
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
</head>
<body>
<div class="container" style="margin-bottom: 4.5rem;">
<h1 style="text-align: center; margin-top: 7rem; margin-bottom: 20px">Sign Up</h1>
<div class="col-lg-6" style="margin: auto;">
<form action="/register" method="POST" enctype="multipart/form-data">
<div class="form-row">
<div class="form-group col-6">
<input class="form-control" type="text" name="firstName" placeholder="First Name" required>
</div>
<div class="form-group col-6">
<input class="form-control" type="text" name="lastName" placeholder="Last Name" required>
</div>
</div>
<div class="form-group">
<input class="form-control" type="text" name="username" placeholder="Username" required>
</div>
<!-- <div class="form-group">
<input class="form-control" type="email" name="email" placeholder="E-mail" required>
</div> -->
<div class="form-group">
<input class="form-control" type="password" name="password" placeholder="Password" required>
</div>
<div class="form-group">
<input class="form-control" type="password" name="c_password" placeholder="Confirm Password" required>
</div>
<div class="form-group">
<button class="btn btn-lg btn-primary btn-block">Submit</button>
</div>
</form>
Go Back
</div>
</div>
</body>
Help very much appreciated!!!
Express uses middleware, which are functions that have access to incoming requests. Requests can be modified etc. Simply put middleware can be used for lots of things.
You have not setup bodyParser as middleware so it will not work. This can be done by:
app.use(bodyParser.urlencoded({extended: false})) for form data
app.use(bodyParser.json()) for incoming JSON before your routes.
Here's the ExpressJs guide on middle: https://expressjs.com/en/guide/writing-middleware.html
You've successfully imported body-parser into your app, but you've failed to use it. Add the following code before you use your routes.
app.use(bodyParser.urlencoded({ extended: false }))
I hope it was helpful.

How to use an Angular app as your View Engine with Node.js

I am trying to create an Angular app that sends an email using Nodemailer.
I am able to create a standard Angular app that contains a form. I then want to pass data from this form to a .JS file which will then use Nodemailer to send that data to an email address.
All the examples I have found so far for Nodemailer use View engines such as handlebars, etc. but I want to use my angular app's HTML rather than a view engine.
How do I pass data from my Angular app's form to a .JS file to send an email without having to use a View Engine?
Below is what I have so far in my Angular app:
<form method="POST" action="send">
<p>
<label>Name</label>
<input type="text" name="name">
</p>
<p>
<label>Company</label>
<input type="text" name="company">
</p>
<p>
<label>Email Address</label>
<input type="email" name="email">
</p>
<p>
<label>Phone Number</label>
<input type="text" name="phone">
</p>
<p class="full">
<label>Message</label>
<textarea name="message" rows="5"></textarea>
</p>
<p class="full">
<button type="submit">Submit</button>
</p>
</form>
And this is what I have in the tutorial code:
APP.JS
const express = require("express");
const bodyParser = require("body-parser");
const exphbs = require("express-handlebars");
const path = require("path");
const nodemailer = require("nodemailer");
const app = express();
// View engine setup
app.engine("handlebars", exphbs());
app.set("view engine", "handlebars");
// Static folder
app.use("/public", express.static(path.join(__dirname, "public")));
// Body Parser Middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get("/", (req, res) => {
res.render("contact");
});
app.post("/send", async (req, res) => {
const output = `
<p>You have a new contact request</p>
<h3>Contact Details</h3>
<ul>
<li>Name: ${req.body.name}</li>
<li>Company: ${req.body.company}</li>
<li>Email: ${req.body.email}</li>
<li>Phone: ${req.body.phone}</li>
</ul>
<h3>Message</h3>
<p>${req.body.message}</p>
`;
try{
var transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: "myemail#mail.com",
pass: "myPassword"
},
tls: {
rejectUnauthorized: false
}
});
}
catch(err){
console.log(err.message);
}
const mailOptions = {
from: "myemail#mail.com", // sender address
to: "myemail#mail.com", // list of receivers
subject: "Test email", // Subject line
html: output // plain text body
};
let info = await transporter.sendMail(mailOptions);
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
res.render("contact", { msg: "Email has been sent" });
});
app.listen(3000, () => console.log("Server started..."));
CONTACT.HANDLEBARS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Acme Web Design</title>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.css" />
<link rel="stylesheet" href="public/css/style.css">
</head>
<body>
<div class="container">
<h1 class="brand"><span>Acme</span> Web Design</h1>
<div class="wrapper animated bounceInLeft">
<div class="company-info">
<h3>Acme Web Design</h3>
<ul>
<li><i class="fa fa-road"></i> 44 Something st</li>
<li><i class="fa fa-phone"></i> (555) 555-5555</li>
<li><i class="fa fa-envelope"></i> test#acme.test</li>
</ul>
</div>
<div class="contact">
<h3>Email Us</h3>
{{ msg }}
<form method="POST" action="send">
<p>
<label>Name</label>
<input type="text" name="name">
</p>
<p>
<label>Company</label>
<input type="text" name="company">
</p>
<p>
<label>Email Address</label>
<input type="email" name="email">
</p>
<p>
<label>Phone Number</label>
<input type="text" name="phone">
</p>
<p class="full">
<label>Message</label>
<textarea name="message" rows="5"></textarea>
</p>
<p class="full">
<button type="submit">Submit</button>
</p>
</form>
</div>
</div>
</div>
</body>
I can post further code if necessary.
So I managed to pass data from the form (root.component.html) to the server (app.js), capture it & print it to the console via the POST method.
Code is below:
root.component.html:
<form #emailForm="ngForm">
<div class="col-md-6">
<div>
<label for="username">
Username
</label>
<input
type="text"
id="username"
[(ngModel)]="username"
required
name="username"
#txtUsername="ngModel"
/>
</div>
<div>
<label for="message">Message</label>
<textarea
id="message"
placeholder="Please enter your message here"
[(ngModel)]="message"
required
name="message"
#txtMessage="ngModel"
></textarea>
</div>
<button
axis-button
class="axis-btn"
title="Submit"
data-kind="primary"
(click)="sendMessage()"
[disabled]="emailForm.invalid"
>
Send Email
</button>
</div>
</form>
root.component.ts:
export class RootComponent implements OnInit {
constructor(private rootService: RootService) {}
username: string;
message: string;
ngOnInit() {
this.getData();
}
getData() {
this.rootService.getAPIData().subscribe(
response => {
console.log('response from GET API is ', response);
},
error => {
console.log('error is ', error);
}
);
}
postData(name: string, message: string) {
this.rootService.postAPIData(name, message).subscribe(
response => {
console.log('response from POST API is ', response);
},
error => {
console.log('error during post is ', error);
}
);
}
sendMessage() {
this.postData(this.username, this.message);
}
}
root.service.ts:
export class RootService {
constructor(private http: HttpClient) {}
getAPIData() {
return this.http.get('https://jsonplaceholder.typicode.com/users');
}
postAPIData(name: string, message: string) {
return this.http.post('/api/postData', {
name: name,
message: message
});
}
}
app.js:
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
app.get('/', (req, res) => {
res.send('Welcome to Node API')
})
app.get('/getData', (req, res) => {
res.json({'message': 'Hello World'})
})
app.post('/postData', bodyParser.json(), (req, res) => {
res.json(req.body) // Prints the request body to the browser console
const output = `Name: ${req.body.name}......Email: ${req.body.message}`;
console.log(output);
})
app.listen(3000, () => console.log('Example app listening on port 3000!'))

Resources