Packages
ash_authentication
4.4.1
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/info.ex
defmodule AshAuthentication.Info do
@moduledoc """
Generated configuration functions based on a resource's DSL configuration.
"""
use Spark.InfoGenerator,
extension: AshAuthentication,
sections: [:authentication]
alias Ash.{Changeset, Domain, Query, Resource}
alias AshAuthentication.Strategy
alias Spark.Dsl.Extension
@type dsl_or_resource :: module | map
@doc """
Retrieve a named strategy from a resource.
"""
@spec strategy(dsl_or_resource | module, atom) :: {:ok, strategy} | :error
when strategy: struct
def strategy(dsl_or_resource, name) do
dsl_or_resource
|> authentication_strategies()
|> Stream.concat(authentication_add_ons(dsl_or_resource))
|> Enum.find_value(:error, fn strategy ->
if Strategy.name(strategy) == name, do: {:ok, strategy}
end)
end
@doc """
Retrieve a named strategy from a resource (raising version).
"""
@spec strategy!(dsl_or_resource | module, atom) :: strategy | no_return
when strategy: struct
def strategy!(dsl_or_resource, name) do
case strategy(dsl_or_resource, name) do
{:ok, strategy} ->
strategy
:error ->
raise "No strategy named `#{inspect(name)}` found on resource `#{inspect(dsl_or_resource)}`"
end
end
@doc """
Given an action name, retrieve the strategy it is for from the DSL
configuration.
"""
@spec strategy_for_action(dsl_or_resource, atom) :: {:ok, Strategy.t()} | :error
def strategy_for_action(dsl_or_resource, action_name) do
case Extension.get_persisted(dsl_or_resource, {:authentication_action, action_name}) do
nil -> :error
value -> {:ok, value}
end
end
@doc """
Given an action name, retrieve the strategy it is for from the DSL
configuration.
"""
@spec strategy_for_action!(dsl_or_resource, atom) :: Strategy.t() | no_return
def strategy_for_action!(dsl_or_resource, action_name) do
case strategy_for_action(dsl_or_resource, action_name) do
{:ok, value} ->
value
:error ->
raise "No strategy action named `#{inspect(action_name)}` found on resource `#{inspect(dsl_or_resource)}`"
end
end
@doc """
Find the underlying strategy that required a change/preparation to be used.
This is because the `strategy_name` can be passed on the change options, eg:
```elixir
change {AshAuthentication.Strategy.Password.HashPasswordChange, strategy_name: :banana_custard}
```
Or via the action context, eg:
```elixir
prepare set_context(%{strategy_name: :banana_custard})
prepare AshAuthentication.Strategy.Password.SignInPreparation
```
Or via the passed-in context on calling the action.
"""
@spec find_strategy(Query.t() | Changeset.t(), context, options) :: {:ok, Strategy.t()} | :error
when context: map, options: Keyword.t()
def find_strategy(queryset, context \\ %{}, options) do
with :error <- Keyword.fetch(options, :strategy_name),
:error <- Map.fetch(context, :strategy_name),
:error <- Map.fetch(queryset.context, :strategy_name),
:error <- strategy_for_action(queryset.resource, queryset.action.name) do
:error
else
{:ok, strategy_name} when is_atom(strategy_name) ->
strategy(queryset.resource, strategy_name)
{:ok, strategy} ->
{:ok, strategy}
end
end
@doc """
Retrieve the domain to use for authentication.
If the `authentication.domain` DSL option is set, it will be used, otherwise
it will default to that configured on the resource.
"""
@spec domain(dsl_or_resource) :: {:ok, Domain.t()} | :error
def domain(dsl_or_resource) do
auth_domain =
case authentication_domain(dsl_or_resource) do
{:ok, value} -> value
:error -> nil
end
resource_domain = Resource.Info.domain(dsl_or_resource)
domain = auth_domain || resource_domain
if domain, do: {:ok, domain}, else: :error
end
@doc "Raising version of `domain/1`"
def domain!(dsl_or_resource) do
case domain(dsl_or_resource) do
{:ok, value} -> value
:error -> raise "No `domain` configured on resource `#{inspect(dsl_or_resource)}`"
end
end
end