Flash Message from ejs in Express 4 - node.js

I am trying to show a confirmation message before user deletes anything. I've tried following various related sources that I found in internet, but couldn't get them to work. I am using EJS template and Express 4.
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
var flash = require('connect-flash');
var session = require('express-session');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use('/js', express.static(__dirname + '/node_modules/bootstrap/dist/js')); // redirect bootstrap JS
app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css')); // redirect CSS bootstrap
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({ secret: 'zxcv' })); // session secret
app.use(flash()); // use connect-flash for flash messages stored in session
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.listen(8000);
module.exports = app;
index.js
var express = require('express');
var router = express.Router();
var searchModule = require('../crud_module/search.js');
var updateModule = require('../crud_module/update.js');
var deleteModule = require('../crud_module/delete.js');
/* GET home page. */
router.get('/', function (req, res) {
res.render('index', { title: '' });
});
router.post('/search-results', function (req, res) {
searchModule.search(req.body, function (data) {
res.render('index', { title: '', results: data });
});
});
router.post('/edit-data', function (req, res) {
searchModule.searchById(req.body, function (data) {
res.render('edit', { title: '', results: data });
});
});
router.post('/save-changes', function (req, res) {
if (req.body.change == "update") {
updateModule.saveChanges(req.body, function (err) {
if (err) {
res.render('edit', { message: req.flash('Error', 'Error Occured') });
} else {
//req.flash('success', 'Your name was updated');
res.render('edit', { message: req.flash('success', 'Data was updated')) });
}
res.redirect('/edit-data');
});
}
if (req.body.change == "delete") {
deleteModule.deleteRecord(req.body, function (data) {
res.render('edit', { title: 'Volume Tracker', confirmation: data });
});
}
});
module.exports = router;
edit.ejs
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<link href="node_modules/popups/css/popupS.min.css" rel="stylesheet" />
<script type="text/javascript" src="https://gc.kis.scr.kaspersky-labs.com/5B1FA715-F8FF-784F-A4C9-0D867337CB3D/main.js" charset="UTF-8"></script><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="node_modules/elasticsearch/src/elasticsearch.angular.js"></script>
<script src="node_modules/popups/dist/popupS.min.js"></script>
<script language="javascript">
</script>
<style type="text/css">
</style>
</head>
<body>
<br>
<form action='/save-changes' method='post'>
<div class="container">
<% if(locals.results) { %>
<table class="table table-bordered table-hover table-condensed">
<tr>
<th bgcolor="silver">Term Key</th>
<td>
<input name="termKey" value= "<%= results[0]._source.termkey %>" style="border:none; width:100%"/>
</td>
</tr>
<tr>
<th bgcolor="silver">Active</th>
<td>
<input name="active" value= "<%= results[0]._source.active %>" style="border:none; width:100%"/>
</td>
</tr>
<tr>
<th bgcolor="silver">Term Description</th>
<td>
<input name="termDescription" value= "<%= results[0]._source.termdescription %>" style="border:none; width:100%"/>
</td>
</tr>
</table>
<div align="center">
<button type="submit" class="btn btn-info" name="change" value="update"> Save Changes </button>
<button type="submit" class="btn btn-danger" name="change" value="delete"> Delete Record </button>
</div>
<% } %>
</form>
<br>
</div>
</body>
</html>
Here, when the user will click on the delete button, a confirmation message will be shown (here--> in index.js, I first tried showing confirmation message after user updates anything; which didn't work either). But whenever I try to include this:
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>
in edit.ejs , I get error:
ReferenceError:
92| </form>
93| <br>
>> 94| <% if (message.length > 0) { %>
95| <div class="alert alert-danger"><%= message %></div>
96| <% } %>
message is not defined
at eval (eval at <anonymous> (\ElasticSearch\ES\VolumeTracker\VolumeTracker\node_modules\ejs\lib\ejs.js:495:12), <anonymous>:41:12)
at Template.compile.returnedFn (\ElasticSearch\ES\VolumeTracker\VolumeTracker\node_modules\ejs\lib\ejs.js:524:17)
at View.exports.renderFile [as engine] (\ElasticSearch\ES\VolumeTracker\VolumeTracker\node_modules\ejs\lib\ejs.js:378:31)
at View.render (\ElasticSearch\ES\VolumeTracker\VolumeTracker\node_modules\express\lib\view.js:76:8)
at Function.app.render (\ElasticSearch\ES\VolumeTracker\VolumeTracker\node_modules\express\lib\application.js:527:10)
at ServerResponse.res.render (\ElasticSearch\ES\VolumeTracker\VolumeTracker\node_modules\express\lib\response.js:900:7)
at \ElasticSearch\ES\VolumeTracker\VolumeTracker\routes\index.js:22:13
at \ElasticSearch\ES\VolumeTracker\VolumeTracker\crud_module\search.js:45:9
at tryCallOne (\ElasticSearch\ES\VolumeTracker\VolumeTracker\node_modules\elasticsearch\node_modules\promise\lib\core.js:37:12)
at \ElasticSearch\ES\VolumeTracker\VolumeTracker\node_modules\elasticsearch\node_modules\promise\lib\core.js:123:15

I have a simpler solution; as an example: after a succesful registration of a new user in the file routes/users.js:
req.flash('success_msg', 'You are registered and can now log in');
res.redirect('login');
In a file views/partials/_messages.ejs:
<% if (success_msg != '') { %>
<div class="alert alert__success"><%= success_msg %></div>
<% } %>
And in views/login.ejs include:
<% include ./partials/_messages %>
No other JavaScript needed!

I am posting here answer to my own question, in case anyone needs the same thing. To pass flash message to view, in your app.js ensure the following is present (note I am using ejs template for view) :
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
var flash = require('connect-flash');
var session = require('express-session');
app.use(cookieParser());
app.use(session({ secret: 'zxcv' })); // session secret
app.use(flash()); // use connect-flash for flash messages stored in session
in your index.js
router.post('/edit', function (req, res) {
if (req.body.change == "update") { //if update btn is clicked
updateModule.saveChanges(req.body, function (err) { //call update module
if (err) {
//if error
req.flash("msg","Error Occured");
res.locals.messages = req.flash();
res.render('edit', { title: 'myApp'});
} else {
//on success
req.flash("msg", "Data updated successfully");
res.locals.messages = req.flash();
res.render('index', { 'title': 'myApp'});
}
});
}
});
and here is my view: for editing--> edit.ejs
<body>
<form action='/edit' method='post'>
<!--your data-->
<script language="javascript">
function UpdateConfirm() {
var userPreference;
if (confirm("Do you want to save changes?") == true) {
return true;}
else {
return false;}
}
</script>
<button type="submit" class="btn btn-info" name="change" value="update" onClick= "<%- "return UpdateConfirm()" %>" > Save Changes </button>
</form>
</body>
Here, if you click on the button, it will first popup a confirmation alert box (will call UpdateConfirm()), and if you click yes then it will submit the form.
Now, after updating I am passing flash message from my index.js. The view where you want to show the flash message, put this:
<% if (locals.messages) { %>
<script language="javascript">
alert("<%= messages.msg %>");
</script>
<% } %>
It will show the message in an alert box.
P.S: You have to install these npm packages: cookie-parser,connect-flash and connect-flash

Related

Socket.io does not get the message automatically

i tried to emplement socket.io but it does not show the way that it should be. Can anyone know where the problem. i tried to solve this around 2 weeks. Its headache to me. I tried many time already which is used emit,write, all of it. this is my code
HTML
<section class="msger" style="margin: auto;">
<header class="msger-header">
<div class="msger-header-title">
<i class="fas fa-comment-alt"></i> Chat
</div>
<div class="msger-header-options">
<span><i class="fas fa-cog"></i></span>
</div>
</header>
<main class="msger-chat" id="msger-chat">
</main>
<form class="msger-inputarea" >
<input type="hidden" name="booking" value="<%= booking %>">
<input type="hidden" id="name" class="form-control" readonly placeholder="Name"
value="<%= user.username %>">
<input type="text" name="user" value="<%= user._id %>">
<input id="message" type="text" class="msger-input" placeholder="Enter your message...">
<button id="send" type="submit" class="msger-send-btn">Send</button>
</form>
</section>
<!-- End of Main Content -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
</div>
<!-- End of Main Content -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Bootstrap core JavaScript-->
<script src="/vendor/jquery/jquery.min.js"></script>
<script src="/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="/vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="/js/sb-admin-2.min.js"></script>
<script type="text/javascript" src="/js/mdb.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<!-- Custom scripts -->
<script>
var socket = io();
$(() => {
$("#send").click(() => {
sendMessage({
booking: $("input[name=booking]").val(),
user: $("input[name=user]").val(),
message: $("#message").val()
});
})
getMessages()
})
socket.on('message', addMessages)
function addMessages(message) {
if (message.user && message.user != '') {
if ($("input[name=user]").val() == message.user._id) {
html = '<div class="msg right-msg"><div class="msg-img" style="background-image: url(' + message.user.image +
')"></div>'
html += '<div class="msg-bubble"><div class="msg-info"><div class="msg-info-name">' + message.user.username +
'</div><div class="msg-info-time">' + message.createdAt + '</div></div>'
}
} else {
html = '<div class="msg left-msg"><div class="msg-img" style="background-image: url(' + message.pro.image +
')"></div>'
html += '<div class="msg-bubble"><div class="msg-info"><div class="msg-info-name">' + message.pro.username +
'</div><div class="msg-info-time">' + message.createdAt + '</div></div>'
}
html += '<div class="msg-text">' + message.message + '</div></div></div>'
window.scrollTo(0, document.body.scrollHeight);
$("#msger-chat")+$(".msger-chat").append(html)
}
function getMessages() {
$.get('http://127.0.0.1:3000/messageslist/<%=booking%>', (data) => {
data.forEach(addMessages);
})
}
function sendMessage(message) {
$.post('http://127.0.0.1:3000/messages', message)
}
</script>
this is my routes
Route
var http = require('http').Server(router);
var io = require('socket.io')(http);
// Render Message
router.get('/messages/:id', async function (req, res, next) {
user = await User.findOne({_id: req.session.userId}, {username: 1})
return res.render("user/messages.ejs", {user: user, booking: req.params.id});
});
// Display Message from DB
router.get('/messageslist/:booking', (req, res) => {
Message.find({booking: req.params.booking})
.populate({
path: "pro",
model: Pro,
}).populate({
path: "user",
model: User,
}).exec().then((data) => {
res.json(data)
})
})
router.post('/messages', async (req, res) => {
const {booking, user, message} = req.body
try {
var msg = new Message({
booking: booking,
message: message,
user: user
});
var savedMessage = await msg.save()
console.log('saved');
var censored = await Message.findOne({
message: 'badword'
});
if (censored)
await Message.remove({
_id: censored.id
})
else
io.emit('message', req.body);
res.sendStatus(200);
} catch (error) {
res.sendStatus(500);
return console.log('error', error);
} finally {
console.log('Message Posted')
}
})
Server
var express = require('express');
var env = require('dotenv').config()
var ejs = require('ejs');
var path = require('path');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session)
const cookieParser = require('cookie-parser')
var http = require('http').Server(app);
var io = require('socket.io')(http);
var cors = require('cors')
app.use(cors())
app.use(cookieParser());
// mongodb://localhost:27017 127.0.0.1:27017
mongoose.set('strictQuery', true);
mongoose.connect('mongodb://127.0.0.1:27017/findaprofessional', {
useNewUrlParser: true,
useUnifiedTopology: true
}, (err) => {
if (!err) {
console.log('MongoDB Connection Succeeded.');
} else {
console.log('Error in DB connection : ' + err);
}
});
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
});
const oneDay = 1000 * 60 * 60 * 24;
app.use(session({
secret: 'work hard',
saveUninitialized:true,
cookie: { maxAge: oneDay },
resave: true
}));
// ni lain
app.set("view engine", "ejs")
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/css', express.static(path.resolve(__dirname, "asset/css")))
app.use('/img', express.static(path.resolve(__dirname, "asset/img")))
app.use('/js', express.static(path.resolve(__dirname, "asset/js")))
app.use('/vendor', express.static(path.resolve(__dirname, "asset/vendor")))
app.use('/lib', express.static(path.resolve(__dirname, "asset/lib")))
app.use('/scss', express.static(path.resolve(__dirname, "asset/scss")))
app.use('/pic', express.static(path.resolve(__dirname, "asset/img/pic")))
var index = require('./routes/index');
const { Socket } = require('socket.io');
app.use('/', index);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('File Not Found');
err.status = 404;
next(err);
});
// error handler
// define as the last app.use callback
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.send(err.message);
});
io.on('connection', () =>{
console.log('a user is connected')
})
var server = http.listen(3000, () => {
console.log('Server is started on http://127.0.0.1:'+ server.address().port);
});
Im expecting someone can go thru my codes and solve the problem. i thinks my problem at html socken.on. but im not sure enough.

