Improve member adding and excluding flow
Allow to exclude a member Send emails to the member when it's excluded Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -51,7 +51,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
%CommentModel{actor_id: comment_actor_id} = comment <-
|
||||
Mobilizon.Discussions.get_comment(comment_id),
|
||||
Mobilizon.Discussions.get_comment_with_preload(comment_id),
|
||||
true <- actor_id === comment_actor_id,
|
||||
{:ok, _, %CommentModel{} = comment} <- Comments.update_comment(comment, %{text: text}) do
|
||||
{:ok, comment}
|
||||
@@ -64,15 +64,14 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
|
||||
|
||||
def delete_comment(
|
||||
_parent,
|
||||
%{actor_id: actor_id, comment_id: comment_id},
|
||||
%{comment_id: comment_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{role: role} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {actor_id, ""} <- Integer.parse(actor_id),
|
||||
{:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
|
||||
with {:actor, %Actor{id: actor_id} = actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
%CommentModel{deleted_at: nil} = comment <-
|
||||
Discussions.get_comment_with_preload(comment_id) do
|
||||
cond do
|
||||
|
||||
@@ -213,40 +213,25 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
"""
|
||||
def leave_group(
|
||||
_parent,
|
||||
%{group_id: group_id, actor_id: actor_id},
|
||||
%{group_id: group_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
current_user: %User{} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {actor_id, ""} <- Integer.parse(actor_id),
|
||||
{group_id, ""} <- Integer.parse(group_id),
|
||||
{:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
|
||||
{:ok, %Member{} = member} <- Actors.get_member(actor.id, group_id),
|
||||
{:only_administrator, false} <-
|
||||
{:only_administrator, check_that_member_is_not_last_administrator(group_id, actor_id)},
|
||||
{:ok, _} <-
|
||||
Mobilizon.Actors.delete_member(member) do
|
||||
{
|
||||
:ok,
|
||||
%{
|
||||
parent: %{
|
||||
id: group_id
|
||||
},
|
||||
actor: %{
|
||||
id: actor_id
|
||||
}
|
||||
}
|
||||
}
|
||||
with {:actor, %Actor{} = actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:group, %Actor{type: :Group} = group} <- {:group, Actors.get_actor(group_id)},
|
||||
{:ok, _activity, %Member{} = member} <- ActivityPub.leave(group, actor, true) do
|
||||
{:ok, member}
|
||||
else
|
||||
{:is_owned, nil} ->
|
||||
{:error, "Actor id is not owned by authenticated user"}
|
||||
|
||||
{:error, :member_not_found} ->
|
||||
{:error, "Member not found"}
|
||||
|
||||
{:only_administrator, true} ->
|
||||
{:group, nil} ->
|
||||
{:error, "Group not found"}
|
||||
|
||||
{:is_only_admin, true} ->
|
||||
{:error, "You can't leave this group because you are the only administrator"}
|
||||
end
|
||||
end
|
||||
@@ -278,32 +263,6 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
{:ok, %Page{total: 0, elements: []}}
|
||||
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_last_administrator(integer, integer) :: boolean
|
||||
defp check_that_member_is_not_last_administrator(group_id, actor_id) do
|
||||
case Actors.list_administrator_members_for_group(group_id) do
|
||||
%Page{total: total} when total > 1 ->
|
||||
true
|
||||
|
||||
%Page{
|
||||
total: 1,
|
||||
elements: [
|
||||
%Member{
|
||||
actor: %Actor{
|
||||
id: member_actor_id
|
||||
}
|
||||
}
|
||||
]
|
||||
} ->
|
||||
actor_id == member_actor_id
|
||||
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
defp restrict_fields_for_non_member_request(%Actor{} = group) do
|
||||
Map.merge(
|
||||
group,
|
||||
|
||||
@@ -6,6 +6,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
alias Mobilizon.{Actors, Users}
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Refresher
|
||||
alias Mobilizon.Storage.Page
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
@@ -65,7 +66,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
{:target_actor_username, {:ok, %Actor{id: target_actor_id} = target_actor}} <-
|
||||
{:target_actor_username,
|
||||
ActivityPub.find_or_make_actor_from_nickname(target_actor_username)},
|
||||
{:error, :member_not_found} <- Actors.get_member(target_actor_id, group.id),
|
||||
true <- check_member_not_existant_or_rejected(target_actor_id, group.id),
|
||||
{:ok, _activity, %Member{} = member} <- ActivityPub.invite(group, actor, target_actor) do
|
||||
{:ok, member}
|
||||
else
|
||||
@@ -91,7 +92,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
|
||||
def accept_invitation(_parent, %{id: member_id}, %{context: %{current_user: %User{} = user}}) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
%Member{actor: %Actor{id: member_actor_id}} = member <- Actors.get_member(member_id),
|
||||
%Member{actor: %Actor{id: member_actor_id} = actor} = member <-
|
||||
Actors.get_member(member_id),
|
||||
{:is_same_actor, true} <- {:is_same_actor, member_actor_id === actor_id},
|
||||
{:ok, _activity, %Member{} = member} <-
|
||||
ActivityPub.accept(
|
||||
@@ -100,7 +102,51 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
true
|
||||
) do
|
||||
# Launch an async task to refresh the group profile, fetch resources, discussions, members
|
||||
Refresher.fetch_group(member.parent.url, actor)
|
||||
{:ok, member}
|
||||
end
|
||||
end
|
||||
|
||||
def reject_invitation(_parent, %{id: member_id}, %{context: %{current_user: %User{} = user}}) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
%Member{actor: %Actor{id: member_actor_id}} = member <- Actors.get_member(member_id),
|
||||
{:is_same_actor, true} <- {:is_same_actor, member_actor_id === actor_id},
|
||||
{:ok, _activity, %Member{} = member} <-
|
||||
ActivityPub.reject(
|
||||
:invite,
|
||||
member,
|
||||
true
|
||||
) do
|
||||
{:ok, member}
|
||||
end
|
||||
end
|
||||
|
||||
def remove_member(_parent, %{member_id: member_id, group_id: group_id}, %{
|
||||
context: %{current_user: %User{} = user}
|
||||
}) do
|
||||
with %Actor{} = moderator <- Users.get_actor_for_user(user),
|
||||
%Member{} = member <- Actors.get_member(member_id),
|
||||
%Actor{type: :Group} = group <- Actors.get_actor(group_id),
|
||||
{:ok, _activity, %Member{}} <- ActivityPub.remove(member, group, moderator, true) do
|
||||
{:ok, member}
|
||||
end
|
||||
end
|
||||
|
||||
# Rejected members can be invited again
|
||||
@spec check_member_not_existant_or_rejected(String.t() | integer, String.t() | integer()) ::
|
||||
boolean()
|
||||
defp check_member_not_existant_or_rejected(target_actor_id, group_id) do
|
||||
case Actors.get_member(target_actor_id, group_id) do
|
||||
{:ok, %Member{role: :rejected}} ->
|
||||
true
|
||||
|
||||
{:error, :member_not_found} ->
|
||||
true
|
||||
|
||||
err ->
|
||||
require Logger
|
||||
Logger.error(inspect(err))
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,6 +16,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
field(:role, :member_role_enum, description: "The role of this membership")
|
||||
field(:invited_by, :person, description: "Who invited this member")
|
||||
field(:inserted_at, :naive_datetime, description: "When was this member created")
|
||||
field(:updated_at, :naive_datetime, description: "When was this member updated")
|
||||
end
|
||||
|
||||
enum :member_role_enum do
|
||||
@@ -28,12 +29,6 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
value(:rejected)
|
||||
end
|
||||
|
||||
@desc "Represents a deleted member"
|
||||
object :deleted_member do
|
||||
field(:parent, :deleted_object)
|
||||
field(:actor, :deleted_object)
|
||||
end
|
||||
|
||||
object :paginated_member_list do
|
||||
field(:elements, list_of(:member), description: "A list of members")
|
||||
field(:total, :integer, description: "The total number of elements in the list")
|
||||
@@ -49,9 +44,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
end
|
||||
|
||||
@desc "Leave a group"
|
||||
field :leave_group, :deleted_member do
|
||||
field :leave_group, :deleted_object do
|
||||
arg(:group_id, non_null(:id))
|
||||
arg(:actor_id, non_null(:id))
|
||||
|
||||
resolve(&Group.leave_group/3)
|
||||
end
|
||||
@@ -70,5 +64,20 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
|
||||
resolve(&Member.accept_invitation/3)
|
||||
end
|
||||
|
||||
@desc "Reject an invitation to a group"
|
||||
field :reject_invitation, :member do
|
||||
arg(:id, non_null(:id))
|
||||
|
||||
resolve(&Member.reject_invitation/3)
|
||||
end
|
||||
|
||||
@desc "Remove a member from a group"
|
||||
field :remove_member, :member do
|
||||
arg(:group_id, non_null(:id))
|
||||
arg(:member_id, non_null(:id))
|
||||
|
||||
resolve(&Member.remove_member/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -80,9 +80,9 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
||||
resolve(&Comment.update_comment/3)
|
||||
end
|
||||
|
||||
@desc "Delete a single comment"
|
||||
field :delete_comment, type: :comment do
|
||||
arg(:comment_id, non_null(:id))
|
||||
arg(:actor_id, non_null(:id))
|
||||
|
||||
resolve(&Comment.delete_comment/3)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user