Introduce group posts

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2020-07-09 17:24:28 +02:00
parent bec1c69d4b
commit 9c9f1385fb
249 changed files with 11886 additions and 5023 deletions

View File

@@ -9,7 +9,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
alias Mobilizon.Actors.Actor
alias Mobilizon.Admin.{ActionLog, Setting}
alias Mobilizon.Config
alias Mobilizon.Conversations.Comment
alias Mobilizon.Discussions.Comment
alias Mobilizon.Events.Event
alias Mobilizon.Federation.ActivityPub
alias Mobilizon.Federation.ActivityPub.Relay
@@ -297,7 +297,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
with {:changes, true} <- {:changes, args != %{}},
%Actor{} = instance_actor <- Relay.get_actor(),
{:ok, _activity, _actor} <- ActivityPub.update(:actor, instance_actor, args, true) do
{:ok, _activity, _actor} <- ActivityPub.update(instance_actor, args, true) do
:ok
else
{:changes, false} ->

View File

@@ -3,9 +3,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
Handles the comment-related GraphQL calls.
"""
alias Mobilizon.{Actors, Admin, Conversations}
alias Mobilizon.{Actors, Admin, Discussions}
alias Mobilizon.Actors.Actor
alias Mobilizon.Conversations.Comment, as: CommentModel
alias Mobilizon.Discussions.Comment, as: CommentModel
alias Mobilizon.Users
alias Mobilizon.Users.User
@@ -14,7 +14,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
require Logger
def get_thread(_parent, %{id: thread_id}, _context) do
{:ok, Conversations.get_thread_replies(thread_id)}
{:ok, Discussions.get_thread_replies(thread_id)}
end
def create_comment(
@@ -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.Conversations.get_comment(comment_id),
Mobilizon.Discussions.get_comment(comment_id),
true <- actor_id === comment_actor_id,
{:ok, _, %CommentModel{} = comment} <- Comments.update_comment(comment, %{text: text}) do
{:ok, comment}
@@ -72,15 +72,15 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
}
) do
with {actor_id, ""} <- Integer.parse(actor_id),
{:is_owned, %Actor{} = _organizer_actor} <- User.owns_actor(user, actor_id),
{:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
%CommentModel{deleted_at: nil} = comment <-
Conversations.get_comment_with_preload(comment_id) do
Discussions.get_comment_with_preload(comment_id) do
cond do
{:comment_can_be_managed, true} == CommentModel.can_be_managed_by(comment, actor_id) ->
do_delete_comment(comment)
do_delete_comment(comment, actor)
role in [:moderator, :administrator] ->
with {:ok, res} <- do_delete_comment(comment),
with {:ok, res} <- do_delete_comment(comment, actor),
%Actor{} = actor <- Actors.get_actor(actor_id) do
Admin.log_action(actor, "delete", comment)
@@ -103,9 +103,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Comment do
{:error, "You are not allowed to delete a comment if not connected"}
end
defp do_delete_comment(%CommentModel{} = comment) do
defp do_delete_comment(%CommentModel{} = comment, %Actor{} = actor) do
with {:ok, _, %CommentModel{} = comment} <-
Comments.delete_comment(comment) do
Comments.delete_comment(comment, actor) do
{:ok, comment}
end
end

View File

@@ -1,110 +0,0 @@
defmodule Mobilizon.GraphQL.Resolvers.Conversation do
@moduledoc """
Handles the group-related GraphQL calls.
"""
alias Mobilizon.{Actors, Conversations, Users}
alias Mobilizon.Actors.Actor
alias Mobilizon.Conversations.Conversation, as: ConversationModel
alias Mobilizon.Storage.Page
alias Mobilizon.Users.User
def find_conversations_for_actor(
%Actor{id: group_id},
_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
{:ok, Conversations.find_conversations_for_actor(group_id)}
else
{:member, false} ->
{:ok, %Page{total: 0, elements: []}}
end
end
def find_conversations_for_actor(%Actor{}, _args, _resolution) do
{:ok, %Page{total: 0, elements: []}}
end
def get_conversation(_parent, %{id: id}, _resolution) do
{:ok, Conversations.get_conversation(id)}
end
def get_comments_for_conversation(
%ConversationModel{id: conversation_id},
%{page: page, limit: limit},
_resolution
) do
{:ok, Conversations.get_comments_for_conversation(conversation_id, page, limit)}
end
def create_conversation(
_parent,
%{title: title, text: text, actor_id: actor_id, creator_id: creator_id},
_resolution
) do
with {:ok, %ConversationModel{} = conversation} <-
Conversations.create_conversation(%{
title: title,
text: text,
actor_id: actor_id,
creator_id: creator_id
}) do
{:ok, conversation}
end
end
def reply_to_conversation(
_parent,
%{text: text, conversation_id: conversation_id},
%{
context: %{
current_user: %User{} = user
}
}
) do
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
{:no_conversation, %ConversationModel{} = conversation} <-
{:no_conversation, Conversations.get_conversation(conversation_id)},
{:ok, %ConversationModel{} = conversation} <-
Conversations.reply_to_conversation(
conversation,
%{
text: text,
actor_id: actor_id
}
) do
{:ok, conversation}
end
end
@spec update_conversation(map(), map(), map()) :: {:ok, ConversationModel.t()}
def update_conversation(
_parent,
%{title: title, conversation_id: conversation_id},
%{
context: %{
current_user: %User{} = user
}
}
) do
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
{:no_conversation, %ConversationModel{creator_id: creator_id} = conversation} <-
{:no_conversation, Conversations.get_conversation(conversation_id)},
{:check_access, true} <- {:check_access, actor_id == creator_id},
{:ok, %ConversationModel{} = conversation} <-
Conversations.update_conversation(
conversation,
%{
title: title
}
) do
{:ok, conversation}
end
end
end

View File

@@ -0,0 +1,179 @@
defmodule Mobilizon.GraphQL.Resolvers.Discussion do
@moduledoc """
Handles the group-related GraphQL calls.
"""
alias Mobilizon.{Actors, Discussions, Users}
alias Mobilizon.Actors.Actor
alias Mobilizon.Discussions.{Comment, Discussion}
alias Mobilizon.Federation.ActivityPub
alias Mobilizon.Storage.Page
alias Mobilizon.Users.User
def find_discussions_for_actor(
%Actor{id: group_id},
_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
{:ok, Discussions.find_discussions_for_actor(group_id)}
else
{:member, false} ->
{:ok, %Page{total: 0, elements: []}}
end
end
def find_discussions_for_actor(%Actor{}, _args, _resolution) do
{:ok, %Page{total: 0, elements: []}}
end
def get_discussion(_parent, %{id: id}, %{
context: %{
current_user: %User{} = user
}
}) do
with {:actor, %Actor{id: creator_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
%Discussion{actor_id: actor_id} = discussion <-
Discussions.get_discussion(id),
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)} do
{:ok, discussion}
end
end
def get_discussion(_parent, %{slug: slug}, %{
context: %{
current_user: %User{} = user
}
}) do
with {:actor, %Actor{id: creator_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
%Discussion{actor_id: actor_id} = discussion <-
Discussions.get_discussion_by_slug(slug),
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)} do
{:ok, discussion}
else
nil -> {:error, "No such discussion"}
end
end
def get_discussion(_parent, _args, _resolution),
do: {:error, "You need to be logged-in to access discussions"}
def get_comments_for_discussion(
%Discussion{id: discussion_id},
%{page: page, limit: limit},
_resolution
) do
{:ok, Discussions.get_comments_for_discussion(discussion_id, page, limit)}
end
def create_discussion(
_parent,
%{title: title, text: text, actor_id: actor_id},
%{
context: %{
current_user: %User{} = user
}
}
) do
with {:actor, %Actor{id: creator_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)},
{:ok, _activity, %Discussion{} = discussion} <-
ActivityPub.create(
:discussion,
%{
title: title,
text: text,
actor_id: actor_id,
creator_id: creator_id,
attributed_to_id: actor_id
},
true
) do
{:ok, discussion}
end
end
def reply_to_discussion(
_parent,
%{text: text, discussion_id: discussion_id},
%{
context: %{
current_user: %User{} = user
}
}
) do
with {:actor, %Actor{id: creator_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
{:no_discussion,
%Discussion{
actor_id: actor_id,
last_comment: %Comment{
id: last_comment_id,
origin_comment_id: origin_comment_id,
in_reply_to_comment_id: previous_in_reply_to_comment_id
}
} = _discussion} <-
{:no_discussion, Discussions.get_discussion(discussion_id)},
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)},
{:ok, _activity, %Discussion{} = discussion} <-
ActivityPub.create(
:discussion,
%{
text: text,
discussion_id: discussion_id,
actor_id: creator_id,
attributed_to_id: actor_id,
in_reply_to_comment_id: last_comment_id,
origin_comment_id:
origin_comment_id || previous_in_reply_to_comment_id || last_comment_id
},
true
) do
{:ok, discussion}
end
end
@spec update_discussion(map(), map(), map()) :: {:ok, Discussion.t()}
def update_discussion(
_parent,
%{title: title, discussion_id: discussion_id},
%{
context: %{
current_user: %User{} = user
}
}
) do
with {:actor, %Actor{id: creator_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
{:no_discussion, %Discussion{actor_id: actor_id} = discussion} <-
{:no_discussion, Discussions.get_discussion(discussion_id)},
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)},
{:ok, _activity, %Discussion{} = discussion} <-
ActivityPub.update(
discussion,
%{
title: title
}
) do
{:ok, discussion}
end
end
def delete_discussion(_parent, %{discussion_id: discussion_id}, %{
context: %{
current_user: %User{} = user
}
}) do
with {:actor, %Actor{id: creator_id} = actor} <- {:actor, Users.get_actor_for_user(user)},
{:no_discussion, %Discussion{actor_id: actor_id} = discussion} <-
{:no_discussion, Discussions.get_discussion(discussion_id)},
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)},
{:ok, _activity, %Discussion{} = discussion} <-
ActivityPub.delete(discussion, actor) do
{:ok, discussion}
end
end
end

View File

@@ -255,13 +255,13 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
) do
with {:ok, %Event{local: is_local} = event} <- Events.get_event_with_preload(event_id),
{actor_id, ""} <- Integer.parse(actor_id),
{:is_owned, %Actor{}} <- User.owns_actor(user, actor_id) do
{:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id) do
cond do
{:event_can_be_managed, true} == Event.can_be_managed_by(event, actor_id) ->
do_delete_event(event)
do_delete_event(event, actor)
role in [:moderator, :administrator] ->
with {:ok, res} <- do_delete_event(event, !is_local),
with {:ok, res} <- do_delete_event(event, actor, !is_local),
%Actor{} = actor <- Actors.get_actor(actor_id) do
Admin.log_action(actor, "delete", event)
@@ -284,8 +284,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
{:error, "You need to be logged-in to delete an event"}
end
defp do_delete_event(event, federate \\ true) when is_boolean(federate) do
with {:ok, _activity, event} <- API.Events.delete_event(event) do
defp do_delete_event(%Event{} = event, %Actor{} = actor, federate \\ true)
when is_boolean(federate) do
with {:ok, _activity, event} <- API.Events.delete_event(event, actor) do
{:ok, %{id: event.id}}
end
end

View File

@@ -80,7 +80,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
API.Groups.create_group(args) do
{:ok, group}
else
{:error, err} when is_bitstring(err) ->
{:error, err} when is_binary(err) ->
{:error, err}
{:is_owned, nil} ->
@@ -92,6 +92,36 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
{:error, "You need to be logged-in to create a group"}
end
@doc """
Create a new group. The creator is automatically added as admin
"""
def update_group(
_parent,
args,
%{
context: %{
current_user: %User{} = user
}
}
) do
with %Actor{} = updater_actor <- Users.get_actor_for_user(user),
args <- Map.put(args, :updater_actor, updater_actor),
{:ok, _activity, %Actor{type: :Group} = group} <-
API.Groups.update_group(args) do
{:ok, group}
else
{:error, err} when is_binary(err) ->
{:error, err}
{:is_owned, nil} ->
{:error, "Creator actor id is not owned by the current user"}
end
end
def update_group(_parent, _args, _resolution) do
{:error, "You need to be logged-in to update a group"}
end
@doc """
Delete an existing group
"""

View File

@@ -16,14 +16,26 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
"""
def find_members_for_group(
%Actor{id: group_id} = group,
_args,
%{page: page, limit: limit, roles: roles},
%{
context: %{current_user: %User{} = user}
} = _resolution
) do
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
%Page{} = page <- Actors.list_members_for_group(group) do
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
roles =
case roles do
"" ->
[]
roles ->
roles
|> String.split(",")
|> Enum.map(&String.downcase/1)
|> Enum.map(&String.to_existing_atom/1)
end
%Page{} = page = Actors.list_members_for_group(group, roles, page, limit)
{:ok, page}
else
{:member, false} ->

