2018-12-03 11:58:57 +01:00
|
|
|
defmodule MobilizonWeb.Resolvers.Group do
|
2019-01-03 14:59:59 +01:00
|
|
|
@moduledoc """
|
|
|
|
Handles the group-related GraphQL calls
|
|
|
|
"""
|
2018-12-03 11:58:57 +01:00
|
|
|
alias Mobilizon.Actors
|
2019-03-05 17:23:05 +01:00
|
|
|
alias Mobilizon.Actors.{Actor, Member}
|
|
|
|
alias Mobilizon.Users.User
|
2018-12-03 11:58:57 +01:00
|
|
|
alias Mobilizon.Service.ActivityPub
|
2018-12-14 17:41:55 +01:00
|
|
|
alias Mobilizon.Activity
|
2018-12-03 11:58:57 +01:00
|
|
|
require Logger
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Find a group
|
|
|
|
"""
|
|
|
|
def find_group(_parent, %{preferred_username: name}, _resolution) do
|
|
|
|
case ActivityPub.find_or_make_group_from_nickname(name) do
|
|
|
|
{:ok, actor} ->
|
|
|
|
{:ok, actor}
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
{:error, "Group with name #{name} not found"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Lists all groups
|
|
|
|
"""
|
2018-12-14 11:23:36 +01:00
|
|
|
def list_groups(_parent, %{page: page, limit: limit}, _resolution) do
|
|
|
|
{:ok, Actors.list_groups(page, limit)}
|
2018-12-03 11:58:57 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Create a new group. The creator is automatically added as admin
|
|
|
|
"""
|
|
|
|
def create_group(
|
|
|
|
_parent,
|
2018-12-14 17:41:55 +01:00
|
|
|
args,
|
2018-12-03 11:58:57 +01:00
|
|
|
%{
|
2019-03-01 17:11:28 +01:00
|
|
|
context: %{
|
|
|
|
current_user: _user
|
|
|
|
}
|
2018-12-03 11:58:57 +01:00
|
|
|
}
|
|
|
|
) do
|
2019-03-01 17:11:28 +01:00
|
|
|
with {
|
|
|
|
:ok,
|
|
|
|
%Activity{
|
|
|
|
data: %{
|
|
|
|
"object" => %{"type" => "Group"} = object
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} <-
|
2018-12-14 17:41:55 +01:00
|
|
|
MobilizonWeb.API.Groups.create_group(args) do
|
2019-03-01 17:11:28 +01:00
|
|
|
{
|
|
|
|
:ok,
|
|
|
|
%Actor{
|
|
|
|
preferred_username: object["preferredUsername"],
|
|
|
|
summary: object["summary"],
|
|
|
|
type: :Group,
|
|
|
|
# uuid: object["uuid"],
|
|
|
|
url: object["id"]
|
|
|
|
}
|
|
|
|
}
|
2018-12-03 11:58:57 +01:00
|
|
|
end
|
2018-12-14 17:41:55 +01:00
|
|
|
|
|
|
|
# with %Actor{id: actor_id} <- Actors.get_local_actor_by_name(actor_username),
|
|
|
|
# {:user_actor, true} <-
|
|
|
|
# {:user_actor, actor_id in Enum.map(Actors.get_actors_for_user(user), & &1.id)},
|
|
|
|
# {:ok, %Actor{} = group} <- Actors.create_group(%{preferred_username: preferred_username}) do
|
|
|
|
# {:ok, group}
|
|
|
|
# else
|
|
|
|
# {:error, %Ecto.Changeset{errors: [url: {"has already been taken", []}]}} ->
|
|
|
|
# {:error, :group_name_not_available}
|
|
|
|
|
|
|
|
# err ->
|
|
|
|
# Logger.error(inspect(err))
|
|
|
|
# err
|
|
|
|
# end
|
2018-12-03 11:58:57 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def create_group(_parent, _args, _resolution) do
|
|
|
|
{:error, "You need to be logged-in to create a group"}
|
|
|
|
end
|
2019-01-25 09:23:44 +01:00
|
|
|
|
|
|
|
@doc """
|
|
|
|
Delete an existing group
|
|
|
|
"""
|
|
|
|
def delete_group(
|
|
|
|
_parent,
|
|
|
|
%{group_id: group_id, actor_id: actor_id},
|
|
|
|
%{
|
|
|
|
context: %{
|
|
|
|
current_user: user
|
|
|
|
}
|
|
|
|
}
|
|
|
|
) do
|
2019-02-21 18:11:49 +01:00
|
|
|
with {:ok, %Actor{} = group} <- Actors.get_group_by_actor_id(group_id),
|
2019-02-01 15:38:35 +01:00
|
|
|
{:is_owned, true, _} <- User.owns_actor(user, actor_id),
|
2019-01-25 09:23:44 +01:00
|
|
|
{:ok, %Member{} = member} <- Member.get_member(actor_id, group.id),
|
|
|
|
{:is_admin, true} <- Member.is_administrator(member),
|
|
|
|
group <- Actors.delete_group!(group) do
|
|
|
|
{:ok, %{id: group.id}}
|
|
|
|
else
|
|
|
|
{:error, :group_not_found} ->
|
2019-01-25 17:06:57 +01:00
|
|
|
{:error, "Group not found"}
|
2019-01-25 09:23:44 +01:00
|
|
|
|
|
|
|
{:is_owned, false} ->
|
|
|
|
{:error, "Actor id is not owned by authenticated user"}
|
|
|
|
|
|
|
|
{:error, :member_not_found} ->
|
|
|
|
{:error, "Actor id is not a member of this group"}
|
|
|
|
|
|
|
|
{:is_admin, false} ->
|
2019-02-01 09:42:31 +01:00
|
|
|
{:error, "Actor id is not an administrator of the selected group"}
|
2019-01-25 09:23:44 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def delete_group(_parent, _args, _resolution) do
|
|
|
|
{:error, "You need to be logged-in to delete a group"}
|
|
|
|
end
|
2019-03-01 17:11:28 +01:00
|
|
|
|
|
|
|
@doc """
|
|
|
|
Join an existing group
|
|
|
|
"""
|
|
|
|
def join_group(
|
|
|
|
_parent,
|
|
|
|
%{group_id: group_id, actor_id: actor_id},
|
|
|
|
%{
|
|
|
|
context: %{
|
|
|
|
current_user: user
|
|
|
|
}
|
|
|
|
}
|
|
|
|
) do
|
|
|
|
with {:is_owned, true, actor} <- User.owns_actor(user, actor_id),
|
|
|
|
{:ok, %Actor{} = group} <- Actors.get_group_by_actor_id(group_id),
|
|
|
|
{:error, :member_not_found} <- Member.get_member(actor.id, group.id),
|
|
|
|
{:is_able_to_join, true} <- {:is_able_to_join, Member.can_be_joined(group)},
|
|
|
|
role <- Mobilizon.Actors.get_default_member_role(group),
|
|
|
|
{:ok, _} <-
|
|
|
|
Actors.create_member(%{
|
|
|
|
parent_id: group.id,
|
|
|
|
actor_id: actor.id,
|
|
|
|
role: role
|
|
|
|
}) do
|
|
|
|
{:ok, %{parent: group, person: actor, role: role}}
|
|
|
|
else
|
|
|
|
{:is_owned, false} ->
|
|
|
|
{:error, "Actor id is not owned by authenticated user"}
|
|
|
|
|
|
|
|
{:error, :group_not_found} ->
|
|
|
|
{:error, "Group id not found"}
|
|
|
|
|
|
|
|
{:is_able_to_join, false} ->
|
|
|
|
{:error, "You cannot join this group"}
|
|
|
|
|
|
|
|
{:ok, %Member{}} ->
|
|
|
|
{:error, "You are already a member of this group"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def join_group(_parent, _args, _resolution) do
|
|
|
|
{:error, "You need to be logged-in to join a group"}
|
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Leave a existing group
|
|
|
|
"""
|
|
|
|
def leave_group(
|
|
|
|
_parent,
|
|
|
|
%{group_id: group_id, actor_id: actor_id},
|
|
|
|
%{
|
|
|
|
context: %{
|
|
|
|
current_user: user
|
|
|
|
}
|
|
|
|
}
|
|
|
|
) do
|
|
|
|
with {:is_owned, true, actor} <- User.owns_actor(user, actor_id),
|
|
|
|
{:ok, %Member{} = member} <- Member.get_member(actor.id, group_id),
|
|
|
|
{:only_administrator, false} <-
|
|
|
|
{:only_administrator, check_that_member_is_not_only_administrator(group_id, actor_id)},
|
|
|
|
{:ok, _} <-
|
|
|
|
Mobilizon.Actors.delete_member(member) do
|
|
|
|
{
|
|
|
|
:ok,
|
|
|
|
%{
|
|
|
|
parent: %{
|
|
|
|
id: group_id
|
|
|
|
},
|
|
|
|
person: %{
|
|
|
|
id: actor_id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{:is_owned, false} ->
|
|
|
|
{:error, "Actor id is not owned by authenticated user"}
|
|
|
|
|
|
|
|
{:error, :member_not_found} ->
|
|
|
|
{:error, "Member not found"}
|
|
|
|
|
|
|
|
{:only_administrator, true} ->
|
|
|
|
{:error, "You can't leave this group because you are the only administrator"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def leave_group(_parent, _args, _resolution) do
|
|
|
|
{:error, "You need to be logged-in to leave a group"}
|
|
|
|
end
|
|
|
|
|
|
|
|
# We check that the actor asking to leave the group is not it's only administrator
|
|
|
|
# We start by fetching the list of administrator or creators and if there's only one of them
|
|
|
|
# and that it's the actor requesting leaving the group we return true
|
|
|
|
@spec check_that_member_is_not_only_administrator(integer(), integer()) :: boolean()
|
|
|
|
defp check_that_member_is_not_only_administrator(group_id, actor_id) do
|
|
|
|
with [
|
|
|
|
%Member{
|
|
|
|
actor: %Actor{
|
|
|
|
id: member_actor_id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
] <-
|
|
|
|
Member.list_administrator_members_for_group(group_id) do
|
|
|
|
actor_id == member_actor_id
|
|
|
|
else
|
|
|
|
_ -> false
|
|
|
|
end
|
|
|
|
end
|
2018-12-03 11:58:57 +01:00
|
|
|
end
|