[Feature Request] Stop certain access control rules not to be applied while connecting/disconnecting relationship
Is your feature request related to a problem? Please describe. I have zmodels structured like this:
model User {
...
roles Role[]
modifiedById String? @default(auth().id)
modifiedBy User? @relation("modifiedBy", fields: [modifiedById], references: [id])
modifiedUsers User[] @relation("modifiedBy")
@@deny('update', future().modifiedById != auth().id)
}
model Role {
name String
description String
users User[]
permissions Permission[]
modifiedById String? @default(auth().id)
modifiedBy User? @relation("ModifiedRole", fields: [modifiedById], references: [id])
@@deny('update', future().modifiedById != auth().id)
}
model Permission {
name String
description String
roles Role[]
modifiedById String? @default(auth().id)
modifiedBy User? @relation("ModifiedPermission", fields: [modifiedById], references: [id])
@@deny('update', future().modifiedById != auth().id)
}
This works fine for normal scenarios of editing/updating/creating roles or permissions or users. But this causes us issues when we are just trying to associate Permissions (connect/disconnect) to a Role OR connecting/disconnecting roles from users.
The issue here is that UPDATE is rejected with error of ACCESS_POLICY_VIOLATION for e.g. while trying to assign a role to a user with
const { mutateAsync: addRoles } = useUpdateUser({
onSuccess: async () => {
...
},
});
addRoles({
where: {
id: '......',
},
data: {
modifiedById: '......',
roles: {
connect: newRoles,
},
},
});
will fail with error
{
"error": {
"message": "denied by policy: Role entities failed 'postUpdate' check, entity {\"id\":\"......................................\"} failed policy check",
"reason": "ACCESS_POLICY_VIOLATION",
"rejectedByPolicy": true,
"prisma": true,
"code": "P2004"
}
}
The problem is being caused by post-update check on modifiedById on both sides of the relationship.
Describe the solution you'd like Stop the post update checks when the modification is just connecting/disconnecting and not actual update of the model
Describe alternatives you've considered ...
Additional context ...
Hi @mbhele-xrdigital , thanks for bringing this up.
The current design of policy behavior is explained here: https://zenstack.dev/docs/the-complete-guide/part1/access-policy/model-level#evaluation-of-model-level-policies.
Basically, for relation connect/disconnect, the side that gets the foreign key field update is required to be "updatable". However, implicit many-to-many is a special case because there's an implied "join table" that connects both sides. Currently, ZenStack is conservative and requires both sides to be updatable.
There was a suggestion for utilizing the field-level policies to fine-tune this behavior: https://github.com/zenstackhq/zenstack/issues/856
It hasn't been implemented yet.