Rajeshwar
Rajeshwar

Reputation: 2509

.when() in joi validation, to validate one key based on another key

Admin will create users, and while doing so he will enter some random string as a password. When admin edit the existing user, he don't need to enter any password unless he wants to change it. If the admin doesn't enter any password, then the old password will be used.

So i am trying to use .when() to handle this case. When _id exists in the payload (which is possible only when the user exists), then we should make the password field optional or else password is required.

Here is my Joi validation

const usersJoiSchema = Joi.object({
  _id: Joi.string().optional(),
  firstName: Joi.string().required(),
  lastName: Joi.string().required(),
  email: Joi.string().required(),
  password: Joi.string().when('_id', { is: Joi.exist(), then: Joi.optional(), otherwise: Joi.required() })
})

Joi have a method .when in case of such cases. But for some strange reason it is giving me

{"statusCode":500,"error":"Internal Server Error","message":"An internal server error occurred"}

as the response of the api, and there is nothing in the server console. I tried to compare the string length for _id as well instead of exists() and i have also tried

password: Joi.string().when('_id', { is: Joi.string().required(), then: Joi.string().optional(), otherwise: Joi.string().required() }),

password: Joi.string().when('_id', { is: Joi.string(), then: Joi.string().optional(), otherwise: Joi.string().required() }),

for password key, but still the same issue.

If any one has any kind of idea on this issue, please help me.

Upvotes: 10

Views: 21191

Answers (2)

Princewill Iroka
Princewill Iroka

Reputation: 546

  _id: Joi.string(),
  password: Joi.string().when("_id", {
     is: Joi.exist(),
     then: Joi.required()
  })

With the above, Joi will ensure that password is required whenever _id exists

Upvotes: 6

metoikos
metoikos

Reputation: 1364

Well, I created a simple test and all conditions are passed according to your requirements. I believe there is something else in your code occurs that error. Here is my test code, please take a look.

const Lab = require('lab');
const lab = exports.lab = Lab.script();
const describe = lab.describe;
const it = lab.it;
const expect = require('code').expect;
const Joi = require('joi');

const usersJoiSchema = Joi.object({
    _id: Joi.string().optional(),
    firstName: Joi.string().required(),
    lastName: Joi.string().required(),
    email: Joi.string().required(),
    password: Joi.string().when('_id', {is: Joi.exist(), then: Joi.optional(), otherwise: Joi.required()})
});

describe('Validator usersJoiSchema checks', () => {

    it('It should save new user without id', () => {
        const result = Joi.validate({
            firstName: "Hello",
            lastName: "World",
            email: "[email protected]",
            password: "123456"
        }, usersJoiSchema, {abortEarly: false});
        expect(result.error).to.null();
        expect(result.error).to.not.exist();
    });

    it('It should update user without password field when id included', () => {
        const result = Joi.validate({
            _id: "some-id-string-here",
            firstName: "Hello",
            lastName: "World",
            email: "[email protected]",
        }, usersJoiSchema, {abortEarly: false});
        expect(result.error).to.null();
        expect(result.error).to.not.exist();
    });


    it('It should fail when id is empty and no password provided', () => {
        const result = Joi.validate({
            firstName: "Hello",
            lastName: "World",
            email: "[email protected]",
        }, usersJoiSchema, {abortEarly: false});
        expect(result.error).to.not.null();
        expect(result.error).to.exist();
    });
    it('It should fail when id is empty and password is also empty', () => {
        const result = Joi.validate({
            firstName: "Hello",
            lastName: "World",
            email: "[email protected]",
            password: "",
        }, usersJoiSchema, {abortEarly: false});
        expect(result.error).to.not.null();
        expect(result.error).to.exist();
    });
});

Here is the test command

> lab --coverage-exclude test/data -m 5000n -a code -P "simple" "test/validators"

  ....

4 tests complete
Test duration: 8 ms
Assertions count: 8 (verbosity: 2.00)
No global variable leaks detected

Upvotes: 8

Related Questions