Login system with nodejs express mysql - javascript

I have the code below for a login system with nodejs express and mySQL. The registration and the login services work, but the logout doesn't. Also, how can I restrict my pages from a normal user, in order only an admin can access them. File structure:
Here is the code:
app.js
onst path = require('path');
const express = require('express');
const ejs = require('ejs');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const dotenv = require('dotenv');
const cookieParser = require('cookie-parser');
dotenv.config({ path: './.env' });
var flash = require('express-flash');
var session = require("express-session");
const app = express();
// DB connection
const connection = mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE
});
connection.connect(function(error) {
if (!!error) console.log(error);
else console.log('CONGRATS! Database Connected! (app)');
});
//set views file
app.set('views', path.join(__dirname, 'views'));
//set public file
app.use(express.static(__dirname + '/public'));
//set view engine
app.set('view engine', 'ejs');
app.use(express.json());
app.use(express.urlencoded({ extended: false })); //instead of false
const routes = require('./server/routes/index');
app.use(session({
cookie: { maxAge: 60000 },
store: new session.MemoryStore,
saveUninitialized: true,
resave: true,
secret: 'mysecret'
}))
app.use(flash());
// Defining Routes
app.use('/', routes);
app.use('/auth', require('./server/routes/auth'));
// Server Listening
app.listen(3000, () => {
console.log('Server is running at port 3000');
});
routes/auth.js
const express = require('express');
const authController = require('../controllers/auth');
const auth_router = express.Router();
auth_router.post('/register', authController.register)
auth_router.post('/login', authController.login);
module.exports = auth_router;
routes/index.js
var express = require('express');
const jwt = require('jsonwebtoken');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
console.log(req.session);
console.log(req.headers.cookie);
res.render('home', {
title: 'Express',
loggedIn: req.headers.cookie
});
});
router.get('/register', (req, res) => {
res.render('register');
});
router.get('/login', (req, res) => {
res.render('login');
});
router.get('/logout', function(req, res) {
req.session.destroy();
res.redirect('/');
})
controllers/auth.js
const mysql = require("mysql");
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
var flash = require('express-flash');
const db = mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE
});
exports.login = async(req, res) => {
try {
const { username, password } = req.body;
if (!username || !password) {
req.flash('danger', 'Please provide username and password!');
return res.status(400).render('login');
}
db.query('SELECT * FROM users WHERE username = ?', [username], async(error, results) => {
console.log(results);
if (!results || !(await bcrypt.compare(password, results[0].password))) {
req.flash('danger', 'Username or password is incorrect!');
res.status(401).render('login')
} else {
const id = results[0].user_id;
const token = jwt.sign({ id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRES_IN
});
console.log("The token is: " + token);
const cookieOptions = {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000
),
httpOnly: true
}
res.cookie('jwt', token, cookieOptions);
req.flash('success', 'You logged in successfully');
res.status(200).redirect("/");
}
})
} catch (error) {
console.log(error);
}
}
exports.register = (req, res) => {
console.log(req.body);
const { username, password, passwordConfirm } = req.body;
db.query('SELECT username FROM users WHERE username = ?', [username], async(error, results) => {
if (error) {
console.log(error);
}
if (results.length > 0) {
req.flash('danger', 'That username is already in use!');
return res.render('register');
} else if (password !== passwordConfirm) {
req.flash('danger', 'Passwords do not match!');
return res.render('register');
}
let hashedPassword = await bcrypt.hash(password, 8);
console.log(hashedPassword);
db.query('INSERT INTO users SET ?', { username: username, password: hashedPassword }, (error, results) => {
if (error) {
console.log(error);
} else {
console.log(results);
req.flash('success', 'User registered!');
return res.render('register');
}
})
});
}
views/register.ejs
<!--Navbar Section-->
<%- include('./partials/header'); %>
<!--End Navbar Section-->
<br>
<% if (messages.danger) { %>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<%- messages.danger %>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<% } %>
<% if (messages.success) { %>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<%- messages.success %>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<% } %>
<div class="container mt-4">
<div class="card">
<div class="card-header">
Register Form
</div>
<div class="card-body">
<form action="/auth/register" method="POST">
<div class="form-group">
<label for="username">Userame: </label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="form-group">
<label for="password">Password: </label>
<input type="password" class="form-control" id="password" name="password">
</div>
<div class="form-group">
<label for="passwordConfirm">Confirm Password: </label>
<input type="password" class="form-control" id="passwordConfirm" name="passwordConfirm">
</div>
<button type="submit" class="btn btn-primary">Register User</button>
</form>
</div>
</div>
</div>
views/login.ejs
<!--Navbar Section-->
<%- include('./partials/header'); %>
<!--End Navbar Section-->
<br>
<% if (messages.danger) { %>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<%- messages.danger %>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<% } %>
<div class="container mt-4">
<div class="card">
<div class="card-header">
Login Form
</div>
<div class="card-body">
<form action="/auth/login" method="POST">
<div class="form-group">
<label for="username">Username: </label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="form-group">
<label for="password">Password: </label>
<input type="password" class="form-control" id="password" name="password">
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</div>
</div>
views/partial/header.ejs
<div class="navbar-collapse collapse w-100 order-3 dual-collapse2">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<!-- <a class="nav-link" href="#" onclick="document.getElementById('id02').style.display='block'">Sign up</a> -->
<a class="nav-link" href="/register">Register</a>
</li>
<li class="nav-item">
<!-- <a class="nav-link" href="#" onclick="document.getElementById('id01').style.display='block'">Login</a> -->
<a class="nav-link" href="/login">Login</a>
</li>
<li class="nav-item">
<!-- <a class="nav-link" href="#" onclick="document.getElementById('id02').style.display='block'">Sign up</a> -->
<a class="nav-link" href="/logout">Logout</a>
</li>
</ul>
</div>

