Joi: How do you set up either/or Joi validation on route payloads?

Created on 30 Jun 2017  路  5Comments  路  Source: sideway/joi

Context

  • node 7.10.0:
  • joi 10.6.0:
  • environment (node):
  • used with hapi:
  • requirement for form in hapi-swagger:

I want my app to be allowed to POST either username or email as part of the login payload. Either must be required and validated along with the password.

I have a schema that checks one or the other, but I am struggling at understanding how to add the schema correctly to the route payload so that either a username or email payload is acceptable.

const Joi = require('joi');

// accepts either or, and errors if neither
const userSchema = Joi.alternatives().try(
    Joi.object().keys({
        username: Joi.string().allow(''),
        email: Joi.string().email()
    }),
    Joi.object().keys({
        username: Joi.string(),
        email: Joi.string().email().allow('')
    })
);

exports.register = (server, options, next) => {

    server.route({

        path: '/login',
        method: 'POST',
        config: {
            description: 'User login',
            notes: 'Login with email or username and password.',
            tags: ['api'],
            plugins: {
                'hapi-swagger': {
                    payloadType: 'form'
                }
            },
            validate: {
                // How do I include something like the schema above as an either/or payload attribute?
                payload: {
                    password: Joi.string().min(6).max(200).required()
                }
            }
        },
        handler: require('./login')
    });

    next();
};

exports.register.attributes = {
    name: 'auth-routes'
};
support

Most helpful comment

Why not that one ?

Joi.object().keys({
    username: Joi.string(),
    email: Joi.string().email(),
    password: Joi.string().min(6).max(200).required()
}).xor('username', 'email')

All 5 comments

Why not that one ?

Joi.object().keys({
    username: Joi.string(),
    email: Joi.string().email(),
    password: Joi.string().min(6).max(200).required()
}).xor('username', 'email')

Works perfectly, thank you. xor was the command I was looking for!

@Marsup What is the syntax if I want to accept either latitude and longitude or just address?

Nevermind, I figured it out. You can chain functions.

const schema = Joi.object()
      .keys({
        latitude: Joi.number(),
        longitude: Joi.number(),
        address: Joi.string(),
      })
      .xor('latitude', 'address')
      .xor('longitude', 'address')

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chrisegner picture chrisegner  路  4Comments

mohamadresaaa picture mohamadresaaa  路  3Comments

Dreamystify picture Dreamystify  路  4Comments

n-sviridenko picture n-sviridenko  路  3Comments

Taxi4you picture Taxi4you  路  3Comments