Add group admin profiles
And other fixes Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
104
lib/graphql/resolvers/actor.ex
Normal file
104
lib/graphql/resolvers/actor.ex
Normal file
@@ -0,0 +1,104 @@
|
||||
defmodule Mobilizon.GraphQL.Resolvers.Actor do
|
||||
@moduledoc """
|
||||
Handles the group-related GraphQL calls.
|
||||
"""
|
||||
|
||||
import Mobilizon.Users.Guards
|
||||
alias Mobilizon.{Actors, Admin, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Refresher
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
require Logger
|
||||
|
||||
def refresh_profile(_parent, %{id: id}, %{context: %{current_user: %User{role: role}}})
|
||||
when is_admin(role) do
|
||||
case Actors.get_actor(id) do
|
||||
%Actor{domain: domain} = actor when not is_nil(domain) ->
|
||||
Refresher.refresh_profile(actor)
|
||||
{:ok, actor}
|
||||
|
||||
%Actor{} ->
|
||||
{:error, "Only remote actors may be refreshed"}
|
||||
|
||||
_ ->
|
||||
{:error, "No actor found with this ID"}
|
||||
end
|
||||
end
|
||||
|
||||
def suspend_profile(_parent, %{id: id}, %{
|
||||
context: %{current_user: %User{role: role} = user}
|
||||
})
|
||||
when is_moderator(role) do
|
||||
with {:moderator_actor, %Actor{} = moderator_actor} <-
|
||||
{:moderator_actor, Users.get_actor_for_user(user)},
|
||||
%Actor{suspended: false} = actor <- Actors.get_actor_with_preload(id) do
|
||||
case actor do
|
||||
# Suspend a group on this instance
|
||||
%Actor{type: :Group, domain: nil} ->
|
||||
Logger.debug("We're suspending a group on this very instance")
|
||||
ActivityPub.delete(actor, moderator_actor, true, %{suspension: true})
|
||||
Admin.log_action(moderator_actor, "suspend", actor)
|
||||
{:ok, actor}
|
||||
|
||||
# Delete a remote actor
|
||||
%Actor{domain: domain} when not is_nil(domain) ->
|
||||
Logger.debug("We're just deleting a remote instance")
|
||||
Actors.delete_actor(actor, suspension: true)
|
||||
Admin.log_action(moderator_actor, "suspend", actor)
|
||||
{:ok, actor}
|
||||
|
||||
%Actor{domain: nil} ->
|
||||
{:error, "No remote profile found with this ID"}
|
||||
end
|
||||
else
|
||||
{:moderator_actor, nil} ->
|
||||
{:error, "No actor found for the moderator user"}
|
||||
|
||||
%Actor{suspended: true} ->
|
||||
{:error, "Actor already suspended"}
|
||||
|
||||
{:error, _} ->
|
||||
{:error, "Error while performing background task"}
|
||||
end
|
||||
end
|
||||
|
||||
def suspend_profile(_parent, _args, _resolution) do
|
||||
{:error, "Only moderators and administrators can suspend a profile"}
|
||||
end
|
||||
|
||||
def unsuspend_profile(_parent, %{id: id}, %{
|
||||
context: %{current_user: %User{role: role} = user}
|
||||
})
|
||||
when is_moderator(role) do
|
||||
with {:moderator_actor, %Actor{} = moderator_actor} <-
|
||||
{:moderator_actor, Users.get_actor_for_user(user)},
|
||||
%Actor{suspended: true} = actor <-
|
||||
Actors.get_actor_with_preload(id, true),
|
||||
{:delete_tombstones, {_, nil}} <-
|
||||
{:delete_tombstones, Mobilizon.Tombstone.delete_actor_tombstones(id)},
|
||||
{:ok, %Actor{} = actor} <- Actors.update_actor(actor, %{suspended: false}),
|
||||
{:ok, %Actor{} = actor} <- refresh_if_remote(actor),
|
||||
{:ok, _} <- Admin.log_action(moderator_actor, "unsuspend", actor) do
|
||||
{:ok, actor}
|
||||
else
|
||||
{:moderator_actor, nil} ->
|
||||
{:error, "No actor found for the moderator user"}
|
||||
|
||||
nil ->
|
||||
{:error, "No remote profile found with this ID"}
|
||||
|
||||
{:error, _} ->
|
||||
{:error, "Error while performing background task"}
|
||||
end
|
||||
end
|
||||
|
||||
def unsuspend_profile(_parent, _args, _resolution) do
|
||||
{:error, "Only moderators and administrators can unsuspend a profile"}
|
||||
end
|
||||
|
||||
@spec refresh_if_remote(Actor.t()) :: {:ok, Actor.t()}
|
||||
defp refresh_if_remote(%Actor{domain: nil} = actor), do: {:ok, actor}
|
||||
defp refresh_if_remote(%Actor{} = actor), do: Refresher.refresh_profile(actor)
|
||||
end
|
||||
@@ -20,8 +20,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
||||
}
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
{:ok, Discussions.find_discussions_for_actor(group_id)}
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:ok, %Actor{type: :Group} = group} <- Actors.get_group_by_actor_id(group_id) do
|
||||
{:ok, Discussions.find_discussions_for_actor(group)}
|
||||
else
|
||||
{:member, false} ->
|
||||
{:ok, %Page{total: 0, elements: []}}
|
||||
@@ -174,6 +175,12 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
||||
{:ok, _activity, %Discussion{} = discussion} <-
|
||||
ActivityPub.delete(discussion, actor) do
|
||||
{:ok, discussion}
|
||||
else
|
||||
{:no_discussion, _} ->
|
||||
{:error, "No discussion with ID #{discussion_id}"}
|
||||
|
||||
{:member, _} ->
|
||||
{:error, "You are not a member of the group the discussion belongs to"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
Handles the group-related GraphQL calls.
|
||||
"""
|
||||
|
||||
import Mobilizon.Users.Guards
|
||||
alias Mobilizon.{Actors, Events, Users}
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
@@ -54,13 +55,46 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get a group
|
||||
"""
|
||||
def get_group(_parent, %{id: id}, %{context: %{current_user: %User{role: role}}}) do
|
||||
with %Actor{type: :Group, suspended: suspended} = actor <-
|
||||
Actors.get_actor_with_preload(id, true),
|
||||
true <- suspended == false or is_moderator(role) do
|
||||
{:ok, actor}
|
||||
else
|
||||
_ ->
|
||||
{:error, "Group with ID #{id} not found"}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Lists all groups
|
||||
"""
|
||||
def list_groups(_parent, %{page: page, limit: limit}, _resolution) do
|
||||
{:ok, Actors.list_groups(page, limit)}
|
||||
def list_groups(
|
||||
_parent,
|
||||
%{
|
||||
preferred_username: preferred_username,
|
||||
name: name,
|
||||
domain: domain,
|
||||
local: local,
|
||||
suspended: suspended,
|
||||
page: page,
|
||||
limit: limit
|
||||
},
|
||||
%{
|
||||
context: %{current_user: %User{role: role}}
|
||||
}
|
||||
)
|
||||
when is_moderator(role) do
|
||||
{:ok,
|
||||
Actors.list_actors(:Group, preferred_username, name, domain, local, suspended, page, limit)}
|
||||
end
|
||||
|
||||
def list_groups(_parent, _args, _resolution),
|
||||
do: {:error, "You may not list groups unless moderator."}
|
||||
|
||||
@doc """
|
||||
Create a new group. The creator is automatically added as admin
|
||||
"""
|
||||
@@ -127,28 +161,23 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
"""
|
||||
def delete_group(
|
||||
_parent,
|
||||
%{group_id: group_id, actor_id: actor_id},
|
||||
%{group_id: group_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {actor_id, ""} <- Integer.parse(actor_id),
|
||||
{group_id, ""} <- Integer.parse(group_id),
|
||||
with %Actor{id: actor_id} = actor <- Users.get_actor_for_user(user),
|
||||
{:ok, %Actor{} = group} <- Actors.get_group_by_actor_id(group_id),
|
||||
{:is_owned, %Actor{}} <- User.owns_actor(user, actor_id),
|
||||
{:ok, %Member{} = member} <- Actors.get_member(actor_id, group.id),
|
||||
{:is_admin, true} <- {:is_admin, Member.is_administrator(member)},
|
||||
group <- Actors.delete_group!(group) do
|
||||
{:ok, _activity, group} <- ActivityPub.delete(group, actor, true) do
|
||||
{:ok, %{id: group.id}}
|
||||
else
|
||||
{:error, :group_not_found} ->
|
||||
{:error, "Group not found"}
|
||||
|
||||
{:is_owned, nil} ->
|
||||
{:error, "Actor id is not owned by authenticated user"}
|
||||
|
||||
{:error, :member_not_found} ->
|
||||
{:error, "Actor id is not a member of this group"}
|
||||
|
||||
@@ -231,7 +260,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
{:group, nil} ->
|
||||
{:error, "Group not found"}
|
||||
|
||||
{:is_only_admin, true} ->
|
||||
{:is_not_only_admin, false} ->
|
||||
{:error, "You can't leave this group because you are the only administrator"}
|
||||
end
|
||||
end
|
||||
@@ -245,12 +274,13 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
||||
_args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
current_user: %User{role: user_role} = user
|
||||
}
|
||||
}
|
||||
) do
|
||||
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
{:member, true} <-
|
||||
{:member, Actors.is_member?(actor_id, group_id) or is_moderator(user_role)} do
|
||||
# TODO : Handle public / restricted to group members events
|
||||
{:ok, Events.list_organized_events_for_group(group)}
|
||||
else
|
||||
|
||||
@@ -3,6 +3,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
Handles the member-related GraphQL calls
|
||||
"""
|
||||
|
||||
import Mobilizon.Users.Guards
|
||||
alias Mobilizon.{Actors, Users}
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
@@ -19,11 +20,12 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
%Actor{id: group_id} = group,
|
||||
%{page: page, limit: limit, roles: roles},
|
||||
%{
|
||||
context: %{current_user: %User{} = user}
|
||||
context: %{current_user: %User{role: user_role} = user}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
{:member, true} <-
|
||||
{:member, Actors.is_member?(actor_id, group_id) or is_moderator(user_role)} do
|
||||
roles =
|
||||
case roles do
|
||||
"" ->
|
||||
@@ -167,9 +169,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
||||
{:error, :member_not_found} ->
|
||||
true
|
||||
|
||||
err ->
|
||||
require Logger
|
||||
Logger.error(inspect(err))
|
||||
_err ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,6 @@ defmodule Mobilizon.GraphQL.Resolvers.Person do
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Admin
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Participant
|
||||
alias Mobilizon.Storage.Page
|
||||
@@ -321,64 +320,6 @@ defmodule Mobilizon.GraphQL.Resolvers.Person do
|
||||
end
|
||||
end
|
||||
|
||||
def suspend_profile(_parent, %{id: id}, %{
|
||||
context: %{current_user: %User{role: role} = user}
|
||||
})
|
||||
when is_moderator(role) do
|
||||
with {:moderator_actor, %Actor{} = moderator_actor} <-
|
||||
{:moderator_actor, Users.get_actor_for_user(user)},
|
||||
%Actor{suspended: false} = actor <- Actors.get_remote_actor_with_preload(id),
|
||||
{:ok, _} <- Actors.delete_actor(actor),
|
||||
{:ok, _} <- Admin.log_action(moderator_actor, "suspend", actor) do
|
||||
{:ok, actor}
|
||||
else
|
||||
{:moderator_actor, nil} ->
|
||||
{:error, "No actor found for the moderator user"}
|
||||
|
||||
%Actor{suspended: true} ->
|
||||
{:error, "Actor already suspended"}
|
||||
|
||||
nil ->
|
||||
{:error, "No remote profile found with this ID"}
|
||||
|
||||
{:error, _} ->
|
||||
{:error, "Error while performing background task"}
|
||||
end
|
||||
end
|
||||
|
||||
def suspend_profile(_parent, _args, _resolution) do
|
||||
{:error, "Only moderators and administrators can suspend a profile"}
|
||||
end
|
||||
|
||||
def unsuspend_profile(_parent, %{id: id}, %{
|
||||
context: %{current_user: %User{role: role} = user}
|
||||
})
|
||||
when is_moderator(role) do
|
||||
with {:moderator_actor, %Actor{} = moderator_actor} <-
|
||||
{:moderator_actor, Users.get_actor_for_user(user)},
|
||||
%Actor{preferred_username: preferred_username, domain: domain} = actor <-
|
||||
Actors.get_remote_actor_with_preload(id, true),
|
||||
{:ok, _} <- Actors.update_actor(actor, %{suspended: false}),
|
||||
{:ok, %Actor{} = actor} <-
|
||||
ActivityPub.make_actor_from_nickname("#{preferred_username}@#{domain}"),
|
||||
{:ok, _} <- Admin.log_action(moderator_actor, "unsuspend", actor) do
|
||||
{:ok, actor}
|
||||
else
|
||||
{:moderator_actor, nil} ->
|
||||
{:error, "No actor found for the moderator user"}
|
||||
|
||||
nil ->
|
||||
{:error, "No remote profile found with this ID"}
|
||||
|
||||
{:error, _} ->
|
||||
{:error, "Error while performing background task"}
|
||||
end
|
||||
end
|
||||
|
||||
def unsuspend_profile(_parent, _args, _resolution) do
|
||||
{:error, "Only moderators and administrators can unsuspend a profile"}
|
||||
end
|
||||
|
||||
# We check that the actor is not the last administrator/creator of a group
|
||||
@spec last_admin_of_a_group?(integer()) :: boolean()
|
||||
defp last_admin_of_a_group?(actor_id) do
|
||||
|
||||
@@ -3,6 +3,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
||||
Handles the posts-related GraphQL calls
|
||||
"""
|
||||
|
||||
import Mobilizon.Users.Guards
|
||||
alias Mobilizon.{Actors, Posts, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
@@ -24,12 +25,13 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
||||
%{page: page, limit: limit} = args,
|
||||
%{
|
||||
context: %{
|
||||
current_user: %User{} = user
|
||||
current_user: %User{role: user_role} = user
|
||||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:member, true} <-
|
||||
{:member, Actors.is_member?(actor_id, group_id) or is_moderator(user_role)},
|
||||
%Page{} = page <- Posts.get_posts_for_group(group, page, limit) do
|
||||
{:ok, page}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user