Use middleware to restrict user to access any page without logging in and
I can't seem to find any reason why logout wont work, if you can give the git repo link then I can help you for sure

Related

Bcrypt compare method returning false

I have read other post in StackOverflow about Bcrypt compare method returning false always. But I can not solve mine with the suggested answers. I am about to give up using Bcrypt. Could someone please point out what is wrong in my code. I am simply storing registration data with encrypted password in users array and after login attempt I am trying to compare the user-input password with the saved one in users array. No matter what I am doing the compare() method is returning false. PLease point out my mistake. I am providing the server.js file and passport.js file here.
The server.js -->
const express = require("express")
const bcrypt = require("bcrypt")
const initializePassport = require("./passport.js")
const flash = require("express-flash")
const session = require("express-session")
const { application } = require("express")
const passport = require("passport")
const server = express()
const users = []
const salt = bcrypt.genSaltSync(10);
initializePassport(
passport,
email => users.find(u => u.email === email),
id => users.find(u => u.id === id)
)
// below line of code is to get the form data in req.body
server.use(express.urlencoded({ extended: false }))
server.use(flash())
server.use(session({
secret: "1234",
resave: false, // we want to resave the session variable if nothing is changed
saveUninitialized: false
}))
server.use(passport.initialize())
server.use(passport.session())
async function main() {
const PORT = 8080
server.listen(PORT, function() {
console.log(`Server started on port ${PORT}...`)
})
}
server.get('/', async(req, res) => {
res.render("index.ejs")
})
server.get('/login', (req, res) => {
res.render('login.ejs')
})
server.post('/login', passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login",
failureFlash: true
}))
server.get('/registration', (req, res) => {
res.render('registration.ejs')
})
server.post('/registration', async(req, res) => {
const { firstName, lastName, email, password } = req.body
await bcrypt.hash(password.toString(), salt)
.then((hashedPassword) => {
// Store the hashed password in the users array
users.push({
id: Date.now().toString(),
email: email,
password: hashedPassword,
firstName: firstName,
lastName: lastName
})
console.log(users)
res.redirect("/login")
})
.catch((error) => {
console.log(error);
});
})
main();
The passport.js file -->
const LocalStrategy = require("passport-local").Strategy
const bcrypt = require("bcrypt")
function initialize(passport, getUserByEmail, getUserById) {
// Function to authenticate users
const authenticateUsers = async(email, password, done) => {
// Get users by email
const user = await getUserByEmail(email)
console.log("THE Password BEFORE COMPARISON --> " + password)
console.log(user)
if (user == null) {
console.log("user null;;;lllll")
return done(null, false, { message: "User is not registered" })
}
bcrypt.compare(password.toString().trim(), user.password, function(err, result) {
console.log("THE PASSWORD AFTER COMPARISON --> " + password)
console.log(user)
if (err) {
console.log(err)
}
if (result == true) {
console.log("PASSWORD MATCHES")
} else {
console.log("DOESNOT MATCH")
}
})
}
passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUsers))
passport.serializeUser((user, done) => {
console.log(`---------------> Serialize User`)
console.log(user)
done(null, user.id)
})
passport.deserializeUser((id, done) => {
console.log("---------> Deserialize Id")
console.log(id)
return done(null, getUserById(id))
})
}
module.exports = initialize
And here is the registration view
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Registration</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<style>
.main {
background-color: #EAF7FF;
width: 100%;
height: 100vh;
margin: auto;
}
.form-container {
background-color: rgb(255, 255, 255);
max-width: 500px;
margin: 0 auto;
padding: 30px;
border: 1px solid #ccc;
border-radius: 10px;
box-shadow: 0 0 10px #ccc;
}
.btn {
background-color: #4F95FF;
border-radius: 14px;
}
</style>
</head>
<body>
<div class="main">
<div class="form-container">
<form action="/registration" method="POST">
<% if(messages.error) { %>
<div class="alert alert-danger" role="alert">
<strong><%= messages.error %></strong>
</div>
<% } %>
<h2 class="text-center">Register</h2>
<div class="form-group">
<input type="text" name="firstName" class="form-control" id="firstName" placeholder="First name">
</div>
<div class="form-group">
<input type="text" name="lastName" class="form-control" id="lastName" placeholder="Last name">
</div>
<div class="form-group">
<input type="email" name="email" class="form-control" id="email" placeholder="Email">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" id="password" placeholder="Password">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" id="password" placeholder="Confirm Password">
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary btn-rounded btn-lg">Create Account</button>
</div>
<div class="text-center">
<p>Already have an account?
<a href="login">Login</p>
</div>
</form>
</div>
</div>
</body>
</html>
Actually I found the issue. Its in frontend. I used same "name" and "id" attribute for password and confirmPassword field. So req.body.password was appending password from both field.

