1
0
mirror of https://github.com/algora-io/tv.git synced 2025-03-17 20:17:45 +02:00
2024-09-12 11:00:16 +02:00

118 lines
3.5 KiB
Elixir

defmodule Algora.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
alias Algora.Accounts.{User, Identity, Entity}
schema "users" do
field :email, :string
field :name, :string
field :handle, :string
field :channel_tagline, :string
field :avatar_url, :string
field :external_homepage_url, :string
field :twitter_url, :string
field :videos_count, :integer
field :is_live, :boolean, default: false
field :stream_key, :string
field :visibility, Ecto.Enum, values: [public: 1, unlisted: 2]
field :bounties_count, :integer
field :solving_challenge, :boolean, default: false
field :featured, :boolean, default: false
embeds_many :tech, Tech do
field :name, :string
field :pct, :float
field :color, :string
end
embeds_many :orgs_contributed, Org do
field :handle, :string
field :avatar_url, :string
end
has_many :identities, Identity
has_one :entity, Entity
timestamps()
end
def get_visibility(info) do
# HACK: temporary heuristic to prevent abuse
with %{"followers" => followers, "created_at" => created_at} <- info,
{:ok, registered_at, _} <- DateTime.from_iso8601(created_at),
true <- DateTime.diff(DateTime.utc_now(), registered_at, :second) > 30 * 24 * 60 * 60,
true <- followers >= 20 do
:public
else
_ -> :unlisted
end
end
@doc """
A user changeset for github registration.
"""
def github_registration_changeset(info, primary_email, emails, token) do
%{"login" => handle, "avatar_url" => avatar_url, "html_url" => external_homepage_url} = info
identity_changeset =
Identity.github_registration_changeset(info, primary_email, emails, token)
if identity_changeset.valid? do
params = %{
"handle" => handle,
"email" => primary_email,
"name" => get_change(identity_changeset, :provider_name),
"avatar_url" => avatar_url,
"external_homepage_url" => external_homepage_url,
"visibility" => get_visibility(info)
}
%User{}
|> cast(params, [:email, :name, :handle, :avatar_url, :external_homepage_url, :visibility])
|> validate_required([:email, :name, :handle, :visibility])
|> validate_handle()
|> validate_email()
|> put_assoc(:identities, [identity_changeset])
else
%User{}
|> change()
|> Map.put(:valid?, false)
|> put_assoc(:identities, [identity_changeset])
end
end
def settings_changeset(%User{} = user, params) do
user
|> cast(params, [:handle, :name, :channel_tagline])
|> validate_required([:handle, :name, :channel_tagline])
|> validate_handle()
end
defp validate_email(changeset) do
changeset
|> validate_required([:email])
|> validate_format(:email, ~r/^[^\s]+@[^\s]+$/, message: "must have the @ sign and no spaces")
|> validate_length(:email, max: 160)
|> unsafe_validate_unique(:email, Algora.Repo)
|> unique_constraint(:email)
end
defp validate_handle(changeset) do
changeset
|> validate_format(:handle, ~r/^[a-zA-Z0-9_-]{2,32}$/)
|> unsafe_validate_unique(:handle, Algora.Repo)
|> unique_constraint(:handle)
|> prepare_changes(fn changeset ->
case fetch_change(changeset, :channel_tagline) do
{:ok, _} ->
changeset
:error ->
handle = get_field(changeset, :handle)
put_change(changeset, :channel_tagline, "#{handle}'s channel")
end
end)
end
end