You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I use Prisma and I have a problem to make a consistent solution for the "is any related item" check with both prisma-plan-adaptor and cerbos.checkResources implementations.
So I have N:M relations between User and Role models.
And policy like this:
# yaml-language-server: $schema=https://api.cerbos.dev/v0.38.1/cerbos/policy/v1/Policy.schema.json
---
apiVersion: api.cerbos.dev/v1
disabled: false
resourcePolicy:
version: default
resource: role
variables:
local:
hasUsers1: ({} in R.attr.users)
# hasUsers2: size(R.attr.users) > 0
# hasUsers3: R.attr._count.users > 0
rules:
# admin can read the role(s)
- actions:
- read
effect: EFFECT_ALLOW
roles:
- admin
# admin can delete the role
- actions:
- delete
effect: EFFECT_ALLOW
roles:
- admin
# but admin can't delete the role which has users
- actions:
- delete
effect: EFFECT_DENY
roles:
- admin
condition:
match:
expr: V.hasUsers1
Option 1
hasUsers1: ({} in R.attr.users) it works as expected with Prisma plan adapter and returns KIND_CONDITIONAL plan with {"NOT":{"users":{"some":{}}}} filters, but when i check the resource for delete action permissions, it returns EFFECT_ALLOW. I populate and pass the list of users into the checkResources request (ideally, i'd like to avoid this population if possible):
{
"resource": {
"id": "1",
"kind": "role",
"policyVersion": "",
"scope": ""
},
"actions": {
"delete": "EFFECT_ALLOW", // <------- but i expect to have EFFECT_DENY here
"read": "EFFECT_ALLOW"
},
"validationErrors": [],
"outputs": []
}
Option 2
hasUsers2: size(R.attr.users) > 0 - i've tried to use it as alternative solution and it works as expected with cerbos.checkResources and the same payload as I mentioned above but it seems that Prisma plan adapter doesn't support size method and it throws the error with the following error stack:
exception: Error: Unexpected variable [object Object],[object Object]
at mapOperand (/usr/src/app/node_modules/@cerbos/orm-prisma/lib/cjs/index.js:123:15)
at /usr/src/app/node_modules/@cerbos/orm-prisma/lib/cjs/index.js:114:42
at Array.map (<anonymous>)
at mapOperand (/usr/src/app/node_modules/@cerbos/orm-prisma/lib/cjs/index.js:114:31)
at queryPlanToPrisma (/usr/src/app/node_modules/@cerbos/orm-prisma/lib/cjs/index.js:40:26)
at AccessControlService.getQueryPlan (/usr/src/app/src/access-control/access-control.service.ts:241:37)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at async CerbosInterceptor.intercept (/usr/src/app/src/access-control/interceptors/cerbos.interceptor.ts:144:18)
And the query plan i pass into queryPlanToPrisma looks like this:
hasUsers3: R.attr._count.users > 0 i've tried it as another approach (instead of actual population of the users, just to count the related users) and check this number, in this case it works as expected till the DB request. Prisma throws the error because Role model has no _count field, which exists in plan-adapter filters: KIND_CONDITIONAL {"NOT":{"_count":{"users":{"gt":0}}}}.
The error says:
Invalid `this.prisma.role.findUnique()` invocation in
/usr/src/app/src/roles/roles.service.ts:249:46
246 });
247 }
248
→ 249 const isAllowed = await this.prisma.role.findUnique({
where: {
id: 1,
AND: {
NOT: {
_count: {
~~~~~~
users: {
gt: 0
}
},
? AND?: RoleWhereInput | RoleWhereInput[],
? OR?: RoleWhereInput[],
? NOT?: RoleWhereInput | RoleWhereInput[],
? id?: IntFilter | Int,
? name?: StringFilter | String,
? users?: UserListRelationFilter
}
}
}
})
Unknown argument `_count`. Available options are marked with ?.
at In (/usr/src/app/node_modules/@prisma/client/runtime/library.js:114:7526)
at Ln.handleRequestError (/usr/src/app/node_modules/@prisma/client/runtime/library.js:121:7396)
at Ln.handleAndLogRequestError (/usr/src/app/node_modules/@prisma/client/runtime/library.js:121:7061)
at Ln.request (/usr/src/app/node_modules/@prisma/client/runtime/library.js:121:6745)
at async l (/usr/src/app/node_modules/@prisma/client/runtime/library.js:130:9633)
at async RolesService.checkAccessById (/usr/src/app/src/roles/roles.service.ts:249:23)
at async RolesService.findOne (/usr/src/app/src/roles/roles.service.ts:108:5) {
clientVersion: '5.19.0'
}
Solution?
I've tried to combine the options, like this hasUsers1or3: ({} in R.attr.users) || (R.attr._count.users > 0) which kind of makes sense to me, but i didn't find a way to say queryPlanToPrisma via fieldMapper/relationMapper that _count condition should be ignorred in this case.
So I'm looking for advice on how to make it properly?
The text was updated successfully, but these errors were encountered:
Hey! Thanks for the detailed issue. I want to setup a test case for this and then work from there - could you share the relevant parts of your Prisma schema (or a representative example)?
I use Prisma and I have a problem to make a consistent solution for the "is any related item" check with both
prisma-plan-adaptor
andcerbos.checkResources
implementations.So I have
N:M
relations betweenUser
andRole
models.And policy like this:
Option 1
hasUsers1: ({} in R.attr.users)
it works as expected with Prisma plan adapter and returnsKIND_CONDITIONAL
plan with{"NOT":{"users":{"some":{}}}}
filters, but when i check the resource fordelete
action permissions, it returnsEFFECT_ALLOW
. I populate and pass the list of users into thecheckResources
request (ideally, i'd like to avoid this population if possible):and i'm get back
results
as:Option 2
hasUsers2: size(R.attr.users) > 0
- i've tried to use it as alternative solution and it works as expected withcerbos.checkResources
and the same payload as I mentioned above but it seems that Prisma plan adapter doesn't supportsize
method and it throws the error with the following error stack:And the query plan i pass into
queryPlanToPrisma
looks like this:Option 3
hasUsers3: R.attr._count.users > 0
i've tried it as another approach (instead of actual population of the users, just to count the related users) and check this number, in this case it works as expected till the DB request. Prisma throws the error because Role model has no_count
field, which exists in plan-adapter filters:KIND_CONDITIONAL {"NOT":{"_count":{"users":{"gt":0}}}}
.The error says:
Solution?
I've tried to combine the options, like this
hasUsers1or3: ({} in R.attr.users) || (R.attr._count.users > 0)
which kind of makes sense to me, but i didn't find a way to sayqueryPlanToPrisma
via fieldMapper/relationMapper that_count
condition should be ignorred in this case.So I'm looking for advice on how to make it properly?
The text was updated successfully, but these errors were encountered: