Search code examples
node.jsmongoosejoi

Why isn't my mongoose validation method on the model not working with Joi?


The Problem:

I have a basic authentication flow set up. I have this custom method on my users model:

userSchema.methods.joiValidate = function() {
  console.log(typeof this.username);
  const Joi = require("joi");
  const schema = {
    username: Joi.types.String.min(6)
      .max(24)
      .required(),
    email: Joi.types.String.email().required(),
    password: Joi.types.String.min(8)
      .max(30)
      .regex(/[a-zA-Z0-9]{3,30}/)
      .required()
  };
  return Joi.validate(this, schema);
};

But it isn't working as expected.

When I create a new user and validate it like so:

const invalidUser = new User({
      username: "bob",
      email: "test@gmail.com",
      password: "test123"
    });
invalidUser.joiValidate();

I get this error message: TypeError: Cannot read property 'String' of undefined

I don't know why? this in my method refers to exact this user and it has all required fields on it (username, email and password) when I console.log it in the model (document) itself. I also tried to Joi.validate(this.toObject(), schema) on the method but that doesn't change anything.

Could anybody explain me what is going on and why it's not working?


Solution

  • For anyone curious what the problem was - I somehow messed up the whole syntax of joi (Copied some old code I found on StackOverflow, LOL).

    I fixed it like this:

        userSchema.methods.joiValidate = function() {
        
          // pull out just the properties that has to be checked (generated fields from mongoose we ignore)
          const { username, email, password } = this;
          const user = { username, email, password };
          const Joi = require("joi");
          const schema = Joi.object().keys({
            username: Joi.string()
              .min(6)
              .max(24)
              .required(),
            email: Joi.string()
              .email()
              .required(),
            password: Joi.string()
              .min(8)
              .max(30)
              .regex(/[a-zA-Z0-9]{3,30}/)
              .required(),
            _id: Joi.string()
          });
        
          return Joi.validate(user, schema, { abortEarly: false });
        };