I'm trying to develop a Cerbos-Strapi.js middlewar...
# help
a
I'm trying to develop a Cerbos-Strapi.js middleware to enforce access control on APIs. This is based on the Cerbos-Prisma.js adapter. I'm encountering difficulties in creating a filter for relations that could be populated in the REST API request. Initially, I thought I could simply insert Cerbos filters before retrieving data from the database. However, these filters seem to only apply to the primary resource. For instance, suppose we have a blog, and we're attempting to fetch blog posts and their related comments, but only those made by the blog's author. If we apply a filter to retrieve only the posts from the author and add a filter to include comments only from the same author, the filter will only be applied to the primary resource (the blog posts) and not the related resources (the comments). As a result, it will return blog posts from the author but will populate all the comments, regardless of who made them. This is the issue I'm facing, and I'm seeking solutions to effectively apply filters on related resources as well. My current strategy involves: 1. Using
planResources
before fetching request data with
await next()
. This is to append a filter to the query if it's a 'find' action. I do this through a
queryPlanToStrapi
function that maps Cerbos conditions and creates filters for Strapi. 2. After the data is retrieved, I verify access control on the remaining resource actions with Cerbos. 3. Since Strapi and Sift.js are similar I use a
querySiftFilters
very similar to
queryPlanToStrapi
to create filters that sift can use and I'm planing to iterate the response (
ctx.body.data
) to filter the queried data after await next() and exclude items from the relation that weren't meant to be retrieved. (I'm still working on this and looking for better approaches). Is there a better approach? Perhaps a library that can directly convert from Cerbos AST condition and filter a list of nested objects? Any help or insight would be greatly appreciated.
👍 1
a
Hey, Relations are a bit tricky but we have managed to implement this inside the Prisma and SQLAlchmey adapters. You need to be able to provide the mapping of Cerbos attribute field to the data’s relational fields - then inside the mapper use this mapping to do joins/fetch the related data. I’m not overly famailar with strapi but in theory the same model should work. https://github.com/cerbos/query-plan-adapters/tree/main/prisma https://github.com/cerbos/query-plan-adapters/tree/main/sqlalchemy
a
Yest. I pretty much made an adaptation from the prisma adapter. But the output was not filtered and it struck me that strapi probably handles filtering by relationships on a different way than prisma.
a
Are you getting back a filter object from the mapper before passing it to strapi?
a
Yes, I've been using similar filters for both the primary resource and its relation. I have also tried applying a filter specifically from a relation, without using one on the primary resource, but the results remain unchanged. For example. If I apply a filter based on the comments owned by a user, it retrieves all the blogs where the user has commented. However, it's worth noting that the comments used as a filter criterion will also retrieve all comments, both those made by the user and those not made by the user. Chatgpt also said they don´t support deep filtering on relation fields and suggested me to make a custom controller or use graphql. Anyway, thanks for your concerns. It seems development got blocked by the orm