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
|
|
@ -4,14 +4,17 @@
|
|||
|
||||
defmodule Mix.Tasks.Pleroma.UserTest do
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
use Pleroma.DataCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureIO
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do
|
||||
Mix.shell(Mix.Shell.Process)
|
||||
|
|
@ -87,12 +90,17 @@ defmodule Mix.Tasks.Pleroma.UserTest do
|
|||
test "user is deleted" do
|
||||
user = insert(:user)
|
||||
|
||||
Mix.Tasks.Pleroma.User.run(["rm", user.nickname])
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
Mix.Tasks.Pleroma.User.run(["rm", user.nickname])
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ " deleted"
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ " deleted"
|
||||
assert %{deactivated: true} = User.get_by_nickname(user.nickname)
|
||||
|
||||
assert %{deactivated: true} = User.get_by_nickname(user.nickname)
|
||||
assert called(Pleroma.Web.Federator.publish(:_))
|
||||
end
|
||||
end
|
||||
|
||||
test "no user to delete" do
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ defmodule Pleroma.UserTest do
|
|||
use Pleroma.DataCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
|
|
@ -1131,7 +1130,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
User.delete_user_activities(user)
|
||||
|
||||
# TODO: Remove favorites, repeats, delete activities.
|
||||
# TODO: Test removal favorites, repeats, delete activities.
|
||||
refute Activity.get_by_id(activity.id)
|
||||
end
|
||||
|
||||
|
|
@ -1170,31 +1169,6 @@ defmodule Pleroma.UserTest do
|
|||
refute Activity.get_by_id(like_two.id)
|
||||
refute Activity.get_by_id(repeat.id)
|
||||
end
|
||||
|
||||
test_with_mock "it sends out User Delete activity",
|
||||
%{user: user},
|
||||
Pleroma.Web.ActivityPub.Publisher,
|
||||
[:passthrough],
|
||||
[] do
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
|
||||
{:ok, follower} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
|
||||
{:ok, _} = User.follow(follower, user)
|
||||
|
||||
{:ok, job} = User.delete(user)
|
||||
{:ok, _user} = ObanHelpers.perform(job)
|
||||
|
||||
assert ObanHelpers.member?(
|
||||
%{
|
||||
"op" => "publish_one",
|
||||
"params" => %{
|
||||
"inbox" => "http://mastodon.example.org/inbox",
|
||||
"id" => "pleroma:fakeid"
|
||||
}
|
||||
},
|
||||
all_enqueued(worker: Pleroma.Workers.PublisherWorker)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "get_public_key_for_ap_id fetches a user that's not in the db" do
|
||||
|
|
|
|||
|
|
@ -1332,143 +1332,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "deletion" do
|
||||
setup do: clear_config([:instance, :rewrite_policy])
|
||||
|
||||
test "it reverts deletion on error" do
|
||||
note = insert(:note_activity)
|
||||
object = Object.normalize(note)
|
||||
|
||||
with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
|
||||
assert {:error, :reverted} = ActivityPub.delete(object)
|
||||
end
|
||||
|
||||
assert Repo.aggregate(Activity, :count, :id) == 1
|
||||
assert Repo.get(Object, object.id) == object
|
||||
assert Activity.get_by_id(note.id) == note
|
||||
end
|
||||
|
||||
test "it creates a delete activity and deletes the original object" do
|
||||
note = insert(:note_activity)
|
||||
object = Object.normalize(note)
|
||||
{:ok, delete} = ActivityPub.delete(object)
|
||||
|
||||
assert delete.data["type"] == "Delete"
|
||||
assert delete.data["actor"] == note.data["actor"]
|
||||
assert delete.data["object"] == object.data["id"]
|
||||
|
||||
assert Activity.get_by_id(delete.id) != nil
|
||||
|
||||
assert Repo.get(Object, object.id).data["type"] == "Tombstone"
|
||||
end
|
||||
|
||||
test "it doesn't fail when an activity was already deleted" do
|
||||
{:ok, delete} = insert(:note_activity) |> Object.normalize() |> ActivityPub.delete()
|
||||
|
||||
assert {:ok, ^delete} = delete |> Object.normalize() |> ActivityPub.delete()
|
||||
end
|
||||
|
||||
test "decrements user note count only for public activities" do
|
||||
user = insert(:user, note_count: 10)
|
||||
|
||||
{:ok, a1} =
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "yeah",
|
||||
"visibility" => "public"
|
||||
})
|
||||
|
||||
{:ok, a2} =
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "yeah",
|
||||
"visibility" => "unlisted"
|
||||
})
|
||||
|
||||
{:ok, a3} =
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "yeah",
|
||||
"visibility" => "private"
|
||||
})
|
||||
|
||||
{:ok, a4} =
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "yeah",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
{:ok, _} = Object.normalize(a1) |> ActivityPub.delete()
|
||||
{:ok, _} = Object.normalize(a2) |> ActivityPub.delete()
|
||||
{:ok, _} = Object.normalize(a3) |> ActivityPub.delete()
|
||||
{:ok, _} = Object.normalize(a4) |> ActivityPub.delete()
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.note_count == 10
|
||||
end
|
||||
|
||||
test "it creates a delete activity and checks that it is also sent to users mentioned by the deleted object" do
|
||||
user = insert(:user)
|
||||
note = insert(:note_activity)
|
||||
object = Object.normalize(note)
|
||||
|
||||
{:ok, object} =
|
||||
object
|
||||
|> Object.change(%{
|
||||
data: %{
|
||||
"actor" => object.data["actor"],
|
||||
"id" => object.data["id"],
|
||||
"to" => [user.ap_id],
|
||||
"type" => "Note"
|
||||
}
|
||||
})
|
||||
|> Object.update_and_set_cache()
|
||||
|
||||
{:ok, delete} = ActivityPub.delete(object)
|
||||
|
||||
assert user.ap_id in delete.data["to"]
|
||||
end
|
||||
|
||||
test "decreases reply count" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "1", "visibility" => "public"})
|
||||
reply_data = %{"status" => "1", "in_reply_to_status_id" => activity.id}
|
||||
ap_id = activity.data["id"]
|
||||
|
||||
{:ok, public_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "public"))
|
||||
{:ok, unlisted_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "unlisted"))
|
||||
{:ok, private_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "private"))
|
||||
{:ok, direct_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "direct"))
|
||||
|
||||
_ = CommonAPI.delete(direct_reply.id, user2)
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 2
|
||||
|
||||
_ = CommonAPI.delete(private_reply.id, user2)
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 2
|
||||
|
||||
_ = CommonAPI.delete(public_reply.id, user2)
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 1
|
||||
|
||||
_ = CommonAPI.delete(unlisted_reply.id, user2)
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 0
|
||||
end
|
||||
|
||||
test "it passes delete activity through MRF before deleting the object" do
|
||||
Pleroma.Config.put([:instance, :rewrite_policy], Pleroma.Web.ActivityPub.MRF.DropPolicy)
|
||||
|
||||
note = insert(:note_activity)
|
||||
object = Object.normalize(note)
|
||||
|
||||
{:error, {:reject, _}} = ActivityPub.delete(object)
|
||||
|
||||
assert Activity.get_by_id(note.id)
|
||||
assert Repo.get(Object, object.id).data["type"] == object.data["type"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "timeline post-processing" do
|
||||
test "it filters broken threads" do
|
||||
user1 = insert(:user)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
|
|
@ -8,6 +10,98 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
|
|||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "deletes" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{"status" => "cancel me daddy"})
|
||||
|
||||
{:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"])
|
||||
{:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id)
|
||||
|
||||
%{user: user, valid_post_delete: valid_post_delete, valid_user_delete: valid_user_delete}
|
||||
end
|
||||
|
||||
test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do
|
||||
{:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, [])
|
||||
|
||||
assert valid_post_delete["deleted_activity_id"]
|
||||
end
|
||||
|
||||
test "it is invalid if the object isn't in a list of certain types", %{
|
||||
valid_post_delete: valid_post_delete
|
||||
} do
|
||||
object = Object.get_by_ap_id(valid_post_delete["object"])
|
||||
|
||||
data =
|
||||
object.data
|
||||
|> Map.put("type", "Like")
|
||||
|
||||
{:ok, _object} =
|
||||
object
|
||||
|> Ecto.Changeset.change(%{data: data})
|
||||
|> Object.update_and_set_cache()
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(valid_post_delete, [])
|
||||
assert {:object, {"object not in allowed types", []}} in cng.errors
|
||||
end
|
||||
|
||||
test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do
|
||||
assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, []))
|
||||
end
|
||||
|
||||
test "it's invalid if the id is missing", %{valid_post_delete: valid_post_delete} do
|
||||
no_id =
|
||||
valid_post_delete
|
||||
|> Map.delete("id")
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(no_id, [])
|
||||
|
||||
assert {:id, {"can't be blank", [validation: :required]}} in cng.errors
|
||||
end
|
||||
|
||||
test "it's invalid if the object doesn't exist", %{valid_post_delete: valid_post_delete} do
|
||||
missing_object =
|
||||
valid_post_delete
|
||||
|> Map.put("object", "http://does.not/exist")
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(missing_object, [])
|
||||
|
||||
assert {:object, {"can't find object", []}} in cng.errors
|
||||
end
|
||||
|
||||
test "it's invalid if the actor of the object and the actor of delete are from different domains",
|
||||
%{valid_post_delete: valid_post_delete} do
|
||||
valid_user = insert(:user)
|
||||
|
||||
valid_other_actor =
|
||||
valid_post_delete
|
||||
|> Map.put("actor", valid_user.ap_id)
|
||||
|
||||
assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, []))
|
||||
|
||||
invalid_other_actor =
|
||||
valid_post_delete
|
||||
|> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(invalid_other_actor, [])
|
||||
|
||||
assert {:actor, {"is not allowed to delete object", []}} in cng.errors
|
||||
end
|
||||
|
||||
test "it's valid if the actor of the object is a local superuser",
|
||||
%{valid_post_delete: valid_post_delete} do
|
||||
user =
|
||||
insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo")
|
||||
|
||||
valid_other_actor =
|
||||
valid_post_delete
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _, meta} = ObjectValidator.validate(valid_other_actor, [])
|
||||
assert meta[:do_not_federate]
|
||||
end
|
||||
end
|
||||
|
||||
describe "likes" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
defmodule Pleroma.Web.ObjectValidators.Types.RecipientsTest do
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.Types.Recipients
|
||||
use Pleroma.DataCase
|
||||
|
||||
test "it asserts that all elements of the list are object ids" do
|
||||
list = ["https://lain.com/users/lain", "invalid"]
|
||||
|
||||
assert :error == Recipients.cast(list)
|
||||
end
|
||||
|
||||
test "it works with a list" do
|
||||
list = ["https://lain.com/users/lain"]
|
||||
assert {:ok, list} == Recipients.cast(list)
|
||||
end
|
||||
|
||||
test "it works with a list with whole objects" do
|
||||
list = ["https://lain.com/users/lain", %{"id" => "https://gensokyo.2hu/users/raymoo"}]
|
||||
resulting_list = ["https://gensokyo.2hu/users/raymoo", "https://lain.com/users/lain"]
|
||||
assert {:ok, resulting_list} == Recipients.cast(list)
|
||||
end
|
||||
|
||||
test "it turns a single string into a list" do
|
||||
recipient = "https://lain.com/users/lain"
|
||||
|
||||
assert {:ok, [recipient]} == Recipients.cast(recipient)
|
||||
end
|
||||
end
|
||||
|
|
@ -3,17 +3,74 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.SideEffects
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
|
||||
describe "delete objects" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, op} = CommonAPI.post(other_user, %{"status" => "big oof"})
|
||||
{:ok, post} = CommonAPI.post(user, %{"status" => "hey", "in_reply_to_id" => op})
|
||||
object = Object.normalize(post)
|
||||
{:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
|
||||
{:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
|
||||
{:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
|
||||
{:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
|
||||
%{user: user, delete: delete, post: post, object: object, delete_user: delete_user, op: op}
|
||||
end
|
||||
|
||||
test "it handles object deletions", %{
|
||||
delete: delete,
|
||||
post: post,
|
||||
object: object,
|
||||
user: user,
|
||||
op: op
|
||||
} do
|
||||
with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
|
||||
stream_out: fn _ -> nil end,
|
||||
stream_out_participations: fn _, _ -> nil end do
|
||||
{:ok, delete, _} = SideEffects.handle(delete)
|
||||
user = User.get_cached_by_ap_id(object.data["actor"])
|
||||
|
||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
|
||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
|
||||
end
|
||||
|
||||
object = Object.get_by_id(object.id)
|
||||
assert object.data["type"] == "Tombstone"
|
||||
refute Activity.get_by_id(post.id)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.note_count == 0
|
||||
|
||||
object = Object.normalize(op.data["object"], false)
|
||||
|
||||
assert object.data["repliesCount"] == 0
|
||||
end
|
||||
|
||||
test "it handles user deletions", %{delete_user: delete, user: user} do
|
||||
{:ok, _delete, _} = SideEffects.handle(delete)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert User.get_cached_by_ap_id(user.ap_id).deactivated
|
||||
end
|
||||
end
|
||||
|
||||
describe "like objects" do
|
||||
setup do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
# 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.Transmogrifier.DeleteHandlingTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it works for incoming deletes" do
|
||||
activity = insert(:note_activity)
|
||||
deleting_user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", deleting_user.ap_id)
|
||||
|> put_in(["object", "id"], activity.data["object"])
|
||||
|
||||
{:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert id == data["id"]
|
||||
|
||||
# We delete the Create activity because we base our timelines on it.
|
||||
# This should be changed after we unify objects and activities
|
||||
refute Activity.get_by_id(activity.id)
|
||||
assert actor == deleting_user.ap_id
|
||||
|
||||
# Objects are replaced by a tombstone object.
|
||||
object = Object.normalize(activity.data["object"])
|
||||
assert object.data["type"] == "Tombstone"
|
||||
end
|
||||
|
||||
test "it fails for incoming deletes with spoofed origin" do
|
||||
activity = insert(:note_activity)
|
||||
%{ap_id: ap_id} = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo")
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", ap_id)
|
||||
|> put_in(["object", "id"], activity.data["object"])
|
||||
|
||||
assert match?({:error, _}, Transmogrifier.handle_incoming(data))
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works for incoming user deletes" do
|
||||
%{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete-user.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
{:ok, _} = Transmogrifier.handle_incoming(data)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert User.get_cached_by_ap_id(ap_id).deactivated
|
||||
end
|
||||
|
||||
test "it fails for incoming user deletes with spoofed origin" do
|
||||
%{ap_id: ap_id} = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete-user.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", ap_id)
|
||||
|
||||
assert match?({:error, _}, Transmogrifier.handle_incoming(data))
|
||||
|
||||
assert User.get_cached_by_ap_id(ap_id)
|
||||
end
|
||||
end
|
||||
|
|
@ -766,84 +766,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert user.locked == true
|
||||
end
|
||||
|
||||
test "it works for incoming deletes" do
|
||||
activity = insert(:note_activity)
|
||||
deleting_user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("id", activity.data["object"])
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|> Map.put("actor", deleting_user.ap_id)
|
||||
|
||||
{:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert id == data["id"]
|
||||
refute Activity.get_by_id(activity.id)
|
||||
assert actor == deleting_user.ap_id
|
||||
end
|
||||
|
||||
test "it fails for incoming deletes with spoofed origin" do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("id", activity.data["object"])
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|
||||
assert capture_log(fn ->
|
||||
:error = Transmogrifier.handle_incoming(data)
|
||||
end) =~
|
||||
"[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, :nxdomain}"
|
||||
|
||||
assert Activity.get_by_id(activity.id)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works for incoming user deletes" do
|
||||
%{ap_id: ap_id} =
|
||||
insert(:user, ap_id: "http://mastodon.example.org/users/admin", local: false)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete-user.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
{:ok, _} = Transmogrifier.handle_incoming(data)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
refute User.get_cached_by_ap_id(ap_id)
|
||||
end
|
||||
|
||||
test "it fails for incoming user deletes with spoofed origin" do
|
||||
%{ap_id: ap_id} = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete-user.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", ap_id)
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert :error == Transmogrifier.handle_incoming(data)
|
||||
end) =~ "Object containment failed"
|
||||
|
||||
assert User.get_cached_by_ap_id(ap_id)
|
||||
end
|
||||
|
||||
test "it works for incoming unannounces with an existing notice" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
use Pleroma.Web.ConnCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
|
|
@ -147,17 +148,26 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
test "single user", %{admin: admin, conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} deleted users: @#{user.nickname}"
|
||||
assert User.get_by_nickname(user.nickname).deactivated
|
||||
|
||||
assert json_response(conn, 200) == user.nickname
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} deleted users: @#{user.nickname}"
|
||||
|
||||
assert json_response(conn, 200) == [user.nickname]
|
||||
|
||||
assert called(Pleroma.Web.Federator.publish(:_))
|
||||
end
|
||||
end
|
||||
|
||||
test "multiple users", %{admin: admin, conn: conn} do
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.AdminAPI.AccountView
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
|
|
@ -21,6 +23,84 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
setup do: clear_config([:instance, :limit])
|
||||
setup do: clear_config([:instance, :max_pinned_statuses])
|
||||
|
||||
describe "deletion" do
|
||||
test "it allows users to delete their posts" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, post} = CommonAPI.post(user, %{"status" => "namu amida butsu"})
|
||||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
assert {:ok, delete} = CommonAPI.delete(post.id, user)
|
||||
assert delete.local
|
||||
assert called(Pleroma.Web.Federator.publish(delete))
|
||||
end
|
||||
|
||||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "it does not allow a user to delete their posts" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, post} = CommonAPI.post(user, %{"status" => "namu amida butsu"})
|
||||
|
||||
assert {:error, "Could not delete"} = CommonAPI.delete(post.id, other_user)
|
||||
assert Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "it allows moderators to delete other user's posts" do
|
||||
user = insert(:user)
|
||||
moderator = insert(:user, is_moderator: true)
|
||||
|
||||
{:ok, post} = CommonAPI.post(user, %{"status" => "namu amida butsu"})
|
||||
|
||||
assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
|
||||
assert delete.local
|
||||
|
||||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "it allows admins to delete other user's posts" do
|
||||
user = insert(:user)
|
||||
moderator = insert(:user, is_admin: true)
|
||||
|
||||
{:ok, post} = CommonAPI.post(user, %{"status" => "namu amida butsu"})
|
||||
|
||||
assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
|
||||
assert delete.local
|
||||
|
||||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "superusers deleting non-local posts won't federate the delete" do
|
||||
# This is the user of the ingested activity
|
||||
_user =
|
||||
insert(:user,
|
||||
local: false,
|
||||
ap_id: "http://mastodon.example.org/users/admin",
|
||||
last_refreshed_at: NaiveDateTime.utc_now()
|
||||
)
|
||||
|
||||
moderator = insert(:user, is_admin: true)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
{:ok, post} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
|
||||
assert delete.local
|
||||
refute called(Pleroma.Web.Federator.publish(:_))
|
||||
end
|
||||
|
||||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
end
|
||||
|
||||
test "favoriting race condition" do
|
||||
user = insert(:user)
|
||||
users_serial = insert_list(10, :user)
|
||||
|
|
|
|||
|
|
@ -210,6 +210,12 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
Worker.push_to_socket(topics, "public", activity)
|
||||
|
||||
Task.await(task)
|
||||
end
|
||||
|
||||
test "works for deletions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "Test"})
|
||||
|
||||
task =
|
||||
Task.async(fn ->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue