live_beats/lib/live_beats/accounts.ex
2021-11-11 22:42:10 -05:00

132 lines
3 KiB
Elixir

defmodule LiveBeats.Accounts do
import Ecto.Query
import Ecto.Changeset
alias LiveBeats.Repo
alias LiveBeats.Accounts.{User, Identity}
@admin_emails ["chris@chrismccord.com"]
@pubsub LiveBeats.PubSub
def subscribe(user_id) do
Phoenix.PubSub.subscribe(@pubsub, topic(user_id))
end
def unsubscribe(user_id) do
Phoenix.PubSub.unsubscribe(@pubsub, topic(user_id))
end
defp topic(user_id), do: "user:#{user_id}"
def list_users(opts) do
Repo.all(from u in User, limit: ^Keyword.fetch!(opts, :limit))
end
def admin?(%User{} = user), do: user.email in @admin_emails
## 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_by!(fields), do: Repo.get_by!(User, fields)
def update_active_profile(%User{active_profile_user_id: same_id} = current_user, same_id) do
current_user
end
def update_active_profile(%User{} = current_user, profile_user_id) do
{1, _} =
Repo.update_all(from(u in User, where: u.id == ^current_user.id),
set: [active_profile_user_id: profile_user_id]
)
Phoenix.PubSub.broadcast!(
@pubsub,
topic(current_user.id),
{__MODULE__, :active_profile_changed, current_user, %{user_id: profile_user_id}}
)
%User{current_user | active_profile_user_id: profile_user_id}
end
## User registration
@doc """
Registers a user from their GithHub information.
"""
def register_github_user(primary_email, info, emails, token) do
if user = get_user_by_provider(:github, primary_email) do
update_github_token(user, token)
else
info
|> User.github_registration_changeset(primary_email, emails, token)
|> Repo.insert()
end
end
def get_user_by_provider(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 change_settings(%User{} = user, attrs) do
User.settings_changeset(user, attrs)
end
def update_settings(%User{} = user, attrs) do
user
|> change_settings(attrs)
|> Repo.update()
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
end