How to make the message automatically get other that reload page using socket.io, nodejs, and mongodb

I'm having a go with the socket.io https://socket.io/get-started/chat, but my problem is that when i send message then the message cant automatically into chat box. i need to reload the page to view the chat that i sent. So how to make the chat automatically insert to chat box?. i already implement into my project. i already used socket.emit as you can see at then html file. is there the right way to put it?
server.js
var express = require('express');
var env = require('dotenv').config()
var ejs = require('ejs');
var path = require('path');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session)
const cookieParser = require('cookie-parser')
var http = require('http').Server(app);
var io = require('socket.io')(http);
var cors = require('cors')
app.use(cors())
app.use(cookieParser());
// mongodb://localhost:27017 127.0.0.1:27017
mongoose.set('strictQuery', true);
mongoose.connect('mongodb://127.0.0.1:27017/findaprofessional', {
useNewUrlParser: true,
useUnifiedTopology: true
}, (err) => {
if (!err) {
console.log('MongoDB Connection Succeeded.');
} else {
console.log('Error in DB connection : ' + err);
}
});
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
});
const oneDay = 1000 * 60 * 60 * 24;
app.use(session({
secret: 'work hard',
saveUninitialized:true,
cookie: { maxAge: oneDay },
resave: true
}));
// ni lain
app.set("view engine", "ejs")
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/css', express.static(path.resolve(__dirname, "asset/css")))
app.use('/img', express.static(path.resolve(__dirname, "asset/img")))
app.use('/js', express.static(path.resolve(__dirname, "asset/js")))
app.use('/vendor', express.static(path.resolve(__dirname, "asset/vendor")))
app.use('/lib', express.static(path.resolve(__dirname, "asset/lib")))
app.use('/scss', express.static(path.resolve(__dirname, "asset/scss")))
app.use('/pic', express.static(path.resolve(__dirname, "asset/img/pic")))
var index = require('./routes/index');
const { Socket } = require('socket.io');
app.use('/', index);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('File Not Found');
err.status = 404;
next(err);
});
// error handler
// define as the last app.use callback
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.send(err.message);
});
io.on('connection', () =>{
console.log('a user is connected')
io.on("disconnect", function () {
console.log("user disconnected");
});
})
var server = http.listen(3000, () => {
console.log('Server is started on http://127.0.0.1:'+ server.address().port);
});
routing
// user chat
var http = require('http').Server(router);
var io = require('socket.io')(http);
// Render Message
router.get('/messages/:id', async function (req, res, next) {
user = await User.findOne({_id: req.session.userId}, {username: 1})
return res.render("user/messages.ejs", {user: user, booking: req.params.id});
});
// Display Message from DB
router.get('/messageslist/:booking', (req, res) => {
Message.find({booking: req.params.booking})
.populate({
path: "pro",
model: Pro,
}).populate({
path: "user",
model: User,
}).exec().then((data) => {
res.json(data)
})
})
router.get('/messages', (req, res) => {
Message.find({}, (err, messages) => {
res.send(messages);
})
})
router.post('/messages', async (req, res) => {
const {booking, user, message} = req.body
try {
var msg = new Message({
booking: booking,
message: message,
user: user
});
var savedMessage = await msg.save()
console.log('saved');
var censored = await Message.findOne({
message: 'badword'
});
if (censored)
await Message.remove({
_id: censored.id
})
else
io.emit('message', req.body);
res.sendStatus(200);
} catch (error) {
res.sendStatus(500);
return console.log('error', error);
} finally {
console.log('Message Posted')
}
})
HTML
<!DOCTYPE html>
<html lang="en">
<%- include("../header.ejs") %>
<head>
<link href="/css/sb-admin-2.min.css" rel="stylesheet">
<link href="/css/chat.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.2.1.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"
integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous">
</script>
</script>
<script src="/socket.io/socket.io.js"></script>
</head>
</head>
<!-- start here! -->
<section class="msger" style="margin: auto;">
<header class="msger-header">
<div class="msger-header-title">
<i class="fas fa-comment-alt"></i> Chat
</div>
<div class="msger-header-options">
<span><i class="fas fa-cog"></i></span>
</div>
</header>
<main class="msger-chat">
</main>
<form class="msger-inputarea">
<input type="hidden" name="booking" value="<%= booking %>">
<input type="hidden" id="name" class="form-control" readonly placeholder="Name"
value="<%= user.username %>">
<input type="text" name="user" value="<%= user._id %>">
<input id="message" type="text" class="msger-input" placeholder="Enter your message...">
<button id="send" type="submit" class="msger-send-btn">Send</button>
</form>
</section>
<!-- End of Main Content -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
</div>
<!-- End of Main Content -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Bootstrap core JavaScript-->
<script src="/vendor/jquery/jquery.min.js"></script>
<script src="/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="/vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="/js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="/vendor/datatables/jquery.dataTables.min.js"></script>
<script src="/vendor/datatables/dataTables.bootstrap4.min.js"></script>
<!-- Page level custom scripts -->
<script src="/js/demo/datatables-demo.js"></script>
<script type="text/javascript" src="/js/mdb.min.js"></script>
<!-- Custom scripts -->
<script>
var socket = io();
$(() => {
$("#send").click(() => {
sendMessage({
booking: $("input[name=booking]").val(),
user: $("input[name=user]").val(),
message: $("#message").val()
});
})
getMessages()
})
socket.on('message', addMessages)
socket.on('message', getMessages)
socket.emit('message', getMessages)
socket.emit('message', addMessages)
function addMessages(message) {
if(message.user && message.user != '') {
if($("input[name=user]").val() == message.user._id) {
html = '<div class="msg right-msg"><div class="msg-img" style="background-image: url('+message.user.image +')"></div>'
html += '<div class="msg-bubble"><div class="msg-info"><div class="msg-info-name">' + message.user.username + '</div><div class="msg-info-time">' + message.createdAt + '</div></div>'
}
}
else {
html = '<div class="msg left-msg"><div class="msg-img" style="background-image: url('+message.pro.image +')"></div>'
html += '<div class="msg-bubble"><div class="msg-info"><div class="msg-info-name">' + message.pro.username + '</div><div class="msg-info-time">' + message.createdAt + '</div></div>'
}
html += '<div class="msg-text">' + message.message + '</div></div></div>'
$(".msger-chat").append(html)
}
function getMessages() {
$.get('http://localhost:3000/messageslist/<%=booking%>', (data) => {
data.forEach(addMessages);
})
}
function sendMessage(message) {
$.post('http://localhost:3000/messages', message)
}
</script>
i tried to automatically get the message without reload the page but it doenst work. Can anyone see where the problem is?
From what I know, the default behavior when you click a button with type submit inside a form, it tries to reload the page even though you haven't defined any function or other page for it to go.
You would have to get the submit event from the form and use the preventDefault() funciton for this event, check out this thread for more info:
JavaScript code to stop form submission
So you would stop the form submission and then get new messages for the page, executing the javascript to add the new messages to the page by manipulating the DOM.
You can write socker.write() method for accessing real time messages in nodejs.

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

