mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 13:33:20 +12:00
improvement: add more authorizer state management
Added more opportunities for authorizers to pass back state. This is being used to ensure that ash policy authorizer errors can always have enough information to provide a policy breakdown
This commit is contained in:
parent
6b95dec339
commit
ce3ae44a4c
3 changed files with 37 additions and 9 deletions
|
@ -36,7 +36,11 @@ defmodule Ash.Authorizer do
|
|||
if function_exported?(module, :exception, 2) do
|
||||
module.exception(reason, state)
|
||||
else
|
||||
Ash.Error.Forbidden.exception([])
|
||||
if reason == :must_pass_strict_check do
|
||||
Ash.Error.Forbidden.MustPassStrictCheck.exception([])
|
||||
else
|
||||
Ash.Error.Forbidden.exception([])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ defmodule Ash.Engine.Request do
|
|||
@type t :: %__MODULE__{}
|
||||
|
||||
alias Ash.Authorizer
|
||||
alias Ash.Error.Forbidden.MustPassStrictCheck
|
||||
alias Ash.Error.Invalid.{DuplicatedPath, ImpossiblePath}
|
||||
|
||||
require Ash.Query
|
||||
|
@ -504,6 +503,21 @@ defmodule Ash.Engine.Request do
|
|||
:authorized ->
|
||||
{:ok, set_authorizer_state(request, authorizer, :authorized), notifications, []}
|
||||
|
||||
{:filter, authorizer_state, filter} ->
|
||||
request
|
||||
|> set_authorizer_state(authorizer, authorizer_state)
|
||||
|> apply_filter(authorizer, filter, true)
|
||||
|> case do
|
||||
{:ok, request} ->
|
||||
{:ok, request, notifications, []}
|
||||
|
||||
{:ok, request, new_notifications, deps} ->
|
||||
{:ok, request, new_notifications ++ notifications, deps}
|
||||
|
||||
other ->
|
||||
other
|
||||
end
|
||||
|
||||
{:filter, filter} ->
|
||||
request
|
||||
|> apply_filter(authorizer, filter, true)
|
||||
|
@ -518,8 +532,13 @@ defmodule Ash.Engine.Request do
|
|||
other
|
||||
end
|
||||
|
||||
{:filter_and_continue, _, _} when strict_check_only? ->
|
||||
{:error, MustPassStrictCheck.exception(resource: request.resource)}
|
||||
{:filter_and_continue, _, authorizer_state} when strict_check_only? ->
|
||||
{:error,
|
||||
Authorizer.exception(
|
||||
authorizer,
|
||||
:must_pass_strict_check,
|
||||
authorizer_state
|
||||
)}
|
||||
|
||||
{:filter_and_continue, filter, new_authorizer_state} ->
|
||||
request
|
||||
|
@ -536,8 +555,13 @@ defmodule Ash.Engine.Request do
|
|||
other
|
||||
end
|
||||
|
||||
{:continue, _} when strict_check_only? ->
|
||||
{:error, MustPassStrictCheck.exception(resource: request.resource)}
|
||||
{:continue, authorizer_state} when strict_check_only? ->
|
||||
{:error,
|
||||
Authorizer.exception(
|
||||
authorizer,
|
||||
:must_pass_strict_check,
|
||||
authorizer_state
|
||||
)}
|
||||
|
||||
{:continue, authorizer_state} ->
|
||||
{:ok, set_authorizer_state(request, authorizer, authorizer_state), notifications, []}
|
||||
|
|
|
@ -2,15 +2,15 @@ defmodule Ash.Error.Forbidden.MustPassStrictCheck do
|
|||
@moduledoc "Used when unreachable code/conditions are reached in the framework"
|
||||
use Ash.Error.Exception
|
||||
|
||||
def_ash_error([:resource], class: :forbidden)
|
||||
def_ash_error([], class: :forbidden)
|
||||
|
||||
defimpl Ash.ErrorKind do
|
||||
def id(_), do: Ash.UUID.generate()
|
||||
|
||||
def code(_), do: "must_pass_strict_check"
|
||||
|
||||
def message(%{resource: resource}) do
|
||||
"A request against #{inspect(resource)} was required to pass strict check, but it did not"
|
||||
def message(_) do
|
||||
"The request was required to pass strict check, but it did not"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue