Introduce group basic federation, event new page and notifications

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2020-02-18 08:57:00 +01:00
parent 300ef8f245
commit 4144e9ffd0
416 changed files with 32220 additions and 16750 deletions

View File

@@ -3,23 +3,50 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
Handles the group-related GraphQL calls.
"""
alias Mobilizon.Actors
alias Mobilizon.{Actors, Events, Users}
alias Mobilizon.Actors.{Actor, Member}
alias Mobilizon.Users.User
alias Mobilizon.Federation.ActivityPub
alias Mobilizon.GraphQL.API
alias Mobilizon.GraphQL.Resolvers.Person
alias Mobilizon.Federation.ActivityPub
alias Mobilizon.Storage.Page
alias Mobilizon.Users.User
require Logger
@doc """
Find a group
"""
def find_group(
parent,
%{preferred_username: name} = args,
%{
context: %{
current_user: %User{} = user
}
}
) do
with {:ok, %Actor{id: group_id} = group} <-
ActivityPub.find_or_make_group_from_nickname(name),
{:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
group <- Person.proxify_pictures(group) do
{:ok, group}
else
{:member, false} ->
find_group(parent, args, nil)
_ ->
{:error, "Group with name #{name} not found"}
end
end
@doc """
Find a group
"""
def find_group(_parent, %{preferred_username: name}, _resolution) do
with {:ok, actor} <- ActivityPub.find_or_make_group_from_nickname(name),
actor <- Person.proxify_pictures(actor) do
%Actor{} = actor <- Person.proxify_pictures(actor),
%Actor{} = actor <- restrict_fields_for_non_member_request(actor) do
{:ok, actor}
else
_ ->
@@ -31,18 +58,21 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
Lists all groups
"""
def list_groups(_parent, %{page: page, limit: limit}, _resolution) do
{
:ok,
page
|> Actors.list_groups(limit)
|> Enum.map(fn actor -> Person.proxify_pictures(actor) end)
}
{:ok, Actors.list_groups(page, limit)}
end
@doc """
Create a new group. The creator is automatically added as admin
"""
def create_group(_parent, args, %{context: %{current_user: user}}) do
def create_group(
_parent,
args,
%{
context: %{
current_user: user
}
}
) do
with creator_actor_id <- Map.get(args, :creator_actor_id),
{:is_owned, %Actor{} = creator_actor} <- User.owns_actor(user, creator_actor_id),
args <- Map.put(args, :creator_actor, creator_actor),
@@ -68,14 +98,18 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
def delete_group(
_parent,
%{group_id: group_id, actor_id: actor_id},
%{context: %{current_user: user}}
%{
context: %{
current_user: user
}
}
) do
with {actor_id, ""} <- Integer.parse(actor_id),
{group_id, ""} <- Integer.parse(group_id),
{: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} <- Member.is_administrator(member),
{:is_admin, true} <- {:is_admin, Member.is_administrator(member)},
group <- Actors.delete_group!(group) do
{:ok, %{id: group.id}}
else
@@ -103,7 +137,11 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
def join_group(
_parent,
%{group_id: group_id, actor_id: actor_id},
%{context: %{current_user: user}}
%{
context: %{
current_user: user
}
}
) do
with {actor_id, ""} <- Integer.parse(actor_id),
{group_id, ""} <- Integer.parse(group_id),
@@ -146,7 +184,11 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
def leave_group(
_parent,
%{group_id: group_id, actor_id: actor_id},
%{context: %{current_user: user}}
%{
context: %{
current_user: user
}
}
) do
with {actor_id, ""} <- Integer.parse(actor_id),
{group_id, ""} <- Integer.parse(group_id),
@@ -156,7 +198,17 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
{: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}}}
{
:ok,
%{
parent: %{
id: group_id
},
actor: %{
id: actor_id
}
}
}
else
{:is_owned, nil} ->
{:error, "Actor id is not owned by authenticated user"}
@@ -173,17 +225,65 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
{:error, "You need to be logged-in to leave a group"}
end
def find_events_for_group(
%Actor{id: group_id} = group,
_args,
%{
context: %{
current_user: %User{} = 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
# TODO : Handle public / restricted to group members events
{:ok, Events.list_organized_events_for_group(group)}
else
{:member, false} ->
{:ok, %Page{total: 0, elements: []}}
end
end
def find_events_for_group(_parent, _args, _resolution) 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
[%Member{actor: %Actor{id: member_actor_id}}] ->
%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,
%{
followers: [],
followings: [],
organized_events: [],
comments: [],
feed_tokens: []
}
)
end
end