Having some trouble with a custom policy

Hi! I'm using a custom policy like this:
policy action(:request_generation) do
forbid_unless Scribble.Checks.ActorIsPayingOrTrialing
end
policy action(:request_generation) do
forbid_unless Scribble.Checks.ActorIsPayingOrTrialing
end
and then I have:
defmodule Scribble.Checks.ActorIsPayingOrTrialing do
use Ash.Policy.SimpleCheck
require Logger

def describe(_) do
"actor is paying or trialing"
end

def match?(%Scribble.EmailHandler.User{} = user, _context, _options) do
Logger.error("\n\n\n============================CHECKING\n\n\n")
IO.puts("======")
IO.inspect(user)
# Scribble.EmailHandler.User.is_paying_or_trialing!(user)
true
end

def match?(_, _, _) do
Logger.error("===========WHAT IS THIS")
true
end
end
defmodule Scribble.Checks.ActorIsPayingOrTrialing do
use Ash.Policy.SimpleCheck
require Logger

def describe(_) do
"actor is paying or trialing"
end

def match?(%Scribble.EmailHandler.User{} = user, _context, _options) do
Logger.error("\n\n\n============================CHECKING\n\n\n")
IO.puts("======")
IO.inspect(user)
# Scribble.EmailHandler.User.is_paying_or_trialing!(user)
true
end

def match?(_, _, _) do
Logger.error("===========WHAT IS THIS")
true
end
end
However even with this policy with everything set to true, the match? is failing. And my logs aren't showing up. If I delete the policy, it does what I expect (allow even non paying users through). But adding the policy makes it forbid every user
5 Replies
rohan
rohanOP2y ago
Oh nm I figured it out. I thought the policies would "stack" so if I had
policy action_type([:read, :update]) do
authorize_if relates_to_actor_via(:user)
end
policy action_type([:read, :update]) do
authorize_if relates_to_actor_via(:user)
end
then that would also get executed. But it seems like maybe the most specific one gets executed?
ZachDaniel
ZachDaniel2y ago
All policies that apply have to pass The issue is that a forbid_unless being the inly check in a policy has no possibility of passing So the solver didnt bother running the check You’d need to add an authorize_if or an authorize_unless somewhere below it for that to make sense
rohan
rohanOP2y ago
hmm I had this:
policies do
policy action(:request_generation) do
forbid_unless Scribble.Checks.ActorIsPayingOrTrialing
end

policy action_type([:read, :update]) do
authorize_if relates_to_actor_via(:user)
end

policy action_type(:create) do
authorize_if actor_present()
end
end
policies do
policy action(:request_generation) do
forbid_unless Scribble.Checks.ActorIsPayingOrTrialing
end

policy action_type([:read, :update]) do
authorize_if relates_to_actor_via(:user)
end

policy action_type(:create) do
authorize_if actor_present()
end
end
so I was expecting the action policy for request generation to get run, and then the action type policy for update to also get run. But it seems like only one block will run
barnabasj
barnabasj2y ago
All blocks with a matching condition need to return authorized for an action to be alowed. Therefore if the first one already returns :unknown or :forbidden there is no need to check the others. you could add authorize_if always() at the end of your :request_generation block then it would check the next block because the first one would authorize and the other blocks needs to be evaluated because the condition matches
rohan
rohanOP2y ago
ah I see thanks!

Did you find this page helpful?