Brandon Choe
02/19/2025, 11:45 PMAlex Olivier (Cerbos)
Brandon Choe
02/20/2025, 3:04 PMexists
. I thought I might be able to accomplish this with in
, but the adapter only supports one column.
Policy expression
R.attr.userRoles.exists(userRole,
userRole.role == V.WORKFLOW_ROLE_OWNER && userRole.userId == P.id
)
Prisma I would expect
where: {
userRoles: {
some: {
role: WORKFLOW_ROLE_OWNER,
userId: “1234”
}
}
}
Alex Olivier (Cerbos)
Brandon Choe
02/20/2025, 3:14 PMexists
to support my use case. Does that seem correct to you? I’ll take a better look once I’m in the office. Thank you so much!Alex Olivier (Cerbos)
Brandon Choe
02/20/2025, 3:27 PMexists
? I’d like to do it in a way that I can contribute it backAlex Olivier (Cerbos)
Alex Olivier (Cerbos)
Brandon Choe
02/20/2025, 3:43 PMAlex Olivier (Cerbos)
Alex Olivier (Cerbos)
@cerbos/orm-prisma@v2.0.0-alpha.1
has been published which reworks a large portion of this mapper and simplifies providing the relationships mapper and should handle your use case.
https://www.npmjs.com/package/@cerbos/orm-prisma/v/2.0.0-alpha.1Brandon Choe
02/21/2025, 5:06 PM// Pruned version of our Prisma schema
model User {
id String @id @default(cuid())
workflows Workflow[]
workflowUserRoles WorkflowUserRole[]
}
model Workflow {
id String @id @default(uuid())
userRoles WorkflowUserRole[]
}
model WorkflowUserRole {
workflowId String
workflow Workflow @relation(fields: [workflowId], references: [id], onDelete: Restrict)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role String
}
# Pruned version of Cerbos policy
# yaml-language-server: $schema=<https://api.cerbos.dev/latest/cerbos/policy/v1/Policy.schema.json>
apiVersion: api.cerbos.dev/v1
derivedRoles:
name: workflow_derived_roles
definitions:
- name: workflow_owner
parentRoles: ["user"]
condition:
match:
all:
of:
- any:
of:
- expr: >
R.attr.userRoles.exists(userRole,
userRole.role == ("OWNER") && userRole.workflowId == R.id
)
# Other conditions...
# Other conditions...
Brandon Choe
02/21/2025, 5:06 PMBrandon Choe
02/21/2025, 8:01 PMexists
is working as intended (at least on an immediate relation)!! thank you so much!!
but now I'm struggling with the new way that nested relations are handled. in the previous version I was on (1.1.1), I was able to do the following. maybe this wasn't how we were supposed to do it, but it did work.
return queryPlanToPrisma({
queryPlan,
fieldNameMapper: {
'request.resource.attr.creator.org.settings.externalSharingEnabled':
'creator.org.settings.externalSharingEnabled'
},
});
I've tried a few things with the new version (2.0.0-alpha.1), but I'm struggling a bit.
return queryPlanToPrisma({
queryPlan,
mapper: {
'request.resource.attr.creator.org.settings.externalSharingEnabled': {
relation: {
name: 'creator',
type: 'one',
fields: {
org: {
relation: {
name: 'org',
type: 'one',
fields: {
settings: {
relation: {
name: 'settings',
type: 'one',
field: 'externalSharingEnabled'
}
}
}
}
}
}
}
}
}
});
// policy expression
- expr: R.attr.creator.org.settings.externalSharingEnabled == true
this is the Prisma I get
{ creator: { is: { equals: true } } }
but what I'm expecting is a deeply nested version of that. I'm gonna try to debug myself, but just wanted to share to see if I'm missing something obvious or if there might be a bug (probably the former).Brandon Choe
02/21/2025, 8:05 PMrelation
, I don't get the reduce 🤔
if ("path" in left) {
const { path, relation } = left;
if (relation) {
const relationOperator = getPrismaRelationOperator(relation);
if (relation.field) {
return {
[relation.name]: {
[relationOperator]: {
[relation.field]: { [prismaOperator]: right.value },
},
},
};
}
return {
[relation.name]: {
[relationOperator]: { [prismaOperator]: right.value },
},
};
}
// Create nested filter for field path
return path.reduceRight((acc, key, index) => index === path.length - 1
? { [key]: { [prismaOperator]: right.value } }
: { [key]: acc }, {});
}
Brandon Choe
02/21/2025, 8:12 PMresolveFieldReference
be recursive?Alex Olivier (Cerbos)
Alex Olivier (Cerbos)
@cerbos/orm-prisma@2.0.0-alpha.2
is up and should cover this use caseBrandon Choe
02/24/2025, 5:37 PMBrandon Choe
02/24/2025, 6:35 PMAlex Olivier (Cerbos)
Brandon Choe
02/24/2025, 8:46 PMAlex Olivier (Cerbos)
Alex Olivier (Cerbos)
Brandon Choe
02/25/2025, 5:43 PMAlex Olivier (Cerbos)