adonisjs/validator

Validating user instance in hook

Closed this issue · 1 comments

I wanted to move my validation calls into the hooks because this allows me to not worry about calling the validation in the routes or controllers.

Inside my User model I register the hook.

class User extends Model {
  static boot() {
    super.boot();
    this.addHook('beforeSave', 'UserHook.validate');
  }
  static get hidden() {
    return ['password'];
  }
}

and in my User hook I add the validation

UserHook.validate = async (user) => {
const rules = {
    password: 'required|min:8|max:256',
    username: 'required|min:2|max:18',
    mail: 'required|email'
}
 const validation = await validateAll(user, rules);

Afterwards I check if validation.fails() and throw an error which is then handled by the controller that executes queries with lucid. With the code above it can't validate any field and fails with following message:

[
  {
    "field": "password",
    "message": "required validation failed on password",
    "validation": "required"
  },
  {
    "field": "username",
    "message": "required validation failed on username",
    "validation": "required"
  },
  {
    "field": "mail",
    "message": "required validation failed on mail",
    "validation": "required"
  }
]

If I call toJSON() on the user instance only the password validation is missing because the field is hidden.

 const validation = await validateAll(user.toJSON(), rules);
[
  {
    "field": "password",
    "message": "required validation failed on password",
    "validation": "required"
  }
]

If I store the user instance in another object while explicitly calling the properties of the instance e.g user.password, everything works as expected and no field is missing.

UserHook.validate = async (user) => {
const rules = {
    password: 'required|min:8|max:256',
    username: 'required|min:2|max:18',
    mail: 'required|email'
}

const adonisUser = {
  username: user.username,
  password: user.password,
  mail: user.mail
};
const validation = await validateAll(adonisUser, rules);

Is there a more elegant way to validate the user instance?

Simply use user.$attributes over user.toJSON()