mirror of
https://github.com/algora-io/tv.git
synced 2025-03-17 20:17:45 +02:00
118 lines
3.5 KiB
Elixir
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
|