I'm getting this error 500 on my command prompt when trying to add a page to my project

So i'm trying to set this addpost page and i keep getting this "GET /posts/add 500 4.339 ms - 204" on my command prompt.
full code: https://github.com/vnkvp/blog
thanks for any feedback
this is my router/posts.js:
router.get('/add', (req, res, next)=>{
res.render('addpost', {
'title':'Add post'
});
});
module.exports = router;
and this is my app.js:
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use((req, res, next)=>{
req.db = db;
next();
});
app.use('/', indexRouter);
app.use('/posts', postsRouter);
//catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
//error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
//render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
addpost.ejs file
<html>
<body>
<div class="container">
<h1>title</h1>
<ul class="errors">
<% if(errors) { %>
<% for (var i = 0; i < errors.length;i++) { %>
<li><%= errors[i].msg %></li>
<% } %>
<% } %>
</ul>
<form method="POST" action="/posts/add" enctype="multipart/form-data">
<div class="form">
<label>Title:</label>
<input type="text" name="title">
</div>
<div class="form">
<label>Category</label>
<input type="text" name="title">
</div>
</form>
</div>
</body>
</html>
In your call to res.render
res.render('addpost', {
'title':'Add post'
});
you are sending the variable title to your addpost.ejs view, but title is not used in that view. That view is trying to use an array called errors, but you haven't passed that array to the view so the following will fail:
<% if(errors) { %>
<% for (var i = 0; i < errors.length;i++) { %>
<li><%= errors[i].msg %></li>
<% } %>
<% } %>
Try something like this:
res.render('addpost', {
'title':'Add post',
'errors': ['test error1', 'test error2']
});
If you can see those test errors on your page then you just need to make sure you send the correct error to your view.

