From 41fe964bcc91552d9bac2fdf719a1e6cbfba2459 Mon Sep 17 00:00:00 2001 From: Franklin Rakotomalala Date: Sun, 13 Oct 2024 11:20:12 +0200 Subject: [PATCH 1/9] docs: add alternative ways to write a policy --- documentation/topics/security/policies.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/documentation/topics/security/policies.md b/documentation/topics/security/policies.md index b872f25ea..3582f1b79 100644 --- a/documentation/topics/security/policies.md +++ b/documentation/topics/security/policies.md @@ -54,6 +54,27 @@ There are four check types, all of which do what they sound like they do: If a single check does not explicitly authorize or forbid the whole policy, then the flow moves to the next check. For example, if an `authorize_if` check does NOT return true, this _does not mean the whole policy is forbidden_ - it means that further checking is required. +### Alternative Ways To Write a Policy + +#### Policy with keyword list + +```elixir +policies do + policy always(), authorize_if: always() +end +``` + +#### Policy with `condition` inside `do` block + +```elixir +policies do + policy do + condition always() + authorize_if always() + end +end +``` + ### How a Decision is Reached **Not every check in a policy must pass!** This is described above, but is very important so another example is provided here. Checks go from top to bottom, are evaluated independently of each other, and _the first one that reaches a decision_ determines the overall _policy result_. For example: From 0f324fc23de05dbe043192e38b7ca6e2d9625efc Mon Sep 17 00:00:00 2001 From: Franklin Rakotomalala Date: Sun, 13 Oct 2024 11:28:29 +0200 Subject: [PATCH 2/9] chore: add condition/1 from policy --- .formatter.exs | 1 + 1 file changed, 1 insertion(+) diff --git a/.formatter.exs b/.formatter.exs index 185154bb7..c90fd5706 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -52,6 +52,7 @@ spark_locals_without_parens = [ count: 2, count: 3, countable: 1, + condition: 1, create: 1, create: 2, create_timestamp: 1, From 49702669cec2993c4973c540f7988f5260a03843 Mon Sep 17 00:00:00 2001 From: Franklin Rakotomalala Date: Sun, 13 Oct 2024 11:43:45 +0200 Subject: [PATCH 3/9] docs: add example of policy with multiple conditions --- documentation/topics/security/policies.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/documentation/topics/security/policies.md b/documentation/topics/security/policies.md index 3582f1b79..f16185f56 100644 --- a/documentation/topics/security/policies.md +++ b/documentation/topics/security/policies.md @@ -22,7 +22,7 @@ Then you can start defining policies for your resource. Each policy defined in a resource has two parts - -- a condition, such as `action_type(:read)` or `actor_attribute_equals(:admin, true)` or `always()`. If this condition is true for a given action request, then the policy will be applied to the request. +- a condition or a list of conditions, such as `action_type(:read)` or `actor_attribute_equals(:admin, true)` or `always()`. If this condition is true for a given action request, then the policy will be applied to the request. - a set of policy checks, each of which will be evaluated individually if a policy applies to a request. If more than one policy applies to any given request (eg. an admin actor calls a read action) then **all applicable policies must pass** for the action to be performed. @@ -75,6 +75,16 @@ policies do end ``` +#### Policy with multiple conditions + +```elixir +policies do + policy [condition1, condition2, condition3] do + authorize_if always() + end +end +``` + ### How a Decision is Reached **Not every check in a policy must pass!** This is described above, but is very important so another example is provided here. Checks go from top to bottom, are evaluated independently of each other, and _the first one that reaches a decision_ determines the overall _policy result_. For example: From e525cd4d523986b292fa02b695d2fdff21df505d Mon Sep 17 00:00:00 2001 From: aifrak Date: Sun, 13 Oct 2024 12:04:47 +0200 Subject: [PATCH 4/9] chore: remove condition/1 --- .formatter.exs | 1 - 1 file changed, 1 deletion(-) diff --git a/.formatter.exs b/.formatter.exs index c90fd5706..185154bb7 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -52,7 +52,6 @@ spark_locals_without_parens = [ count: 2, count: 3, countable: 1, - condition: 1, create: 1, create: 2, create_timestamp: 1, From 9af501a013a5ee9d0fafbfd0a2081b0ddacaec10 Mon Sep 17 00:00:00 2001 From: aifrak Date: Sun, 13 Oct 2024 12:06:26 +0200 Subject: [PATCH 5/9] docs: use parens for condition --- documentation/topics/security/policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/topics/security/policies.md b/documentation/topics/security/policies.md index f16185f56..009fcfbe9 100644 --- a/documentation/topics/security/policies.md +++ b/documentation/topics/security/policies.md @@ -69,7 +69,7 @@ end ```elixir policies do policy do - condition always() + condition(always()) authorize_if always() end end From 03b2a5adb2ff8f0321079758b853d8da52ead17f Mon Sep 17 00:00:00 2001 From: Franklin Rakotomalala Date: Sun, 13 Oct 2024 22:05:35 +0200 Subject: [PATCH 6/9] docs: explain better about list of conditions Co-authored-by: Zach Daniel --- documentation/topics/security/policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/topics/security/policies.md b/documentation/topics/security/policies.md index 009fcfbe9..c04c182a9 100644 --- a/documentation/topics/security/policies.md +++ b/documentation/topics/security/policies.md @@ -22,7 +22,7 @@ Then you can start defining policies for your resource. Each policy defined in a resource has two parts - -- a condition or a list of conditions, such as `action_type(:read)` or `actor_attribute_equals(:admin, true)` or `always()`. If this condition is true for a given action request, then the policy will be applied to the request. +- a condition or a list of conditions, such as `action_type(:read)`, `[action_type(:read), actor_attribute_equals(:admin, true)]` or `always()`. If the condition, or all conditions if given a list are true for a given action request, then the policy will be applied to the request. - a set of policy checks, each of which will be evaluated individually if a policy applies to a request. If more than one policy applies to any given request (eg. an admin actor calls a read action) then **all applicable policies must pass** for the action to be performed. From 62557419400941590b4ba2367ed9b73d6ee72847 Mon Sep 17 00:00:00 2001 From: Franklin Rakotomalala Date: Sun, 13 Oct 2024 22:23:32 +0200 Subject: [PATCH 7/9] docs: explain policy with condition inside do block --- documentation/topics/security/policies.md | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/documentation/topics/security/policies.md b/documentation/topics/security/policies.md index c04c182a9..78da23e44 100644 --- a/documentation/topics/security/policies.md +++ b/documentation/topics/security/policies.md @@ -54,17 +54,11 @@ There are four check types, all of which do what they sound like they do: If a single check does not explicitly authorize or forbid the whole policy, then the flow moves to the next check. For example, if an `authorize_if` check does NOT return true, this _does not mean the whole policy is forbidden_ - it means that further checking is required. -### Alternative Ways To Write a Policy +### Policy with `condition` inside `do` block -#### Policy with keyword list +A condition or a list of conditions can also be moved inside the `policy` block. -```elixir -policies do - policy always(), authorize_if: always() -end -``` - -#### Policy with `condition` inside `do` block +This way can make a really long list of conditions easier to read. ```elixir policies do @@ -75,16 +69,6 @@ policies do end ``` -#### Policy with multiple conditions - -```elixir -policies do - policy [condition1, condition2, condition3] do - authorize_if always() - end -end -``` - ### How a Decision is Reached **Not every check in a policy must pass!** This is described above, but is very important so another example is provided here. Checks go from top to bottom, are evaluated independently of each other, and _the first one that reaches a decision_ determines the overall _policy result_. For example: From abdd3be70fbb41d9258ff211683ba3750ec5f583 Mon Sep 17 00:00:00 2001 From: Franklin Rakotomalala Date: Sun, 13 Oct 2024 22:26:10 +0200 Subject: [PATCH 8/9] docs: remove parens for condition --- documentation/topics/security/policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/topics/security/policies.md b/documentation/topics/security/policies.md index 78da23e44..431ab7682 100644 --- a/documentation/topics/security/policies.md +++ b/documentation/topics/security/policies.md @@ -63,7 +63,7 @@ This way can make a really long list of conditions easier to read. ```elixir policies do policy do - condition(always()) + condition always() authorize_if always() end end From ad97d875cb728a8ecde0910fc4ee23c663dfd307 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Sun, 13 Oct 2024 20:11:27 -0400 Subject: [PATCH 9/9] Update documentation/topics/security/policies.md --- documentation/topics/security/policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/topics/security/policies.md b/documentation/topics/security/policies.md index 431ab7682..3988ffb24 100644 --- a/documentation/topics/security/policies.md +++ b/documentation/topics/security/policies.md @@ -58,7 +58,7 @@ If a single check does not explicitly authorize or forbid the whole policy, then A condition or a list of conditions can also be moved inside the `policy` block. -This way can make a really long list of conditions easier to read. +This can make a really long list of conditions easier to read. ```elixir policies do