Introduce instances admin page

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2021-12-28 11:42:08 +01:00
parent 65249b60f2
commit e717312de7
25 changed files with 1415 additions and 778 deletions

View File

@@ -5,7 +5,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
import Mobilizon.Users.Guards
alias Mobilizon.{Actors, Admin, Config, Events}
alias Mobilizon.{Actors, Admin, Config, Events, Instances}
alias Mobilizon.Actors.{Actor, Follower}
alias Mobilizon.Admin.{ActionLog, Setting}
alias Mobilizon.Cldr.Language
@@ -329,6 +329,79 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
{:error, :unauthenticated}
end
def get_instances(
_parent,
args,
%{
context: %{current_user: %User{role: role}}
}
)
when is_admin(role) do
{:ok,
Instances.instances(
args
|> Keyword.new()
|> Keyword.take([
:page,
:limit,
:order_by,
:direction,
:filter_domain,
:filter_follow_status,
:filter_suspend_status
])
)}
end
def get_instances(_parent, _args, %{context: %{current_user: %User{}}}) do
{:error, :unauthorized}
end
def get_instances(_parent, _args, _resolution) do
{:error, :unauthenticated}
end
def get_instance(_parent, %{domain: domain}, %{
context: %{current_user: %User{role: role}}
})
when is_admin(role) do
has_relay = Actors.has_relay?(domain)
remote_relay = Actors.get_actor_by_name("relay@#{domain}")
local_relay = Relay.get_actor()
result = %{
has_relay: has_relay,
follower_status: follow_status(remote_relay, local_relay),
followed_status: follow_status(local_relay, remote_relay)
}
{:ok, Map.merge(Instances.instance(domain), result)}
end
def get_instance(_parent, _args, %{context: %{current_user: %User{}}}) do
{:error, :unauthorized}
end
def get_instance(_parent, _args, _resolution) do
{:error, :unauthenticated}
end
def create_instance(
parent,
%{domain: domain} = args,
%{context: %{current_user: %User{role: role}}} = resolution
)
when is_admin(role) do
case Relay.follow(domain) do
{:ok, _activity, _follow} ->
Instances.refresh()
get_instance(parent, args, resolution)
{:error, err} ->
{:error, err}
end
end
@spec create_relay(any(), map(), Absinthe.Resolution.t()) ::
{:ok, Follower.t()} | {:error, any()}
def create_relay(_parent, %{address: address}, %{context: %{current_user: %User{role: role}}})
@@ -425,4 +498,15 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
:ok
end
end
@spec follow_status(Actor.t() | nil, Actor.t() | nil) :: :approved | :pending | :none
defp follow_status(follower, followed) when follower != nil and followed != nil do
case Actors.check_follow(follower, followed) do
%Follower{approved: true} -> :approved
%Follower{approved: false} -> :pending
_ -> :none
end
end
defp follow_status(_, _), do: :none
end

View File

@@ -153,6 +153,80 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
value(:custom, as: "CUSTOM", description: "Custom privacy policy text")
end
enum :instance_follow_status do
value(:approved, description: "The instance follow was approved")
value(:pending, description: "The instance follow is still pending")
value(:none, description: "There's no instance follow etablished")
end
enum :instances_sort_fields do
value(:event_count)
value(:person_count)
value(:group_count)
value(:followers_count)
value(:followings_count)
value(:reports_count)
value(:media_size)
end
enum :instance_filter_follow_status do
value(:all)
value(:following)
value(:followed)
end
enum :instance_filter_suspend_status do
value(:all)
value(:suspended)
end
@desc """
An instance representation
"""
object :instance do
field(:domain, :id, description: "The domain name of the instance")
field(:has_relay, :boolean, description: "Whether this instance has a Mobilizon relay actor")
field(:follower_status, :instance_follow_status, description: "Do we follow this instance")
field(:followed_status, :instance_follow_status, description: "Does this instance follow us?")
field(:event_count, :integer, description: "The number of events on this instance we know of")
field(:person_count, :integer,
description: "The number of profiles on this instance we know of"
)
field(:group_count, :integer, description: "The number of grouo on this instance we know of")
field(:followers_count, :integer,
description: "The number of their profiles who follow our groups"
)
field(:followings_count, :integer,
description: "The number of our profiles who follow their groups"
)
field(:reports_count, :integer,
description: "The number of reports made against profiles from this instance"
)
field(:media_size, :integer,
description: "The size of all the media files sent by actors from this instance"
)
field(:has_relay, :boolean,
description:
"Whether this instance has a relay, meaning that it's a Mobilizon instance that we can follow"
)
end
@desc """
A paginated list of instances
"""
object :paginated_instance_list do
field(:elements, list_of(:instance), description: "A list of instances")
field(:total, :integer, description: "The total number of instances in the list")
end
object :admin_queries do
@desc "Get the list of action logs"
field :action_logs, type: :paginated_action_log_list do
@@ -226,9 +300,59 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
arg(:direction, :string, default_value: :desc, description: "The sorting direction")
resolve(&Admin.list_relay_followings/3)
end
@desc """
List instances
"""
field :instances, :paginated_instance_list do
arg(:page, :integer,
default_value: 1,
description: "The page in the paginated relay followings list"
)
arg(:limit, :integer,
default_value: 10,
description: "The limit of relay followings per page"
)
arg(:order_by, :instances_sort_fields,
default_value: :event_count,
description: "The field to order by the list"
)
arg(:filter_domain, :string, default_value: nil, description: "Filter by domain")
arg(:filter_follow_status, :instance_filter_follow_status,
default_value: :all,
description: "Whether or not to filter instances by the follow status"
)
arg(:filter_suspend_status, :instance_filter_suspend_status,
default_value: :all,
description: "Whether or not to filter instances by the suspended status"
)
arg(:direction, :string, default_value: :desc, description: "The sorting direction")
resolve(&Admin.get_instances/3)
end
@desc """
Get an instance's details
"""
field :instance, :instance do
arg(:domain, non_null(:id), description: "The instance domain")
resolve(&Admin.get_instance/3)
end
end
object :admin_mutations do
@desc "Add an instance subscription"
field :add_instance, type: :instance do
arg(:domain, non_null(:string), description: "The instance domain to add")
resolve(&Admin.create_instance/3)
end
@desc "Add a relay subscription"
field :add_relay, type: :follower do
arg(:address, non_null(:string), description: "The relay hostname to add")