2

This code is used to add the products and then to cart and orders creating pdf using mongodb in the backend. actually session.isLoggedIn is defined in the auth js check that code but still in the app.js it gives this error!

app.JS code

const path = require('path');

const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const csrf = require('csurf');
const flash = require('connect-flash');
const multer = require('multer');

const errorController = require('./controllers/error');
const User = require('./models/user');

const MONGODB_URI =
  'mongodb....url';

const app = express();
const store = new MongoDBStore({
  uri: MONGODB_URI,
  collection: 'sessions'
});
const csrfProtection = csrf();

const fileStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'images');
  },
  filename: (req, file, cb) => {
    cb(null, new Date().toISOString() + '-' + file.originalname);
  }
});

const fileFilter = (req, file, cb) => {
  if (
    file.mimetype === 'image/png' ||
    file.mimetype === 'image/jpg' ||
    file.mimetype === 'image/jpeg'
  ) {
    cb(null, true);
  } else {
    cb(null, false);
  }
};

app.set('view engine', 'ejs');
app.set('views', 'views');

const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
const authRoutes = require('./routes/auth');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(
  multer({ storage: fileStorage, fileFilter: fileFilter }).single('image')
);
app.use(express.static(path.join(__dirname, 'public')));
app.use('/images', express.static(path.join(__dirname, 'images')));
app.use(
  session({
    secret: 'my secret',
    resave: false,
    saveUninitialized: false,
    store: store
  })
);
app.use(csrfProtection);
app.use(flash());

app.use((req, res, next) => {
  res.locals.isAuthenticated = req.session.isLoggedIn;
  res.locals.csrfToken = req.csrfToken();
  next();
});

app.use((req, res, next) => {
  // throw new Error('Sync Dummy');
  if (!req.session.user) {
    return next();
  }
  User.findById(req.session.user._id)
    .then(user => {
      if (!user) {
        return next();
      }
      req.user = user;
      next();
    })
    .catch(err => {
      next(new Error(err));
    });
});

app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.use(authRoutes);

app.get('/500', errorController.get500);

app.use(errorController.get404);

app.use((error, req, res, next) => {
  // res.status(error.httpStatusCode).render(...);
  // res.redirect('/500');
  res.status(500).render('500', {
    pageTitle: 'Error!',
    path: '/500',
    isAuthenticated: req.session.isLoggedIn
  });
});

mongoose
  .connect(MONGODB_URI, { useNewUrlParser: true })
  .then(result => {
    app.listen(3000);
  })
  .catch(err => {
    console.log(err);
  });

auth.js for controlling the isAuthenticated

const crypto = require('crypto');

const bcrypt = require('bcryptjs');
const nodemailer = require('nodemailer');
const sendgridTransport = require('nodemailer-sendgrid-transport');
const { validationResult } = require('express-validator/check');

const User = require('../models/user');

const transporter = nodemailer.createTransport(
  sendgridTransport({
    auth: {
      api_key:
        'api.........key'
    }
  })
);

exports.getLogin = (req, res, next) => {
  let message = req.flash('error');
  if (message.length > 0) {
    message = message[0];
  } else {
    message = null;
  }
  res.render('auth/login', {
    path: '/login',
    pageTitle: 'Login',
    errorMessage: message,
    oldInput: {
      email: '',
      password: ''
    },
    validationErrors: []
  });
};

exports.getSignup = (req, res, next) => {
  let message = req.flash('error');
  if (message.length > 0) {
    message = message[0];
  } else {
    message = null;
  }
  res.render('auth/signup', {
    path: '/signup',
    pageTitle: 'Signup',
    errorMessage: message,
    oldInput: {
      email: '',
      password: '',
      confirmPassword: ''
    },
    validationErrors: []
  });
};

