Changes to the actor - user relation
Now the GraphQL API replies mostly with users which have the default_actor property filled to show profile information Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -59,12 +59,16 @@ defmodule Mobilizon.Actors do
|
||||
"""
|
||||
@spec get_actor_for_user(Mobilizon.Actors.User.t()) :: Mobilizon.Actors.Actor.t()
|
||||
def get_actor_for_user(%Mobilizon.Actors.User{} = user) do
|
||||
with %User{default_actor: actor} = user when not is_nil(user) and not is_nil(actor) <-
|
||||
Repo.preload(user, [:default_actor]) do
|
||||
actor
|
||||
case Repo.one(from(a in Actor, join: u in User, on: u.default_actor_id == a.id)) do
|
||||
nil -> get_actors_for_user(user) |> hd
|
||||
actor -> actor
|
||||
end
|
||||
end
|
||||
|
||||
def get_actors_for_user(%User{id: user_id}) do
|
||||
Repo.all(from(a in Actor, where: a.user_id == ^user_id))
|
||||
end
|
||||
|
||||
def get_actor_with_everything!(id) do
|
||||
actor = Repo.get!(Actor, id)
|
||||
Repo.preload(actor, [:organized_events, :followers, :followings])
|
||||
@@ -106,6 +110,13 @@ defmodule Mobilizon.Actors do
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
def update_user_default_actor(user_id, actor_id) do
|
||||
with from(u in User, where: u.id == ^user_id, update: [set: [default_actor_id: ^actor_id]])
|
||||
|> Repo.update_all([]) do
|
||||
Repo.get!(User, user_id) |> Repo.preload([:default_actor])
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a Actor.
|
||||
|
||||
@@ -248,14 +259,25 @@ defmodule Mobilizon.Actors do
|
||||
@spec get_user_with_actors!(integer()) :: User.t()
|
||||
def get_user_with_actors!(id) do
|
||||
user = Repo.get!(User, id)
|
||||
Repo.preload(user, :actors)
|
||||
Repo.preload(user, [:actors, :default_actor])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get user with it's actors by ID
|
||||
"""
|
||||
@spec get_user_with_actors(integer()) :: User.t()
|
||||
def get_user_with_actors(id) do
|
||||
case Repo.get(User, id) do
|
||||
nil -> {:error, "User with ID #{id} not found"}
|
||||
user -> {:ok, Repo.preload(user, :actors)}
|
||||
nil ->
|
||||
{:error, "User with ID #{id} not found"}
|
||||
|
||||
user ->
|
||||
user =
|
||||
user
|
||||
|> Repo.preload([:actors, :default_actor])
|
||||
|> Map.put(:actors, get_actors_for_user(user))
|
||||
|
||||
{:ok, user}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -497,22 +519,21 @@ defmodule Mobilizon.Actors do
|
||||
pem = [entry] |> :public_key.pem_encode() |> String.trim_trailing()
|
||||
|
||||
with avatar <- gravatar(email),
|
||||
actor_changeset <-
|
||||
Mobilizon.Actors.Actor.registration_changeset(%Mobilizon.Actors.Actor{}, %{
|
||||
preferred_username: username,
|
||||
domain: nil,
|
||||
keys: pem,
|
||||
avatar_url: avatar
|
||||
}),
|
||||
{:ok, %Mobilizon.Actors.Actor{} = actor} <- Mobilizon.Repo.insert(actor_changeset),
|
||||
user_changeset <-
|
||||
Mobilizon.Actors.User.registration_changeset(%Mobilizon.Actors.User{}, %{
|
||||
User.registration_changeset(%User{}, %{
|
||||
email: email,
|
||||
password: password,
|
||||
default_actor: actor
|
||||
default_actor: %{
|
||||
preferred_username: username,
|
||||
domain: nil,
|
||||
keys: pem,
|
||||
avatar_url: avatar
|
||||
}
|
||||
}),
|
||||
{:ok, %Mobilizon.Actors.User{} = user} <- Mobilizon.Repo.insert(user_changeset) do
|
||||
{:ok, Map.put(actor, :user, user)}
|
||||
{:ok, %User{default_actor: %Actor{} = actor, id: user_id} = user} <-
|
||||
Mobilizon.Repo.insert(user_changeset),
|
||||
{:ok, %Actor{} = _actor} <- update_actor(actor, %{user_id: user_id}) do
|
||||
{:ok, Repo.preload(user, [:actors])}
|
||||
else
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
handle_actor_user_changeset(changeset)
|
||||
@@ -600,9 +621,20 @@ defmodule Mobilizon.Actors do
|
||||
def get_user_by_email(email, activated \\ nil) do
|
||||
query =
|
||||
case activated do
|
||||
nil -> from(u in User, where: u.email == ^email)
|
||||
true -> from(u in User, where: u.email == ^email and not is_nil(u.confirmed_at))
|
||||
false -> from(u in User, where: u.email == ^email and is_nil(u.confirmed_at))
|
||||
nil ->
|
||||
from(u in User, where: u.email == ^email, preload: :default_actor)
|
||||
|
||||
true ->
|
||||
from(u in User,
|
||||
where: u.email == ^email and not is_nil(u.confirmed_at),
|
||||
preload: :default_actor
|
||||
)
|
||||
|
||||
false ->
|
||||
from(u in User,
|
||||
where: u.email == ^email and is_nil(u.confirmed_at),
|
||||
preload: :default_actor
|
||||
)
|
||||
end
|
||||
|
||||
case Repo.one(query) do
|
||||
@@ -611,6 +643,9 @@ defmodule Mobilizon.Actors do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get an user by it's activation token
|
||||
"""
|
||||
@spec get_user_by_activation_token(String.t()) :: Actor.t()
|
||||
def get_user_by_activation_token(token) do
|
||||
Repo.one(
|
||||
@@ -621,6 +656,19 @@ defmodule Mobilizon.Actors do
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get an user by it's reset password token
|
||||
"""
|
||||
@spec get_user_by_reset_password_token(String.t()) :: Actor.t()
|
||||
def get_user_by_reset_password_token(token) do
|
||||
Repo.one(
|
||||
from(u in User,
|
||||
where: u.reset_password_token == ^token,
|
||||
preload: [:default_actor]
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a user.
|
||||
|
||||
@@ -634,9 +682,12 @@ defmodule Mobilizon.Actors do
|
||||
|
||||
"""
|
||||
def update_user(%User{} = user, attrs) do
|
||||
user
|
||||
|> User.changeset(attrs)
|
||||
|> Repo.update()
|
||||
with {:ok, %User{} = user} <-
|
||||
user
|
||||
|> User.changeset(attrs)
|
||||
|> Repo.update() do
|
||||
{:ok, Repo.preload(user, [:default_actor])}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
||||
@@ -3,7 +3,7 @@ defmodule Mobilizon.Actors.Service.ResetPassword do
|
||||
|
||||
require Logger
|
||||
|
||||
alias Mobilizon.{Mailer, Repo, Actors.User}
|
||||
alias Mobilizon.{Mailer, Repo, Actors.User, Actors}
|
||||
alias Mobilizon.Email.User, as: UserEmail
|
||||
alias Mobilizon.Actors.Service.Tools
|
||||
|
||||
@@ -12,7 +12,7 @@ defmodule Mobilizon.Actors.Service.ResetPassword do
|
||||
"""
|
||||
@spec check_reset_password_token(String.t(), String.t()) :: tuple
|
||||
def check_reset_password_token(password, token) do
|
||||
with %User{} = user <- Repo.get_by(User, reset_password_token: token),
|
||||
with %User{} = user <- Actors.get_user_by_reset_password_token(token),
|
||||
{:ok, %User{} = user} <-
|
||||
Repo.update(
|
||||
User.password_reset_changeset(user, %{
|
||||
|
||||
@@ -13,7 +13,7 @@ defmodule Mobilizon.Actors.User do
|
||||
field(:password, :string, virtual: true)
|
||||
field(:role, :integer, default: 0)
|
||||
has_many(:actors, Actor)
|
||||
has_one(:default_actor, Actor)
|
||||
belongs_to(:default_actor, Actor)
|
||||
field(:confirmed_at, :utc_datetime)
|
||||
field(:confirmation_sent_at, :utc_datetime)
|
||||
field(:confirmation_token, :string)
|
||||
@@ -25,34 +25,40 @@ defmodule Mobilizon.Actors.User do
|
||||
|
||||
@doc false
|
||||
def changeset(%User{} = user, attrs) do
|
||||
user
|
||||
|> cast(attrs, [
|
||||
:email,
|
||||
:role,
|
||||
# :default_actor,
|
||||
:password_hash,
|
||||
:confirmed_at,
|
||||
:confirmation_sent_at,
|
||||
:confirmation_token,
|
||||
:reset_password_sent_at,
|
||||
:reset_password_token
|
||||
])
|
||||
|> validate_required([:email])
|
||||
|> unique_constraint(:email, message: "registration.error.email_already_used")
|
||||
|> validate_format(:email, ~r/@/)
|
||||
|> validate_length(
|
||||
:password,
|
||||
min: 6,
|
||||
max: 100,
|
||||
message: "registration.error.password_too_short"
|
||||
)
|
||||
changeset =
|
||||
user
|
||||
|> cast(attrs, [
|
||||
:email,
|
||||
:role,
|
||||
:password_hash,
|
||||
:confirmed_at,
|
||||
:confirmation_sent_at,
|
||||
:confirmation_token,
|
||||
:reset_password_sent_at,
|
||||
:reset_password_token
|
||||
])
|
||||
|> validate_required([:email])
|
||||
|> unique_constraint(:email, message: "registration.error.email_already_used")
|
||||
|> validate_format(:email, ~r/@/)
|
||||
|> validate_length(
|
||||
:password,
|
||||
min: 6,
|
||||
max: 100,
|
||||
message: "registration.error.password_too_short"
|
||||
)
|
||||
|
||||
if Map.has_key?(attrs, :default_actor) do
|
||||
put_assoc(changeset, :default_actor, attrs.default_actor)
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
def registration_changeset(struct, params) do
|
||||
struct
|
||||
|> changeset(params)
|
||||
|> cast(params, ~w(password)a, [])
|
||||
|> put_assoc(:default_actor, params.default_actor)
|
||||
|> cast_assoc(:default_actor)
|
||||
|> validate_required([:email, :password])
|
||||
|> validate_email()
|
||||
|> validate_length(
|
||||
|
||||
@@ -26,9 +26,8 @@ defmodule MobilizonWeb.Resolvers.User do
|
||||
"""
|
||||
def login_user(_parent, %{email: email, password: password}, _resolution) do
|
||||
with {:ok, %User{} = user} <- Actors.get_user_by_email(email, true),
|
||||
{:ok, token, _} <- Actors.authenticate(%{user: user, password: password}),
|
||||
%Actor{} = actor <- Actors.get_actor_for_user(user) do
|
||||
{:ok, %{token: token, user: user, person: actor}}
|
||||
{:ok, token, _} <- Actors.authenticate(%{user: user, password: password}) do
|
||||
{:ok, %{token: token, user: user}}
|
||||
else
|
||||
{:error, :user_not_found} ->
|
||||
{:error, "User with email not found"}
|
||||
@@ -47,9 +46,9 @@ defmodule MobilizonWeb.Resolvers.User do
|
||||
"""
|
||||
@spec create_user_actor(any(), map(), any()) :: tuple()
|
||||
def create_user_actor(_parent, args, _resolution) do
|
||||
with {:ok, %Actor{user: user} = actor} <- Actors.register(args) do
|
||||
with {:ok, %User{} = user} <- Actors.register(args) do
|
||||
Mobilizon.Actors.Service.Activation.send_confirmation_email(user)
|
||||
{:ok, actor}
|
||||
{:ok, user}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -114,9 +113,8 @@ defmodule MobilizonWeb.Resolvers.User do
|
||||
def reset_password(_parent, %{password: password, token: token}, _resolution) do
|
||||
with {:ok, %User{} = user} <-
|
||||
Mobilizon.Actors.Service.ResetPassword.check_reset_password_token(password, token),
|
||||
%Actor{} = actor <- Actors.get_actor_for_user(user),
|
||||
{:ok, token, _} <- MobilizonWeb.Guardian.encode_and_sign(user) do
|
||||
{:ok, %{token: token, user: user, actor: actor}}
|
||||
{:ok, %{token: token, user: user}}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -124,8 +122,17 @@ defmodule MobilizonWeb.Resolvers.User do
|
||||
def change_default_actor(_parent, %{preferred_username: username}, %{
|
||||
context: %{current_user: user}
|
||||
}) do
|
||||
with %Actor{} = actor <- Actors.get_local_actor_by_name(username) do
|
||||
Actors.update_user(user, %{default_actor: actor})
|
||||
with %Actor{id: actor_id} <- Actors.get_local_actor_by_name(username),
|
||||
{:user_actor, true} <-
|
||||
{:user_actor, actor_id in Enum.map(Actors.get_actors_for_user(user), & &1.id)},
|
||||
%User{} = user <- Actors.update_user_default_actor(user.id, actor_id) do
|
||||
{:ok, user}
|
||||
else
|
||||
{:user_actor, _} ->
|
||||
{:error, :actor_not_from_user}
|
||||
|
||||
_err ->
|
||||
{:error, :unable_to_change_default_actor}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -202,7 +202,6 @@ defmodule MobilizonWeb.Schema do
|
||||
object :login do
|
||||
field(:token, non_null(:string), description: "A JWT Token for this session")
|
||||
field(:user, non_null(:user), description: "The user associated to this session")
|
||||
field(:person, non_null(:person), description: "The person associated to this session")
|
||||
end
|
||||
|
||||
@desc "An event"
|
||||
@@ -480,8 +479,8 @@ defmodule MobilizonWeb.Schema do
|
||||
resolve(&Resolvers.Category.create_category/3)
|
||||
end
|
||||
|
||||
@desc "Create an user (returns an actor)"
|
||||
field :create_user, type: :person do
|
||||
@desc "Create an user"
|
||||
field :create_user, type: :user do
|
||||
arg(:email, non_null(:string))
|
||||
arg(:password, non_null(:string))
|
||||
arg(:username, non_null(:string))
|
||||
|
||||
Reference in New Issue
Block a user