TypeError: Cannot read property 'id' of undefined - sails and mongodb

mrcni picture mrcni · Jul 28, 2014 · Viewed 11.2k times · Source

Sails@beta, mongodb, windows 7 32bit,

i am receiving the above error after trying to make a new user through the app. when i remove the policy isPawn from config/policies.js everything works. i don't understand what is wrong with this policy. it seems to me that i am incorrectly accessing the mongodb id property.

isPawn.js https://github.com/mrcn/C_Express/blob/master/api/policies/isPawn.js

module.exports = function(req, res, next) {

  var sessionUserMatchesId = req.session.User.id === req.param('id');
  var isAdmin = req.session.User.admin;

  // The requested id does not match the user's id,
  // and this is not an admin

  if (!(sessionUserMatchesId || isAdmin)) {
    var noRightsError =
    [{
      name: 'noRights',
      message: 'You must be an admin.'
    }];
    req.session.flash = {
      err: noRightsError
    };
    res.redirect('/session/new');
    return;
  }

  next();

};

user model -- user.js https://github.com/mrcn/C_Express/blob/master/api/models/User.js

module.exports = {

  schema: true,

  attributes: {

    name: {
      type: 'string',
      required: true
    },

    email: {
      type: 'string',
      email: true,
      required: true,
      unique: true
    },

    admin: {
      type: 'boolean',
      defaultsTo: false
    },

    encryptedPassword: {
      type: 'string'
    },

    toJSON: function() {
      var obj = this.toObject();
      delete obj.password;
      delete obj.confirmation;
      delete obj.encryptedPassword;
      delete obj._csrf;
      return obj;
    }
  },

  beforeCreate: function (values, next) {
      //this checks to make sure the passwords match
    if (!values.password || values.password != values.confirmation) {
      return next({err: ["Password\'s don\'t match"]});
    }

    require('bcrypt').hash(values.password, 10, function passwordEncrypt(err, encryptedPassword){
      if (err) return next(err);
      values.encryptedPassword = encryptedPassword;

      console.log();
      console.log(values);
      console.log();

      // values.online=true;
      next();
    });
  }
};

UserController.js: https://github.com/mrcn/C_Express/blob/master/api/controllers/UserController.js

module.exports = {

  // this loads the signup page --> new.ejs
  new : function (req, res) {
    res.locals.flash = _.clone(req.session.flash);
    res.view();
    req.session.flash = {};
  },

  create: function (req, res, next) {

    // Create a user with the params sent from
    // the signup form --> new.ejs
    User.create(req.params.all(), function userCreate (err, user) {

      if (err) {
        console.log(err);
        req.session.flash = {
          err: err
        }

        // if error redirect back to signup page
        return res.redirect('/user/new');
      }

      // after successfully create the user
      // redirect to the show action
      // res.json(user);
      // req.session.flash = {};

      res.redirect('/user/show/'+user.id);
    });
  },

    show: function (req, res, next) {
      User.findOne (req.param('id'), function foundUser (err,user) {
        if (err) return next(err);
        if (!user) return next();
        res.view({
          user: user
        });
      });
    },

    index: function (req, res, next) {
      // EP 13
      // console.log(new Date());
      // console.log(req.session.authenticated);

      //get an array of all users in the User Collection (table)
      User.find(function foundUsers (err, users) {
        if (err) return next(err);
        // pass the array down to the /views/index.ejs page
        // we're rendering our index.ejs passing our users as an object.
        res.view({
          users: users
        });
      });
    },

    edit: function (req, res, next) {
      //Find the user from the id passed in via params
      User.findOne(req.param('id'), function foundUser (err, user){
        if (err) return next(err);
        if (!user) return next('User doesn\nt exist!');

        res.view({
          user: user
        });
      });
    },

    update: function (req, res, next) {
      User.update(req.param('id'), req.params.all(), function userUpdated (err) {
        if (err) {
          return res.redirect('/user/edit/' + req.param('id'));
        }

        res.redirect('/user/show/' + req.param('id'));
        });
    },

    destroy: function (req, res, next) {
      User.findOne(req.param('id'), function foundUser (err, user) {
        if (err) return next(err);
        if (!user) return next('User doesn\nt exist!');

        User.destroy(req.param('id'), function userDestroyed(err) {
          if (err) return next(err);
        });
        res.redirect('/user');
      });
    }
};

Answer

sgress454 picture sgress454 · Jul 28, 2014

It looks like you're trying to access the id property of req.session.User, but req.session.User doesn't exist in at least some cases. If it's always supposed to exist, I'd check the code that's responsible for setting it. Otherwise, change the two lines of your policy to:

var sessionUserMatchesId = (req.session.User && req.session.User.id === req.param('id'));
var isAdmin = req.session.User && req.session.User.admin;

that will keep it from crashing if req.session.User is undefined.