Search code examples
javascriptnode.jsexpressflash-message

Can't display express messages


So I am trying to learn new things in Express and at this moment I would like to be able to show express messages. I added flash and express-messages as dependencies and added messages as a locals variable

(require('express-messages')(req, res)). 

In EJS I added <% messages() %> and according to the tutorial this should've output a div element with the messages, but unfortunately it doesn't show anything after I tried to trigger it, after logging in, with a req.flash('info','test') in the index.js file on the server side.

Can anyone see what I did wrong?

Here is my code:

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 mongodb = require('mongodb');
var session = require('express-session');
var expressValidator = require('express-validator');

var passport = require('passport');
var FacebookStrategy = require('passport-facebook').Strategy;
var configAuth = require('./auth');
var User = require('./models/Users');
var LocalStrategy = require('passport-local').Strategy;
var bcryptjs = require('bcryptjs');

var flash = require('connect-flash');
var mongoose = require("mongoose");
mongoose.connect('mongodb://localhost/nodeTestProject', function () {
    console.log('Now connected to database nodeTestProject');
});

var index = 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 }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use(session({
    secret: 'secret',
    saveUninitialized: true,
    resave: true
}));

app.use(passport.initialize());
app.use(passport.session());


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(flash());

app.listen('5000', function () {
    console.log('Now listening for requests on port 5000 ');
});

app.get('*', function(req, res, next){
    res.locals.user = req.user || null;
    next();
});

app.use(function(req,res,next) {
    res.locals.messages = require('express-messages')(req, res);
    next();
});

app.use('/', index);
app.use('/users', users);

EJS:

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>

    <% if (!user) { %>
    <div class="main row">
    <button class="registerButton">Register</button>
      <button class="loginButton">Log in</button>
      <button class="facebookLoginButton">Facebook login</button>


    <div class="registerDiv">
      <div class="registrationErrors">
        <ul>

        </ul>
      </div>
      <div class="loginDiv">

      </div>

      <% }
      else {
      %>

      <%- messages() %>

      <h1> Welcome <%= user.facebook.name %></h1>
      <img src="<%=user.facebook.photo%>" height="200" width="200" alt="fail">
      <button class="addData">add data</button>
      <div class="addExtraInfo">
            <% if (user.generalInfo) {%>
                <ul>
                    <%
                    for ( prop in user.generalInfo) {
                        if (user.generalInfo.hasOwnProperty(prop)) {%>
                        <li><%= prop %>: <%=user.generalInfo[prop]%></li>
                        <% }} %>

                </ul>
          <% } %>
      </div>
      <br>
      <button class="logoutButton"> Log out</button>

      <% } %>

    </div>
    </div>

    <script src="/jquery-3.2.1.min.js"></script>
    <script src="/javascripts/indexClient.js"></script>
  </body>
</html>

INDEX.JS server side:

var express = require('express');
var mongoose = require('mongoose');
var db = mongoose.connection;
var Schema = mongoose.Schema;
var passport = require('passport');
var localStrategy = require('passport-local').Strategy;

var User = require('../models/Users');
var router = express.Router();

router.post('/login/data', passport.authenticate('local', {successRedirect: '/', failureRedirect: '/login'}), function(req, res) {

    req.flash('info', "test");
    res.redirect('/');

});

Solution

  • You should not call req.flash in your passport verify callback. You should return a message as shown here.

    app.post('/login',
      passport.authenticate('local', { 
        successRedirect: '/',
        failureRedirect: '/login',
        failureFlash: true  // Here
      })
    );
    

    Passport will put the message returned to flash message when failureFlash: true. Your passport local strategy should look somewhat like this.

    passport.use('local', new LocalStrategy({...},
     function(email, password, done) { 
        User.findOne({ 'local.email' :  email }, function(err, user) {
            if (err)
                return done(err);
            if (!user)
                return done(null, false, {message: 'Oops! No account found.'});
            if (!user.validPassword(password))
                return done(null, false, {message: 'Oops! Wrong password.'});
            return done(null, user);
        });
    
    }));