2

I use arangodb 3.0.2 and have problem with joi validation when update/patch schema.

I have user schema like this

_key: joi.string(),
name: joi.string().required(),
username: joi.string(),
email: joi.string().required(),
profilePicture: joi.string(),
provider: joi.object().keys({
  name: joi.string(),
  id: joi.string()
}),
interest: joi.array().items(joi.string()),
level: joi.number().default(0)

When I create new new user, and try to add unknown field, like status it will throw error,

But If I update user, and add unknown field, it doesn't throw any error. Because it not validate request schema.

How to validate schema when update/patch user, with ignoring field that already exists in collection?


Update for routes:

router.post(function (req, res) {
  const user = req.body;
  let provider = user.provider.name;
  let id = user.provider.id;
  let meta;
  try {
    meta = users.save(user);
  } catch (e) {
    if (e.isArangoError && e.errorNum === ARANGO_DUPLICATE) {
      throw httpError(HTTP_CONFLICT, e.message);
    }
    throw e;
  }
  Object.assign(user, meta);
  res.status(201);
  res.set('location', req.makeAbsolute(
    req.reverse('detail', {key: user._key})
  ));
  res.send(user);
}, 'create')
.body(User, 'The user to create.')
.response(201, User, 'The created user.')
.error(HTTP_CONFLICT, 'The user already exists.')
.summary('Create a new user')
.description(dd`
  Creates a new user from the request body and
  returns the saved document.
`);

router.patch(':key', function (req, res) {
  const key = req.pathParams.key;
  const patchData = req.body;
  let user;
  try {
    users.update(key, patchData);
    user = users.document(key);
  } catch (e) {
    if (e.isArangoError && e.errorNum === ARANGO_NOT_FOUND) {
      throw httpError(HTTP_NOT_FOUND, e.message);
    }
    if (e.isArangoError && e.errorNum === ARANGO_CONFLICT) {
      throw httpError(HTTP_CONFLICT, e.message);
    }
    throw e;
  }
  res.send(user);
}, 'update')
.pathParam('key', keySchema)
.body(joi.object().description('The data to update the user with.'))
.response(User, 'The updated user.')
.summary('Update a user')
.description(dd`
  Patches a user with the request body and
  returns the updated document.
`);

This is my routes, as you can see. When I post new user, it will validate user schema, so if I add unknown field, it will give me some error.

But I patch user, it will not validate user schema, because on "body" I'm not set as User Schema. But if add User Schema there, it will check required field, so I can't just patch some know field.

de_3
  • 3,389
  • 5
  • 20
  • 14
  • Hi @de_3, can you provide an example of the routes where you are using the schema? I'm not entirely sure what's going on. – Alan Plum Jul 20 '16 at 14:47
  • Hi @AlanPlum, I've update my question, I've add user routes there. is it enough? – de_3 Jul 20 '16 at 21:33

1 Answers1

1

If you want to ensure a certain schema for both, creation (.post() route) and update (.patch() route), make sure to define the schema only once and reference it in both routes instead of writing it twice inline in .body() (DRY principle).

let userSchema = joi.object().keys({
  _key: joi.string(),
  name: joi.string().required(),
  username: joi.string(),
  email: joi.string().required(),
  profilePicture: joi.string(),
  provider: joi.object().keys({
    name: joi.string(),
    id: joi.string()
  }),
  interest: joi.array().items(joi.string()),
  level: joi.number().default(0)
});

router.post(...)
  .body(userSchema)

router.patch(...)
  .body(userSchema)

It looks like you actually defined a schema like this, stored in a variable User and used in the POST route:

.body(User, 'The user to create.')

But you don't use the schema in the PATCH route:

.body(joi.object().description('The data to update the user with.'))

It only ensures that req.body is an object, but does not enforce any schema.

CodeManX
  • 11,159
  • 5
  • 49
  • 70