In the docs I’ve seen that you can deny writing to properties like so:
client.query(q.CreateRole({
name: "users",
membership: [
{
resource: q.Collection("User"),
},
],
privileges: [
{
resource: q.Collection("User"),
actions: {
read: q.Query(q.Lambda("ref", q.Equals(q.Identity(), q.Var("ref")))),
// TODO: Convert from denylist into allowlist
write: q.Query(
q.Lambda(
["oldData", "newData"],
q.And(
q.Equals(
q.Select(["data", "email"], q.Var("oldData")),
q.Select(["data", "email"], q.Var("newData")),
),
q.Equals(
q.Select(["data", "role"], q.Var("oldData")),
q.Select(["data", "role"], q.Var("newData")),
),
q.Equals(
q.Select(["data", "customerID"], q.Var("oldData")),
q.Select(["data", "customerID"], q.Var("newData")),
),
),
),
),
delete: q.Query(q.Lambda("ref", q.Equals(q.Identity(), q.Var("ref")))),
},
}
],
});
As I add new props to a user
document I need to then potentially also remember to block writing to that new prop. I’d prefer to instead create an allowlist to be more explicit. I’ve tried the following:
write: q.Query(
q.Lambda(
["oldData", "newData"],
q.And(
// Only allow the user that owns the document to update it
q.Equals(q.Identity(), q.Select(["ref"], q.Var("oldData"))),
// Allowlist
q.IsEmpty(
q.Difference(
q.Map(
q.ToArray(q.Var("newData")),
q.Lambda(["k", "v"], q.Var("k")),
),
["shoppingCart"], // This is the prop that I want to allow the user to update
),
),
),
),
),
I’ve spent half the day going through different variations of this and can’t get it to work. It’s super difficult to debug predicate functions and I’m kinda just stabbing in the dark here…
Ideally I would also like to set in the allowlist what data type the properties should be. Eg, in the FQL above I’d like to allow the user to only update the shoppingCart
property which should be of type Ref
.
The GraphQL endpoint enforces the data types in the mutation input types but a crafty user could still send HTTP queries with the wrong data type.
Additionally, I’m also curious about the following:
- Is there any way to debug predicate functions, or at least get some insight into their internals?
- What is the exact shape of the
write
lambda inputs? It seems I can’t access theref
prop. - Is it possible for a user to change props like
ref
,_ts
, etc?