Packages
ash_authentication
5.0.0-rc.0
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/magic_link/request_preparation.ex
# SPDX-FileCopyrightText: 2022 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.Strategy.MagicLink.RequestPreparation do
@moduledoc """
Prepare a query for a magic link request.
This preparation performs three jobs, one before the query executes and two
after:
1. it constraints the query to match the identity field passed to the action.
2. if there is a user returned by the query, then
a. generate a magic link token and
b. publish a notification.
Always returns an empty result.
"""
use Ash.Resource.Preparation
alias Ash.{Query, Resource.Preparation}
alias AshAuthentication.{Errors.SenderFailed, Info, Strategy.MagicLink}
require Ash.Query
@doc false
@impl true
@spec prepare(Query.t(), keyword, Preparation.Context.t()) :: Query.t()
def prepare(query, _opts, context) do
strategy = Info.strategy_for_action!(query.resource, query.action.name)
identity_field = strategy.identity_field
identity = Query.get_argument(query, identity_field)
select_for_senders = Info.authentication_select_for_senders!(query.resource)
if is_nil(identity) do
Query.filter(query, false)
else
Query.filter(query, ^ref(identity_field) == ^identity)
end
|> Query.before_action(fn query ->
query
|> Ash.Query.ensure_selected(select_for_senders)
|> Ash.Query.ensure_selected([identity_field])
end)
|> Query.after_action(&after_action(&1, &2, strategy, identity, context))
end
defp after_action(_query, [user], %{sender: {sender, send_opts}} = strategy, _identity, context) do
context_opts = Ash.Context.to_opts(context)
with {:ok, token} <- MagicLink.request_token_for(strategy, user, context_opts, context),
:ok <- sender.send(user, token, Keyword.put(send_opts, :tenant, context.tenant)) do
{:ok, []}
else
{:error, reason} when not is_struct(reason) ->
{:error, SenderFailed.exception(sender: sender, reason: reason, strategy: strategy.name)}
{:error, _} = error ->
error
_ ->
{:ok, []}
end
end
defp after_action(
_query,
_,
%{registration_enabled?: true, sender: {sender, send_opts}} = strategy,
identity,
context
)
when not is_nil(identity) do
context_opts = Ash.Context.to_opts(context)
with {:ok, token} <-
MagicLink.request_token_for_identity(strategy, identity, context_opts, context),
:ok <-
sender.send(
to_string(identity),
token,
Keyword.put(send_opts, :tenant, context.tenant)
) do
{:ok, []}
else
{:error, reason} when not is_struct(reason) ->
{:error, SenderFailed.exception(sender: sender, reason: reason, strategy: strategy.name)}
{:error, _} = error ->
error
_ ->
{:ok, []}
end
end
defp after_action(_, _, _, _, _) do
{:ok, []}
end
end