No recipients defined from server Nodemailer . From local work fine

I need help with my code, when i use my app in local, everything works perfect. But when i run in server, the app show me this error. Try sending me a message from the form in this link https://silvioli-cv.herokuapp.com/contacto
I don't know what is wrong.
This is my app.js
require('dotenv').config();
var express = require('express'),
app = express(),
bodyParser = require('body-parser'),
nodemailer = require('nodemailer'),
flash = require('connect-flash');
// APP CONFIG
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
app.use(express.static('public'));
// FLASH
app.use(
require('express-session')({
secret: 'Nana es la perra mas bella del mundo',
resave: false,
saveUninitialized: false
})
);
app.use(flash());
app.use(function(req, res, next) {
res.locals.message = req.flash('success');
next();
});
// RUTAS
app.get('/', function(req, res) {
res.render('perfil');
});
app.get('/contacto', function(req, res) {
res.render('contacto');
});
// NODEMAILER CONFIG
app.post('/contacto', function(req, res) {
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
type: 'OAuth2',
user: process.env.EMAIL_USERNAME,
clientId: process.env.GMAIL_OAUTH_CLIENT_ID,
clientSecret: process.env.GMAIL_OAUTH_CLIENT_SECRET,
refreshToken: process.env.GMAIL_OAUTH_REFRESH_TOKEN,
accessToken: process.env.GMAIL_OAUTH_ACCESS_TOKEN,
expires: Number.parseInt(process.env.GMAIL_OAUTH_TOKEN_EXPIRE, 10)
}
});
var mailOptions = {
from: req.body.nombre + '<' + req.body.email + '>',
to: process.env.EMAIL_RECIEVER,
subject: req.body.asunto,
html: `
<div>
<p>${req.body.nombre}</p>
<p>${req.body.email}</p>
<p>${req.body.asunto}</p>
<p>${req.body.mensaje}</p>
</div>
`
};
transporter.sendMail(mailOptions, function(err, info) {
if (err) {
console.log(err);
res.send(500, err.message);
} else {
console.log('Email sent');
req.flash('success', 'Su mensaje ha sido enviado con éxito. Muchas gracias.');
res.redirect('/contacto');
}
});
});
// SERVIDOR
// app.listen(3000, function(req, res) {
// console.log('Conectado');
// });
app.listen(process.env.PORT, process.env.IP);
And this is my form contact
<%- include("partials/header") %>
<header class="card-header">
<h2>Contacto</h2>
</header>
<% if(message && message.length > 0){ %>
<div class="container">
<div class="alert alert-success col-md-8" role="alert">
<%= message %>
</div>
</div>
<% } %>
<div class="container mt-4">
<div class="row">
<div class="col-md-12">
<h2>Envíame un correo</h2>
</div>
<div class="col-md-8">
<form action="/contacto" method="POST" style="width: 100%;">
<div class="form-group">
<label for="nombre">Nombre (requerido)</label>
<input type="text" class="form-control" id="nombre" name="nombre" required>
</div>
<div class="form-group">
<label for="email">Email (requerido)</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="form-group">
<label for="asunto">Asunto</label>
<input type="text" class="form-control" id="asunto" name="asunto">
</div>
<div class="form-group">
<label for="mensaje">Su mensaje</label>
<textarea class="form-control" name="mensaje" id="mensaje" rows="4"></textarea>
</div>
<button class="btn btn-lg btn-primary">Enviar mensaje</button>
</form>
</div>
</div>
</div>
<%- include("partials/footer") %>

