frenzy/lib/frenzy/user.ex

92 lines
2.5 KiB
Elixir

defmodule Frenzy.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :username, :string
field :password, :string, virtual: true
field :password_hash, :string
field :fever_password, :string, virtual: true
field :fever_auth_token, :string
field :oidc_subject, :string
has_many :approved_clients, Frenzy.ApprovedClient, on_delete: :delete_all
has_many :groups, Frenzy.Group, on_delete: :delete_all
has_many :feeds, through: [:groups, :feeds]
timestamps()
end
@type t() :: %__MODULE__{
__meta__: Ecto.Schema.Metadata.t(),
id: integer() | nil,
username: String.t(),
password: String.t() | nil,
password_hash: String.t(),
fever_password: String.t() | nil,
fever_auth_token: String.t(),
oidc_subject: String.t() | nil,
approved_clients: [Frenzy.ApprovedClient.t()] | Ecto.Association.NotLoaded.t(),
groups: [Frenzy.Group.t()] | Ecto.Association.NotLoaded.t(),
inserted_at: NaiveDateTime.t(),
updated_at: NaiveDateTime.t()
}
@doc false
def changeset(user, attrs) do
user
|> cast(attrs, [:username, :password_hash])
|> validate_required([:username, :password_hash])
end
def registration_changeset(user, attrs) do
user
|> cast(attrs, [:username, :password, :fever_password])
|> validate_length(:password, min: 8)
|> validate_length(:fever_password, min: 8)
|> put_password_hash()
|> put_fever_token()
end
def change_password_changeset(user, attrs) do
user
|> cast(attrs, [:password])
|> validate_length(:password, min: 8)
|> put_password_hash()
end
def change_fever_password_changeset(user, attrs) do
user
|> cast(attrs, [:username, :fever_password])
|> validate_length(:fever_password, min: 8)
|> put_fever_token()
end
def set_oidc_subject_changeset(user, attrs) do
user
|> cast(attrs, [:oidc_subject])
end
defp put_password_hash(
%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
) do
change(changeset, Bcrypt.add_hash(password))
end
defp put_fever_token(
%Ecto.Changeset{
valid?: true,
changes: %{fever_password: fever_password}
} = changeset
) do
username = Map.get(changeset.changes, "username") || changeset.data.username
IO.inspect(username)
change(changeset, %{
fever_auth_token:
:crypto.hash(:md5, "#{username}:#{fever_password}") |> Base.encode16(case: :lower)
})
end
end