Skip to content

Instantly share code, notes, and snippets.

@stongo
Last active Oct 12, 2021
Embed
What would you like to do?
Joi validation in a Mongoose model
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', function() {
return console.error.bind(console, 'connection error: ');
});
db.once('open', function() {
var User;
return User = require('./user.js');
});
// Validate a user
(function() {
var User = require('./user.js');
var me = { username: 'foo' };
var user = new User(me);
var err = user.joiValidate(me);
if (err) throw err;
user.save(function(err, saved) {
...
});
})();
var userSchema = mongoose.Schema({
username: String,
password: String,
email: String,
first_name: String,
last_name: String,
created: { type: Date, default: Date.now },
});
userSchema.methods.joiValidate = function(obj) {
var Joi = require('joi');
var schema = {
username: Joi.types.String().min(6).max(30).required(),
password: Joi.types.String().min(8).max(30).regex(/[a-zA-Z0-9]{3,30}/).required(),
email: Joi.types.String().email().required(),
first_name: Joi.types.String().required(),
last_name: Joi.types.String().required(),
created: Joi.types.Date(),
}
return Joi.validate(obj, schema);
}
module.exports = mongoose.model('User', userSchema);
@dhavaljardosh

This comment has been minimized.

Copy link

@dhavaljardosh dhavaljardosh commented Jul 23, 2018

Spend 4 days to understand Joi with Mongoose, even tried Joigoose (it had several limitations) and finally found this. This is very clear. Thank you very much.

@JeffLabonte

This comment has been minimized.

Copy link

@JeffLabonte JeffLabonte commented Aug 3, 2018

Good thinking! Good job! Thank you for sharing!

@sagar-gavhane

This comment has been minimized.

Copy link

@sagar-gavhane sagar-gavhane commented Aug 5, 2018

Combination of Joi and Mongoose is great...

@meteorlxy

This comment has been minimized.

Copy link

@meteorlxy meteorlxy commented Aug 20, 2018

userSchema.statics.joiValidate = ...

Could be another choice

@cicconewk

This comment has been minimized.

Copy link

@cicconewk cicconewk commented Aug 26, 2019

Good job! It helped me a lot 👍.

I think it is better to use the validator method before creating a new user schema.

@deoncasas

This comment has been minimized.

Copy link

@deoncasas deoncasas commented Dec 13, 2019

Nice validation for mongoose make my life easier

@srujanpurohit

This comment has been minimized.

Copy link

@srujanpurohit srujanpurohit commented Jul 28, 2020

The problem with this approach is that if you need some fields only for Joi validation, while creating schema mongoose will remove those field. For example in this case, what if there is another field for "repeat password" that is not being saved in db but is required for validation.

@devChedar

This comment has been minimized.

Copy link

@devChedar devChedar commented Oct 3, 2020

If you are using express better method would be to add a middleware for validation so that the problem mentioned by @srujanpurohit doesn't exist. So instead it would look something like this

// user Model

const mongoose = require('mongoose')
const Joi = require('joi')

const userSchema = new mongoose.Schema({
  email: {
    type: String,
    required: [true, 'Please enter a email'],
    unique: true,
    lowercase: true,
  },
  password: {
    type: String,
    required: [true, 'Please enter a password'],
    minlength: 8,
  },
})

const User = mongoose.model('user', userSchema)

const validateUser = (user) => {
  const schema = Joi.object({
    email: Joi.string().email().min(5).max(500).required(),
    password: Joi.string().min(8).max(1024).required(),
  })
  return schema.validate(user)
}
module.exports = {
  User,
  validateUser,
}

// validateMiddleware
module.exports = (validator) => {
  return (req, res, next) => {
    const { error } = validator(req.body)
    console.log('error: ', error)
    if (error) {
      return res.status(400).send(error.details[0].message)
    }
    next()
  }
}
// authRoute

const { validateUser } = require('../models/User')
const validateMiddleWare = require('../middleware/validate')
const authController = require('../controllers/authController')

router.post('/signup', [validateMiddleWare(validateUser)], authController.signup_post)

@geraldanosike

This comment has been minimized.

Copy link

@geraldanosike geraldanosike commented Jul 24, 2021

If you are using express better method would be to add a middleware for validation so that the problem mentioned by @srujanpurohit doesn't exist. So instead it would look something like this

// user Model

const mongoose = require('mongoose')
const Joi = require('joi')

const userSchema = new mongoose.Schema({
  email: {
    type: String,
    required: [true, 'Please enter a email'],
    unique: true,
    lowercase: true,
  },
  password: {
    type: String,
    required: [true, 'Please enter a password'],
    minlength: 8,
  },
})

const User = mongoose.model('user', userSchema)

const validateUser = (user) => {
  const schema = Joi.object({
    email: Joi.string().email().min(5).max(500).required(),
    password: Joi.string().min(8).max(1024).required(),
  })
  return schema.validate(user)
}
module.exports = {
  User,
  validateUser,
}
// validateMiddleware
module.exports = (validator) => {
  return (req, res, next) => {
    const { error } = validator(req.body)
    console.log('error: ', error)
    if (error) {
      return res.status(400).send(error.details[0].message)
    }
    next()
  }
}
// authRoute

const { validateUser } = require('../models/User')
const validateMiddleWare = require('../middleware/validate')
const authController = require('../controllers/authController')

router.post('/signup', [validateMiddleWare(validateUser)], authController.signup_post)

Awesome. Thanks for this. Really helped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment