Allow setting policy condition inside policy code block

Sometimes, a policy condition can be very long, making the code ugly when formatted and hard to follow, for example:

    policy [
      action([
        :action_1,
        :action_2,
        :action_3,
        :action_4,
        :action_5,
        :action_6,
        :action_7,
        :action_8,
        :action_9,
        :action_10
      ]),
      expr(field = "bla"),
      expr(some_other_field = :admin)
    ] do
      authorize_if Check1
      forbid_if Check2
      authorize_if Check3
      authorize_if Check4
    end

Can’t we allow the policy condition to be defined inside the policy code block in these cases to make things easier?

Example:

    policy do
      condition [
        action([
          :action_1,
          :action_2,
          :action_3,
          :action_4,
          :action_5,
          :action_6,
          :action_7,
          :action_8,
          :action_9,
          :action_10
        ]),
        expr(field = "bla"),
        expr(some_other_field = :admin)
      ]

      authorize_if Check1
      forbid_if Check2
      authorize_if Check3
      authorize_if Check4
    end

or how I personally would write this:

    policy do
      @actions [
        :action_1,
        :action_2,
        :action_3,
        :action_4,
        :action_5,
        :action_6,
        :action_7,
        :action_8,
        :action_9,
        :action_10
      ]

      condition([action(@actions), expr(field = "bla"), expr(some_other_field = :admin)])

      authorize_if(Check1)
      forbid_if(Check2)
      authorize_if(Check3)
      authorize_if(Check4)
    end

This would work similarly to how a calculate call accepts a calculationcall inside the code block too.

Random ideas for prettification:

  • If you want to use a module attribute, you could move the actions outside the policy macro.

  • Use an atom wordlist to save space (whitespace formatting is totally up to you):

~w(action_1 action2
   action_3 action4)a

That’s normally what I do, but unless that module attribute is used in more than one policy, I would prefer to keep it inside the policy itself since it will be scoped for that policy only, allowing me to do something like this:

policies do
  policy do
    @actions ~w(action_1 action_2 action_3 action_4)a

    condition [action(@actions)]
    authorize_if ...
  end

  policy do
    @actions ~w(action_5 action_6 action_7)a

    condition [action(@actions)]
    authorize_if ...
  end
end

Which is cleaner IMO

1 Like

I’ve pushed something to main which will be in the next release. It allows specifying conditions inside the policy block like you described @sezaru

1 Like

Worked perfectly! Thanks a lot!