Packages
ash_authentication
3.6.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/password/actions.ex
defmodule AshAuthentication.Strategy.Password.Actions do
@moduledoc """
Actions for the password strategy
Provides the code interface for working with resources via a password
strategy.
"""
alias Ash.{Changeset, Error.Invalid.NoSuchAction, Query, Resource}
alias AshAuthentication.{Errors, Info, Jwt, Strategy.Password}
@doc """
Attempt to sign in a user.
"""
@spec sign_in(Password.t(), map, keyword) ::
{:ok, Resource.record()} | {:error, Errors.AuthenticationFailed.t()}
def sign_in(%Password{} = strategy, params, options) do
api = Info.authentication_api!(strategy.resource)
strategy.resource
|> Query.new()
|> Query.set_context(%{
private: %{
ash_authentication?: true
}
})
|> Query.for_read(strategy.sign_in_action_name, params)
|> api.read(options)
|> case do
{:ok, [user]} -> {:ok, user}
_ -> {:error, Errors.AuthenticationFailed.exception([])}
end
end
@doc """
Attempt to register a new user.
"""
@spec register(Password.t(), map, keyword) :: {:ok, Resource.record()} | {:error, any}
def register(%Password{} = strategy, params, options) do
api = Info.authentication_api!(strategy.resource)
strategy.resource
|> Changeset.new()
|> Changeset.set_context(%{
private: %{
ash_authentication?: true
}
})
|> Changeset.for_create(strategy.register_action_name, params)
|> api.create(options)
end
@doc """
Request a password reset.
"""
@spec reset_request(Password.t(), map, keyword) :: :ok | {:error, any}
def reset_request(
%Password{resettable: [%Password.Resettable{} = resettable]} = strategy,
params,
options
) do
api = Info.authentication_api!(strategy.resource)
strategy.resource
|> Query.new()
|> Query.set_context(%{
private: %{
ash_authentication?: true
}
})
|> Query.for_read(resettable.request_password_reset_action_name, params)
|> api.read(options)
|> case do
{:ok, _} -> :ok
{:error, reason} -> {:error, reason}
end
end
def reset_request(%Password{} = strategy, _params, _options),
do:
{:error,
NoSuchAction.exception(resource: strategy.resource, action: :reset_request, type: :read)}
@doc """
Attempt to change a user's password using a reset token.
"""
@spec reset(Password.t(), map, keyword) :: {:ok, Resource.record()} | {:error, any}
def reset(
%Password{resettable: [%Password.Resettable{} = resettable]} = strategy,
params,
options
) do
with {:ok, token} <- Map.fetch(params, "reset_token"),
{:ok, %{"sub" => subject}, resource} <- Jwt.verify(token, strategy.resource),
{:ok, user} <- AshAuthentication.subject_to_user(subject, resource) do
api = Info.authentication_api!(resource)
user
|> Changeset.new()
|> Changeset.set_context(%{
private: %{
ash_authentication?: true
}
})
|> Changeset.for_update(resettable.password_reset_action_name, params)
|> api.update(options)
else
{:error, %Changeset{} = changeset} -> {:error, changeset}
_ -> {:error, Errors.InvalidToken.exception(type: :reset)}
end
end
def reset(%Password{} = strategy, _params, _options),
do: {:error, NoSuchAction.exception(resource: strategy.resource, action: :reset, type: :read)}
end