Error During File upload in Express.js using Multer

I am learning Node.js from a book "Web Development with Nodejs and MongoDB" and is Stuck at a point where I have to upload a Image using Multer.
The Code goes like this :-
Below is My Configure.js file :
var path = require('path'),
routes = require('./routes'),
exphbs = require('express-handlebars'),
express = require('express'),
bodyParser = require('body-parser'),
cookieParser = require('cookie-parser'),
morgan = require('morgan'),
methodOverride = require('method-override'),
errorHandler = require('errorhandler');
multer = require('multer');
moment = require('moment');
var upload = multer({ dest: './public/upload/temp' });
module.exports = function(app) {
app.use(morgan('dev'));
app.use(methodOverride());
app.use(cookieParser('some-secret-value-here'));
routes(app);
app.post('/public/upload/temp', upload.single('img'), function(req, res) {
//var form_description = req.body.description;
console.log(req.file.name);
// insert operations into database get placed here
res.redirect('/');
});
app.use('/public/', express.static(path.join(__dirname,
'../public')));
if ('development' === app.get('env')) {
app.use(errorHandler());
}
app.engine('handlebars', exphbs.create({
defaultLayout: 'main',
layoutsDir: app.get('views') + '/layouts',
partialsDir: app.get('views') + '/partials',
helpers: {
timeago: function(timestamp) {
return moment(timestamp).startOf('minute').fromNow();
}
}
}).engine);
return app;
};
Below is the Handlebar file or (HTML) file :-
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">
Upload an Image
</h3>
</div>
<form method="post" action="/images" enctype="multipart/formdata">
<div class="panel-body form-horizontal">
<div class="form-group col-md-12">
<label class="col-sm-2 control-label" for="file">Browse:</label>
<div class="col-md-10">
<input class="form-control" type="file" name="file" id="file">
</div>
</div>
<div class="form-group col-md-12">
<label class="col-md-2 control-label" for="title">Title:</label>
<div class="col-md-10">
<input class="form-control" type="text" name="title">
</div>
</div>
<div class="form-group col-md-12">
<label class="col-md-2 control-label" for="description">Description
</label>
<div class="col-md-10">
<textarea class="form-control" name="description" rows="2"></textarea>
</div>
</div>
<div class="form-group col-md-12">
<div class="col-md-12 text-right">
<button type="submit" id="login-btn"
class="btn btn-success" type="button">
<i class="fa fa-cloud-upload ">
</i> Upload Image</button>
</div>
</div>
</div>
</form>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
</h3>
</div>
<div class="panel-body">
{{#each images}}
<div class="col-md-4 text-center" style="padding-bottom:1em;">
<a href="/images/{{ uniqueId }}">
<img src="/public/upload/{{filename}}" alt="{{title}}" style="width:
175px; height: 175px;" class="imgthumbnail">
</a></div>
{{/each}}
</div>
</div>
Below is the image.js Controller File :-
var fs = require('fs');
var path = require('path');
module.exports = {
index: function(req, res) {
var viewModel = {
image: {
uniqueId: 1,
title: 'Sample Image 1',
description: 'This is a sample.',
filename: 'sample1.jpg',
views: 0,
likes: 0,
timestamp: Date.now
},
comments: [{
image_id: 1,
email: 'test#testing.com',
name: 'Test Tester',
gravatar: 'http://lorempixel.com/75/75/animals/1',
comment: 'This is a test comment...',
timestamp: Date.now
}, {
image_id: 1,
email: 'test#testing.com',
name: 'Test Tester',
gravatar: 'http://lorempixel.com/75/75/animals/2',
comment: 'Another followup comment!',
timestamp: Date.now
}]
};
res.render('image.handlebars', viewModel);
},
create: function(req, res) {
var possible = 'abcdefghijklmnopqrstuvwxyz0123456789',
imgUrl = '';
for (var i = 0; i < 6; i += 1) {
imgUrl += possible.charAt(Math.floor(Math.random() *
possible.length));
}
var tempPath = req.file.path,
ext = path.extname(req.file.name).toLowerCase(),
targetPath = path.resolve('./public/upload/' + imgUrl + ext);
if (ext === '.png' || ext === '.jpg' || ext === '.jpeg' || ext ===
'.gif') {
fs.rename(tempPath, targetPath, function(err) {
if (err) throw err;
res.redirect('/images/' + imgUrl);
});
} else {
fs.unlink(tempPath, function() {
if (err) throw err;
res.json(500, { error: 'Only image files are allowed.' });
});
}
},
like: function(req, res) {
res.send('The image:like POST controller');
},
comment: function(req, res) {
res.send('The image:comment POST controller');
}
};
When run the server and visit the website on localhost and try to upload a image by clicking on Upload Image button this error comes :-
Cannot read property 'path' of undefined
at create (G:\Docs\Node.js\Project\imgploader.io\controllers\image.js:40:32)
at Layer.handle [as handle_request] (G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\layer.js:95:5)
at next (G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\layer.js:95:5)
at G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\index.js:281:22
at Function.process_params (G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\index.js:335:12)
at next (G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\index.js:275:10)
at Function.handle (G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\index.js:174:3)
at router (G:\Docs\Node.js\Project\imgploader.io\node_modules\express\lib\router\index.js:47:12)
What is the Problem ? I have tried everything available on the Internet but still the same !
Please Help
Maybe because you have used ( ; ) at the end of error handler declaration
errorHandler = require('errorhandler');
also in your HTML name attribute should be img as you have used it multer.

Why do my POST requests keep infinitely loading?

Im trying to build a node.js application and when I try to do a post request on a register or login method, it seems to keep loading and not do anything. I get the following error in my web broswer - "localhost didn’t send any data" . Here is the way I have my code setup:
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
passport = require("passport"),
flash = require("connect-flash"),
LocalStrategy = require("passport-local"),
methodOverride = require("method-override"),
User = require("./models/user");
mongoose.connect("mongod://localhost/supportApp_v1");
app.use(bodyParser.urlencoded({extended:true}));
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
app.use(methodOverride("_method"));
app.use(flash());
app.use(require("express-session")({
secret: "luck",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(function(req,res,next){
res.locals.currentUser = req.user;
res.locals.error = req.flash("error");
res.locals.success = req.flash("success");
next();
});
app.get("/", function(req, res){
res.render("landing");
});
app.get("/register", function(req, res){
res.render("register");
});
app.post("/register", function(req, res){
var newUser = new User({username: req.body.username});
User.register(newUser, req.body.password, function(err, user){
if (err) {
return res.render("register", {"error": err.message});
} else {
passport.authenticate("local")(req, res, function(){
req.flash("success", "Welcome " + user.username);
res.redirect("/");
});
}
});
});
app.get("/login", function(req, res){
res.render("login");
});
app.post("/login", passport.authenticate("local",
{
successRedirect: "/",
failureRedirect: "/login",
}), function (req, res){
});
app.listen(process.env.PORT || 3000, process.env.IP, function(){
console.log("Server has started");
});
The model that Im using:
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String,
email: String,
age: Number
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
and a registration form:
<div class="container" id="regContainer">
<h1>Register</h1>
<hr>
<form action="/register" method="POST">
<div class="form-group row">
<label for="regUser" class="col-sm-2 col-form-label">Username:
</label>
<div class="col-sm-10">
<input id="regUser" type="text" name="username" placeholder="Username">
</div>
</div>
<div class="form-group row">
<label for="regUser" class="col-sm-2 col-form-label">Email:</label>
<div class="col-sm-10">
<input id="regUser" type="text" name="email" placeholder="Email">
</div>
</div>
<div class="form-group row">
<label for="regPass" class="col-sm-2 col-form-label">Password:</label>
<div class="col-sm-10">
<input id="regUser" type="password" name="password" placeholder="Password">
</div>
</div>
<div class="form-group row">
<label for="regPass" class="col-sm-2 col-form-label">Age:</label>
<div class="col-sm-10">
<input id="regUser" type="number" name="age" placeholder="Age">
</div>
</div>
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button type="submit" class="btn btn-primary">Register</button>
</div>
</div>
Connection via Mongoose is
mongoose.connect('mongodb://localhost/myapp');
Yours is missing a d. #MariaInesParnisari also suspected connection problem. I also notice that your register.html is missing a dew tags near the end such as </form>(may be due to incomplete copy-and-paste). I also wonder where you place the .html files, as you did not set the path for 'views' , for example
app.set('views', path.join(__dirname, '/views'));
Perhaps you are using the default?

Getting error "title not defined " on EJS template engine with Express

I was learning NodeJS and I am using EJS as templating engine. But whenever I click on register button my Registration page I am getting an error that title is not defined.
Here is my code.
users.js
var express = require('express');
var router = express.Router();
var multer = require('multer');
var uploads = multer({dest: './uploads'});
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.get('/register', function(req, res, next) {
res.render('register',{
'title': 'Register'
});
});
router.get('/login', function(req, res, next) {
res.render('login',{
'title': 'Login'
});
});
router.post('/register', uploads.single('profileImage'), function(req, res, next){
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;
//Check for image field
if(req.file){
console.log('Uploading file.....');
var profileImageOriginalName = req.files.profileimage.originalname;
var profileImageName = req.files.profileimage.name;
var profileImageMime = req.files.profileimage.mimetype;
var profileImagePath = req.files.profileimage.path;
var profileImageExt = req.files.profileimage.extension;
var profileImageSize = req.files.profileimage.size;
}
else{
//set a default image
var profileImageName = 'noimage.png';
}
//Form Validation
req.checkBody('name','This field is required').notEmpty();
req.checkBody('email','This field is required').notEmpty();
req.checkBody('email','Invalid Email').isEmail();
req.checkBody('username','This field is required').notEmpty();
req.checkBody('password','This field is required').notEmpty();
req.checkBody('password2','Passwords do not match').equals(req.body.password);
//check for errors
var errors = req.validationErrors();
if(errors){
res.render('register',{
errors: errors,
name: name,
email: email,
username: username,
password: password,
password2: password2
});
}
else{
var newUser = new User({
name: name,
email: email,
username: username,
password: password,
profileimage: profileImageName
});
//Create user
/*User.createUser(newUser, function(err, user){
if(err) throw err;
console.log(user);
});*/
//success message
req.flash('success', 'Your account registered successfully');
res.location('/');
res.redirect('/');
}
});
module.exports = router;
head.ejs
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/bootstrap.css' />
<link rel='stylesheet' href='/stylesheets/style.css' />
header.ejs
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li <% if (title == "Members") { %>class="active" <% } %> >Members</li>
<li <% if (title == "Register") { %>class="active" <% } %> >Register</li>
<li <% if (title == "Login") { %>class="active" <% } %> >Log In</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>Log Out</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
register.ejs
<!DOCTYPE html>
<html>
<head>
<% include ./partials/head.ejs %>
</head>
<body>
<div class="container">
<% include ./partials/header.ejs %>
<h1>Register</h1>
<p>Please Register using the below form</p>
<form method="post" action="/users/register" enctype="multipart/form-data">
<div class="form-group">
<label>Name</label>
<input class="form-control" type="text" name="name" placeholder="Enter your name">
</div>
<div class="form-group">
<label>Email</label>
<input class="form-control" type="email" name="email" placeholder="Enter your email">
</div>
<div class="form-group">
<label>Username</label>
<input class="form-control" type="text" name="username" placeholder="Enter your username">
</div>
<div class="form-group">
<label>Password</label>
<input class="form-control" type="password" name="password" placeholder="Enter your Password">
</div>
<div class="form-group">
<label>Confirm Password</label>
<input class="form-control" type="password" name="password2" placeholder="Confirm your Password">
</div>
<div class="form-group">
<label>Profile Image</label>
<input class="form-control" type="file" name="profileImage">
</div>
<button class="btn btn-default" name="submit" type="submit" value="Register">Register</button>
</form>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="/javascript/bootstrap.js"></script>
</html>
I am not getting why this is happening. I have tried this solution but it's not working. Any help would be appreciated.
I could not understand exactly where your router will redirect when the request hits the /.
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
Usually for / it redirects to index template. Using EJS, you could redirect to a template, for example.
router.get('/', function(req, res, next) {
res.render('index', {param: value});
});
What seems to be happening is that when your request hits the /, it redirects to a template that has head.ejs included, which needs the title parameter sent to it.
In your route to GET, you send this correctly:
router.get('/register', function(req, res, next) {
res.render('register',{
'title': 'Register'
});
});
But, when your request hit the POST method, after all the logic, you don't redirect to a template, you're redirecting it to /, with no parameters. If your / route access a template using your head.ejs, that's why you're getting this error.
In your case, even if your redirecting to index.ejs or to messageUserAdded.ejs (for example), I would then call it with render method to be rendering an EJS template (instead of res.location('/'); and res.redirect('/');), as the following:
res.render('index', {title: 'User Successfully Added'});
And just to add a possibility, you could create a template for successful messages, then you can pass a message to it, customized to each page you have something done right. As an example, a template like this:
successfulMessage.ejs
<html>
<head><title> <%=title%> </title></head>
<body>
<h1>This works!</h1>
<h2> <%=messageTitle%> </h2>
<span> <%=messageDetails%> </span>
</body>
</html>
And then use it in your POST:
// After all the logic
res.render('successfulMessage', {
title: 'Success',
messageTitle: 'Account Created',
messageDetails: 'John has been added to our database!'
})
Hope it helps you to solve it.
I discovered you should NOT name your keys with "reserved" HTML tag names. (list here)
title is a "reserved" HTML tag name thus this will not work properly.
you can change
code
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
to
code
router.get('/', function(req, res, next) {
return res.send('respond with a resource');
});

Categories

Resources