Packages
ash_authentication
4.13.7
5.0.0-rc.12
5.0.0-rc.11
5.0.0-rc.10
5.0.0-rc.9
5.0.0-rc.8
5.0.0-rc.7
5.0.0-rc.6
5.0.0-rc.5
5.0.0-rc.4
5.0.0-rc.3
5.0.0-rc.2
5.0.0-rc.1
5.0.0-rc.0
4.14.1
4.14.0
4.13.7
4.13.6
4.13.5
4.13.4
4.13.3
4.13.2
retired
4.13.1
retired
4.13.0
4.12.0
4.11.0
4.10.0
4.9.9
4.9.8
4.9.7
4.9.6
4.9.5
4.9.4
4.9.3
4.9.2
4.9.1
4.9.0
4.8.7
4.8.6
4.8.5
4.8.3
4.8.2
4.8.1
4.8.0
4.7.6
4.7.5
4.7.4
4.7.3
4.7.2
4.7.1
4.7.0
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.6
4.5.5
4.5.4
4.5.3
4.5.2
4.5.1
4.5.0
4.4.9
4.4.8
4.4.7
4.4.6
4.4.5
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.3.12
4.3.11
4.3.10
4.3.9
4.3.8
4.3.7
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.7
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.4
4.0.3
4.0.2
4.0.1
4.0.0
4.0.0-rc.6
4.0.0-rc.5
4.0.0-rc.3
4.0.0-rc.2
4.0.0-rc.1
4.0.0-rc.0
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.16
3.11.15
3.11.14
3.11.13
3.11.12
3.11.11
3.11.10
3.11.9
3.11.8
3.11.7
3.11.6
3.11.5
3.11.4
3.11.3
3.11.2
3.11.1
3.11.0
3.10.8
3.10.7
3.10.6
3.10.5
3.10.4
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.0
3.7.9
3.7.8
3.7.6
3.7.5
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
3.6.1
3.6.0
3.5.3
3.5.2
3.5.1
3.5.0
3.3.1
3.3.0
3.2.2
3.2.1
3.2.0
3.1.0
3.0.3
Authentication extension for the Ash Framework.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/ash_authentication/strategies/custom/transformer.ex
# SPDX-FileCopyrightText: 2022 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.Strategy.Custom.Transformer do
@moduledoc """
Transformer used by custom strategies.
It delegates transformation passes to the individual strategies.
"""
use Spark.Dsl.Transformer
alias AshAuthentication.{Info, Strategy}
alias Spark.{Dsl.Transformer, Error.DslError}
import AshAuthentication.Strategy.Custom.Helpers
@doc false
@impl true
@spec after?(module) :: boolean
def after?(AshAuthentication.Transformer), do: true
def after?(_), do: false
@doc false
@impl true
@spec before?(module) :: boolean
def before?(Resource.Transformers.DefaultAccept), do: true
def before?(_), do: false
@doc false
@impl true
@spec transform(map) ::
:ok
| {:ok, map()}
| {:error, term()}
| {:warn, map(), String.t() | [String.t()]}
| :halt
def transform(dsl_state) do
with {:ok, dsl_state} <- do_strategy_transforms(dsl_state) do
do_add_on_transforms(dsl_state)
end
end
defp do_strategy_transforms(dsl_state) do
dsl_state
|> Info.authentication_strategies()
|> Enum.reduce_while({:ok, dsl_state}, fn strategy, {:ok, dsl_state} ->
case do_transform(strategy, dsl_state, :strategy) do
{:ok, dsl_state} -> {:cont, {:ok, dsl_state}}
{:error, reason} -> {:halt, {:error, reason}}
end
end)
end
defp do_add_on_transforms(dsl_state) do
dsl_state
|> Info.authentication_add_ons()
|> Enum.reduce_while({:ok, dsl_state}, fn strategy, {:ok, dsl_state} ->
case do_transform(strategy, dsl_state, :add_on) do
{:ok, dsl_state} -> {:cont, {:ok, dsl_state}}
{:error, reason} -> {:halt, {:error, reason}}
end
end)
end
defp do_transform(strategy, _, _) when not is_map_key(strategy, :resource) do
name = Strategy.name(strategy)
{:error,
DslError.exception(
path: [:authentication, name],
message:
"The struct defined by `#{inspect(strategy.__struct__)}` must contain a `resource` field."
)}
end
defp do_transform(strategy, dsl_state, :strategy) do
strategy = %{strategy | resource: Transformer.get_persisted(dsl_state, :module)}
dsl_state = put_strategy(dsl_state, strategy)
entity_module = strategy.__struct__
strategy_module = strategy_module(strategy)
strategy
|> strategy_module.transform(dsl_state)
|> case do
{:ok, strategy} when is_struct(strategy, entity_module) ->
{:ok, put_strategy(dsl_state, strategy)}
{:ok, dsl_state} when is_map(dsl_state) ->
{:ok, dsl_state}
{:error, reason} ->
{:error, reason}
end
end
defp do_transform(strategy, dsl_state, :add_on) do
strategy = %{strategy | resource: Transformer.get_persisted(dsl_state, :module)}
dsl_state = put_add_on(dsl_state, strategy)
entity_module = strategy.__struct__
strategy_module = strategy_module(strategy)
strategy
|> strategy_module.transform(dsl_state)
|> case do
{:ok, strategy} when is_struct(strategy, entity_module) ->
{:ok, put_add_on(dsl_state, strategy)}
{:ok, dsl_state} when is_map(dsl_state) ->
{:ok, dsl_state}
{:error, reason} ->
{:error, reason}
end
end
# This is needed by some strategies which re-use another strategy's entity (ie everything based on oauth2).
defp strategy_module(strategy) when is_nil(strategy.strategy_module), do: strategy.__struct__
defp strategy_module(strategy) when is_atom(strategy.strategy_module),
do: strategy.strategy_module
defp strategy_module(strategy), do: strategy.__struct__
end