Validating Permissions
Hi!
A common operation that I'm doing in tRPC is validating that a person has permissions to perform the action they're trying to do, i.e:
Where
assertCanEditServer
is the permissions check. In this instance, I'm taking the ID of the server they're editing and comparing it against a list of server permissions to validate they can edit that server. I'd like to find a better way of doing this instead of just having to repeat a bunch of code with this assertCanEditServer function
Having to put that inside of each router is a bit ugly, but the information to ensure the caller can edit isn't available inside of Context so that's the only place that I can think to put it.
Is this the best approach to this where I just make an assert function at throw that inside of the procedure or is there some better way of doing this? Thanks10 Replies
I've actually done a bit of work on this https://twitter.com/alexdotjs/status/1588205093576675328?t=dd8KODcSmAxA2tElBpfAwg&s=19
Alex / KATT π± (@alexdotjs)
This week I've been working on a declarative isomorphic permission library.
On the backend we create Prisma
WhereInput
s & on the frontend we get rules like this
hopefully will OSS it soonLikes
798
Twitter
But haven't OSS'd it yet
But some stuff to give you places to look or get ideas
- use multiple input parsers (e.g. a base procedure that does auth checks and see that the user is in a specific orgsnizarik if it's a multitenant SaaS thing)
- use metadata to decorate permissions
- have auth resolvers based on the entity
Also, in your prisma queries, you can limit your where statement instead of doing an auth check
Thanks for the reply! Iβll experiment with those methods and see what works best
Limiting it in the Prisma query is an interesting approach although what Iβm using to check is fetching from the Discord API and storing that in memory so I canβt use that approach
i guess most procs will be around a "server" then
so you can do some base proc like this
or maybe something like
I ended up implementing this in a functional way
Still figuring out if this is a way I like or not but so far it seems good - I can take it a step further and make the auth check a functional element as well to have different permission checks
Sample file from the branch I'm working on where this is heavily used
https://github.com/AnswerOverflow/AnswerOverflow/blob/API/packages/api/src/router/channel/channel_settings.ts
GitHub
AnswerOverflow/channel_settings.ts at API Β· AnswerOverflow/AnswerOv...
Index Discord Questions into Google. Contribute to AnswerOverflow/AnswerOverflow development by creating an account on GitHub.
Completely necroposting on this to share how I'm handling permissions now to help others out in the future
Here's two variants
It makes adding / removing permissions from procedures super easy - along with that I'm now just using middlewares for data prep and putting the relevant permissions inside of the procedure itself so that way it's readable as to what permissions are required for the route
Once I get this merged into my main I'll put some links here of code snippets, really happy with this approach for it - still could use some expanding on but for now sticking with this
That work can definitely be pushed up to a middleware and Meta on the procedure used to define what protection level/roles each procedure has
It can be as simple as
Ah which is actually what KATT already suggested now I see it. Definitely do what works for you at the end of the day π
I might be missing something with this but I think with this approach I'm not able to pass in values from the input into it
To give a few examples
For validating permissions when editing a server, I have to check if the user can edit the server id that was passed in from the input
For validating permissions when editing channel settings, i first have to fetch the channel from the database and then check against the server id on that channel if they can edit
From my understanding I can't access input values from anywhere except for the mutation/query which results in putting the validation inside of this
If I could do something like this with dynamically setting meta properties
or
then I'd be able to move this into the meta which would be nice
(cc @Nick Lucas forgot to do that as a reply sorry, no rush on responding)
Makes sense, middlewares do have access to the parsed/validated input I believe, but then your challenge becomes having a middleware which can understand the input type, by convention or configuration.
You might end up with something like this to invert control up to the middleware
Since I haven't built this for my own needs obviously I revert to your expertise, and inverting control to middlewares is definitely my opinion