From b8056e69e0a2505fc466dd5742b0986b7c1895ae Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 29 Apr 2020 19:08:08 +0200 Subject: Object Validator Types: Add Recipients. --- .../object_validators/types/recipients_test.exs | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/web/activity_pub/object_validators/types/recipients_test.exs (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validators/types/recipients_test.exs b/test/web/activity_pub/object_validators/types/recipients_test.exs new file mode 100644 index 000000000..f278f039b --- /dev/null +++ b/test/web/activity_pub/object_validators/types/recipients_test.exs @@ -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 -- cgit v1.2.3 From 503de4b8df0bfc34008c3c856edc488633290f0e Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 29 Apr 2020 19:09:51 +0200 Subject: ObjectValidator: Add validation for `Delete`s. --- test/web/activity_pub/object_validator_test.exs | 67 +++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 3c5c3696e..64b9ee1ec 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -1,6 +1,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do use Pleroma.DataCase + alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.ObjectValidator alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator alias Pleroma.Web.ActivityPub.Utils @@ -8,6 +9,72 @@ 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"]) + + %{user: user, valid_post_delete: valid_post_delete} + end + + test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do + assert match?({:ok, _, _}, ObjectValidator.validate(valid_post_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_other_actor = + valid_post_delete + |> Map.put("actor", valid_post_delete["actor"] <> "1") + + 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 invalid if all the recipient fields are empty", %{ + valid_post_delete: valid_post_delete + } do + empty_recipients = + valid_post_delete + |> Map.put("to", []) + |> Map.put("cc", []) + + {:error, cng} = ObjectValidator.validate(empty_recipients, []) + + assert {:to, {"no recipients in any field", []}} in cng.errors + assert {:cc, {"no recipients in any field", []}} in cng.errors + end + end + describe "likes" do setup do user = insert(:user) -- cgit v1.2.3 From bd219ba7e884d694cc1c8747f0b48cd646821222 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 14:14:00 +0200 Subject: Transmogrifier Tests: Extract deletion tests. --- .../transmogrifier/delete_handling_test.exs | 106 +++++++++++++++++++++ test/web/activity_pub/transmogrifier_test.exs | 77 --------------- 2 files changed, 106 insertions(+), 77 deletions(-) create mode 100644 test/web/activity_pub/transmogrifier/delete_handling_test.exs (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/transmogrifier/delete_handling_test.exs b/test/web/activity_pub/transmogrifier/delete_handling_test.exs new file mode 100644 index 000000000..c15de5a95 --- /dev/null +++ b/test/web/activity_pub/transmogrifier/delete_handling_test.exs @@ -0,0 +1,106 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# 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 + import ExUnit.CaptureLog + + 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!() + + 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"] + + # We delete the Create activity because 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) + + 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") + + 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 +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 6057e360a..64e56d378 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -822,83 +822,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") - - 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"}) -- cgit v1.2.3 From db184a8eb495865334f47a24f8c5b1fec65450b6 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 14:37:14 +0200 Subject: DeleteValidator: Mastodon sends unaddressed deletes. --- test/web/activity_pub/object_validator_test.exs | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 64b9ee1ec..ab26d3501 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -59,20 +59,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do assert {:actor, {"is not allowed to delete object", []}} in cng.errors end - - test "it's invalid if all the recipient fields are empty", %{ - valid_post_delete: valid_post_delete - } do - empty_recipients = - valid_post_delete - |> Map.put("to", []) - |> Map.put("cc", []) - - {:error, cng} = ObjectValidator.validate(empty_recipients, []) - - assert {:to, {"no recipients in any field", []}} in cng.errors - assert {:cc, {"no recipients in any field", []}} in cng.errors - end end describe "likes" do -- cgit v1.2.3 From 4dc5302f455e56d3c2cb669e8a70f52457690a86 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 15:26:23 +0200 Subject: Transmogrifier: Handle incoming deletes for non-user objects. --- test/web/activity_pub/side_effects_test.exs | 23 ++++++++++++++++++++++ .../transmogrifier/delete_handling_test.exs | 6 ++---- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index 0b6b55156..eec9488e7 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -5,6 +5,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do use Pleroma.DataCase + alias Pleroma.Activity alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Repo @@ -15,6 +16,28 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do import Pleroma.Factory + describe "delete objects" do + setup do + user = insert(:user) + {:ok, post} = CommonAPI.post(user, %{"status" => "hey"}) + object = Object.normalize(post) + {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"]) + {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true) + %{user: user, delete: delete, post: post, object: object} + end + + test "it handles object deletions", %{delete: delete, post: post, object: object} do + # In object deletions, the object is replaced by a tombstone and the + # create activity is deleted + + {:ok, _delete, _} = SideEffects.handle(delete) + + object = Object.get_by_id(object.id) + assert object.data["type"] == "Tombstone" + refute Activity.get_by_id(post.id) + end + end + describe "like objects" do setup do poster = insert(:user) diff --git a/test/web/activity_pub/transmogrifier/delete_handling_test.exs b/test/web/activity_pub/transmogrifier/delete_handling_test.exs index c15de5a95..64c908a05 100644 --- a/test/web/activity_pub/transmogrifier/delete_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/delete_handling_test.exs @@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do |> Map.put("object", object) assert capture_log(fn -> - :error = Transmogrifier.handle_incoming(data) + {:error, _} = Transmogrifier.handle_incoming(data) end) =~ "[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, :nxdomain}" @@ -97,9 +97,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do |> Poison.decode!() |> Map.put("actor", ap_id) - assert capture_log(fn -> - assert :error == Transmogrifier.handle_incoming(data) - end) =~ "Object containment failed" + assert match?({:error, _}, Transmogrifier.handle_incoming(data)) assert User.get_cached_by_ap_id(ap_id) end -- cgit v1.2.3 From 1fb383f368b861d7aea77770ba7be6e3dfe3468e Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 15:42:30 +0200 Subject: DeleteValidator: Deleting a user is valid. --- test/web/activity_pub/object_validator_test.exs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index ab26d3501..83b21a9bc 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -15,14 +15,19 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do {: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} + %{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 assert match?({:ok, _, _}, ObjectValidator.validate(valid_post_delete, [])) 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 -- cgit v1.2.3 From 417eed4a2b10b0a1fd916839ddb03d0345966123 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 15:57:27 +0200 Subject: SideEffects: Handle deletions. --- test/web/activity_pub/side_effects_test.exs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index eec9488e7..b3d0addc7 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -3,12 +3,15 @@ # 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.User + alias Pleroma.Tests.ObanHelpers alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.SideEffects @@ -22,8 +25,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do {:ok, post} = CommonAPI.post(user, %{"status" => "hey"}) 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) - %{user: user, delete: delete, post: post, object: object} + {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true) + %{user: user, delete: delete, post: post, object: object, delete_user: delete_user} end test "it handles object deletions", %{delete: delete, post: post, object: object} do @@ -36,6 +41,13 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do assert object.data["type"] == "Tombstone" refute Activity.get_by_id(post.id) end + + test "it handles user deletions", %{delete_user: delete, user: user} do + {:ok, _delete, _} = SideEffects.handle(delete) + ObanHelpers.perform_all() + + refute User.get_cached_by_ap_id(user.ap_id) + end end describe "like objects" do -- cgit v1.2.3 From c9bfa51ea9c0048ffa4c0d3e28c196da2f38e384 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 15:58:37 +0200 Subject: Credo fixes. --- test/web/activity_pub/side_effects_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index b3d0addc7..fffe0ca38 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -10,8 +10,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Repo - alias Pleroma.User alias Pleroma.Tests.ObanHelpers + alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.SideEffects -- cgit v1.2.3 From 4500fdc04c528331f7289745dc08a34ce18d4da7 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 17:53:02 +0200 Subject: DeleteValidator: Add internal helper field after validation. --- test/web/activity_pub/object_validator_test.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 83b21a9bc..9e0589722 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -21,7 +21,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do end test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do - assert match?({:ok, _, _}, ObjectValidator.validate(valid_post_delete, [])) + {:ok, valid_post_delete_u, _} = ObjectValidator.validate(valid_post_delete, []) + + assert valid_post_delete_u["deleted_activity_id"] end test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do -- cgit v1.2.3 From 315b773dd9fa185aef75b115efd90ac92113e6c3 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 17:58:31 +0200 Subject: ObjectValidator: Refactor. --- test/web/activity_pub/object_validator_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 9e0589722..1d3646487 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -21,9 +21,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do end test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do - {:ok, valid_post_delete_u, _} = ObjectValidator.validate(valid_post_delete, []) + {:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, []) - assert valid_post_delete_u["deleted_activity_id"] + assert valid_post_delete["deleted_activity_id"] end test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do -- cgit v1.2.3 From 3d0dc58e2e0a84cb46df5339596205f7baceb0a4 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 18:10:36 +0200 Subject: SideEffectsTest: Test streaming. --- test/web/activity_pub/side_effects_test.exs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index fffe0ca38..f5c57d887 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -18,6 +18,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do alias Pleroma.Web.CommonAPI import Pleroma.Factory + import Mock describe "delete objects" do setup do @@ -33,9 +34,16 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do test "it handles object deletions", %{delete: delete, post: post, object: object} do # In object deletions, the object is replaced by a tombstone and the - # create activity is deleted + # create activity is deleted. - {:ok, _delete, _} = SideEffects.handle(delete) + with_mock Pleroma.Web.ActivityPub.ActivityPub, + 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" -- cgit v1.2.3 From ab60ee17765ee9d7dcb69cbf9c0630b97d4f5a93 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 18:19:39 +0200 Subject: SideEffects: On deletion, reduce the User note count. --- test/web/activity_pub/side_effects_test.exs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index f5c57d887..06b3400d8 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -32,15 +32,16 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do %{user: user, delete: delete, post: post, object: object, delete_user: delete_user} end - test "it handles object deletions", %{delete: delete, post: post, object: object} do + test "it handles object deletions", %{delete: delete, post: post, object: object, user: user} do # In object deletions, the object is replaced by a tombstone and the # create activity is deleted. - with_mock Pleroma.Web.ActivityPub.ActivityPub, + 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 @@ -48,6 +49,9 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do 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 end test "it handles user deletions", %{delete_user: delete, user: user} do -- cgit v1.2.3 From 500f5ec14eb02cd1c5a07970a557756b590caab0 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 19:47:13 +0200 Subject: SideEffects: On deletion, reduce the reply count cache --- test/web/activity_pub/side_effects_test.exs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index 06b3400d8..ce34eed4c 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -23,19 +23,25 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do describe "delete objects" do setup do user = insert(:user) - {:ok, post} = CommonAPI.post(user, %{"status" => "hey"}) + 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} + %{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} do - # In object deletions, the object is replaced by a tombstone and the - # create activity is deleted. - + 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 @@ -52,6 +58,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do 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 -- cgit v1.2.3 From 999d639873b70f75c340dbac3360d25bca27a998 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 20:13:47 +0200 Subject: ActivityPub: Remove `delete` function. This is handled by the common pipeline now. --- test/web/activity_pub/activity_pub_test.exs | 137 ---------------------------- 1 file changed, 137 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index edd7dfb22..b93ee708e 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -1331,143 +1331,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) -- cgit v1.2.3 From 32b8386edeec3e9b24123c3ccc81a22f1edd5a1c Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 30 Apr 2020 21:23:18 +0200 Subject: DeleteValidator: Don't federate local deletions of remote objects. Closes #1497 --- test/web/activity_pub/object_validator_test.exs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 1d3646487..412db09ff 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -52,9 +52,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do 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_post_delete["actor"] <> "1") + |> Map.put("actor", valid_user.ap_id) assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, [])) @@ -66,6 +68,19 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do 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 -- cgit v1.2.3 From 5f42e6629d862f0a8dcbbd1527998685b6932d52 Mon Sep 17 00:00:00 2001 From: lain Date: Fri, 1 May 2020 13:34:47 +0200 Subject: DeleteValidator: Only allow deletion of certain types. --- test/web/activity_pub/object_validator_test.exs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 412db09ff..7ab1c8ffb 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -1,6 +1,7 @@ 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 @@ -26,6 +27,24 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do 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 -- cgit v1.2.3 From 4dfc617cdf1c2579f4f941dcd0fa5c728178df06 Mon Sep 17 00:00:00 2001 From: lain Date: Sun, 3 May 2020 12:51:28 +0200 Subject: Transmogrifier: Don't fetch actor that's guaranteed to be there. --- .../transmogrifier/delete_handling_test.exs | 30 +++++----------------- 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/transmogrifier/delete_handling_test.exs b/test/web/activity_pub/transmogrifier/delete_handling_test.exs index 64c908a05..c141e25bc 100644 --- a/test/web/activity_pub/transmogrifier/delete_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/delete_handling_test.exs @@ -13,7 +13,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do alias Pleroma.Web.ActivityPub.Transmogrifier import Pleroma.Factory - import ExUnit.CaptureLog setup_all do Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -27,22 +26,15 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do 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) + |> 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 base our timelines on it. + # 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 @@ -54,25 +46,15 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do 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"]) - 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) + assert match?({:error, _}, Transmogrifier.handle_incoming(data)) end @tag capture_log: true -- cgit v1.2.3 From 6c337489f4db28f78be940bef01ef3a80e279ffc Mon Sep 17 00:00:00 2001 From: lain Date: Sun, 3 May 2020 13:01:19 +0200 Subject: Various testing fixes in relation to user deletion. --- test/web/activity_pub/side_effects_test.exs | 2 +- test/web/activity_pub/transmogrifier/delete_handling_test.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index ce34eed4c..a9598d7b3 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do {:ok, _delete, _} = SideEffects.handle(delete) ObanHelpers.perform_all() - refute User.get_cached_by_ap_id(user.ap_id) + assert User.get_cached_by_ap_id(user.ap_id).deactivated end end diff --git a/test/web/activity_pub/transmogrifier/delete_handling_test.exs b/test/web/activity_pub/transmogrifier/delete_handling_test.exs index c141e25bc..f235a8e63 100644 --- a/test/web/activity_pub/transmogrifier/delete_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/delete_handling_test.exs @@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do {:ok, _} = Transmogrifier.handle_incoming(data) ObanHelpers.perform_all() - refute User.get_cached_by_ap_id(ap_id) + assert User.get_cached_by_ap_id(ap_id).deactivated end test "it fails for incoming user deletes with spoofed origin" do -- cgit v1.2.3 From 6400998820084c7b81a53bbeb705b0eb2c0a0e1b Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 5 May 2020 10:12:37 +0200 Subject: AP C2S: Restrict creation to `Note`s for now. --- test/web/activity_pub/activity_pub_controller_test.exs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index a8f1f0e26..9a085ffc5 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -815,6 +815,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert object["content"] == activity["object"]["content"] end + test "it rejects anything beyond 'Note' creations", %{conn: conn, activity: activity} do + user = insert(:user) + + activity = + activity + |> put_in(["object", "type"], "Benis") + + _result = + conn + |> assign(:user, user) + |> put_req_header("content-type", "application/activity+json") + |> post("/users/#{user.nickname}/outbox", activity) + |> json_response(400) + end + test "it inserts an incoming sensitive activity into the database", %{ conn: conn, activity: activity -- cgit v1.2.3 From 8b2457bdbf8791923701b0b015f6ddf2e7c89bf7 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 5 May 2020 13:25:34 +0200 Subject: Transmogrifier tests: Extract Undo handling --- .../transmogrifier/undo_handling_test.exs | 185 +++++++++++++++++++++ test/web/activity_pub/transmogrifier_test.exs | 161 ------------------ 2 files changed, 185 insertions(+), 161 deletions(-) create mode 100644 test/web/activity_pub/transmogrifier/undo_handling_test.exs (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs new file mode 100644 index 000000000..a9ebfdb18 --- /dev/null +++ b/test/web/activity_pub/transmogrifier/undo_handling_test.exs @@ -0,0 +1,185 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.User + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + test "it works for incoming emoji reaction undos" do + user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"}) + {:ok, reaction_activity, _object} = CommonAPI.react_with_emoji(activity.id, user, "👌") + + data = + File.read!("test/fixtures/mastodon-undo-like.json") + |> Poison.decode!() + |> Map.put("object", reaction_activity.data["id"]) + |> Map.put("actor", user.ap_id) + + {:ok, activity} = Transmogrifier.handle_incoming(data) + + assert activity.actor == user.ap_id + assert activity.data["id"] == data["id"] + assert activity.data["type"] == "Undo" + end + + test "it returns an error for incoming unlikes wihout a like activity" do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"}) + + data = + File.read!("test/fixtures/mastodon-undo-like.json") + |> Poison.decode!() + |> Map.put("object", activity.data["object"]) + + assert Transmogrifier.handle_incoming(data) == :error + end + + test "it works for incoming unlikes with an existing like activity" do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"}) + + like_data = + File.read!("test/fixtures/mastodon-like.json") + |> Poison.decode!() + |> Map.put("object", activity.data["object"]) + + _liker = insert(:user, ap_id: like_data["actor"], local: false) + + {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data) + + data = + File.read!("test/fixtures/mastodon-undo-like.json") + |> Poison.decode!() + |> Map.put("object", like_data) + |> Map.put("actor", like_data["actor"]) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + assert data["actor"] == "http://mastodon.example.org/users/admin" + assert data["type"] == "Undo" + assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo" + assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2" + end + + test "it works for incoming unlikes with an existing like activity and a compact object" do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"}) + + like_data = + File.read!("test/fixtures/mastodon-like.json") + |> Poison.decode!() + |> Map.put("object", activity.data["object"]) + + _liker = insert(:user, ap_id: like_data["actor"], local: false) + + {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data) + + data = + File.read!("test/fixtures/mastodon-undo-like.json") + |> Poison.decode!() + |> Map.put("object", like_data["id"]) + |> Map.put("actor", like_data["actor"]) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + assert data["actor"] == "http://mastodon.example.org/users/admin" + assert data["type"] == "Undo" + assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo" + assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2" + end + + test "it works for incoming unannounces with an existing notice" do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"}) + + announce_data = + File.read!("test/fixtures/mastodon-announce.json") + |> Poison.decode!() + |> Map.put("object", activity.data["object"]) + + _announcer = insert(:user, ap_id: announce_data["actor"], local: false) + + {:ok, %Activity{data: announce_data, local: false}} = + Transmogrifier.handle_incoming(announce_data) + + data = + File.read!("test/fixtures/mastodon-undo-announce.json") + |> Poison.decode!() + |> Map.put("object", announce_data) + |> Map.put("actor", announce_data["actor"]) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + assert data["type"] == "Undo" + assert object_data = data["object"] + assert object_data["type"] == "Announce" + assert object_data["object"] == activity.data["object"] + + assert object_data["id"] == + "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" + end + + test "it works for incomming unfollows with an existing follow" do + user = insert(:user) + + follow_data = + File.read!("test/fixtures/mastodon-follow-activity.json") + |> Poison.decode!() + |> Map.put("object", user.ap_id) + + _follower = insert(:user, ap_id: follow_data["actor"], local: false) + + {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data) + + data = + File.read!("test/fixtures/mastodon-unfollow-activity.json") + |> Poison.decode!() + |> Map.put("object", follow_data) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + assert data["type"] == "Undo" + assert data["object"]["type"] == "Follow" + assert data["object"]["object"] == user.ap_id + assert data["actor"] == "http://mastodon.example.org/users/admin" + + refute User.following?(User.get_cached_by_ap_id(data["actor"]), user) + end + + test "it works for incoming unblocks with an existing block" do + user = insert(:user) + + block_data = + File.read!("test/fixtures/mastodon-block-activity.json") + |> Poison.decode!() + |> Map.put("object", user.ap_id) + + _blocker = insert(:user, ap_id: block_data["actor"], local: false) + + {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data) + + data = + File.read!("test/fixtures/mastodon-unblock-activity.json") + |> Poison.decode!() + |> Map.put("object", block_data) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + assert data["type"] == "Undo" + assert data["object"]["type"] == "Block" + assert data["object"]["object"] == user.ap_id + assert data["actor"] == "http://mastodon.example.org/users/admin" + + blocker = User.get_cached_by_ap_id(data["actor"]) + + refute User.blocks?(blocker, user) + end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 23efa4be6..a315ff42d 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -362,87 +362,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert :error = Transmogrifier.handle_incoming(data) end - test "it works for incoming emoji reaction undos" do - user = insert(:user) - - {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"}) - {:ok, reaction_activity, _object} = CommonAPI.react_with_emoji(activity.id, user, "👌") - - data = - File.read!("test/fixtures/mastodon-undo-like.json") - |> Poison.decode!() - |> Map.put("object", reaction_activity.data["id"]) - |> Map.put("actor", user.ap_id) - - {:ok, activity} = Transmogrifier.handle_incoming(data) - - assert activity.actor == user.ap_id - assert activity.data["id"] == data["id"] - assert activity.data["type"] == "Undo" - end - - test "it returns an error for incoming unlikes wihout a like activity" do - user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"}) - - data = - File.read!("test/fixtures/mastodon-undo-like.json") - |> Poison.decode!() - |> Map.put("object", activity.data["object"]) - - assert Transmogrifier.handle_incoming(data) == :error - end - - test "it works for incoming unlikes with an existing like activity" do - user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"}) - - like_data = - File.read!("test/fixtures/mastodon-like.json") - |> Poison.decode!() - |> Map.put("object", activity.data["object"]) - - {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data) - - data = - File.read!("test/fixtures/mastodon-undo-like.json") - |> Poison.decode!() - |> Map.put("object", like_data) - |> Map.put("actor", like_data["actor"]) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["actor"] == "http://mastodon.example.org/users/admin" - assert data["type"] == "Undo" - assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo" - assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2" - end - - test "it works for incoming unlikes with an existing like activity and a compact object" do - user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"}) - - like_data = - File.read!("test/fixtures/mastodon-like.json") - |> Poison.decode!() - |> Map.put("object", activity.data["object"]) - - {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data) - - data = - File.read!("test/fixtures/mastodon-undo-like.json") - |> Poison.decode!() - |> Map.put("object", like_data["id"]) - |> Map.put("actor", like_data["actor"]) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["actor"] == "http://mastodon.example.org/users/admin" - assert data["type"] == "Undo" - assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo" - assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2" - end - test "it works for incoming announces" do data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!() @@ -844,60 +763,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do 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"}) - - announce_data = - File.read!("test/fixtures/mastodon-announce.json") - |> Poison.decode!() - |> Map.put("object", activity.data["object"]) - - {:ok, %Activity{data: announce_data, local: false}} = - Transmogrifier.handle_incoming(announce_data) - - data = - File.read!("test/fixtures/mastodon-undo-announce.json") - |> Poison.decode!() - |> Map.put("object", announce_data) - |> Map.put("actor", announce_data["actor"]) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["type"] == "Undo" - assert object_data = data["object"] - assert object_data["type"] == "Announce" - assert object_data["object"] == activity.data["object"] - - assert object_data["id"] == - "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" - end - - test "it works for incomming unfollows with an existing follow" do - user = insert(:user) - - follow_data = - File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() - |> Map.put("object", user.ap_id) - - {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data) - - data = - File.read!("test/fixtures/mastodon-unfollow-activity.json") - |> Poison.decode!() - |> Map.put("object", follow_data) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["type"] == "Undo" - assert data["object"]["type"] == "Follow" - assert data["object"]["object"] == user.ap_id - assert data["actor"] == "http://mastodon.example.org/users/admin" - - refute User.following?(User.get_cached_by_ap_id(data["actor"]), user) - end - test "it works for incoming follows to locked account" do pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin") user = insert(:user, locked: true) @@ -967,32 +832,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do refute User.following?(blocked, blocker) end - test "it works for incoming unblocks with an existing block" do - user = insert(:user) - - block_data = - File.read!("test/fixtures/mastodon-block-activity.json") - |> Poison.decode!() - |> Map.put("object", user.ap_id) - - {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data) - - data = - File.read!("test/fixtures/mastodon-unblock-activity.json") - |> Poison.decode!() - |> Map.put("object", block_data) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - assert data["type"] == "Undo" - assert data["object"]["type"] == "Block" - assert data["object"]["object"] == user.ap_id - assert data["actor"] == "http://mastodon.example.org/users/admin" - - blocker = User.get_cached_by_ap_id(data["actor"]) - - refute User.blocks?(blocker, user) - end - test "it works for incoming accepts which were pre-accepted" do follower = insert(:user) followed = insert(:user) -- cgit v1.2.3 From f1da8882f971f932b65f655b6457759387dafe51 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 5 May 2020 14:17:47 +0200 Subject: UndoValidator: Add UndoValidator. --- test/web/activity_pub/object_validator_test.exs | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 93989e28a..8626e127e 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -1,6 +1,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do use Pleroma.DataCase + alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.ObjectValidator alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator alias Pleroma.Web.ActivityPub.Utils @@ -8,6 +9,46 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do import Pleroma.Factory + describe "Undos" do + setup do + user = insert(:user) + {:ok, post_activity} = CommonAPI.post(user, %{"status" => "uguu"}) + {:ok, like} = CommonAPI.favorite(user, post_activity.id) + {:ok, valid_like_undo, []} = Builder.undo(user, like) + + %{user: user, like: like, valid_like_undo: valid_like_undo} + end + + test "it validates a basic like undo", %{valid_like_undo: valid_like_undo} do + assert {:ok, _, _} = ObjectValidator.validate(valid_like_undo, []) + end + + test "it does not validate if the actor of the undo is not the actor of the object", %{ + valid_like_undo: valid_like_undo + } do + other_user = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo") + + bad_actor = + valid_like_undo + |> Map.put("actor", other_user.ap_id) + + {:error, cng} = ObjectValidator.validate(bad_actor, []) + + assert {:actor, {"not the same as object actor", []}} in cng.errors + end + + test "it does not validate if the object is missing", %{valid_like_undo: valid_like_undo} do + missing_object = + valid_like_undo + |> Map.put("object", "https://gensokyo.2hu/objects/1") + + {:error, cng} = ObjectValidator.validate(missing_object, []) + + assert {:object, {"can't find object", []}} in cng.errors + assert length(cng.errors) == 1 + end + end + describe "likes" do setup do user = insert(:user) -- cgit v1.2.3 From a3071f023166cb5364ce56e3666d5a77baa16434 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 5 May 2020 15:08:41 +0200 Subject: Undoing: Move undoing likes to the pipeline everywhere. --- test/web/activity_pub/activity_pub_test.exs | 60 ---------------------- test/web/activity_pub/side_effects_test.exs | 29 +++++++++++ .../transmogrifier/undo_handling_test.exs | 9 +++- 3 files changed, 36 insertions(+), 62 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 84ead93bb..797af66a0 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -995,66 +995,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end end - describe "unliking" do - test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do - Config.put([:instance, :federating], true) - - note_activity = insert(:note_activity) - object = Object.normalize(note_activity) - user = insert(:user) - - {:ok, object} = ActivityPub.unlike(user, object) - refute called(Federator.publish()) - - {:ok, _like_activity} = CommonAPI.favorite(user, note_activity.id) - object = Object.get_by_id(object.id) - assert object.data["like_count"] == 1 - - {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object) - assert object.data["like_count"] == 0 - - assert called(Federator.publish(unlike_activity)) - end - - test "reverts unliking on error" do - note_activity = insert(:note_activity) - user = insert(:user) - - {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id) - object = Object.normalize(note_activity) - assert object.data["like_count"] == 1 - - with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do - assert {:error, :reverted} = ActivityPub.unlike(user, object) - end - - assert Object.get_by_ap_id(object.data["id"]) == object - assert object.data["like_count"] == 1 - assert Activity.get_by_id(like_activity.id) - end - - test "unliking a previously liked object" do - note_activity = insert(:note_activity) - object = Object.normalize(note_activity) - user = insert(:user) - - # Unliking something that hasn't been liked does nothing - {:ok, object} = ActivityPub.unlike(user, object) - assert object.data["like_count"] == 0 - - {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id) - - object = Object.get_by_id(object.id) - assert object.data["like_count"] == 1 - - {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object) - assert object.data["like_count"] == 0 - - assert Activity.get_by_id(like_activity.id) == nil - assert note_activity.actor in unlike_activity.recipients - end - end - describe "announcing an object" do test "adds an announce activity to the db" do note_activity = insert(:note_activity) diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index 0b6b55156..61ef72742 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -5,6 +5,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do use Pleroma.DataCase + alias Pleroma.Activity alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Repo @@ -15,6 +16,34 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do import Pleroma.Factory + describe "Undo objects" do + setup do + poster = insert(:user) + user = insert(:user) + {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"}) + {:ok, like} = CommonAPI.favorite(user, post.id) + + {:ok, undo_data, _meta} = Builder.undo(user, like) + {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true) + + %{like_undo: like_undo, post: post, like: like} + end + + test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do + {:ok, _like_undo, _} = SideEffects.handle(like_undo) + + object = Object.get_by_ap_id(post.data["object"]) + + assert object.data["like_count"] == 0 + assert object.data["likes"] == [] + end + + test "deletes the original like", %{like_undo: like_undo, like: like} do + {:ok, _like_undo, _} = SideEffects.handle(like_undo) + refute Activity.get_by_id(like.id) + end + end + describe "like objects" do setup do poster = insert(:user) diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs index a9ebfdb18..bf2a6bc5b 100644 --- a/test/web/activity_pub/transmogrifier/undo_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/undo_handling_test.exs @@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do use Pleroma.DataCase alias Pleroma.Activity + alias Pleroma.Object alias Pleroma.User alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.CommonAPI @@ -67,7 +68,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do assert data["actor"] == "http://mastodon.example.org/users/admin" assert data["type"] == "Undo" assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo" - assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2" + assert data["object"] == "http://mastodon.example.org/users/admin#likes/2" + + note = Object.get_by_ap_id(like_data["object"]) + assert note.data["like_count"] == 0 + assert note.data["likes"] == [] end test "it works for incoming unlikes with an existing like activity and a compact object" do @@ -94,7 +99,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do assert data["actor"] == "http://mastodon.example.org/users/admin" assert data["type"] == "Undo" assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo" - assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2" + assert data["object"] == "http://mastodon.example.org/users/admin#likes/2" end test "it works for incoming unannounces with an existing notice" do -- cgit v1.2.3 From b34debe61540cf845ccf4ac93066e45a1d9c8f85 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 5 May 2020 16:17:09 +0200 Subject: Undoing: Move undoing reactions to the pipeline everywhere. --- test/web/activity_pub/activity_pub_test.exs | 56 ----------------------------- test/web/activity_pub/side_effects_test.exs | 30 +++++++++++++++- 2 files changed, 29 insertions(+), 57 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 797af66a0..cb2d41f0b 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -939,62 +939,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end end - describe "unreacting to an object" do - test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do - Config.put([:instance, :federating], true) - user = insert(:user) - reactor = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"}) - assert object = Object.normalize(activity) - - {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥") - - assert called(Federator.publish(reaction_activity)) - - {:ok, unreaction_activity, _object} = - ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"]) - - assert called(Federator.publish(unreaction_activity)) - end - - test "adds an undo activity to the db" do - user = insert(:user) - reactor = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"}) - assert object = Object.normalize(activity) - - {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥") - - {:ok, unreaction_activity, _object} = - ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"]) - - assert unreaction_activity.actor == reactor.ap_id - assert unreaction_activity.data["object"] == reaction_activity.data["id"] - - object = Object.get_by_ap_id(object.data["id"]) - assert object.data["reaction_count"] == 0 - assert object.data["reactions"] == [] - end - - test "reverts emoji unreact on error" do - [user, reactor] = insert_list(2, :user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "Status"}) - object = Object.normalize(activity) - - {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "😀") - - with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do - assert {:error, :reverted} = - ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"]) - end - - object = Object.get_by_ap_id(object.data["id"]) - - assert object.data["reaction_count"] == 1 - assert object.data["reactions"] == [["😀", [reactor.ap_id]]] - end - end - describe "announcing an object" do test "adds an announce activity to the db" do note_activity = insert(:note_activity) diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index 61ef72742..abcfdfa2f 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -23,10 +23,38 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"}) {:ok, like} = CommonAPI.favorite(user, post.id) + {:ok, reaction, _} = CommonAPI.react_with_emoji(post.id, user, "👍") + {:ok, undo_data, _meta} = Builder.undo(user, like) {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true) - %{like_undo: like_undo, post: post, like: like} + {:ok, undo_data, _meta} = Builder.undo(user, reaction) + {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true) + + %{ + like_undo: like_undo, + post: post, + like: like, + reaction_undo: reaction_undo, + reaction: reaction + } + end + + test "a reaction undo removes the reaction from the object", %{ + reaction_undo: reaction_undo, + post: post + } do + {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo) + + object = Object.get_by_ap_id(post.data["object"]) + + assert object.data["reaction_count"] == 0 + assert object.data["reactions"] == [] + end + + test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do + {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo) + refute Activity.get_by_id(reaction.id) end test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do -- cgit v1.2.3 From a3bb2e5474ee068bf375b24df8906e51654c9699 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 5 May 2020 16:42:34 +0200 Subject: Undoing: Move undoing announcements to the pipeline everywhere. --- test/web/activity_pub/activity_pub_test.exs | 46 ---------------------- test/web/activity_pub/side_effects_test.exs | 26 +++++++++++- .../transmogrifier/undo_handling_test.exs | 5 +-- 3 files changed, 25 insertions(+), 52 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index cb2d41f0b..2c3d354f2 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -1008,52 +1008,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end end - describe "unannouncing an object" do - test "unannouncing a previously announced object" do - note_activity = insert(:note_activity) - object = Object.normalize(note_activity) - user = insert(:user) - - # Unannouncing an object that is not announced does nothing - {:ok, object} = ActivityPub.unannounce(user, object) - refute object.data["announcement_count"] - - {:ok, announce_activity, object} = ActivityPub.announce(user, object) - assert object.data["announcement_count"] == 1 - - {:ok, unannounce_activity, object} = ActivityPub.unannounce(user, object) - assert object.data["announcement_count"] == 0 - - assert unannounce_activity.data["to"] == [ - User.ap_followers(user), - object.data["actor"] - ] - - assert unannounce_activity.data["type"] == "Undo" - assert unannounce_activity.data["object"] == announce_activity.data - assert unannounce_activity.data["actor"] == user.ap_id - assert unannounce_activity.data["context"] == announce_activity.data["context"] - - assert Activity.get_by_id(announce_activity.id) == nil - end - - test "reverts unannouncing on error" do - note_activity = insert(:note_activity) - object = Object.normalize(note_activity) - user = insert(:user) - - {:ok, _announce_activity, object} = ActivityPub.announce(user, object) - assert object.data["announcement_count"] == 1 - - with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do - assert {:error, :reverted} = ActivityPub.unannounce(user, object) - end - - object = Object.get_by_ap_id(object.data["id"]) - assert object.data["announcement_count"] == 1 - end - end - describe "uploading files" do test "copies the file to the configured folder" do file = %Plug.Upload{ diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index abcfdfa2f..00241320b 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -22,8 +22,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do user = insert(:user) {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"}) {:ok, like} = CommonAPI.favorite(user, post.id) - {:ok, reaction, _} = CommonAPI.react_with_emoji(post.id, user, "👍") + {:ok, announce, _} = CommonAPI.repeat(post.id, user) {:ok, undo_data, _meta} = Builder.undo(user, like) {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true) @@ -31,15 +31,37 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do {:ok, undo_data, _meta} = Builder.undo(user, reaction) {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true) + {:ok, undo_data, _meta} = Builder.undo(user, announce) + {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true) + %{ like_undo: like_undo, post: post, like: like, reaction_undo: reaction_undo, - reaction: reaction + reaction: reaction, + announce_undo: announce_undo, + announce: announce } end + test "an announce undo removes the announce from the object", %{ + announce_undo: announce_undo, + post: post + } do + {:ok, _announce_undo, _} = SideEffects.handle(announce_undo) + + object = Object.get_by_ap_id(post.data["object"]) + + assert object.data["announcement_count"] == 0 + assert object.data["announcements"] == [] + end + + test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do + {:ok, _announce_undo, _} = SideEffects.handle(announce_undo) + refute Activity.get_by_id(announce.id) + end + test "a reaction undo removes the reaction from the object", %{ reaction_undo: reaction_undo, post: post diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs index bf2a6bc5b..281cf5b0d 100644 --- a/test/web/activity_pub/transmogrifier/undo_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/undo_handling_test.exs @@ -125,11 +125,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) assert data["type"] == "Undo" - assert object_data = data["object"] - assert object_data["type"] == "Announce" - assert object_data["object"] == activity.data["object"] - assert object_data["id"] == + assert data["object"] == "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" end -- cgit v1.2.3 From 92caae592338a3ca307686e7644f2de18bb57ce5 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 5 May 2020 18:00:37 +0200 Subject: Undoing: Move undoing blocks to the pipeline everywhere. --- test/web/activity_pub/activity_pub_test.exs | 34 +--------------------- test/web/activity_pub/side_effects_test.exs | 25 +++++++++++++++- .../transmogrifier/undo_handling_test.exs | 4 +-- test/web/activity_pub/utils_test.exs | 28 ------------------ 4 files changed, 26 insertions(+), 65 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 2c3d354f2..7824095c7 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -1114,7 +1114,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end end - describe "blocking / unblocking" do + describe "blocking" do test "reverts block activity on error" do [blocker, blocked] = insert_list(2, :user) @@ -1136,38 +1136,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert activity.data["actor"] == blocker.ap_id assert activity.data["object"] == blocked.ap_id end - - test "reverts unblock activity on error" do - [blocker, blocked] = insert_list(2, :user) - {:ok, block_activity} = ActivityPub.block(blocker, blocked) - - with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do - assert {:error, :reverted} = ActivityPub.unblock(blocker, blocked) - end - - assert block_activity.data["type"] == "Block" - assert block_activity.data["actor"] == blocker.ap_id - - assert Repo.aggregate(Activity, :count, :id) == 1 - assert Repo.aggregate(Object, :count, :id) == 1 - end - - test "creates an undo activity for the last block" do - blocker = insert(:user) - blocked = insert(:user) - - {:ok, block_activity} = ActivityPub.block(blocker, blocked) - {:ok, activity} = ActivityPub.unblock(blocker, blocked) - - assert activity.data["type"] == "Undo" - assert activity.data["actor"] == blocker.ap_id - - embedded_object = activity.data["object"] - assert is_map(embedded_object) - assert embedded_object["type"] == "Block" - assert embedded_object["object"] == blocked.ap_id - assert embedded_object["id"] == block_activity.data["id"] - end end describe "deletion" do diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index 00241320b..f41a7f3c1 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Repo + alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.SideEffects @@ -24,6 +25,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do {:ok, like} = CommonAPI.favorite(user, post.id) {:ok, reaction, _} = CommonAPI.react_with_emoji(post.id, user, "👍") {:ok, announce, _} = CommonAPI.repeat(post.id, user) + {:ok, block} = ActivityPub.block(user, poster) + User.block(user, poster) {:ok, undo_data, _meta} = Builder.undo(user, like) {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true) @@ -34,6 +37,9 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do {:ok, undo_data, _meta} = Builder.undo(user, announce) {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true) + {:ok, undo_data, _meta} = Builder.undo(user, block) + {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true) + %{ like_undo: like_undo, post: post, @@ -41,10 +47,27 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do reaction_undo: reaction_undo, reaction: reaction, announce_undo: announce_undo, - announce: announce + announce: announce, + block_undo: block_undo, + block: block, + poster: poster, + user: user } end + test "deletes the original block", %{block_undo: block_undo, block: block} do + {:ok, _block_undo, _} = SideEffects.handle(block_undo) + refute Activity.get_by_id(block.id) + end + + test "unblocks the blocked user", %{block_undo: block_undo, block: block} do + blocker = User.get_by_ap_id(block.data["actor"]) + blocked = User.get_by_ap_id(block.data["object"]) + + {:ok, _block_undo, _} = SideEffects.handle(block_undo) + refute User.blocks?(blocker, blocked) + end + test "an announce undo removes the announce from the object", %{ announce_undo: announce_undo, post: post diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs index 281cf5b0d..6f5e61ac3 100644 --- a/test/web/activity_pub/transmogrifier/undo_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/undo_handling_test.exs @@ -176,9 +176,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) assert data["type"] == "Undo" - assert data["object"]["type"] == "Block" - assert data["object"]["object"] == user.ap_id - assert data["actor"] == "http://mastodon.example.org/users/admin" + assert data["object"] == block_data["id"] blocker = User.get_cached_by_ap_id(data["actor"]) diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index b0bfed917..b8d811c73 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -102,34 +102,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do end end - describe "make_unlike_data/3" do - test "returns data for unlike activity" do - user = insert(:user) - like_activity = insert(:like_activity, data_attrs: %{"context" => "test context"}) - - object = Object.normalize(like_activity.data["object"]) - - assert Utils.make_unlike_data(user, like_activity, nil) == %{ - "type" => "Undo", - "actor" => user.ap_id, - "object" => like_activity.data, - "to" => [user.follower_address, object.data["actor"]], - "cc" => [Pleroma.Constants.as_public()], - "context" => like_activity.data["context"] - } - - assert Utils.make_unlike_data(user, like_activity, "9mJEZK0tky1w2xD2vY") == %{ - "type" => "Undo", - "actor" => user.ap_id, - "object" => like_activity.data, - "to" => [user.follower_address, object.data["actor"]], - "cc" => [Pleroma.Constants.as_public()], - "context" => like_activity.data["context"], - "id" => "9mJEZK0tky1w2xD2vY" - } - end - end - describe "make_like_data" do setup do user = insert(:user) -- cgit v1.2.3 From 788b7e7bbd2732e2af72adad1a660cf363486c6b Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 7 May 2020 14:52:37 +0200 Subject: Merge fixes. --- test/web/activity_pub/object_validator_test.exs | 1 - test/web/activity_pub/transmogrifier_test.exs | 107 ------------------------ 2 files changed, 108 deletions(-) (limited to 'test/web/activity_pub') diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 4d90a0cf3..174be5ec6 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -107,7 +107,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do {:error, cng} = ObjectValidator.validate(missing_object, []) assert {:object, {"can't find object", []}} in cng.errors - assert length(cng.errors) == 1 end test "it's invalid if the actor of the object and the actor of delete are from different domains", diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index ae5d3bf92..4fd6c8b00 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -685,113 +685,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"}) - - announce_data = - File.read!("test/fixtures/mastodon-announce.json") - |> Poison.decode!() - |> Map.put("object", activity.data["object"]) - - {:ok, %Activity{data: announce_data, local: false}} = - Transmogrifier.handle_incoming(announce_data) - - data = - File.read!("test/fixtures/mastodon-undo-announce.json") - |> Poison.decode!() - |> Map.put("object", announce_data) - |> Map.put("actor", announce_data["actor"]) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["type"] == "Undo" - assert object_data = data["object"] - assert object_data["type"] == "Announce" - assert object_data["object"] == activity.data["object"] - - assert object_data["id"] == - "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" - end - test "it works for incomming unfollows with an existing follow" do user = insert(:user) -- cgit v1.2.3