Ash.Policy.FilterCheck
Are we using this wrong? We have the following policy module:
This is tied to an action:
However, even when the
filter
function inside policy module returns false
(from the []
clause), the policy still authorizes the action. Running DashboardGroup.can_get_groups_for_organization?(current_user, current_organization.id, %{})
returns true
.
Should we be using SimpleCheck
instead?11 Replies
If you're returning statically a value like that then you're essentially writing a simple check anyway. The idea with filter checks is that you can return an expression that will apply some logic to the filter. like
expr(exists(...))
, this helps you write optimal policies
With that said, the reason its returning true
is because thats how policies work for read actions
they filter the query, as opposed to rejecting the request, for security
If the question is "can they read this specific thing", for example, you can supply that thing as the data
option
If you write it as a simple check instead of a filter check, then you can do this:
strict policies on read actions will produce a forbidden result, as opposed to filtering
I was trying to explain this before but I don't think I succeeded, but typically a filter check would do something like this:
If you have everything you need to know without filtering, then you'd do a simple check like this:
Then you can do access_type :strict
Access type is explained here in the docs: https://hexdocs.pm/ash/policies.html#access-typeLot to process. Starting from the top: the question in this case is "should the user be able to fetch groups for the given organization" which is predicated on "are they an admin of that org or any of the parent orgs"
When I changed
use Ash.Policy.FilterCheck
to use Ash.Policy.SimpleCheck
, the organization_members = Ash.Query.filter(OrganizationMember, user_id == ^user_id and role == :admin)
line started giving compilation errorsThats just a quirk I didn't consider.
FilterCheck
has require Ash.Query
implicitlyAh, I see
And I guess I would change
filter
to match?
Yes
SimpleCheck -> "true or false given query/actor"
FilterCheck -> "filter expression given query/actor"
They have the same end result, with one main exception, which is that SimpleCheck can be used with
access_type :strict
on the policy.The
can?
function is still returning true
Ah
strict
let me add thatWith all that said, where you are asking
can_...
you can also do something like data: %Organization{id: id}
to say "do these policy filters return this record"
it owuld be instances of whatever the resource in question isIt worked when I added strict
Right, so now if that action is called w/ an incorrect organization id, it will be forbidden instead of filtered, just keep that in mind
OK. We have two tabs on the page: "My Groups" tab, which runs the
groups_for_educator
action, which is tied to a policy that simply checks authorize_if relates_to_actor_via(:educator)
. We also have an "All Groups" tab, which runs the groups_for_organization
action, which is tied to this policy above, i.e. they need to be an admin of the org to be able to fetch all groups in that org
I think the way I've set it up is correct now - I don't want a filter, because that would filter the results. So simple/strict make senseMakes sense 👍 We default to filtering as it has the least potential to expose internal information, but there are plenty of cases where you'd want
:strict