mobilizon/lib/eventos/actors/user.ex

97 lines
2.8 KiB
Elixir

defmodule Eventos.Actors.User do
@moduledoc """
Represents a local user
"""
use Ecto.Schema
import Ecto.Changeset
alias Eventos.Actors.{Actor, User}
schema "users" do
field :email, :string
field :password_hash, :string
field :password, :string, virtual: true
field :role, :integer, default: 0
has_many :actors, Actor
field :confirmed_at, :utc_datetime
field :confirmation_sent_at, :utc_datetime
field :confirmation_token, :string
field :reset_password_sent_at, :utc_datetime
field :reset_password_token, :string
timestamps()
end
@doc false
def changeset(%User{} = user, attrs) do
user
|> cast(attrs, [:email, :role, :password_hash, :confirmed_at, :confirmation_sent_at, :confirmation_token, :reset_password_sent_at, :reset_password_token])
|> validate_required([:email])
|> unique_constraint(:email, [message: "registration.error.email_already_used"])
|> validate_format(:email, ~r/@/)
|> validate_length(:password, min: 6, max: 100, message: "registration.error.password_too_short")
end
def registration_changeset(struct, params) do
struct
|> changeset(params)
|> cast(params, ~w(password)a, [])
|> validate_required([:email, :password])
|> validate_length(:password, min: 6, max: 100, message: "registration.error.password_too_short")
|> hash_password()
|> save_confirmation_token()
|> unique_constraint(:confirmation_token, [message: "regisration.error.confirmation_token_already_in_use"])
end
def send_password_reset_changeset(%User{} = user, attrs) do
user
|> cast(attrs, [:reset_password_token, :reset_password_sent_at])
end
def password_reset_changeset(%User{} = user, attrs) do
user
|> cast(attrs, [:password, :reset_password_token, :reset_password_sent_at])
|> validate_length(:password, min: 6, max: 100, message: "registration.error.password_too_short")
|> hash_password()
end
defp save_confirmation_token(changeset) do
case changeset do
%Ecto.Changeset{valid?: true,
changes: %{email: _email}} ->
changeset = put_change(changeset, :confirmation_token, random_string(30))
put_change(changeset, :confirmation_sent_at, DateTime.utc_now())
_ ->
changeset
end
end
defp random_string(length) do
length
|> :crypto.strong_rand_bytes()
|> Base.url_encode64
end
@doc """
Hash password when it's changed
"""
defp hash_password(changeset) do
case changeset do
%Ecto.Changeset{valid?: true,
changes: %{password: password}} ->
put_change(changeset,
:password_hash,
Comeonin.Argon2.hashpwsalt(password))
_ ->
changeset
end
end
def is_confirmed(%User{confirmed_at: nil} = _user) do
{:error, :unconfirmed}
end
def is_confirmed(%User{} = user) do
{:ok, user}
end
end