Originating from the following GitHub discussion: https://github.com/strapi/strapi/discussions/8101
I needed to implement an “alias” feature for an item type in a Strapi database, which necessitates non-standard validation logic:
- Each Item has a self-referential relationship
reimplements_item
- When setting
reimplements_item
, it cannot be set to an Item that also has a value forreimplements_item
(because this would necessitate looking up the root item down an arbitrarily long chain) - When deleting an Item, it must throw an error if there are any items with that item in their
reimplements_item
field
I was able to implement this validation by overriding the custom services with logic similar to this:
async update(params, data, { files } = {}) {
const validData = await strapi.entityValidator.validateEntityUpdate(strapi.models.item, data)
// This utility function checks for valid reimplements_item data (shared between create and update)
// Returns undefined on success, or an error object if it fails
const reimplementsError = await checkReimplementsItem(validData)
if (reimplementsError) throw reimplementsError
const entry = await strapi.query('item').update(params, validData)
// ...and continue on with the standard logic
}
This works alright; I also needed to make a light override for the controller update
method with a try/catch block around the service to avoid generic 500 server errors, which isn’t ideal but works.
However, if a user modifies an Item through the Strapi admin screen, all of this fancy logic is apparently bypassed (according to @DMehaffy).
Suggestions for things that would make this whole process a lot less onerous:
- Add a way to attach arbitrary validation logic that will be called by the entityValidator on a per-model basis. This would allow me to leave the vanilla services and controller methods in place, because I could just add some validation if the reimplements_item property is populated. It would presumably also affect the Strapi admin.
- As an alternative, provide generic errors that can be thrown by services that will be automatically converted into
ctx
error output (instead of getting obscured by 500 server error). This would allow customization of generic services without needing to also add logic to the generic controller. - Ensure that CRUD logic is centralized. It’s weird that the Strapi admin would be circumventing the logic that’s in place for handling model creation. At that point, it seems kind of redundant to have the service at all since it’s just being used by simple CRUD (unless maybe it’s invoked when creating items via relationships? Dunno, haven’t played with that)