mirror of
https://github.com/algora-io/tv.git
synced 2025-03-17 20:17:45 +02:00
276 lines
6.8 KiB
Elixir
276 lines
6.8 KiB
Elixir
defmodule Algora.Accounts do
|
|
import Ecto.Query
|
|
import Ecto.Changeset
|
|
|
|
alias Algora.{Repo, Restream}
|
|
alias Algora.Accounts.{User, Identity, Destination, Entity}
|
|
|
|
def list_users(opts) do
|
|
Repo.all(from u in User, limit: ^Keyword.fetch!(opts, :limit))
|
|
end
|
|
|
|
def get_users_map(user_ids) when is_list(user_ids) do
|
|
Repo.all(from u in User, where: u.id in ^user_ids, select: {u.id, u})
|
|
end
|
|
|
|
def admin?(%User{} = user) do
|
|
user.email in Algora.config([:admin_emails])
|
|
end
|
|
|
|
def update_settings(%User{} = user, attrs) do
|
|
user |> change_settings(attrs) |> Repo.update()
|
|
end
|
|
|
|
## Database getters
|
|
|
|
@doc """
|
|
Gets a user by email.
|
|
|
|
## Examples
|
|
|
|
iex> get_user_by_email("foo@example.com")
|
|
%User{}
|
|
|
|
iex> get_user_by_email("unknown@example.com")
|
|
nil
|
|
|
|
"""
|
|
def get_user_by_email(email) when is_binary(email) do
|
|
Repo.get_by(User, email: email)
|
|
end
|
|
|
|
@doc """
|
|
Gets a single user.
|
|
|
|
Raises `Ecto.NoResultsError` if the User does not exist.
|
|
|
|
## Examples
|
|
|
|
iex> get_user!(123)
|
|
%User{}
|
|
|
|
iex> get_user!(456)
|
|
** (Ecto.NoResultsError)
|
|
|
|
"""
|
|
def get_user!(id), do: Repo.get!(User, id)
|
|
|
|
def get_user(id), do: Repo.get(User, id)
|
|
|
|
def get_user_by(fields), do: Repo.get_by(User, fields)
|
|
|
|
def get_user_by!(fields), do: Repo.get_by!(User, fields)
|
|
|
|
## User registration
|
|
|
|
@doc """
|
|
Registers a user from their GitHub information.
|
|
"""
|
|
def register_github_user(primary_email, info, emails, token) do
|
|
if user = get_user_by_provider_email(:github, primary_email) do
|
|
update_github_token(user, token)
|
|
else
|
|
info
|
|
|> User.github_registration_changeset(primary_email, emails, token)
|
|
|> Repo.insert()
|
|
end
|
|
end
|
|
|
|
def link_restream_account(user_id, info, tokens) do
|
|
user = get_user!(user_id)
|
|
|
|
identity =
|
|
from(u in User,
|
|
join: i in assoc(u, :identities),
|
|
where: i.provider == ^to_string(:restream) and u.id == ^user_id
|
|
)
|
|
|> Repo.one()
|
|
|
|
if identity do
|
|
update_restream_tokens(user, tokens)
|
|
else
|
|
{:ok, _} =
|
|
info
|
|
|> Identity.restream_oauth_changeset(user_id, tokens)
|
|
|> Repo.insert()
|
|
|
|
{:ok, Repo.preload(user, :identities, force: true)}
|
|
end
|
|
end
|
|
|
|
def get_user_by_provider_email(provider, email) when provider in [:github] do
|
|
query =
|
|
from(u in User,
|
|
join: i in assoc(u, :identities),
|
|
where:
|
|
i.provider == ^to_string(provider) and
|
|
fragment("lower(?)", u.email) == ^String.downcase(email)
|
|
)
|
|
|
|
Repo.one(query)
|
|
end
|
|
|
|
def get_user_by_provider_id(provider, id) when provider in [:github] do
|
|
query =
|
|
from(u in User,
|
|
join: i in assoc(u, :identities),
|
|
where: i.provider == ^to_string(provider) and i.provider_id == ^id
|
|
)
|
|
|
|
Repo.one(query)
|
|
end
|
|
|
|
def change_settings(%User{} = user, attrs) do
|
|
User.settings_changeset(user, attrs)
|
|
end
|
|
|
|
defp update_github_token(%User{} = user, new_token) do
|
|
identity =
|
|
Repo.one!(from(i in Identity, where: i.user_id == ^user.id and i.provider == "github"))
|
|
|
|
{:ok, _} =
|
|
identity
|
|
|> change()
|
|
|> put_change(:provider_token, new_token)
|
|
|> Repo.update()
|
|
|
|
{:ok, Repo.preload(user, :identities, force: true)}
|
|
end
|
|
|
|
defp update_restream_tokens(%User{} = user, %{token: token, refresh_token: refresh_token}) do
|
|
identity =
|
|
Repo.one!(from(i in Identity, where: i.user_id == ^user.id and i.provider == "restream"))
|
|
|
|
{:ok, _} =
|
|
identity
|
|
|> change()
|
|
|> put_change(:provider_token, token)
|
|
|> put_change(:provider_refresh_token, refresh_token)
|
|
|> Repo.update()
|
|
|
|
{:ok, Repo.preload(user, :identities, force: true)}
|
|
end
|
|
|
|
def refresh_restream_tokens(%User{} = user) do
|
|
identity =
|
|
Repo.one!(from(i in Identity, where: i.user_id == ^user.id and i.provider == "restream"))
|
|
|
|
{:ok, tokens} = Restream.refresh_access_token(identity.provider_refresh_token)
|
|
update_restream_tokens(user, tokens)
|
|
|
|
{:ok, tokens}
|
|
end
|
|
|
|
def has_restream_token?(%User{} = user) do
|
|
query = from(i in Identity, where: i.user_id == ^user.id and i.provider == "restream")
|
|
Repo.one(query) != nil
|
|
end
|
|
|
|
def get_restream_token(%User{} = user) do
|
|
query = from(i in Identity, where: i.user_id == ^user.id and i.provider == "restream")
|
|
|
|
with identity when identity != nil <- Repo.one(query),
|
|
{:ok, %{token: token}} <- refresh_restream_tokens(user) do
|
|
token
|
|
else
|
|
_ -> nil
|
|
end
|
|
end
|
|
|
|
def get_restream_ws_url(%User{} = user) do
|
|
if token = get_restream_token(user), do: Restream.websocket_url(token)
|
|
end
|
|
|
|
def gen_stream_key(%User{} = user) do
|
|
user =
|
|
Repo.one!(from(u in User, where: u.id == ^user.id))
|
|
|
|
token = :crypto.strong_rand_bytes(32)
|
|
hashed_token = :crypto.hash(:sha256, token)
|
|
encoded_token = Base.url_encode64(hashed_token, padding: false)
|
|
|
|
{:ok, _} =
|
|
user
|
|
|> change()
|
|
|> put_change(:stream_key, encoded_token)
|
|
|> Repo.update()
|
|
|
|
{:ok, user}
|
|
end
|
|
|
|
def list_destinations(user_id) do
|
|
Repo.all(from d in Destination, where: d.user_id == ^user_id, order_by: [asc: d.id])
|
|
end
|
|
|
|
def list_active_destinations(user_id) do
|
|
Repo.all(
|
|
from d in Destination,
|
|
where: d.user_id == ^user_id and d.active == true,
|
|
order_by: [asc: d.id]
|
|
)
|
|
end
|
|
|
|
def get_destination!(id), do: Repo.get!(Destination, id)
|
|
|
|
def change_destination(%Destination{} = destination, attrs \\ %{}) do
|
|
destination |> Destination.changeset(attrs)
|
|
end
|
|
|
|
def create_destination(user, attrs \\ %{}) do
|
|
%Destination{}
|
|
|> Destination.changeset(attrs)
|
|
|> put_change(:user_id, user.id)
|
|
|> Repo.insert()
|
|
end
|
|
|
|
def update_destination(%Destination{} = destination, attrs) do
|
|
destination
|
|
|> Destination.changeset(attrs)
|
|
|> Repo.update()
|
|
end
|
|
|
|
def create_entity!(%User{} = user) do
|
|
create_entity!(%{
|
|
user_id: user.id,
|
|
name: user.name,
|
|
handle: user.handle,
|
|
avatar_url: user.avatar_url,
|
|
platform: "algora",
|
|
platform_id: Integer.to_string(user.id),
|
|
platform_meta: %{}
|
|
})
|
|
end
|
|
|
|
def create_entity!(attrs) do
|
|
case %Entity{}
|
|
|> Entity.changeset(attrs)
|
|
|> Repo.insert() do
|
|
{:ok, entity} ->
|
|
entity
|
|
|
|
_ when attrs.id != attrs.handle ->
|
|
create_entity!(%{attrs | handle: attrs.id})
|
|
end
|
|
end
|
|
|
|
def get_entity!(id), do: Repo.get!(Entity, id)
|
|
|
|
def get_entity(id), do: Repo.get(Entity, id)
|
|
|
|
def get_entity_by(fields), do: Repo.get_by(Entity, fields)
|
|
|
|
def get_or_create_entity!(%User{} = user) do
|
|
case get_entity_by(user_id: user.id) do
|
|
nil -> create_entity!(user)
|
|
entity -> entity
|
|
end
|
|
end
|
|
|
|
def get_or_create_entity!(%{platform: platform, platform_id: platform_id} = attrs) do
|
|
case get_entity_by(platform: platform, platform_id: platform_id) do
|
|
nil -> create_entity!(attrs)
|
|
entity -> entity
|
|
end
|
|
end
|
|
end
|