Create tombstone instead of object deletion

This commit is contained in:
Maxim Filippov 2018-12-24 02:25:36 +03:00
parent 61a88a6757
commit 0f412cf6e6
8 changed files with 74 additions and 8 deletions

View file

@ -1,7 +1,7 @@
defmodule Pleroma.Activity do defmodule Pleroma.Activity do
use Ecto.Schema use Ecto.Schema
alias Pleroma.{Repo, Activity, Notification} alias Pleroma.{Repo, Activity, Notification}
import Ecto.Query import Ecto.{Query, Changeset}
# https://github.com/tootsuite/mastodon/blob/master/app/models/notification.rb#L19 # https://github.com/tootsuite/mastodon/blob/master/app/models/notification.rb#L19
@mastodon_notification_types %{ @mastodon_notification_types %{
@ -103,4 +103,22 @@ def mastodon_notification_type(%Activity{data: %{"type" => unquote(ap_type)}}),
end end
def mastodon_notification_type(%Activity{}), do: nil def mastodon_notification_type(%Activity{}), do: nil
def get_tombstone(%Activity{data: data}, deleted \\ DateTime.utc_now()) do
%{
id: data["id"],
context: data["context"],
type: "tombstone",
published: data["published"],
deleted: deleted
}
end
def swap_data_with_tombstone(activity) do
tombstone = get_tombstone(activity)
activity
|> change(%{data: tombstone})
|> Repo.update()
end
end end

View file

@ -62,9 +62,27 @@ def context_mapping(context) do
Object.change(%Object{}, %{data: %{"id" => context}}) Object.change(%Object{}, %{data: %{"id" => context}})
end end
def get_tombstone(%Object{data: data}, deleted \\ DateTime.utc_now()) do
%{
id: data["id"],
type: "tombstone",
deleted: deleted
}
end
def swap_data_with_tombstone(object) do
tombstone = get_tombstone(object)
object
|> Object.change(%{data: tombstone})
|> Repo.update()
end
def delete(%Object{data: %{"id" => id}} = object) do def delete(%Object{data: %{"id" => id}} = object) do
with Repo.delete(object), with swap_data_with_tombstone(object),
Repo.delete_all(Activity.all_non_create_by_object_ap_id_q(id)), Activity.all_non_create_by_object_ap_id_q(id)
|> Repo.all()
|> Enum.each(&Activity.swap_data_with_tombstone/1),
{:ok, true} <- Cachex.del(:object_cache, "object:#{id}") do {:ok, true} <- Cachex.del(:object_cache, "object:#{id}") do
{:ok, object} {:ok, object}
end end

View file

@ -69,7 +69,12 @@ def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do
mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end) mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
if inReplyTo do if inReplyTo do
{Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []} to =
[inReplyTo.data["actor"] | mentioned_users]
|> Enum.uniq()
|> Enum.reject(&is_nil/1)
{to, []}
else else
{mentioned_users, []} {mentioned_users, []}
end end

View file

@ -1,5 +1,6 @@
defmodule Pleroma.ActivityTest do defmodule Pleroma.ActivityTest do
use Pleroma.DataCase use Pleroma.DataCase
alias Pleroma.Activity
import Pleroma.Factory import Pleroma.Factory
test "returns an activity by it's AP id" do test "returns an activity by it's AP id" do
@ -24,4 +25,28 @@ test "returns the activity that created an object" do
assert activity == found_activity assert activity == found_activity
end end
test "returns tombstone" do
activity = insert(:note_activity)
deleted = DateTime.utc_now()
assert Pleroma.Activity.get_tombstone(activity, deleted) == %{
id: activity.data["object"]["id"],
context: activity.data["context"],
type: "tombstone",
published: activity.data["published"],
deleted: deleted
}
end
test "swaps data with tombstone" do
activity = insert(:note_activity)
{:ok, deleted} = Pleroma.Activity.swap_data_with_tombstone(activity)
assert deleted.data.type == "tombstone"
found_activity = Repo.get(Activity, activity.id)
assert deleted.data.type == found_activity.data["type"]
end
end end

View file

@ -625,7 +625,7 @@ test ".delete deactivates a user, all follow relationships and all create activi
# TODO: Remove favorites, repeats, delete activities. # TODO: Remove favorites, repeats, delete activities.
refute Repo.get(Activity, activity.id) assert Repo.get(Activity, activity.id).data["type"] == "tombstone"
end end
test "get_public_key_for_ap_id fetches a user that's not in the db" do test "get_public_key_for_ap_id fetches a user that's not in the db" do

View file

@ -478,7 +478,7 @@ test "it creates a delete activity and deletes the original object" do
assert Repo.get(Activity, delete.id) != nil assert Repo.get(Activity, delete.id) != nil
assert Repo.get(Object, object.id) == nil assert Repo.get(Object, object.id).data["type"] == "tombstone"
end end
end end

View file

@ -363,7 +363,7 @@ test "it works for incoming deletes" do
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data) {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
refute Repo.get(Activity, activity.id) assert Repo.get(Activity, activity.id).data["type"] == "tombstone"
end end
test "it fails for incoming deletes with spoofed origin" do test "it fails for incoming deletes with spoofed origin" do

View file

@ -292,7 +292,7 @@ test "when you created it", %{conn: conn} do
assert %{} = json_response(conn, 200) assert %{} = json_response(conn, 200)
assert Repo.get(Activity, activity.id) == nil assert Repo.get(Activity, activity.id).data["type"] == "tombstone"
end end
test "when you didn't create it", %{conn: conn} do test "when you didn't create it", %{conn: conn} do