View File

@@ -129,7 +129,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Person do
{:find_actor, Actors.get_actor(id)},
{:is_owned, %Actor{}} <- User.owns_actor(user, actor.id),
args <- save_attached_pictures(args),
{:ok, _activity, %Actor{} = actor} <- ActivityPub.update(:actor, actor, args, true) do
{:ok, _activity, %Actor{} = actor} <- ActivityPub.update(actor, args, true) do
{:ok, actor}
else
{:find_actor, nil} ->

View File

@@ -0,0 +1,198 @@
defmodule Mobilizon.GraphQL.Resolvers.Post do
@moduledoc """
Handles the posts-related GraphQL calls
"""
alias Mobilizon.{Actors, Posts, Users}
alias Mobilizon.Actors.Actor
alias Mobilizon.Federation.ActivityPub
alias Mobilizon.Posts.Post
alias Mobilizon.Storage.Page
alias Mobilizon.Users.User
require Logger
@public_accessible_visibilities [:public, :unlisted]
@doc """
Find posts for group.
Returns only if actor requesting is a member of the group
"""
def find_posts_for_group(
%Actor{id: group_id} = group,
%{page: page, limit: limit} = args,
%{
context: %{
current_user: %User{} = user
}
} = _resolution
) do
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
%Page{} = page <- Posts.get_posts_for_group(group, page, limit) do
{:ok, page}
else
{:member, _} ->
find_posts_for_group(group, args, nil)
end
end
def find_posts_for_group(
%Actor{} = group,
%{page: page, limit: limit},
_resolution
) do
with %Page{} = page <- Posts.get_public_posts_for_group(group, page, limit) do
{:ok, page}
end
end
def find_posts_for_group(
_group,
_args,
_resolution
) do
{:ok, %Page{total: 0, elements: []}}
end
def get_post(
parent,
%{slug: slug},
%{
context: %{
current_user: %User{} = user
}
} = _resolution
) do
with {:current_actor, %Actor{id: actor_id}} <-
{:current_actor, Users.get_actor_for_user(user)},
{:post, %Post{attributed_to: %Actor{id: group_id}} = post} <-
{:post, Posts.get_post_by_slug_with_preloads(slug)},
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
{:ok, post}
else
{:member, false} -> get_post(parent, %{slug: slug}, nil)
{:post, _} -> {:error, "No such post"}
end
end
def get_post(
_parent,
%{slug: slug},
_resolution
) do
case {:post, Posts.get_post_by_slug_with_preloads(slug)} do
{:post, %Post{visibility: visibility, draft: false} = post}
when visibility in @public_accessible_visibilities ->
{:ok, post}
{:post, _} ->
{:error, "No such post"}
end
end
def get_post(_parent, _args, _resolution) do
{:error, "No such post"}
end
def create_post(
_parent,
%{attributed_to_id: group_id} = args,
%{
context: %{
current_user: %User{} = user
}
} = _resolution
) do
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
{:ok, _, %Post{} = post} <-
ActivityPub.create(
:post,
args
|> Map.put(:author_id, actor_id)
|> Map.put(:attributed_to_id, group_id),
true,
%{}
) do
{:ok, post}
else
{:own_check, _} ->
{:error, "Parent post doesn't match this group"}
{:member, _} ->
{:error, "Actor id is not member of group"}
end
end
def create_post(_parent, _args, _resolution) do
{:error, "You need to be logged-in to create posts"}
end
def update_post(
_parent,
%{id: id} = args,
%{
context: %{
current_user: %User{} = user
}
} = _resolution
) do
with {:uuid, {:ok, _uuid}} <- {:uuid, Ecto.UUID.cast(id)},
%Actor{id: actor_id} <- Users.get_actor_for_user(user),
{:post, %Post{attributed_to: %Actor{id: group_id}} = post} <-
{:post, Posts.get_post_with_preloads(id)},
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
{:ok, _, %Post{} = post} <-
ActivityPub.update(post, args, true, %{}) do
{:ok, post}
else
{:uuid, :error} ->
{:error, "Post ID is not a valid ID"}
{:post, _} ->
{:error, "Post doesn't exist"}
{:member, _} ->
{:error, "Actor id is not member of group"}
end
end
def update_post(_parent, _args, _resolution) do
{:error, "You need to be logged-in to update posts"}
end
def delete_post(
_parent,
%{id: post_id},
%{
context: %{
current_user: %User{} = user
}
} = _resolution
) do
with {:uuid, {:ok, _uuid}} <- {:uuid, Ecto.UUID.cast(post_id)},
%Actor{id: actor_id} = actor <- Users.get_actor_for_user(user),
{:post, %Post{attributed_to: %Actor{id: group_id}} = post} <-
{:post, Posts.get_post_with_preloads(post_id)},
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
{:ok, _, %Post{} = post} <-
ActivityPub.delete(post, actor) do
{:ok, post}
else
{:uuid, :error} ->
{:error, "Post ID is not a valid ID"}
{:post, _} ->
{:error, "Post doesn't exist"}
{:member, _} ->
{:error, "Actor id is not member of group"}
end
end
def delete_post(_parent, _args, _resolution) do
{:error, "You need to be logged-in to delete posts"}
end
end