exports.postLogin = (req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;

  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).render('auth/login', {
      path: '/login',
      pageTitle: 'Login',
      errorMessage: errors.array()[0].msg,
      oldInput: {
        email: email,
        password: password
      },
      validationErrors: errors.array()
    });
  }

  User.findOne({ email: email })
    .then(user => {
      if (!user) {
        return res.status(422).render('auth/login', {
          path: '/login',
          pageTitle: 'Login',
          errorMessage: 'Invalid email or password.',
          oldInput: {
            email: email,
            password: password
          },
          validationErrors: []
        });
      }
      bcrypt
        .compare(password, user.password)
        .then(doMatch => {
          if (doMatch) {
            req.session.isLoggedIn = true;
            req.session.user = user;
            return req.session.save(err => {
              console.log(err);
              res.redirect('/');
            });
          }
          return res.status(422).render('auth/login', {
            path: '/login',
            pageTitle: 'Login',
            errorMessage: 'Invalid email or password.',
            oldInput: {
              email: email,
              password: password
            },
            validationErrors: []
          });
        })
        .catch(err => {
          console.log(err);
          res.redirect('/login');
        });
    })
    .catch(err => {
      const error = new Error(err);
      error.httpStatusCode = 500;
      return next(error);
    });
};

exports.postSignup = (req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;

  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    console.log(errors.array());
    return res.status(422).render('auth/signup', {
      path: '/signup',
      pageTitle: 'Signup',
      errorMessage: errors.array()[0].msg,
      oldInput: {
        email: email,
        password: password,
        confirmPassword: req.body.confirmPassword
      },
      validationErrors: errors.array()
    });
  }

  bcrypt
    .hash(password, 12)
    .then(hashedPassword => {
      const user = new User({
        email: email,
        password: hashedPassword,
        cart: { items: [] }
      });
      return user.save();
    })
    .then(result => {
      res.redirect('/login');
      return transporter.sendMail({
        to: email,
        from: 'shop@node-complete.com',
        subject: 'Signup succeeded!',
        html: '<h1>You successfully signed up!</h1>'
      });
    })
    .catch(err => {
      const error = new Error(err);
      error.httpStatusCode = 500;
      return next(error);
    });
};

exports.postLogout = (req, res, next) => {
  req.session.destroy(err => {
    console.log(err);
    res.redirect('/');
  });
};

exports.getReset = (req, res, next) => {
  let message = req.flash('error');
  if (message.length > 0) {
    message = message[0];
  } else {
    message = null;
  }
  res.render('auth/reset', {
    path: '/reset',
    pageTitle: 'Reset Password',
    errorMessage: message
  });
};

exports.postReset = (req, res, next) => {
  crypto.randomBytes(32, (err, buffer) => {
    if (err) {
      console.log(err);
      return res.redirect('/reset');
    }
    const token = buffer.toString('hex');
    User.findOne({ email: req.body.email })
      .then(user => {
        if (!user) {
          req.flash('error', 'No account with that email found.');
          return res.redirect('/reset');
        }
        user.resetToken = token;
        user.resetTokenExpiration = Date.now() + 3600000;
        return user.save();
      })
      .then(result => {
        res.redirect('/');
        transporter.sendMail({
          to: req.body.email,
          from: 'shop@node-complete.com',
          subject: 'Password reset',
          html: `
            <p>You requested a password reset</p>
            <p>Click this <a href="http://localhost:3000/reset/${token}">link</a> to set a new password.</p>
          `
        });
      })
      .catch(err => {
        const error = new Error(err);
        error.httpStatusCode = 500;
        return next(error);
      });
  });
};

exports.getNewPassword = (req, res, next) => {
  const token = req.params.token;
  User.findOne({ resetToken: token, resetTokenExpiration: { $gt: Date.now() } })
    .then(user => {
      let message = req.flash('error');
      if (message.length > 0) {
        message = message[0];
      } else {
        message = null;
      }
      res.render('auth/new-password', {
        path: '/new-password',
        pageTitle: 'New Password',
        errorMessage: message,
        userId: user._id.toString(),
        passwordToken: token
      });
    })
    .catch(err => {
      const error = new Error(err);
      error.httpStatusCode = 500;
      return next(error);
    });
};

exports.postNewPassword = (req, res, next) => {
  const newPassword = req.body.password;
  const userId = req.body.userId;
  const passwordToken = req.body.passwordToken;
  let resetUser;

  User.findOne({
    resetToken: passwordToken,
    resetTokenExpiration: { $gt: Date.now() },
    _id: userId
  })
    .then(user => {
      resetUser = user;
      return bcrypt.hash(newPassword, 12);
    })
    .then(hashedPassword => {
      resetUser.password = hashedPassword;
      resetUser.resetToken = undefined;
      resetUser.resetTokenExpiration = undefined;
      return resetUser.save();
    })
    .then(result => {
      res.redirect('/login');
    })
    .catch(err => {
      const error = new Error(err);
      error.httpStatusCode = 500;
      return next(error);
    });
};

Error in the console:-

TypeError: Cannot read property 'isLoggedIn' of undefined
    at app.use (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\app.js:92:34)
    at Layer.handle_error (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\layer.js:71:5)
    at trim_prefix (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:315:13)
    at D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:335:12)
    at next (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:275:10)
    at Layer.handle_error (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\layer.js:67:12)
    at trim_prefix (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:315:13)
    at D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:335:12)
    at next (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:275:10)
    at Layer.handle_error (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\layer.js:67:12)
    at trim_prefix (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:315:13)
    at D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:335:12)
    at next (D:\Udemy Courses\Node Js\19 Error Handling\04-status-codes\node_modules\express\lib\router\index.js:275:10)

I tried to edit code by assigning the value in the LoggedIn but it is then giving the error of undefined crsf code please help regarding this code I am trying to solve it since many times still it is giving the same error.

The code was running perfectly great and this error is thrown after I added multer package to my node app for file uploads and now this error is not going.

Matin Sasan
  • 1,835
  • 1
  • 13
  • 26
  • 1
    Welcome to Stack Overflow! To make it easier for people to understand your question, could you please add a summary of what the code does (and move the question to the top of the post)? – ecraig12345 Mar 17 '19 at 09:10
  • Welcome to Stack Overflow! Please take the [tour] (you get a badge!), have a look around, and read through the [help], in particular [*How do I ask a good question?*](/help/how-to-ask) and [mcve]. You need to trim that code down a **lot** before posting a question here, removing anything unnecessary. I also recommend Jon Skeet's [Writing the Perfect Question](https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/) and [Question Checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). – T.J. Crowder Mar 17 '19 at 09:16
  • Obviously the problem is that `req.session` is not defined. – Barmar Mar 17 '19 at 09:31

4 Answers4

6

I also followed his tutorial and had this problem, and also checked whether its root is Express error handling or multer. After 4 hours of debugging and googling here's the solution that I found:

https://stackoverflow.com/a/48653921/11330560

And this:

https://github.com/expressjs/multer/issues/513#issuecomment-422573221

Basically, Windows OS file don't accept ":" named. He used Mac OS. so you have to add .replace(/:/g, '-') in front of new Date().toISOString() that is:

new Date().toISOString().replace(/:/g, '-')

I hope it solves your problem too :)

Matin Sasan
  • 1,835
  • 1
  • 13
  • 26
1

I've been through the same issue, the answer for this is given in the FAQ section of the course.Still if you're not getting it follow the next steps..

Install uuid package using: npm install --save uuid
require using: const { v4: uuidv4 } = require('uuid')

Rewrite your code as:

const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'images');
},
 filename: (req, file, cb) => {
cb(null, uuidv4() + '-' + file.originalname);
}
});

I hope this will solve your issue too. Thank-you :)

Shreyas
  • 11
  • 1
1

Use uuid for this instead of newDate().toIsoString()

const fileStorage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'images');
    },
    filename: (req, file, cb) => {
        cb(null, uuidv4() + '-' + file.originalname);
    }
});
Zer0
  • 1,580
  • 10
  • 28
1

I was making 2 mistakes 1st as mentioned by Matin Sasan "Basically, Windows OS file don't accept ":" named. He used Mac OS. so you have to add .replace(/:/g, '-') in front of new Date().toISOString(): " and 2nd you had to create images folder by yourself bcz multer will not create for you as default

Just Replace this function with your current function and create an images folder

const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
//! YOU MUST create the images folder by your self bcs multer will not create one for you and you will get error
    cb(null, 'images')
},
filename: (req, file, cb) => {
    cb(
        null,
        new Date().toISOString().replace(/:/g, '-') + '-' + file.originalname
    )
},

})

enter image description here

Muhammad Hamza
  • 111
  • 1
  • 4