rok
rok

Reputation: 597

Is using Joi for validation on top of Mongoose good practice?

I'm developing a RESTful API with Node.js, Mongoose and Koa and I'm a bit stuck on what are the best practices when it comes to schemas and input validation.

Currently I have both a Mongoose and Joi schema for each resource. The Mongoose schema only includes the basic info about the specific resource. Example:

const UserSchema = new mongoose.Schema({
  email: {
    type: String,
    lowercase: true,
  },
  firstName: String,
  lastName: String,
  phone: String,
  city: String,
  state: String,
  country: String,
});

The Joi schema includes details about each property of the object:

{
  email: Joi.string().email().required(),
  firstName: Joi.string().min(2).max(50).required(),
  lastName: Joi.string().min(2).max(50).required(),
  phone: Joi.string().min(2).max(50).required(),
  city: Joi.string().min(2).max(50).required(),
  state: Joi.string().min(2).max(50).required(),
  country: Joi.string().min(2).max(50).required(),
}

The Mongoose schema is used to create new instances of the given resource at endpoint handler level when writing to the database.

router.post('/', validate, routeHandler(async (ctx) => {
  const userObj = new User(ctx.request.body);
  const user = await userObj.save();

  ctx.send(201, {
    success: true,
    user,
  });
}));

The Joi schema is used in validation middleware to validate user input. I have 3 different Joi schemas for each resource, because the allowed input varies depending on the request method (POST, PUT, PATCH).

async function validate(ctx, next) {
  const user = ctx.request.body;
  const { method } = ctx.request;
  const schema = schemas[method];

  const { error } = Joi.validate(user, schema);

  if (error) {
    ctx.send(400, {
      success: false,
      error: 'Bad request',
      message: error.details[0].message,
    });
  } else {
    await next();
  }
}

I am wondering if my current approach of using multiple Joi schemas on top of Mongoose is optimal, considering Mongoose also has built-int validation. If not, what would be some good practices to follow?

Thanks!

Upvotes: 21

Views: 7768

Answers (2)

SnekNOTSnake
SnekNOTSnake

Reputation: 1407

IMO, I don't think there's a definite answer to this question. Like what @omer said in the comment section above, Mongoose is powerful enough to stand its own ground.

But if your code's logic/operations after receiving input is pretty heavy and expensive, it won't hurt adding an extra protection in the API layer to prevent your heavy code from running.

Edit: I just found this good answer by a respectable person.

Upvotes: 2

Santgurlal Singh
Santgurlal Singh

Reputation: 167

It is a common practice to implement a validation service even if you have mongoose schema. As you stated yourself it will return an validation error before any login is executed on the data. so, it will definitely save some time in that case. Moreover, you get better validation control with joi. But, it highly depends upon your requirement also because it will increase the extra code you have to write which can be avoided without making much difference to the end result.

Upvotes: 6

Related Questions