i am defeated by RLS
hello team, can y'all pls help me understand how to do RLS? i currently have a func,
with the rls func defined as below
4 Replies
and here's the hasPermission func
1. do u foresee anything i can improve here?
2. how to correctly to do ctx? i wanted to define the ctx as type
but apparently it doesnt work because the ctx in the
is of type Rule.
3. weird enough i have a definedTable for ROLE_PERMISSION_JOIN_DB with index roleId and the first query below fails when i dont do withIndex. is this expected?
4. i suspect because im doing
ctx: any
, my filter((q: any)
has to be of type any?
5. my
outright fails despite manually checking the IDs actually are correct. i think this will be resolved if the above are taken care of.
thank you in advanced. sorry this is a lengthy one 🙏A few thoughts:
- The
ctx
type in the RowLevelSecurity type param should match what you're passing into it (currently set to {customer: Doc<"customer">}
. And that should be the same type as hasPermission
ctx type.
- If you are passing it to a bare query
the ctx should be QueryCtx
for both. QueryCtx
will be defined for your data model (it's GenericQueryCtx<DataModel> imported from your _generated folder)
- Optimization: I'd suggest wrapping query
in something that looks up the customer if you want this. You could look up user, person, roles, and permission without knowing what the table is, by the looks of it. Then you can avoid doing all this work per-document.
- I'm working on some helpers to make composing wrappers hopefully easier - if you are interested I can share something early once I have it, to see how it works for you.
I'm also thinking of making a new API for RLS like:
For actions read
, create
, update
, delete
, to make it easier to combine rules (e.g. the same rule for update & delete).
One of oldDoc and newDoc will be null if it's not an update.
Just a sketch. or {doc: Doc, updated?: Doc, action: 'read' | 'create' | 'update' | 'delete', }
the current way to compose them is something like:
where withUser
could look up all the things from auth
. there's a stack post on withUser
if that doesn't make sensethank you for the detailed writeup. im still digesting this.
if i were to the following, there's an incompatible type for the getManyFrom
im trying to do something along the lines of, "certain employees who have the "customer" permission, can view the customer db"
which means i'll need to look up the "user" (employee) and do a bunch of checks wrt to the roles and the permissions table. hence, i need the
GenericQueryCtx
can u pls elaborate on the following?
Optimization: I'd suggest wrapping query in something that looks up the customer if you want this. You could look up user, person, roles, and permission without knowing what the table is, by the looks of it. Then you can avoid doing all this work per-document.i think that's what im aiming for, as long as i pass in the
GenericQueryCtx
is that the correct understanding?This is the example that does the optimization outside of the rules:
Note that by typing the ctx how you want it in RowLevelSecurity, you don't need to provide the type params. And by using
generateMiddleware
from middlewareUtils
you don't need to do jump through a ton of hoops to provide basic middleware
where you use your code above for the user, person, and roles lookup
for the "never" comment, this implies to me that there isn't a by_personId
index on PERSON_ROLES_JOIN_DB
. I'm thinking of changing that to just require a "personId" index instead: the by_
prefix isn't my favorite, but by_creation_time
is already there...