moxley

moxley

Proper way to build "OR" expression in policy involving actor()

I’m getting an unexpected policy access failure.

Here’s the policy:

policies
  policy action :read do
    authorize_if expr(is_public == true or ^actor(:active) == true)
  end
end

When I read the resource like this:

{:ok, _event} = Ash.get(GF.Events.Event2, event.id)

It fails with this policy breakdown:

15:13:00.150 [warning] GF.Events.Event2.read

Policy Breakdown
unknown actor

  Policy | 🔎:

    condition: action == :read

    authorize if: (is_public == true) or (nil == true) | ✘ | 🔎

SAT Solver statement: 

 "action == :read" and
  (("action == :read" and "(is_public == true) or ({:_actor, :active} == true)") or
     not "action == :read")

But when I remove the part of the policy expression after the or, it passes:

authorize_if expr(is_public == true)

I would expect that if expr(is_public == true) passes, then, expr(is_public == true or any_valid_expression) should also pass.

I also tried these variations:

  1. Passing an actor that has the attribute active: true. This passes, as expected.
  2. Passing an actor that has the attribute active: false. This passes, as expected.

It seems that the ^actor(:active) is being evaluated, affecting the boolean expression, even though the first part of the expression should have short-circuited the second.

I saw the “unknown actor” in the policy breakdown, but I’m not sure what to do about it.

How do I solve this?

Marked As Solved

zachdaniel

zachdaniel

Creator of Ash

The way that checks that reference the actor work is that they always are false if there is no actor, regardless of the statement.

This is to prevent you from having a check like is_nil(^actor(:disabled_at)) pass for a non-logged in user and accidentally having a security hole.

The nil == true is, in this case, misleading in the way that it is displayed. When describing filter checks we do it by putting the filter into a string, but what would be more accurate is to put in something like “there is an actor and …”.

If you could open an issue in ash showing the DX issue w/ how we’re displaying this in breakdowns, that would be great. What we can do in reality is replace that whole expression with something like "false (actor required for filter)" or something, because we know already that it won’t pass.

For solving the issue, the following syntax is equivalent to your policy and does not have the same problem:

policy action(:read) do
  authorize_if expr(is_public == true)
  authorize_if expr(^actor(:active) == true)
end

Also Liked

zachdaniel

zachdaniel

Creator of Ash

Yep! Policy checks apply top-to-bottom as if it were a script (although it is not executed as such under the hood).

The first check that produces a result of :authorized or :forbidden determines the result of the overall policy.

i.e authorize_if always() produces :authorized and authorize_if never() produces :unknown, meaning we continue to the next check.

To do and you can use an expression with and, and you can also do things like:

policy action(:read) do
  forbid_unless expr(not(something))
  authorize_if expr(something_else)
end

Don’t use the forbid_unless version here, just highlighting tools that may be useful further down the line.

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 41989 114
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39467 209
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

We're in Beta

About us Mission Statement