2018-07-04 14:29:17 +02:00
|
|
|
defmodule Eventos.Actors.Service.ResetPassword do
|
|
|
|
@moduledoc false
|
|
|
|
|
|
|
|
require Logger
|
|
|
|
|
|
|
|
alias Eventos.{Mailer, Repo, Actors.User}
|
|
|
|
alias Eventos.Email.User, as: UserEmail
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Check that the provided token is correct and update provided password
|
|
|
|
"""
|
2018-07-27 10:45:35 +02:00
|
|
|
@spec check_reset_password_token(String.t(), String.t()) :: tuple
|
2018-07-04 14:29:17 +02:00
|
|
|
def check_reset_password_token(password, token) do
|
2018-08-24 11:34:00 +02:00
|
|
|
with %User{} = user <- Repo.get_by(User, reset_password_token: token),
|
|
|
|
{:ok, %User{} = user} <-
|
|
|
|
Repo.update(
|
|
|
|
User.password_reset_changeset(user, %{
|
|
|
|
"password" => password,
|
|
|
|
"reset_password_sent_at" => nil,
|
|
|
|
"reset_password_token" => nil
|
|
|
|
})
|
|
|
|
) do
|
|
|
|
{:ok, Repo.preload(user, :actors)}
|
2018-07-04 14:29:17 +02:00
|
|
|
else
|
2018-08-24 11:34:00 +02:00
|
|
|
err ->
|
2018-07-04 14:29:17 +02:00
|
|
|
{:error, :invalid_token}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Send the email reset password, if it's not too soon since the last send
|
|
|
|
"""
|
2018-07-27 10:45:35 +02:00
|
|
|
@spec send_password_reset_email(User.t(), String.t()) :: tuple
|
2018-07-04 14:29:17 +02:00
|
|
|
def send_password_reset_email(%User{} = user, locale \\ "en") do
|
|
|
|
with :ok <- we_can_send_email(user),
|
2018-07-27 10:45:35 +02:00
|
|
|
{:ok, %User{} = user_updated} <-
|
|
|
|
Repo.update(
|
|
|
|
User.send_password_reset_changeset(user, %{
|
|
|
|
"reset_password_token" => random_string(30),
|
|
|
|
"reset_password_sent_at" => DateTime.utc_now()
|
|
|
|
})
|
|
|
|
) do
|
|
|
|
mail =
|
|
|
|
user_updated
|
|
|
|
|> UserEmail.reset_password_email(locale)
|
|
|
|
|> Mailer.deliver_later()
|
|
|
|
|
2018-07-04 14:29:17 +02:00
|
|
|
{:ok, mail}
|
|
|
|
else
|
|
|
|
{:error, reason} -> {:error, reason}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-07-27 10:45:35 +02:00
|
|
|
@spec random_string(integer) :: String.t()
|
2018-07-04 14:29:17 +02:00
|
|
|
defp random_string(length) do
|
2018-07-04 17:16:02 +02:00
|
|
|
length
|
|
|
|
|> :crypto.strong_rand_bytes()
|
2018-07-27 10:45:35 +02:00
|
|
|
|> Base.url_encode64()
|
2018-07-04 14:29:17 +02:00
|
|
|
end
|
|
|
|
|
2018-07-27 10:45:35 +02:00
|
|
|
@spec we_can_send_email(User.t()) :: boolean
|
2018-07-04 14:29:17 +02:00
|
|
|
defp we_can_send_email(%User{} = user) do
|
|
|
|
case user.reset_password_sent_at do
|
|
|
|
nil ->
|
|
|
|
:ok
|
2018-07-27 10:45:35 +02:00
|
|
|
|
2018-07-04 14:29:17 +02:00
|
|
|
_ ->
|
|
|
|
case Timex.before?(Timex.shift(user.reset_password_sent_at, hours: 1), DateTime.utc_now()) do
|
|
|
|
true ->
|
|
|
|
:ok
|
2018-07-27 10:45:35 +02:00
|
|
|
|
2018-07-04 14:29:17 +02:00
|
|
|
false ->
|
|
|
|
{:error, :email_too_soon}
|
|
|
|
end
|
2018-07-27 10:45:35 +02:00
|
|
|
end
|
2018-07-04 14:29:17 +02:00
|
|
|
end
|
|
|
|
end
|