nodejs: express-validator errors undefined in ejs template

I am using ejs engine instead of pug. When I click register button, I got errors undefined in my register view. There was only little chance that I can get the validation messages, but when I click other links and then back to the register page, the same error occurred again.
Here's my code:
app.js
//app.js code
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var passport = require('passport');
var expressValidator = require('express-validator');
var LocalStrategy = require('passport-local').Strategy;
var multer = require('multer');
var upload = multer({dest: './uploads'});
var flash = require('connect-flash');
var mongo = require('mongodb');
var mongoose = require('mongoose');
var db = mongoose.connection;
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Handle Sessions
app.use(session({
secret:'secret',
saveUninitialized: true,
resave: true
}));
// Passport
app.use(passport.initialize());
app.use(passport.session());
// Validator
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(flash());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
user.js
//user.js code
var express = require('express');
var router = express.Router();
var multer = require('multer');
var upload = multer({dest: 'uploads/'});
/* GET users listing. */
router.get('/', function(req, res, next) {
res.render('members', {page_name : 'members'});
});
router.get('/register', function(req, res, next) {
res.render('register', { page_name: 'register' });
});
router.post('/register', upload.single('profileimage'), function(req, res) {
var name = req.body.name;
var username = req.body.username;
var email = req.body.email;
var password = req.body.password;
var password2 = req.body.password2;
if(req.file){
console.log("uploading file");
var profileimage = req.file.filename;
} else{
var profileimage = "noimage.jpg";
}
req.checkBody('name','Name field is required').notEmpty();
req.checkBody('email','Email field is required').notEmpty();
req.checkBody('email','Email is not valid').isEmail();
req.checkBody('username','Username field is required').notEmpty();
req.checkBody('password','Password field is required').notEmpty();
req.checkBody('password2','Passwords do not match').equals(req.body.password);
// Check Errors
errors = req.validationErrors();
//var errors = JSON.stringify(req.validationErrors());
if(errors){
console.log("errors: " + errors);
res.render('register', {errors: errors});
} else{
console.log('No Errors');
res.render("/");
}
});
router.get('/login', function(req, res, next) {
res.render('login', { page_name: 'login' });
});
module.exports = router;
register.ejs
//register.ejs code
<%include layout%>
<div class="container">
<% if(errors){errors.forEach(function(error){%>
<div class="alert alert-danger"><%= error.msg %></div>
<% })} %>
<h4>register</h4>
<form action="/users/register" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="exampleFormControlInput1">Name</label>
<input type="text" class="form-control" name="name" placeholder="John">
</div>
<div class="form-group">
<label for="exampleFormControlInput1">Email address</label>
<input type="email" class="form-control" name="email" placeholder="name#example.com">
</div>
<div class="form-group">
<label for="exampleFormControlInput1">Username</label>
<input type="text" class="form-control" name="username" placeholder="username">
</div>
<div class="form-group">
<label for="exampleFormControlInput1">Password</label>
<input type="password" class="form-control" name="password" placeholder="password">
</div>
<div class="form-group">
<label for="exampleFormControlInput1">Confirm Password</label>
<input type="password" class="form-control" name="password2" placeholder="confirm password">
</div>
<div class="form-group">
<label for="exampleFormControlInput1">Profile Image</label>
<input type="file" class="form-control" name="profileimage" >
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
Error
ReferenceError: /Users/duanzhen/Documents/web_workspace/12_projects/node_auth/views/register.ejs:5
3| <div class="container">
4|
>> 5| <% if(errors){errors.forEach(function(error){%>
6|
7| <div class="alert alert-danger"><%= error.msg %></div>
8|
errors is not defined
at eval (eval at compile (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/ejs/lib/ejs.js:549:12), <anonymous>:22:8)
at returnedFn (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/ejs/lib/ejs.js:580:17)
at tryHandleCache (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/ejs/lib/ejs.js:223:34)
at View.exports.renderFile [as engine] (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/ejs/lib/ejs.js:437:10)
at View.render (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/view.js:127:8)
at tryRender (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/application.js:640:10)
at Function.render (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/application.js:592:3)
at ServerResponse.render (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/response.js:971:7)
at /Users/duanzhen/Documents/web_workspace/12_projects/node_auth/routes/users.js:12:9
at Layer.handle [as handle_request] (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/router/layer.js:95:5)
at /Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/router/index.js:335:12)
at next (/Users/duanzhen/Documents/web_workspace/12_projects/node_auth/node_modules/express/lib/router/index.js:275:10)
That's because you are trying to access a non existing variable, note that errors variable is only generated and returned to the view if there where validation errors in your form, otherwise it's undefined, that's why in your condition you have to check if errors variable exists, Like this:
if (typeof errors !== 'undefined') { ...
Note: The typeof operator returns a string: the type of the variable, if the variable is not declared it will return undefined
npm uninstall express-validator --save
npm install express-validator#2.20.8 --save
Have a look at my code, it is working
in file 'index.js'
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Home' ,
success:false,
errors:req.session.errors ,
success:req.session.success });
req.session.errors=null;
});
//////////////checking the form validation
router.post('/submit', function(req, res, next) {
req.check('email','Invalid Email Address!!!!!').isEmail();// it's an built in exprexx validator, but we can also write our own
req.check('password','Pssword lenght must be greater than 5!! ').isLength({min:5});
req.check('password','Password is not confirmed!!').equals(req.body.confirmpassword);
var errors=req.validationErrors();
if (errors){
req.session.errors=errors;
req.session.success=false;
}
else{
req.session.success=true;
}
res.redirect('/');
});
module.exports = router;
in file 'index.ejs'
<h1>Fill the form below..</h1><h1></h1>
<h1>It's an example of Express Validator..</h1><h1></h1>
<% if (success) { %>
<h1><span class="badge badge-success">Congrats!! Form validation is secceded!!!</span></h1>
<% } else { %>
<% if (errors) { %>
<div class="alert alert-danger" role="alert">
<h1><span class="badge badge-danger">Errors Occured!! </span></h1>
<% errors.forEach(function(errors) { %>
<h5><%= errors.msg %> </h5>
<% }); %>
</div>
<% } else { %>
<form action="/submit" method="POST">
<div class="form-row">
<div class="col-7">
<input type="email" class="form-control" id="email" placeholder="email" name="email">
</div>
<div class="col">
<input type="password" class="form-control" id="password" placeholder="password" name="password">
</div>
<div class="col">
<input type="password" class="form-control" id="confirmpassword" placeholder="confirmpassword" name="confirmpassword">
</div>
</div>
<h1></h1>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<% } %>
<% } %>
And of course don't forget to add this lines in 'app.js' file:
//adding validator and session
app.use(expressValidator());
app.use(expressSession({secret:'max',saveUninitialized:false,resave:false}));
<% if(locals.errors){locals.errors.forEach(function(error){%>
<div class="alert alert-danger"><%= error.msg %></div>
<% })} %>

Resources