Merge branch 'feature/delete-validator' into 'develop'
Move deletions to the common pipeline Closes #1497 See merge request pleroma/pleroma!2441
This commit is contained in:
commit
473b0d9f3d
27 changed files with 710 additions and 385 deletions
|
|
@ -8,6 +8,8 @@ defmodule Mix.Tasks.Pleroma.User do
|
|||
alias Ecto.Changeset
|
||||
alias Pleroma.User
|
||||
alias Pleroma.UserInviteToken
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.Pipeline
|
||||
|
||||
@shortdoc "Manages Pleroma users"
|
||||
@moduledoc File.read!("docs/administration/CLI_tasks/user.md")
|
||||
|
|
@ -96,8 +98,9 @@ defmodule Mix.Tasks.Pleroma.User do
|
|||
def run(["rm", nickname]) do
|
||||
start_pleroma()
|
||||
|
||||
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
|
||||
User.perform(:delete, user)
|
||||
with %User{local: true} = user <- User.get_cached_by_nickname(nickname),
|
||||
{:ok, delete_data, _} <- Builder.delete(user, user.ap_id),
|
||||
{:ok, _delete, _} <- Pipeline.common_pipeline(delete_data, local: true) do
|
||||
shell_info("User #{nickname} deleted.")
|
||||
else
|
||||
_ -> shell_error("No local user #{nickname}")
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ defmodule Pleroma.User do
|
|||
alias Pleroma.UserRelationship
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
|
||||
alias Pleroma.Web.ActivityPub.Pipeline
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils
|
||||
|
|
@ -1425,8 +1427,6 @@ defmodule Pleroma.User do
|
|||
|
||||
@spec perform(atom(), User.t()) :: {:ok, User.t()}
|
||||
def perform(:delete, %User{} = user) do
|
||||
{:ok, _user} = ActivityPub.delete(user)
|
||||
|
||||
# Remove all relationships
|
||||
user
|
||||
|> get_followers()
|
||||
|
|
@ -1536,21 +1536,23 @@ defmodule Pleroma.User do
|
|||
})
|
||||
end
|
||||
|
||||
def delete_user_activities(%User{ap_id: ap_id}) do
|
||||
def delete_user_activities(%User{ap_id: ap_id} = user) do
|
||||
ap_id
|
||||
|> Activity.Queries.by_actor()
|
||||
|> RepoStreamer.chunk_stream(50)
|
||||
|> Stream.each(fn activities -> Enum.each(activities, &delete_activity/1) end)
|
||||
|> Stream.each(fn activities ->
|
||||
Enum.each(activities, fn activity -> delete_activity(activity, user) end)
|
||||
end)
|
||||
|> Stream.run()
|
||||
end
|
||||
|
||||
defp delete_activity(%{data: %{"type" => "Create"}} = activity) do
|
||||
activity
|
||||
|> Object.normalize()
|
||||
|> ActivityPub.delete()
|
||||
defp delete_activity(%{data: %{"type" => "Create", "object" => object}}, user) do
|
||||
{:ok, delete_data, _} = Builder.delete(user, object)
|
||||
|
||||
Pipeline.common_pipeline(delete_data, local: true)
|
||||
end
|
||||
|
||||
defp delete_activity(%{data: %{"type" => "Like"}} = activity) do
|
||||
defp delete_activity(%{data: %{"type" => "Like"}} = activity, _user) do
|
||||
object = Object.normalize(activity)
|
||||
|
||||
activity.actor
|
||||
|
|
@ -1558,7 +1560,7 @@ defmodule Pleroma.User do
|
|||
|> ActivityPub.unlike(object)
|
||||
end
|
||||
|
||||
defp delete_activity(%{data: %{"type" => "Announce"}} = activity) do
|
||||
defp delete_activity(%{data: %{"type" => "Announce"}} = activity, _user) do
|
||||
object = Object.normalize(activity)
|
||||
|
||||
activity.actor
|
||||
|
|
@ -1566,7 +1568,7 @@ defmodule Pleroma.User do
|
|||
|> ActivityPub.unannounce(object)
|
||||
end
|
||||
|
||||
defp delete_activity(_activity), do: "Doing nothing"
|
||||
defp delete_activity(_activity, _user), do: "Doing nothing"
|
||||
|
||||
def html_filter_policy(%User{no_rich_text: true}) do
|
||||
Pleroma.HTML.Scrubber.TwitterText
|
||||
|
|
|
|||
|
|
@ -519,67 +519,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
end
|
||||
end
|
||||
|
||||
@spec delete(User.t() | Object.t(), keyword()) :: {:ok, User.t() | Object.t()} | {:error, any()}
|
||||
def delete(entity, options \\ []) do
|
||||
with {:ok, result} <- Repo.transaction(fn -> do_delete(entity, options) end) do
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
defp do_delete(%User{ap_id: ap_id, follower_address: follower_address} = user, _) do
|
||||
with data <- %{
|
||||
"to" => [follower_address],
|
||||
"type" => "Delete",
|
||||
"actor" => ap_id,
|
||||
"object" => %{"type" => "Person", "id" => ap_id}
|
||||
},
|
||||
{:ok, activity} <- insert(data, true, true, true),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, user}
|
||||
end
|
||||
end
|
||||
|
||||
defp do_delete(%Object{data: %{"id" => id, "actor" => actor}} = object, options) do
|
||||
local = Keyword.get(options, :local, true)
|
||||
activity_id = Keyword.get(options, :activity_id, nil)
|
||||
actor = Keyword.get(options, :actor, actor)
|
||||
|
||||
user = User.get_cached_by_ap_id(actor)
|
||||
to = (object.data["to"] || []) ++ (object.data["cc"] || [])
|
||||
|
||||
with create_activity <- Activity.get_create_by_object_ap_id(id),
|
||||
data <-
|
||||
%{
|
||||
"type" => "Delete",
|
||||
"actor" => actor,
|
||||
"object" => id,
|
||||
"to" => to,
|
||||
"deleted_activity_id" => create_activity && create_activity.id
|
||||
}
|
||||
|> maybe_put("id", activity_id),
|
||||
{:ok, activity} <- insert(data, local, false),
|
||||
{:ok, object, _create_activity} <- Object.delete(object),
|
||||
stream_out_participations(object, user),
|
||||
_ <- decrease_replies_count_if_reply(object),
|
||||
{:ok, _actor} <- decrease_note_count_if_public(user, object),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:error, error} ->
|
||||
Repo.rollback(error)
|
||||
end
|
||||
end
|
||||
|
||||
defp do_delete(%Object{data: %{"type" => "Tombstone", "id" => ap_id}}, _) do
|
||||
activity =
|
||||
ap_id
|
||||
|> Activity.Queries.by_object_id()
|
||||
|> Activity.Queries.by_type("Delete")
|
||||
|> Repo.one()
|
||||
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
@spec block(User.t(), User.t(), String.t() | nil, boolean()) ::
|
||||
{:ok, Activity.t()} | {:error, any()}
|
||||
def block(blocker, blocked, activity_id \\ nil, local \\ true) do
|
||||
|
|
|
|||
|
|
@ -415,7 +415,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
|||
defp handle_user_activity(%User{} = user, %{"type" => "Delete"} = params) do
|
||||
with %Object{} = object <- Object.normalize(params["object"]),
|
||||
true <- user.is_moderator || user.ap_id == object.data["actor"],
|
||||
{:ok, delete} <- ActivityPub.delete(object) do
|
||||
{:ok, delete_data, _} <- Builder.delete(user, object.data["id"]),
|
||||
{:ok, delete, _} <- Pipeline.common_pipeline(delete_data, local: true) do
|
||||
{:ok, delete}
|
||||
else
|
||||
_ -> {:error, dgettext("errors", "Can't delete object")}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,33 @@ defmodule Pleroma.Web.ActivityPub.Builder do
|
|||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
|
||||
@spec delete(User.t(), String.t()) :: {:ok, map(), keyword()}
|
||||
def delete(actor, object_id) do
|
||||
object = Object.normalize(object_id, false)
|
||||
|
||||
user = !object && User.get_cached_by_ap_id(object_id)
|
||||
|
||||
to =
|
||||
case {object, user} do
|
||||
{%Object{}, _} ->
|
||||
# We are deleting an object, address everyone who was originally mentioned
|
||||
(object.data["to"] || []) ++ (object.data["cc"] || [])
|
||||
|
||||
{_, %User{follower_address: follower_address}} ->
|
||||
# We are deleting a user, address the followers of that user
|
||||
[follower_address]
|
||||
end
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
"id" => Utils.generate_activity_id(),
|
||||
"actor" => actor.ap_id,
|
||||
"object" => object_id,
|
||||
"to" => to,
|
||||
"type" => "Delete"
|
||||
}, []}
|
||||
end
|
||||
|
||||
@spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}
|
||||
def like(actor, object) do
|
||||
object_actor = User.get_cached_by_ap_id(object.data["actor"])
|
||||
|
|
|
|||
|
|
@ -11,11 +11,23 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
|||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
|
||||
|
||||
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
|
||||
def validate(object, meta)
|
||||
|
||||
def validate(%{"type" => "Delete"} = object, meta) do
|
||||
with cng <- DeleteValidator.cast_and_validate(object),
|
||||
do_not_federate <- DeleteValidator.do_not_federate?(cng),
|
||||
{:ok, object} <- Ecto.Changeset.apply_action(cng, :insert) do
|
||||
object = stringify_keys(object)
|
||||
meta = Keyword.put(meta, :do_not_federate, do_not_federate)
|
||||
{:ok, object, meta}
|
||||
end
|
||||
end
|
||||
|
||||
def validate(%{"type" => "Like"} = object, meta) do
|
||||
with {:ok, object} <-
|
||||
object |> LikeValidator.cast_and_validate() |> Ecto.Changeset.apply_action(:insert) do
|
||||
|
|
@ -24,13 +36,25 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
|||
end
|
||||
end
|
||||
|
||||
def stringify_keys(%{__struct__: _} = object) do
|
||||
object
|
||||
|> Map.from_struct()
|
||||
|> stringify_keys
|
||||
end
|
||||
|
||||
def stringify_keys(object) do
|
||||
object
|
||||
|> Map.new(fn {key, val} -> {to_string(key), val} end)
|
||||
end
|
||||
|
||||
def fetch_actor(object) do
|
||||
with {:ok, actor} <- Types.ObjectID.cast(object["actor"]) do
|
||||
User.get_or_fetch_by_ap_id(actor)
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_actor_and_object(object) do
|
||||
User.get_or_fetch_by_ap_id(object["actor"])
|
||||
fetch_actor(object)
|
||||
Object.normalize(object["object"])
|
||||
:ok
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,7 +8,29 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
|
||||
def validate_actor_presence(cng, field_name \\ :actor) do
|
||||
def validate_recipients_presence(cng, fields \\ [:to, :cc]) do
|
||||
non_empty =
|
||||
fields
|
||||
|> Enum.map(fn field -> get_field(cng, field) end)
|
||||
|> Enum.any?(fn
|
||||
[] -> false
|
||||
_ -> true
|
||||
end)
|
||||
|
||||
if non_empty do
|
||||
cng
|
||||
else
|
||||
fields
|
||||
|> Enum.reduce(cng, fn field, cng ->
|
||||
cng
|
||||
|> add_error(field, "no recipients in any field")
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
def validate_actor_presence(cng, options \\ []) do
|
||||
field_name = Keyword.get(options, :field_name, :actor)
|
||||
|
||||
cng
|
||||
|> validate_change(field_name, fn field_name, actor ->
|
||||
if User.get_cached_by_ap_id(actor) do
|
||||
|
|
@ -19,14 +41,39 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations do
|
|||
end)
|
||||
end
|
||||
|
||||
def validate_object_presence(cng, field_name \\ :object) do
|
||||
def validate_object_presence(cng, options \\ []) do
|
||||
field_name = Keyword.get(options, :field_name, :object)
|
||||
allowed_types = Keyword.get(options, :allowed_types, false)
|
||||
|
||||
cng
|
||||
|> validate_change(field_name, fn field_name, object ->
|
||||
if Object.get_cached_by_ap_id(object) do
|
||||
[]
|
||||
else
|
||||
[{field_name, "can't find object"}]
|
||||
|> validate_change(field_name, fn field_name, object_id ->
|
||||
object = Object.get_cached_by_ap_id(object_id)
|
||||
|
||||
cond do
|
||||
!object ->
|
||||
[{field_name, "can't find object"}]
|
||||
|
||||
object && allowed_types && object.data["type"] not in allowed_types ->
|
||||
[{field_name, "object not in allowed types"}]
|
||||
|
||||
true ->
|
||||
[]
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def validate_object_or_user_presence(cng, options \\ []) do
|
||||
field_name = Keyword.get(options, :field_name, :object)
|
||||
options = Keyword.put(options, :field_name, field_name)
|
||||
|
||||
actor_cng =
|
||||
cng
|
||||
|> validate_actor_presence(options)
|
||||
|
||||
object_cng =
|
||||
cng
|
||||
|> validate_object_presence(options)
|
||||
|
||||
if actor_cng.valid?, do: actor_cng, else: object_cng
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator do
|
||||
use Ecto.Schema
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
|
||||
|
||||
import Ecto.Changeset
|
||||
import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
|
||||
|
||||
@primary_key false
|
||||
|
||||
embedded_schema do
|
||||
field(:id, Types.ObjectID, primary_key: true)
|
||||
field(:type, :string)
|
||||
field(:actor, Types.ObjectID)
|
||||
field(:to, Types.Recipients, default: [])
|
||||
field(:cc, Types.Recipients, default: [])
|
||||
field(:deleted_activity_id, Types.ObjectID)
|
||||
field(:object, Types.ObjectID)
|
||||
end
|
||||
|
||||
def cast_data(data) do
|
||||
%__MODULE__{}
|
||||
|> cast(data, __schema__(:fields))
|
||||
end
|
||||
|
||||
def add_deleted_activity_id(cng) do
|
||||
object =
|
||||
cng
|
||||
|> get_field(:object)
|
||||
|
||||
with %Activity{id: id} <- Activity.get_create_by_object_ap_id(object) do
|
||||
cng
|
||||
|> put_change(:deleted_activity_id, id)
|
||||
else
|
||||
_ -> cng
|
||||
end
|
||||
end
|
||||
|
||||
@deletable_types ~w{
|
||||
Answer
|
||||
Article
|
||||
Audio
|
||||
Event
|
||||
Note
|
||||
Page
|
||||
Question
|
||||
Video
|
||||
}
|
||||
def validate_data(cng) do
|
||||
cng
|
||||
|> validate_required([:id, :type, :actor, :to, :cc, :object])
|
||||
|> validate_inclusion(:type, ["Delete"])
|
||||
|> validate_actor_presence()
|
||||
|> validate_deletion_rights()
|
||||
|> validate_object_or_user_presence(allowed_types: @deletable_types)
|
||||
|> add_deleted_activity_id()
|
||||
end
|
||||
|
||||
def do_not_federate?(cng) do
|
||||
!same_domain?(cng)
|
||||
end
|
||||
|
||||
defp same_domain?(cng) do
|
||||
actor_uri =
|
||||
cng
|
||||
|> get_field(:actor)
|
||||
|> URI.parse()
|
||||
|
||||
object_uri =
|
||||
cng
|
||||
|> get_field(:object)
|
||||
|> URI.parse()
|
||||
|
||||
object_uri.host == actor_uri.host
|
||||
end
|
||||
|
||||
def validate_deletion_rights(cng) do
|
||||
actor = User.get_cached_by_ap_id(get_field(cng, :actor))
|
||||
|
||||
if User.superuser?(actor) || same_domain?(cng) do
|
||||
cng
|
||||
else
|
||||
cng
|
||||
|> add_error(:actor, "is not allowed to delete object")
|
||||
end
|
||||
end
|
||||
|
||||
def cast_and_validate(data) do
|
||||
data
|
||||
|> cast_data
|
||||
|> validate_data
|
||||
end
|
||||
end
|
||||
|
|
@ -20,8 +20,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do
|
|||
field(:object, Types.ObjectID)
|
||||
field(:actor, Types.ObjectID)
|
||||
field(:context, :string)
|
||||
field(:to, {:array, :string}, default: [])
|
||||
field(:cc, {:array, :string}, default: [])
|
||||
field(:to, Types.Recipients, default: [])
|
||||
field(:cc, Types.Recipients, default: [])
|
||||
end
|
||||
|
||||
def cast_and_validate(data) do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.Recipients do
|
||||
use Ecto.Type
|
||||
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID
|
||||
|
||||
def type, do: {:array, ObjectID}
|
||||
|
||||
def cast(object) when is_binary(object) do
|
||||
cast([object])
|
||||
end
|
||||
|
||||
def cast(data) when is_list(data) do
|
||||
data
|
||||
|> Enum.reduce({:ok, []}, fn element, acc ->
|
||||
case {acc, ObjectID.cast(element)} do
|
||||
{:error, _} -> :error
|
||||
{_, :error} -> :error
|
||||
{{:ok, list}, {:ok, id}} -> {:ok, [id | list]}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def cast(_) do
|
||||
:error
|
||||
end
|
||||
|
||||
def dump(data) do
|
||||
{:ok, data}
|
||||
end
|
||||
|
||||
def load(data) do
|
||||
{:ok, data}
|
||||
end
|
||||
end
|
||||
|
|
@ -44,7 +44,9 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
|
|||
|
||||
defp maybe_federate(%Activity{} = activity, meta) do
|
||||
with {:ok, local} <- Keyword.fetch(meta, :local) do
|
||||
if local do
|
||||
do_not_federate = meta[:do_not_federate]
|
||||
|
||||
if !do_not_federate && local do
|
||||
Federator.publish(activity)
|
||||
{:ok, :federated}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
"""
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
|
||||
def handle(object, meta \\ [])
|
||||
|
|
@ -23,6 +25,49 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
{:ok, object, meta}
|
||||
end
|
||||
|
||||
# Tasks this handles:
|
||||
# - Delete and unpins the create activity
|
||||
# - Replace object with Tombstone
|
||||
# - Set up notification
|
||||
# - Reduce the user note count
|
||||
# - Reduce the reply count
|
||||
# - Stream out the activity
|
||||
def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
|
||||
deleted_object =
|
||||
Object.normalize(deleted_object, false) || User.get_cached_by_ap_id(deleted_object)
|
||||
|
||||
result =
|
||||
case deleted_object do
|
||||
%Object{} ->
|
||||
with {:ok, deleted_object, activity} <- Object.delete(deleted_object),
|
||||
%User{} = user <- User.get_cached_by_ap_id(deleted_object.data["actor"]) do
|
||||
User.remove_pinnned_activity(user, activity)
|
||||
|
||||
{:ok, user} = ActivityPub.decrease_note_count_if_public(user, deleted_object)
|
||||
|
||||
if in_reply_to = deleted_object.data["inReplyTo"] do
|
||||
Object.decrease_replies_count(in_reply_to)
|
||||
end
|
||||
|
||||
ActivityPub.stream_out(object)
|
||||
ActivityPub.stream_out_participations(deleted_object, user)
|
||||
:ok
|
||||
end
|
||||
|
||||
%User{} ->
|
||||
with {:ok, _} <- User.delete(deleted_object) do
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
if result == :ok do
|
||||
Notification.create_notifications(object)
|
||||
{:ok, object, meta}
|
||||
else
|
||||
{:error, result}
|
||||
end
|
||||
end
|
||||
|
||||
# Nothing to do
|
||||
def handle(object, meta) do
|
||||
{:ok, object, meta}
|
||||
|
|
|
|||
|
|
@ -735,36 +735,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: We presently assume that any actor on the same origin domain as the object being
|
||||
# deleted has the rights to delete that object. A better way to validate whether or not
|
||||
# the object should be deleted is to refetch the object URI, which should return either
|
||||
# an error or a tombstone. This would allow us to verify that a deletion actually took
|
||||
# place.
|
||||
def handle_incoming(
|
||||
%{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data,
|
||||
%{"type" => "Delete"} = data,
|
||||
_options
|
||||
) do
|
||||
object_id = Utils.get_ap_id(object_id)
|
||||
|
||||
with actor <- Containment.get_actor(data),
|
||||
{:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor),
|
||||
{:ok, object} <- get_obj_helper(object_id),
|
||||
:ok <- Containment.contain_origin(actor.ap_id, object.data),
|
||||
{:ok, activity} <-
|
||||
ActivityPub.delete(object, local: false, activity_id: id, actor: actor.ap_id) do
|
||||
with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
|
||||
{:ok, activity}
|
||||
else
|
||||
nil ->
|
||||
case User.get_cached_by_ap_id(object_id) do
|
||||
%User{ap_id: ^actor} = user ->
|
||||
User.delete(user)
|
||||
|
||||
nil ->
|
||||
:error
|
||||
end
|
||||
|
||||
_e ->
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
#### Announce-related helpers
|
||||
|
||||
@doc """
|
||||
Retruns an existing announce activity if the notice has already been announced
|
||||
Returns an existing announce activity if the notice has already been announced
|
||||
"""
|
||||
@spec get_existing_announce(String.t(), map()) :: Activity.t() | nil
|
||||
def get_existing_announce(actor, %{data: %{"id" => ap_id}}) do
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
alias Pleroma.User
|
||||
alias Pleroma.UserInviteToken
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.Pipeline
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.AdminAPI.AccountView
|
||||
|
|
@ -133,23 +135,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
|
||||
action_fallback(:errors)
|
||||
|
||||
def user_delete(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
|
||||
user = User.get_cached_by_nickname(nickname)
|
||||
User.delete(user)
|
||||
|
||||
ModerationLog.insert_log(%{
|
||||
actor: admin,
|
||||
subject: [user],
|
||||
action: "delete"
|
||||
})
|
||||
|
||||
conn
|
||||
|> json(nickname)
|
||||
def user_delete(conn, %{"nickname" => nickname}) do
|
||||
user_delete(conn, %{"nicknames" => [nickname]})
|
||||
end
|
||||
|
||||
def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
|
||||
users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
|
||||
User.delete(users)
|
||||
users =
|
||||
nicknames
|
||||
|> Enum.map(&User.get_cached_by_nickname/1)
|
||||
|
||||
users
|
||||
|> Enum.each(fn user ->
|
||||
{:ok, delete_data, _} = Builder.delete(admin, user.ap_id)
|
||||
Pipeline.common_pipeline(delete_data, local: true)
|
||||
end)
|
||||
|
||||
ModerationLog.insert_log(%{
|
||||
actor: admin,
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
{:find_activity, Activity.get_by_id_with_object(activity_id)},
|
||||
%Object{} = object <- Object.normalize(activity),
|
||||
true <- User.superuser?(user) || user.ap_id == object.data["actor"],
|
||||
{:ok, _} <- unpin(activity_id, user),
|
||||
{:ok, delete} <- ActivityPub.delete(object) do
|
||||
{:ok, delete_data, _} <- Builder.delete(user, object.data["id"]),
|
||||
{:ok, delete, _} <- Pipeline.common_pipeline(delete_data, local: true) do
|
||||
{:ok, delete}
|
||||
else
|
||||
{:find_activity, _} -> {:error, :not_found}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue