Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 525
rok Avatar asked Apr 04 '19 08:04

rok


People also ask

Should I use Joi or express-validator?

Joi can be used for creating schemas (just like we use mongoose for creating NoSQL schemas) and you can use it with plain Javascript objects. It's like a plug n play library and is easy to use. On the other hand, express-validator uses validator. js to validate expressjs routes, and it's mainly built for express.

Is Mongoose validation enough?

If the validation logic is simple and small, there is no problem about mongoose validation. But in case of complex validation rules and multiple fields, then express-validator may be better choice. If the mongoose built-in validators are not enough for your validation logic, you have to create custom validators.

Does mongoose have built-in validation?

Mongoose has several built-in validators. All SchemaTypes have the built-in required validator. The required validator uses the SchemaType's checkRequired() function to determine if the value satisfies the required validator. Numbers have min and max validators.

Why do we use Joi?

Joi module is a popular module for data validation. This module validates the data based on schemas. There are various functions like optional(), required(), min(), max(), etc which make it easy to use and a user-friendly module for validating the data.


1 Answers

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.

like image 110
Santgurlal Singh Avatar answered Nov 15 '22 14:11

Santgurlal Singh