Building can? function that supports filter checks
I am looking to build out a custom GQL query that allows my front-end to ask the backend whether it has permissions to do an action on a resource instance. I have already built this out to a resource level to the extent that the front-end can ask: "Can I perform this action on this resource type".
Next up, I want to support asking "can I perform this action on this particular resource with ID = x". @frankdugan3 already added some
can
functions, which I am using in the above scenario. However I will need extra functionality so that in addition, the filter checks are taken into account. The reason is that some of my action policies use relates_to_actor_via. For the reads I suppose I could actually perform the read and use the result. However for :update there are also filter checks and I can't use that strategy.
Any thoughts on how best to approach this? I have started looking into it however quickly got lost in the engine / request modules.11 Replies
Hey there! So I have something on my list to make this kind of thing work too, but it will take a bit of elbow grease potentially.
Hey Zach! Sounds intriguing :thinkies:
GitHub
ash/info.ex at main · ash-project/ash
A declarative and extensible framework for building Elixir applications. - ash/info.ex at main · ash-project/ash
So the essential gist is going to be getting the
{:filter
back, and then running a query with that filter to see if we get the record that we're attempting to update.
For creates that won't really work
but for updates/destroys, it will
I think thats the main avenue we need to pursueCreates I am not too concerned about, I think creates should always use simple checks. How would the above strategy work for updates?
What you'd do is run the filter, combined with a filter on the id of the current record you're trying to update
if you get the record back, then it will be allowed
if you don't then it won't
Oh yeah, that makes sense. Thanks!
Same can work for
destroy
😄With your guidance I was able to get this working 🥳
I'm not confident it's ready for integration into ash core, so i'll post it here in case anyone else finds it useful: https://gist.github.com/ahey/61238fdc367175589fa90431318705c9
@Zach Daniel while developing this, I found that the following code (https://github.com/ash-project/ash/blob/main/lib/ash/policy/info.ex#L36) was preventing this call (https://github.com/ash-project/ash/blob/main/lib/ash/policy/info.ex#L44) from ever returning
{:filter
. Once i change pre_flight_authorization?
to false
it started working, however i'm not sure why :thinkies:Interesting…I think inside of filter check if preflight authorization is being run and we attach a filter we may not be returning the filter?
Hey @Alan Heywood I've added a version of this built into core now. The latest version has
YourApi.can?
and YourApi.can
Wonderful! I'll see if I can swap over to it from my implementation. Thanks Zach 🤩
The new
can?
function is great. I was able to swap it out with my implementation and all tests are passing. It does everything I would want it to do and more. Thanks again @Zach Daniel 😄