0

Model

const hoursSchema = new Schema({
    date: {
        type: Date,
        required: true,
        trim: true,
    },
    location: {
        type: String,
        required: true,
        trim: true,
        minlength: 1,
    }
});

module.exports = mongoose.model('Hours', hoursSchema);

Route

router.post('/', (req, res) => {
   const body = _.pick(req.body, ['date', 'location']);
   const entry = new Hours(body);
   res.send(entry);
   // rest of code...
});

I make a post request with let's say date: 12 / date: "12". Mongoose is treating this a a timestamp because I've receiving this as a result in date field - 1970-01-01T00:00:00.012Z. How can I prevent that? I want to throw an error when user send other data than date in format yyyy-mm-dd or dd-mm-yyyy

gregooroo
  • 148
  • 1
  • 9
  • Possibly a duplicate of [*How to validate a date?*](https://stackoverflow.com/questions/5812220/how-to-validate-a-date) – RobG Nov 05 '17 at 22:58

1 Answers1

0

The easiest way would be to use an express middleware function and check for legal input there. There is already a middleware library called express-validator that you can use. It doesn't contain a function for checking for legal dates, so you have to make it yourself.

To check for legal date you can use a function such as this (from here):

function isValidDate(value) {
  if (!value.match(/^\d{4}-\d{2}-\d{2}$/)) return false;

  const date = new Date(value);
  if (!date.getTime()) return false;
  return date.toISOString().slice(0, 10) === value;
}

It requires the following format: YYYY-MM-DD. You can combine it with functions for DD-MM-YYYY. You can find some examples here.

Middleware function before the post controller:

const dateValidator = [
  check('date')
   .custom(isValidDate)
   .withMessage('the date is illegal')
]

The route would then become:

router.post('/', dateValidator, (req, res) => {}

And inside the controller function you start with this check:

const errors = validationResult(req);
if (!errors.isEmpty()) {
  return res.status(422).json({ errors: errors.mapped() });
}

The user will then get an error message if the date is illegal.

Mika Sundland
  • 18,120
  • 16
  • 38
  • 50
  • Thank you for your answer. I need to check this express-validator and play with it. So there is no possibility to make that kind of validation in mongoose model? Why exactly mongoose does this kind of conversion? – gregooroo Nov 05 '17 at 22:59
  • You can do custom validation in mongoose too. [Here](http://mongoosejs.com/docs/validation.html) is some information about that. I would assume "12" is a legal date format, and that's why it's allowed. – Mika Sundland Nov 05 '17 at 23:00
  • Actually, when I think of it, date validation doesn't work very well in Mongoose. [Here](https://stackoverflow.com/questions/44770533/mongoose-custom-error-message-for-date-type-validation) is a question about that issue. You will get a casterror before the validation triggers. So you might as well do it with the middleware approach. – Mika Sundland Nov 05 '17 at 23:29
  • Thanks @MikaS for your help. I decided to use this express-validator to validate date. So now should I move all validation cases (for other fields) to express route to keep application organized? What do you think? – gregooroo Nov 06 '17 at 15:50
  • @randomGuyFromTheInternet Yes, I would do that. For simple things like numbers and strings you can also have them validated by both mongoose and express-validator. First by express-validator, and if that fails (it shouldn't) it's caught by mongoose. You would then have several barriers of defense. But it's up to you. There are a couple of [questions](https://stackoverflow.com/questions/7600559/how-do-you-handle-form-validation-especially-with-nested-models-in-node-js-e) already on where it's best to handle validation. – Mika Sundland Nov 06 '17 at 16:00