View File

@@ -141,7 +141,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
{:resource, Resources.get_resource_with_preloads(resource_id)},
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
{:ok, _, %Resource{} = resource} <-
ActivityPub.update(:resource, resource, args, true, %{}) do
ActivityPub.update(resource, args, true, %{}) do
{:ok, resource}
else
{:resource, _} ->
@@ -165,12 +165,12 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
}
} = _resolution
) do
with %Actor{id: actor_id} <- Users.get_actor_for_user(user),
with %Actor{id: actor_id} = actor <- Users.get_actor_for_user(user),
{:resource, %Resource{parent_id: _parent_id, actor_id: group_id} = resource} <-
{:resource, Resources.get_resource_with_preloads(resource_id)},
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
{:ok, _, %Resource{} = resource} <-
ActivityPub.delete(resource) do
ActivityPub.delete(resource, actor) do
{:ok, resource}
else
{:resource, _} ->

View File

@@ -3,8 +3,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Tag do
Handles the tag-related GraphQL calls
"""
alias Mobilizon.Events
alias Mobilizon.{Events, Posts}
alias Mobilizon.Events.{Event, Tag}
alias Mobilizon.Posts.Post
def list_tags(_parent, %{page: page, limit: limit}, _resolution) do
tags = Mobilizon.Events.list_tags(page, limit)
@@ -16,7 +17,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Tag do
Retrieve the list of tags for an event
"""
def list_tags_for_event(%Event{id: id}, _args, _resolution) do
{:ok, Mobilizon.Events.list_tags_for_event(id)}
{:ok, Events.list_tags_for_event(id)}
end
@doc """
@@ -24,10 +25,17 @@ defmodule Mobilizon.GraphQL.Resolvers.Tag do
"""
def list_tags_for_event(%{url: url}, _args, _resolution) do
with %Event{id: event_id} <- Events.get_event_by_url(url) do
{:ok, Mobilizon.Events.list_tags_for_event(event_id)}
{:ok, Events.list_tags_for_event(event_id)}
end
end
@doc """
Retrieve the list of tags for a post
"""
def list_tags_for_post(%Post{id: id}, _args, _resolution) do
{:ok, Posts.list_tags_for_post(id)}
end
# @doc """
# Retrieve the list of related tags for a given tag ID
# """
@@ -42,7 +50,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Tag do
Retrieve the list of related tags for a parent tag
"""
def get_related_tags(%Tag{} = tag, _args, _resolution) do
with tags <- Mobilizon.Events.list_tag_neighbors(tag) do
with tags <- Events.list_tag_neighbors(tag) do
{:ok, tags}
end
end

View File

@@ -211,7 +211,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
{:todo_list, Todos.get_todo_list(todo_list_id)},
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
{:ok, _, %Todo{} = todo} <-
ActivityPub.update(:todo, todo, args, true, %{}) do
ActivityPub.update(todo, args, true, %{}) do
{:ok, todo}
else
{:todo_list, _} ->

View File

@@ -9,6 +9,7 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
alias Mobilizon.Actors.Actor
alias Mobilizon.Crypto
alias Mobilizon.Federation.ActivityPub
alias Mobilizon.Federation.ActivityPub.Relay
alias Mobilizon.Service.Auth.Authenticator
alias Mobilizon.Storage.{Page, Repo}
alias Mobilizon.Users.{Setting, User}
@@ -417,7 +418,8 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
with {:moderator_actor, %Actor{} = moderator_actor} <-
{:moderator_actor, Users.get_actor_for_user(moderator_user)},
%User{disabled: false} = user <- Users.get_user(user_id),
{:ok, %User{}} <- do_delete_account(%User{} = user) do
{:ok, %User{}} <-
do_delete_account(%User{} = user, Relay.get_actor()) do
Admin.log_action(moderator_actor, "delete", user)
else
{:moderator_actor, nil} ->
@@ -432,7 +434,7 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
{:error, "You need to be logged-in to delete your account"}
end
defp do_delete_account(%User{} = user) do
defp do_delete_account(%User{} = user, actor_performing \\ nil) do
with actors <- Users.get_actors_for_user(user),
activated <- not is_nil(user.confirmed_at),
# Detach actors from user
@@ -444,7 +446,8 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
# Launch a background job to delete actors
:ok <-
Enum.each(actors, fn actor ->
ActivityPub.delete(actor, true)
actor_performing = actor_performing || actor
ActivityPub.delete(actor, actor_performing, true)
end),
# Delete user
{:ok, user} <- Users.delete_user(user, reserve_email: activated) do