dresende / node-orm2

Object Relational Mapping
http://github.com/dresende/node-orm2
MIT License
3.07k stars 377 forks source link

Unable to define custom properties #547

Open mhuggins opened 10 years ago

mhuggins commented 10 years ago

Hi there!

I'm trying to use to build out a user model that has an encryptedPassword property attached to a DB field, while trying to add custom password and passwordConfirmation properties (essentially virtual attributes that don't get saved), which are used to generate a password hash. Here's a sample of what I mean.

var User = db.define('user', {
  id                : { type: 'serial', key: true },
  email             : { type: 'text', required: true, unique: true },
  encryptedPassword : { type: 'text', required: true, mapsTo: 'encrypted_password' }
}, {
  hooks: {
    beforeValidation: function (next) {
      this.encryptPassword(function (err, hash) {
        if (err) return next(err);

        this.encryptedPassword = hash;
        next();
      }.bind(this));
    }
  },

  validations: {
    password: [
      orm.enforce.security.password('6', 'must be 6+ characters')
    ],
    passwordConfirmation: [
      orm.enforce.equalToProperty('password', 'does not match password')
    ]
  },

  methods: {
    encryptPassword: function (callback) {
      bcrypt.hash(this.password, config.server.salt, callback);
    }
  }
});

Object.defineProperties(User.prototype, {
  password: {
    writable: true,
    enumerable: true
  },
  passwordConfirmation: {
    writable: true,
    enumerable: true
  }
});

Then when creating a user:

var params = require('params');  // https://github.com/vesln/params

app.post('/register', function (req, res, next) {
  req.models.user.create(userParams(req.body), function (err, user) {
    // post-create logic here
  });
});

function userParams(body) {
  return params(body).only('email', 'password', 'passwordConfirmation');
};

After digging through the code, I see that this doesn't work as I'd hoped, and my custom properties (password/passwordConfirmation) don't get assigned through the create call, instead just getting stripped from the object. I'm wondering if this is something that could/should be added as a feature, or if there's another/better way of approaching this that I'm not familiar with. I couldn't find anything in the docs or elsewhere.

mhuggins commented 10 years ago

After digging around a bit more, this doesn't look doable. However, I can't determine a way to approach this with the existing node-orm without having redundant validation in a separate location, at which point I would rather just use a different ORM. If you are open to a pull request, I think one of the following approaches would be suitable to my needs:

Thoughts?

mhuggins commented 10 years ago

I'm going to switch to Sequelize so I can keep moving forward, thanks anyway.