0

We are building a backoffice web application where people are making changes to an array of nested objects. Because of totally non relevant business reasons there are things that users cannot change but can still send in. It is assumed that some people might not use the frontend but directly call the backend, so we cannot just "omit" values that cannot change from the requests the frontend will send.

To give you an example let's say you have an admin page for users home appliances: you can change the name of the appliance ("Eric's fridge" to "Kitchen fridge") but you are not allowed to change the serialNumber of it.

In the cases when a change is about to happen on those "special paths" we want to drop the it and return useful error messages, e.g. "Changing serialNumber of User[3].device[4] is not allowed".

To go further in the question we use the following technologies:

  • node.js for the backend
  • joi for validating requests

Also I assume that for update operations like these you have to query the object about to change.

The bird's eye view is this:

  1. The request hits backend
  2. Validation by JOI happens
  3. A request is sent to DB to fetch the existing objects
  4. The new and old values are compared and checked if values differ only on specific paths
  5. The request is either committed and 200 sent back or dropped and 400 Bad Request with relevant error message is sent back.

Looking at the documentation I could not find anything on this, but it seems to be fairly common to have existing solutions out there, so it might be that I have missed some obvious ones (I fairly infrequently work on backend).

The expected answers should tell if there are existing libraries for this case to avoid reinventing the wheel and also should point me how much custom logic should be written for this.

Where would you put the comparison logic?

Can it be added to the JOI validation? If so should the custom validator query the DB? Or should it happen after JOI validation as a separate non-JOI custom step?

In this case I am curious what is considered a best practice? Stuffing everything to work in the validator library or can it be a custom "secondary" step?

The scalable solution for us would be to have a configurable list of paths that cannot change.

To give you some pseudo-code:

const listOfPathsThatCannotChange = [
  'user[*].device[*].serialNumber',
  'user[*].id',
  'user[*].auditInfo[*].supportAgentEmail',
  '...'
];

const comparisonResults = compare({ 
  a: request, 
  b: objectStoredInDb, 
  bannedPaths: listOfPathsThatCannotChange 
});

if (comparisonResults.length > 0) {
  send(400, comparisonResults);
  return;
}

send(200);

Thanks for reading/commenting/answering!

4
  • Asking for resources such as libraries is off-topic. You might want to rephrase your question. Oct 6 at 16:36
  • @VincentSavard updated the question.
    – atoth
    Oct 6 at 16:43
  • Why can't you omit those banned paths from the requests made to the backend? If the API specification states that a request cannot include a serialNumber element, then everyone just has to conform to that, regardless of if they are using the regular frontend or not. Oct 7 at 10:54
  • @BartvanIngenSchenau These are deeply nested values inside an array. There are too many layers here.
    – atoth
    Oct 26 at 19:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.