Hi @rzac and welcome!
There is no out-of-the-box way to do this. There are some things you can do to make this possible though. It’s pretty straightforward to duplicate some logic if there are not many roles, and you save some effort by reusing UDFs. There is also a way to implement generic “CurrentRoles” and “HasRole” functions using some advanced FQL to set things up for your database.
Use a UDF with the same logic as the Role
If you use some FQL predicate to determine how a Role is applied, you can use the same logic as a UDF.
For example, if you have a membership predicate that looks for an admin
field to be set to true
CreateRole({
name: "admin",
membership: [
{
resource: Collection("users"),
predicate: Query(Lambda("ref", Select(["data", "admin"], Get(Var("ref")))))
}
],
privileges: [/* ... */]
})
Then you can create an IsAdmin
function to check for the same thing.
CreateFunction({
name: "IsAdmin",
role: "admin",
body: Query(Lambda(
"ref",
Select(["data", "admin"], Get(Var("ref")))
))
})
You couls call it with CurrentIdentity()
to check against the current key, like below, or any users
Ref.
Call("IsAdmin", CurrentIdentity())
Use a UDF as the predicate function
You can call UDF’s from within predicate functions.
They have to be READ ONLY, so be careful as using disallowed functions will result in permission denied. See some recent discussion.
Using the example UDF from above, we can actually Call
that function within the Role we made, passing in the “ref” variable.
Update(Role("admin"), {
membership: [
{
resource: Collection("users"),
predicate: Query(
Lambda("ref", Call("IsAdmin", Var("ref"))
)
}
]
})
Now the logic is not duplicated! If you update the IsAdmin
function the permissions will also be updated.