diff options
Diffstat (limited to 'test')
66 files changed, 2447 insertions, 1327 deletions
diff --git a/test/fixtures/mastodon-delete.json b/test/fixtures/mastodon-delete.json index 87a582002..8559f724e 100644 --- a/test/fixtures/mastodon-delete.json +++ b/test/fixtures/mastodon-delete.json @@ -2,12 +2,9 @@ "type": "Delete", "signature": { "type": "RsaSignature2017", - "signatureValue": "cw0RlfNREf+5VdsOYcCBDrv521eiLsDTAYNHKffjF0bozhCnOh+wHkFik7WamUk$ -uEiN4L2H6vPlGRprAZGRhEwgy+A7rIFQNmLrpW5qV5UNVI/2F7kngEHqZQgbQYj9hW+5GMYmPkHdv3D72ZefGw$ -4Xa2NBLGFpAjQllfzt7kzZLKKY2DM99FdUa64I2Wj3iD04Hs23SbrUdAeuGk/c1Cg6bwGNG4vxoiwn1jikgJLA$ -NAlSGjsRGdR7LfbC7GqWWsW3cSNsLFPoU6FyALjgTrrYoHiXe0QHggw+L3yMLfzB2S/L46/VRbyb+WDKMBIXUL$ -5owmzHSi6e/ZtCI3w==", - "creator": "http://mastodon.example.org/users/gargron#main-key", "created": "2018-03-03T16:24:11Z" + "signatureValue": "cw0RlfNREf+5VdsOYcCBDrv521eiLsDTAYNHKffjF0bozhCnOh+wHkFik7WamUk$uEiN4L2H6vPlGRprAZGRhEwgy+A7rIFQNmLrpW5qV5UNVI/2F7kngEHqZQgbQYj9hW+5GMYmPkHdv3D72ZefGw$4Xa2NBLGFpAjQllfzt7kzZLKKY2DM99FdUa64I2Wj3iD04Hs23SbrUdAeuGk/c1Cg6bwGNG4vxoiwn1jikgJLA$NAlSGjsRGdR7LfbC7GqWWsW3cSNsLFPoU6FyALjgTrrYoHiXe0QHggw+L3yMLfzB2S/L46/VRbyb+WDKMBIXUL$5owmzHSi6e/ZtCI3w==", + "creator": "http://mastodon.example.org/users/gargron#main-key", + "created": "2018-03-03T16:24:11Z" }, "object": { "type": "Tombstone", diff --git a/test/fixtures/mastodon/application_actor.json b/test/fixtures/mastodon/application_actor.json new file mode 100644 index 000000000..2089ea049 --- /dev/null +++ b/test/fixtures/mastodon/application_actor.json @@ -0,0 +1,67 @@ +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "toot": "http://joinmastodon.org/ns#", + "featured": { + "@id": "toot:featured", + "@type": "@id" + }, + "alsoKnownAs": { + "@id": "as:alsoKnownAs", + "@type": "@id" + }, + "movedTo": { + "@id": "as:movedTo", + "@type": "@id" + }, + "schema": "http://schema.org#", + "PropertyValue": "schema:PropertyValue", + "value": "schema:value", + "IdentityProof": "toot:IdentityProof", + "discoverable": "toot:discoverable", + "Device": "toot:Device", + "Ed25519Signature": "toot:Ed25519Signature", + "Ed25519Key": "toot:Ed25519Key", + "Curve25519Key": "toot:Curve25519Key", + "EncryptedMessage": "toot:EncryptedMessage", + "publicKeyBase64": "toot:publicKeyBase64", + "deviceId": "toot:deviceId", + "claim": { + "@type": "@id", + "@id": "toot:claim" + }, + "fingerprintKey": { + "@type": "@id", + "@id": "toot:fingerprintKey" + }, + "identityKey": { + "@type": "@id", + "@id": "toot:identityKey" + }, + "devices": { + "@type": "@id", + "@id": "toot:devices" + }, + "messageFranking": "toot:messageFranking", + "messageType": "toot:messageType", + "cipherText": "toot:cipherText" + } + ], + "id": "https://{{DOMAIN}}/actor", + "type": "Application", + "inbox": "https://{{DOMAIN}}/actor/inbox", + "preferredUsername": "{{DOMAIN}}", + "url": "https://{{DOMAIN}}/about/more?instance_actor=true", + "manuallyApprovesFollowers": true, + "publicKey": { + "id": "https://{{DOMAIN}}/actor#main-key", + "owner": "https://{{DOMAIN}}/actor", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAA0CA08AMIIBCgKCAQEAyi2T2FFZJgRPY+96YQrn\n6J6eF2P60J+nz+/pRc/acv/Nx+NLxxPyXby0F2s60MV7uALRQbBBnf7oNKCd/T4S\nvbr7UXMCWTdaJBpYubMKWT9uBlaUUkUfqL+WTV+IQnlcKtssQ4+AwrAKAZXza8ws\nZypevOsLHzayyEzztmm1KQC9GCUOITCLf7Q6qEhy8z/HuqLBEC0Own0pD7QsbfcS\no1peuZY7g1E/jJ9HR9GqJccMaR0H28KmJ7tT1Yzlyf5uZMRIdPxsoMR9sGLjR2B8\noegSwaf9SogR3ScP395Tt/9Ud1VVzuhpoS8Uy7jKSs+3CuLJsEGoMrib8VyOwadS\n9wIDAQAB\n-----END PUBLIC KEY-----\n" + }, + "endpoints": { + "sharedInbox": "https://{{DOMAIN}}/inbox" + } +} diff --git a/test/fixtures/osada-follow-activity.json b/test/fixtures/osada-follow-activity.json index b991eea36..be10ce88f 100644 --- a/test/fixtures/osada-follow-activity.json +++ b/test/fixtures/osada-follow-activity.json @@ -1,56 +1,52 @@ { - "@context":[ + "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", "https://apfed.club/apschema/v1.4" ], - "id":"https://apfed.club/follow/9", - "type":"Follow", - "actor":{ - "type":"Person", - "id":"https://apfed.club/channel/indio", - "preferredUsername":"indio", - "name":"Indio", - "updated":"2019-08-20T23:52:34Z", - "icon":{ - "type":"Image", - "mediaType":"image/jpeg", - "updated":"2019-08-20T23:53:37Z", - "url":"https://apfed.club/photo/profile/l/2", - "height":300, - "width":300 + "id": "https://apfed.club/follow/9", + "type": "Follow", + "actor": { + "type": "Person", + "id": "https://apfed.club/channel/indio", + "preferredUsername": "indio", + "name": "Indio", + "updated": "2019-08-20T23:52:34Z", + "icon": { + "type": "Image", + "mediaType": "image/jpeg", + "updated": "2019-08-20T23:53:37Z", + "url": "https://apfed.club/photo/profile/l/2", + "height": 300, + "width": 300 }, - "url":"https://apfed.club/channel/indio", - "inbox":"https://apfed.club/inbox/indio", - "outbox":"https://apfed.club/outbox/indio", - "followers":"https://apfed.club/followers/indio", - "following":"https://apfed.club/following/indio", - "endpoints":{ - "sharedInbox":"https://apfed.club/inbox" + "url": "https://apfed.club/channel/indio", + "inbox": "https://apfed.club/inbox/indio", + "outbox": "https://apfed.club/outbox/indio", + "followers": "https://apfed.club/followers/indio", + "following": "https://apfed.club/following/indio", + "endpoints": { + "sharedInbox": "https://apfed.club/inbox" }, - "publicKey":{ - "id":"https://apfed.club/channel/indio", - "owner":"https://apfed.club/channel/indio", - "publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA77TIR1VuSYFnmDRFGHHb\n4vaGdx9ranzRX4bfOKAqa++Ch5L4EqJpPy08RuM+NrYCYiYl4QQFDSSDXAEgb5g9\nC1TgWTfI7q/E0UBX2Vr0mU6X4i1ztv0tuQvegRjcSJ7l1AvoBs8Ip4MEJ3OPEQhB\ngJqAACB3Gnps4zi2I0yavkxUfGVKr6zKT3BxWh5hTpKC7Do+ChIrVZC2EwxND9K6 -\nsAnQHThcb5EQuvuzUQZKeS7IEOsd0JpZDmJjbfMGrAWE81pLIfEeeA2joCJiBBTO\nglDsW+juvZ+lWqJpMr2hMWpvfrFjJeUawNJCIzsLdVIZR+aKj5yy6yqoS8hkN9Ha\n1MljZpsXl+EmwcwAIqim1YeLwERCEAQ/JWbSt8pQTQbzZ6ibwQ4mchCxacrRbIVR -\nnL59fWMBassJcbY0VwrTugm2SBsYbDjESd55UZV03Rwr8qseGTyi+hH8O7w2SIaY\nzjN6AdZiPmsh00YflzlCk8MSLOHMol1vqIUzXxU8CdXn9+KsuQdZGrTz0YKN/db4\naVwUGJatz2Tsvf7R1tJBjJfeQWOWbbn3pycLVH86LjZ83qngp9ZVnAveUnUqz0yS -\nhe+buZ6UMsfGzbIYon2bKNlz6gYTH0YPcr+cLe+29drtt0GZiXha1agbpo4RB8zE -\naNL2fucF5YT0yNpbd/5WoV0CAwEAAQ==\n-----END PUBLIC KEY-----\n" + "publicKey": { + "id": "https://apfed.club/channel/indio", + "owner": "https://apfed.club/channel/indio", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA77TIR1VuSYFnmDRFGHHb\n4vaGdx9ranzRX4bfOKAqa++Ch5L4EqJpPy08RuM+NrYCYiYl4QQFDSSDXAEgb5g9\nC1TgWTfI7q/E0UBX2Vr0mU6X4i1ztv0tuQvegRjcSJ7l1AvoBs8Ip4MEJ3OPEQhB\ngJqAACB3Gnps4zi2I0yavkxUfGVKr6zKT3BxWh5hTpKC7Do+ChIrVZC2EwxND9K6\nsAnQHThcb5EQuvuzUQZKeS7IEOsd0JpZDmJjbfMGrAWE81pLIfEeeA2joCJiBBTO\nglDsW+juvZ+lWqJpMr2hMWpvfrFjJeUawNJCIzsLdVIZR+aKj5yy6yqoS8hkN9Ha\n1MljZpsXl+EmwcwAIqim1YeLwERCEAQ/JWbSt8pQTQbzZ6ibwQ4mchCxacrRbIVR\nnL59fWMBassJcbY0VwrTugm2SBsYbDjESd55UZV03Rwr8qseGTyi+hH8O7w2SIaY\nzjN6AdZiPmsh00YflzlCk8MSLOHMol1vqIUzXxU8CdXn9+KsuQdZGrTz0YKN/db4\naVwUGJatz2Tsvf7R1tJBjJfeQWOWbbn3pycLVH86LjZ83qngp9ZVnAveUnUqz0yS\nhe+buZ6UMsfGzbIYon2bKNlz6gYTH0YPcr+cLe+29drtt0GZiXha1agbpo4RB8zE\naNL2fucF5YT0yNpbd/5WoV0CAwEAAQ==\n-----END PUBLIC KEY-----\n" } }, - "object":"https://pleroma.site/users/kaniini", - "to":[ + "object": "https://pleroma.site/users/kaniini", + "to": [ "https://pleroma.site/users/kaniini" ], - "signature":{ - "@context":[ + "signature": { + "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1" ], - "type":"RsaSignature2017", - "nonce":"52c035e0a9e81dce8b486159204e97c22637e91f75cdfad5378de91de68e9117", - "creator":"https://apfed.club/channel/indio/public_key_pem", - "created":"2019-08-22T03:38:02Z", - "signatureValue":"oVliRCIqNIh6yUp851dYrF0y21aHp3Rz6VkIpW1pFMWfXuzExyWSfcELpyLseeRmsw5bUu9zJkH44B4G2LiJQKA9UoEQDjrDMZBmbeUpiQqq3DVUzkrBOI8bHZ7xyJ/CjSZcNHHh0MHhSKxswyxWMGi4zIqzkAZG3vRRgoPVHdjPm00sR3B8jBLw1cjoffv+KKeM/zEUpe13gqX9qHAWHHqZepxgSWmq+EKOkRvHUPBXiEJZfXzc5uW+vZ09F3WBYmaRoy8Y0e1P29fnRLqSy7EEINdrHaGclRqoUZyiawpkgy3lWWlynesV/HiLBR7EXT79eKstxf4wfTDaPKBCfTCsOWuMWHr7Genu37ew2/t7eiBGqCwwW12ylhml/OLHgNK3LOhmRABhtfpaFZSxfDVnlXfaLpY1xekVOj2oC0FpBtnoxVKLpIcyLw6dkfSil5ANd+hl59W/bpPA8KT90ii1fSNCo3+FcwQVx0YsPznJNA60XfFuVsme7zNcOst6393e1WriZxBanFpfB63zVQc9u1fjyfktx/yiUNxIlre+sz9OCc0AACn94iRhBYh4bbzdleUOTnM7lnD4Dj2FP+xeDIP8CA8wXUeq5+9kopSp2kAmlUEyFUdg4no7naIeu1SZnopfUg56PsVCp9JHiUK1SYAyWbdC+FbUECu5CvI=" + "type": "RsaSignature2017", + "nonce": "52c035e0a9e81dce8b486159204e97c22637e91f75cdfad5378de91de68e9117", + "creator": "https://apfed.club/channel/indio/public_key_pem", + "created": "2019-08-22T03:38:02Z", + "signatureValue": "oVliRCIqNIh6yUp851dYrF0y21aHp3Rz6VkIpW1pFMWfXuzExyWSfcELpyLseeRmsw5bUu9zJkH44B4G2LiJQKA9UoEQDjrDMZBmbeUpiQqq3DVUzkrBOI8bHZ7xyJ/CjSZcNHHh0MHhSKxswyxWMGi4zIqzkAZG3vRRgoPVHdjPm00sR3B8jBLw1cjoffv+KKeM/zEUpe13gqX9qHAWHHqZepxgSWmq+EKOkRvHUPBXiEJZfXzc5uW+vZ09F3WBYmaRoy8Y0e1P29fnRLqSy7EEINdrHaGclRqoUZyiawpkgy3lWWlynesV/HiLBR7EXT79eKstxf4wfTDaPKBCfTCsOWuMWHr7Genu37ew2/t7eiBGqCwwW12ylhml/OLHgNK3LOhmRABhtfpaFZSxfDVnlXfaLpY1xekVOj2oC0FpBtnoxVKLpIcyLw6dkfSil5ANd+hl59W/bpPA8KT90ii1fSNCo3+FcwQVx0YsPznJNA60XfFuVsme7zNcOst6393e1WriZxBanFpfB63zVQc9u1fjyfktx/yiUNxIlre+sz9OCc0AACn94iRhBYh4bbzdleUOTnM7lnD4Dj2FP+xeDIP8CA8wXUeq5+9kopSp2kAmlUEyFUdg4no7naIeu1SZnopfUg56PsVCp9JHiUK1SYAyWbdC+FbUECu5CvI=" } } diff --git a/test/mix/tasks/pleroma/instance_test.exs b/test/mix/tasks/pleroma/instance_test.exs index 8a02710ee..6580fc932 100644 --- a/test/mix/tasks/pleroma/instance_test.exs +++ b/test/mix/tasks/pleroma/instance_test.exs @@ -88,7 +88,7 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do assert generated_config =~ "password: \"dbpass\"" assert generated_config =~ "configurable_from_database: true" assert generated_config =~ "http: [ip: {127, 0, 0, 1}, port: 4000]" - assert generated_config =~ "filters: [Pleroma.Upload.Filter.ExifTool]" + assert generated_config =~ "filters: [Pleroma.Upload.Filter.Exiftool]" assert File.read!(tmp_path() <> "setup.psql") == generated_setup_psql() assert File.exists?(Path.expand("./test/instance/static/robots.txt")) end diff --git a/test/mix/tasks/pleroma/user_test.exs b/test/mix/tasks/pleroma/user_test.exs index ce819f815..ae0c50443 100644 --- a/test/mix/tasks/pleroma/user_test.exs +++ b/test/mix/tasks/pleroma/user_test.exs @@ -36,7 +36,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do unsaved = build(:user) # prepare to answer yes - send(self(), {:mix_shell_input, :yes?, true}) + send(self(), {:mix_shell_input, :prompt, "Y"}) Mix.Tasks.Pleroma.User.run([ "new", @@ -55,7 +55,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do assert_received {:mix_shell, :info, [message]} assert message =~ "user will be created" - assert_received {:mix_shell, :yes?, [message]} + assert_received {:mix_shell, :prompt, [message]} assert message =~ "Continue" assert_received {:mix_shell, :info, [message]} @@ -73,14 +73,14 @@ defmodule Mix.Tasks.Pleroma.UserTest do unsaved = build(:user) # prepare to answer no - send(self(), {:mix_shell_input, :yes?, false}) + send(self(), {:mix_shell_input, :prompt, "N"}) Mix.Tasks.Pleroma.User.run(["new", unsaved.nickname, unsaved.email]) assert_received {:mix_shell, :info, [message]} assert message =~ "user will be created" - assert_received {:mix_shell, :yes?, [message]} + assert_received {:mix_shell, :prompt, [message]} assert message =~ "Continue" assert_received {:mix_shell, :info, [message]} diff --git a/test/pleroma/activity/search_test.exs b/test/pleroma/activity/search_test.exs new file mode 100644 index 000000000..fc910e725 --- /dev/null +++ b/test/pleroma/activity/search_test.exs @@ -0,0 +1,45 @@ +# Pleroma: A lightweight social networking server +# Copyright ยฉ 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Activity.SearchTest do + alias Pleroma.Activity.Search + alias Pleroma.Web.CommonAPI + import Pleroma.Factory + + use Pleroma.DataCase + + test "it finds something" do + user = insert(:user) + {:ok, post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"}) + + [result] = Search.search(nil, "wednesday") + + assert result.id == post.id + end + + test "using plainto_tsquery on postgres < 11" do + old_version = :persistent_term.get({Pleroma.Repo, :postgres_version}) + :persistent_term.put({Pleroma.Repo, :postgres_version}, 10.0) + on_exit(fn -> :persistent_term.put({Pleroma.Repo, :postgres_version}, old_version) end) + + user = insert(:user) + {:ok, post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"}) + {:ok, _post2} = CommonAPI.post(user, %{status: "it's wednesday my bros"}) + + # plainto doesn't understand complex queries + assert [result] = Search.search(nil, "wednesday -dudes") + + assert result.id == post.id + end + + test "using websearch_to_tsquery" do + user = insert(:user) + {:ok, _post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"}) + {:ok, other_post} = CommonAPI.post(user, %{status: "it's wednesday my bros"}) + + assert [result] = Search.search(nil, "wednesday -dudes") + + assert result.id == other_post.id + end +end diff --git a/test/pleroma/activity_test.exs b/test/pleroma/activity_test.exs index ee6a99cc3..105f9f766 100644 --- a/test/pleroma/activity_test.exs +++ b/test/pleroma/activity_test.exs @@ -197,6 +197,13 @@ defmodule Pleroma.ActivityTest do assert [%{id: ^id1, object: %Object{}}, %{id: ^id2, object: %Object{}}] = activities end + test "get_by_id_with_user_actor/1" do + user = insert(:user) + activity = insert(:note_activity, note: insert(:note, user: user)) + + assert Activity.get_by_id_with_user_actor(activity.id).user_actor == user + end + test "get_by_id_with_object/1" do %{id: id} = insert(:note_activity) @@ -231,4 +238,20 @@ defmodule Pleroma.ActivityTest do assert [%Activity{id: ^id1}, %Activity{id: ^id2}] = activities end + + test "get_by_object_ap_id_with_object/1" do + user = insert(:user) + another = insert(:user) + + {:ok, %{id: id, object: %{data: %{"id" => obj_id}}}} = + Pleroma.Web.CommonAPI.post(user, %{status: "cofe"}) + + Pleroma.Web.CommonAPI.favorite(another, id) + + assert obj_id + |> Pleroma.Activity.Queries.by_object_id() + |> Repo.aggregate(:count, :id) == 2 + + assert %{id: ^id} = Activity.get_by_object_ap_id_with_object(obj_id) + end end diff --git a/test/pleroma/config/deprecation_warnings_test.exs b/test/pleroma/config/deprecation_warnings_test.exs index 0cfed4555..f52629f8a 100644 --- a/test/pleroma/config/deprecation_warnings_test.exs +++ b/test/pleroma/config/deprecation_warnings_test.exs @@ -12,7 +12,7 @@ defmodule Pleroma.Config.DeprecationWarningsTest do alias Pleroma.Config.DeprecationWarnings test "check_old_mrf_config/0" do - clear_config([:instance, :rewrite_policy], Pleroma.Web.ActivityPub.MRF.NoOpPolicy) + clear_config([:instance, :rewrite_policy], []) clear_config([:instance, :mrf_transparency], true) clear_config([:instance, :mrf_transparency_exclusions], []) diff --git a/test/pleroma/emoji_test.exs b/test/pleroma/emoji_test.exs index 1dd3c58c6..9cfd7b46b 100644 --- a/test/pleroma/emoji_test.exs +++ b/test/pleroma/emoji_test.exs @@ -9,8 +9,22 @@ defmodule Pleroma.EmojiTest do describe "is_unicode_emoji?/1" do test "tells if a string is an unicode emoji" do refute Emoji.is_unicode_emoji?("X") - assert Emoji.is_unicode_emoji?("โ") + refute Emoji.is_unicode_emoji?("ใญ") + + # Only accept fully-qualified (RGI) emoji + # See http://www.unicode.org/reports/tr51/ + refute Emoji.is_unicode_emoji?("โค") + refute Emoji.is_unicode_emoji?("โ") + assert Emoji.is_unicode_emoji?("๐ฅบ") + assert Emoji.is_unicode_emoji?("๐คฐ") + assert Emoji.is_unicode_emoji?("โค๏ธ") + assert Emoji.is_unicode_emoji?("๐ณ๏ธโโง๏ธ") + + # Additionally, we accept regional indicators. + assert Emoji.is_unicode_emoji?("๐ต") + assert Emoji.is_unicode_emoji?("๐ด") + assert Emoji.is_unicode_emoji?("๐ฌ") end end diff --git a/test/pleroma/formatter_test.exs b/test/pleroma/formatter_test.exs index f066bd50a..5781a3f01 100644 --- a/test/pleroma/formatter_test.exs +++ b/test/pleroma/formatter_test.exs @@ -241,16 +241,14 @@ defmodule Pleroma.FormatterTest do "@@gsimg According to @archaeme, that is @daggsy. Also hello @archaeme@archae.me and @o and @@@jimm" o = insert(:user, %{nickname: "o"}) - jimm = insert(:user, %{nickname: "jimm"}) - gsimg = insert(:user, %{nickname: "gsimg"}) + _jimm = insert(:user, %{nickname: "jimm"}) + _gsimg = insert(:user, %{nickname: "gsimg"}) archaeme = insert(:user, %{nickname: "archaeme"}) archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"}) expected_mentions = [ {"@archaeme", archaeme}, {"@archaeme@archae.me", archaeme_remote}, - {"@gsimg", gsimg}, - {"@jimm", jimm}, {"@o", o} ] diff --git a/test/pleroma/frontend_test.exs b/test/pleroma/frontend_test.exs new file mode 100644 index 000000000..223625857 --- /dev/null +++ b/test/pleroma/frontend_test.exs @@ -0,0 +1,72 @@ +# Pleroma: A lightweight social networking server +# Copyright ยฉ 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.FrontendTest do + use Pleroma.DataCase + alias Pleroma.Frontend + + @dir "test/frontend_static_test" + + setup do + File.mkdir_p!(@dir) + clear_config([:instance, :static_dir], @dir) + + on_exit(fn -> + File.rm_rf(@dir) + end) + end + + test "it downloads and unzips a known frontend" do + clear_config([:frontends, :available], %{ + "pleroma" => %{ + "ref" => "fantasy", + "name" => "pleroma", + "build_url" => "http://gensokyo.2hu/builds/${ref}" + } + }) + + Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")} + end) + + Frontend.install("pleroma") + + assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"])) + end + + test "it also works given a file" do + clear_config([:frontends, :available], %{ + "pleroma" => %{ + "ref" => "fantasy", + "name" => "pleroma", + "build_dir" => "" + } + }) + + folder = Path.join([@dir, "frontends", "pleroma", "fantasy"]) + previously_existing = Path.join([folder, "temp"]) + File.mkdir_p!(folder) + File.write!(previously_existing, "yey") + assert File.exists?(previously_existing) + + Frontend.install("pleroma", file: "test/fixtures/tesla_mock/frontend.zip") + + assert File.exists?(Path.join([folder, "test.txt"])) + refute File.exists?(previously_existing) + end + + test "it downloads and unzips unknown frontends" do + Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend.zip")} + end) + + Frontend.install("unknown", + ref: "baka", + build_url: "http://gensokyo.2hu/madeup.zip", + build_dir: "" + ) + + assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"])) + end +end diff --git a/test/pleroma/moderation_log_test.exs b/test/pleroma/moderation_log_test.exs index 59f4d67f8..03b32a060 100644 --- a/test/pleroma/moderation_log_test.exs +++ b/test/pleroma/moderation_log_test.exs @@ -182,11 +182,14 @@ defmodule Pleroma.ModerationLogTest do end test "logging report update", %{moderator: moderator} do + user = insert(:user) + report = %Activity{ id: "9m9I1F4p8ftrTP6QTI", data: %{ "type" => "Flag", - "state" => "resolved" + "state" => "resolved", + "actor" => user.ap_id } } @@ -194,35 +197,48 @@ defmodule Pleroma.ModerationLogTest do ModerationLog.insert_log(%{ actor: moderator, action: "report_update", - subject: report + subject: report, + subject_actor: user }) log = Repo.one(ModerationLog) assert log.data["message"] == - "@#{moderator.nickname} updated report ##{report.id} with 'resolved' state" + "@#{moderator.nickname} updated report ##{report.id} (on user @#{user.nickname}) with 'resolved' state" end test "logging report response", %{moderator: moderator} do + user = insert(:user) + report = %Activity{ id: "9m9I1F4p8ftrTP6QTI", data: %{ - "type" => "Note" + "type" => "Note", + "actor" => user.ap_id } } - {:ok, _} = - ModerationLog.insert_log(%{ - actor: moderator, - action: "report_note", - subject: report, - text: "look at this" - }) + attrs = %{ + actor: moderator, + action: "report_note", + subject: report, + text: "look at this" + } - log = Repo.one(ModerationLog) + {:ok, log1} = ModerationLog.insert_log(attrs) + log = Repo.get(ModerationLog, log1.id) assert log.data["message"] == "@#{moderator.nickname} added note 'look at this' to report ##{report.id}" + + {:ok, log2} = ModerationLog.insert_log(Map.merge(attrs, %{subject_actor: user})) + + log = Repo.get(ModerationLog, log2.id) + + assert log.data["message"] == + "@#{moderator.nickname} added note 'look at this' to report ##{report.id} on user @#{ + user.nickname + }" end test "logging status sensitivity update", %{moderator: moderator} do diff --git a/test/pleroma/notification_test.exs b/test/pleroma/notification_test.exs index 92c0bc8b6..ed2cd219d 100644 --- a/test/pleroma/notification_test.exs +++ b/test/pleroma/notification_test.exs @@ -32,6 +32,19 @@ defmodule Pleroma.NotificationTest do refute {:ok, [nil]} == Notification.create_notifications(activity) end + test "creates a notification for a report" do + reporting_user = insert(:user) + reported_user = insert(:user) + {:ok, moderator_user} = insert(:user) |> User.admin_api_update(%{is_moderator: true}) + + {:ok, activity} = CommonAPI.report(reporting_user, %{account_id: reported_user.id}) + + {:ok, [notification]} = Notification.create_notifications(activity) + + assert notification.user_id == moderator_user.id + assert notification.type == "pleroma:report" + end + test "creates a notification for an emoji reaction" do user = insert(:user) other_user = insert(:user) diff --git a/test/pleroma/user_search_test.exs b/test/pleroma/user_search_test.exs index 31d787ffa..de1df2e9c 100644 --- a/test/pleroma/user_search_test.exs +++ b/test/pleroma/user_search_test.exs @@ -65,12 +65,13 @@ defmodule Pleroma.UserSearchTest do assert found_user.id == user.id end - test "excludes users when discoverable is false" do + # Note: as in Mastodon, `is_discoverable` doesn't anyhow relate to user searchability + test "includes non-discoverable users in results" do insert(:user, %{nickname: "john 3000", is_discoverable: false}) insert(:user, %{nickname: "john 3001"}) users = User.search("john") - assert Enum.count(users) == 1 + assert Enum.count(users) == 2 end test "excludes service actors from results" do diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index c678dadb3..e01a940cb 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -895,6 +895,13 @@ defmodule Pleroma.UserTest do refute cs.valid? end) end + + test "it is invalid given a local user" do + user = insert(:user) + cs = User.remote_user_changeset(user, %{name: "tom from myspace"}) + + refute cs.valid? + end end describe "followers and friends" do diff --git a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs index b696a24f4..c9b421489 100644 --- a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs @@ -213,6 +213,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do end describe "/objects/:uuid" do + test "it doesn't return a local-only object", %{conn: conn} do + user = insert(:user) + {:ok, post} = CommonAPI.post(user, %{status: "test", visibility: "local"}) + + assert Pleroma.Web.ActivityPub.Visibility.is_local_public?(post) + + object = Object.normalize(post, false) + uuid = String.split(object.data["id"], "/") |> List.last() + + conn = + conn + |> put_req_header("accept", "application/json") + |> get("/objects/#{uuid}") + + assert json_response(conn, 404) + end + test "it returns a json representation of the object with accept application/json", %{ conn: conn } do @@ -326,6 +343,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do end describe "/activities/:uuid" do + test "it doesn't return a local-only activity", %{conn: conn} do + user = insert(:user) + {:ok, post} = CommonAPI.post(user, %{status: "test", visibility: "local"}) + + assert Pleroma.Web.ActivityPub.Visibility.is_local_public?(post) + + uuid = String.split(post.data["id"], "/") |> List.last() + + conn = + conn + |> put_req_header("accept", "application/json") + |> get("/activities/#{uuid}") + + assert json_response(conn, 404) + end + test "it returns a json representation of the activity", %{conn: conn} do activity = insert(:note_activity) uuid = String.split(activity.data["id"], "/") |> List.last() @@ -398,7 +431,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do describe "/inbox" do test "it inserts an incoming activity into the database", %{conn: conn} do - data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() + data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() conn = conn @@ -426,7 +459,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do data = File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", user.ap_id) |> put_in(["object", "attridbutedTo"], user.ap_id) @@ -443,7 +476,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do end test "it clears `unreachable` federation status of the sender", %{conn: conn} do - data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() + data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() sender_url = data["actor"] Instances.set_consistently_unreachable(sender_url) @@ -501,8 +534,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do test "without valid signature, " <> "it only accepts Create activities and requires enabled federation", %{conn: conn} do - data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() - non_create_data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!() + data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() + non_create_data = File.read!("test/fixtures/mastodon-announce.json") |> Jason.decode!() conn = put_req_header(conn, "content-type", "application/activity+json") @@ -531,7 +564,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do setup do data = File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() + |> Jason.decode!() [data: data] end @@ -714,7 +747,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do data = File.read!("test/fixtures/activitypub-client-post-activity.json") - |> Poison.decode!() + |> Jason.decode!() object = Map.put(data["object"], "attributedTo", actor.ap_id) @@ -766,6 +799,142 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert json_response(ret_conn, 200) end + + @tag capture_log: true + test "forwarded report", %{conn: conn} do + admin = insert(:user, is_admin: true) + actor = insert(:user, local: false) + remote_domain = URI.parse(actor.ap_id).host + reported_user = insert(:user) + + note = insert(:note_activity, user: reported_user) + + data = %{ + "@context" => [ + "https://www.w3.org/ns/activitystreams", + "https://#{remote_domain}/schemas/litepub-0.1.jsonld", + %{ + "@language" => "und" + } + ], + "actor" => actor.ap_id, + "cc" => [ + reported_user.ap_id + ], + "content" => "test", + "context" => "context", + "id" => "http://#{remote_domain}/activities/02be56cf-35e3-46b4-b2c6-47ae08dfee9e", + "nickname" => reported_user.nickname, + "object" => [ + reported_user.ap_id, + %{ + "actor" => %{ + "actor_type" => "Person", + "approval_pending" => false, + "avatar" => "", + "confirmation_pending" => false, + "deactivated" => false, + "display_name" => "test user", + "id" => reported_user.id, + "local" => false, + "nickname" => reported_user.nickname, + "registration_reason" => nil, + "roles" => %{ + "admin" => false, + "moderator" => false + }, + "tags" => [], + "url" => reported_user.ap_id + }, + "content" => "", + "id" => note.data["id"], + "published" => note.data["published"], + "type" => "Note" + } + ], + "published" => note.data["published"], + "state" => "open", + "to" => [], + "type" => "Flag" + } + + conn + |> assign(:valid_signature, true) + |> put_req_header("content-type", "application/activity+json") + |> post("/users/#{reported_user.nickname}/inbox", data) + |> json_response(200) + + ObanHelpers.perform(all_enqueued(worker: ReceiverWorker)) + + assert Pleroma.Repo.aggregate(Activity, :count, :id) == 2 + + ObanHelpers.perform_all() + + Swoosh.TestAssertions.assert_email_sent( + to: {admin.name, admin.email}, + html_body: ~r/Reported Account:/i + ) + end + + @tag capture_log: true + test "forwarded report from mastodon", %{conn: conn} do + admin = insert(:user, is_admin: true) + actor = insert(:user, local: false) + remote_domain = URI.parse(actor.ap_id).host + remote_actor = "https://#{remote_domain}/actor" + [reported_user, another] = insert_list(2, :user) + + note = insert(:note_activity, user: reported_user) + + Pleroma.Web.CommonAPI.favorite(another, note.id) + + mock_json_body = + "test/fixtures/mastodon/application_actor.json" + |> File.read!() + |> String.replace("{{DOMAIN}}", remote_domain) + + Tesla.Mock.mock(fn %{url: ^remote_actor} -> + %Tesla.Env{ + status: 200, + body: mock_json_body, + headers: [{"content-type", "application/activity+json"}] + } + end) + + data = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "actor" => remote_actor, + "content" => "test report", + "id" => "https://#{remote_domain}/e3b12fd1-948c-446e-b93b-a5e67edbe1d8", + "nickname" => reported_user.nickname, + "object" => [ + reported_user.ap_id, + note.data["object"] + ], + "type" => "Flag" + } + + conn + |> assign(:valid_signature, true) + |> put_req_header("content-type", "application/activity+json") + |> post("/users/#{reported_user.nickname}/inbox", data) + |> json_response(200) + + ObanHelpers.perform(all_enqueued(worker: ReceiverWorker)) + + flag_activity = "Flag" |> Pleroma.Activity.Queries.by_type() |> Pleroma.Repo.one() + reported_user_ap_id = reported_user.ap_id + + [^reported_user_ap_id, flag_data] = flag_activity.data["object"] + + Enum.each(~w(actor content id published type), &Map.has_key?(flag_data, &1)) + ObanHelpers.perform_all() + + Swoosh.TestAssertions.assert_email_sent( + to: {admin.name, admin.email}, + html_body: ~r/#{note.data["object"]}/i + ) + end end describe "GET /users/:nickname/outbox" do diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index 3eeb0f735..6cc25dd9e 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -1298,6 +1298,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert_called(Utils.maybe_federate(%{activity | data: new_data})) end + + test_with_mock "reverts on error", + %{ + reporter: reporter, + context: context, + target_account: target_account, + reported_activity: reported_activity, + content: content + }, + Utils, + [:passthrough], + maybe_federate: fn _ -> {:error, :reverted} end do + assert {:error, :reverted} = + ActivityPub.flag(%{ + actor: reporter, + context: context, + account: target_account, + statuses: [reported_activity], + content: content + }) + + assert Repo.aggregate(Activity, :count, :id) == 1 + assert Repo.aggregate(Object, :count, :id) == 2 + assert Repo.aggregate(Notification, :count, :id) == 0 + end end test "fetch_activities/2 returns activities addressed to a list " do diff --git a/test/pleroma/web/activity_pub/mrf/media_proxy_warming_policy_test.exs b/test/pleroma/web/activity_pub/mrf/media_proxy_warming_policy_test.exs index 1710c4d2a..84362ce78 100644 --- a/test/pleroma/web/activity_pub/mrf/media_proxy_warming_policy_test.exs +++ b/test/pleroma/web/activity_pub/mrf/media_proxy_warming_policy_test.exs @@ -3,10 +3,10 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do - use Pleroma.DataCase + use ExUnit.Case + use Pleroma.Tests.Helpers alias Pleroma.HTTP - alias Pleroma.Tests.ObanHelpers alias Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy import Mock @@ -25,13 +25,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do setup do: clear_config([:media_proxy, :enabled], true) test "it prefetches media proxy URIs" do + Tesla.Mock.mock(fn %{method: :get, url: "http://example.com/image.jpg"} -> + {:ok, %Tesla.Env{status: 200, body: ""}} + end) + with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do MediaProxyWarmingPolicy.filter(@message) - ObanHelpers.perform_all() - # Performing jobs which has been just enqueued - ObanHelpers.perform_all() - assert called(HTTP.get(:_, :_, :_)) end end diff --git a/test/pleroma/web/activity_pub/mrf/object_age_policy_test.exs b/test/pleroma/web/activity_pub/mrf/object_age_policy_test.exs index cf6acc9a2..e8317b2af 100644 --- a/test/pleroma/web/activity_pub/mrf/object_age_policy_test.exs +++ b/test/pleroma/web/activity_pub/mrf/object_age_policy_test.exs @@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do defp get_old_message do File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() + |> Jason.decode!() end defp get_new_message do diff --git a/test/pleroma/web/activity_pub/side_effects_test.exs b/test/pleroma/web/activity_pub/side_effects_test.exs index 9efbaad04..297fc0b84 100644 --- a/test/pleroma/web/activity_pub/side_effects_test.exs +++ b/test/pleroma/web/activity_pub/side_effects_test.exs @@ -108,7 +108,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do describe "update users" do setup do - user = insert(:user) + user = insert(:user, local: false) {:ok, update_data, []} = Builder.update(user, %{"id" => user.ap_id, "name" => "new name!"}) {:ok, update, _meta} = ActivityPub.persist(update_data, local: true) diff --git a/test/pleroma/web/activity_pub/transmogrifier/accept_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/accept_handling_test.exs index c6ff96f08..0d431df18 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/accept_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/accept_handling_test.exs @@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AcceptHandlingTest do accept_data = File.read!("test/fixtures/mastodon-accept-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", followed.ap_id) object = @@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AcceptHandlingTest do accept_data = File.read!("test/fixtures/mastodon-accept-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", followed.ap_id) |> Map.put("object", follow_activity.data["id"]) @@ -76,7 +76,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AcceptHandlingTest do accept_data = File.read!("test/fixtures/mastodon-accept-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", followed.ap_id) accept_data = diff --git a/test/pleroma/web/activity_pub/transmogrifier/announce_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/announce_handling_test.exs index 99c296c74..c06bbc5e9 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/announce_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/announce_handling_test.exs @@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do end test "it works for incoming announces with actor being inlined (kroeg)" do - data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!() + data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Jason.decode!() _user = insert(:user, local: false, ap_id: data["actor"]["id"]) other_user = insert(:user) @@ -55,7 +55,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do test "it works for incoming announces, fetching the announced object" do data = File.read!("test/fixtures/mastodon-announce.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", "http://mastodon.example.org/users/admin/statuses/99541947525187367") Tesla.Mock.mock(fn @@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do data = File.read!("test/fixtures/mastodon-announce.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) _user = insert(:user, local: false, ap_id: data["actor"]) @@ -113,7 +113,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do test "it works for incoming announces with an inlined activity" do data = File.read!("test/fixtures/mastodon-announce-private.json") - |> Poison.decode!() + |> Jason.decode!() _user = insert(:user, @@ -144,7 +144,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do data = File.read!("test/fixtures/bogus-mastodon-announce.json") - |> Poison.decode!() + |> Jason.decode!() _user = insert(:user, local: false, ap_id: data["actor"]) @@ -157,7 +157,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do data = File.read!("test/fixtures/mastodon-announce.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", Object.normalize(activity).data["id"]) |> Map.put("to", ["http://mastodon.example.org/users/admin/followers"]) |> Map.put("cc", []) diff --git a/test/pleroma/web/activity_pub/transmogrifier/answer_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/answer_handling_test.exs index e7d85a2c5..a1c2ba28a 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/answer_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/answer_handling_test.exs @@ -31,7 +31,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnswerHandlingTest do data = File.read!("test/fixtures/mastodon-vote.json") - |> Poison.decode!() + |> Jason.decode!() |> Kernel.put_in(["to"], user.ap_id) |> Kernel.put_in(["object", "inReplyTo"], object.data["id"]) |> Kernel.put_in(["object", "to"], user.ap_id) @@ -66,7 +66,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnswerHandlingTest do # TODO: Replace with CommonAPI vote creation when implemented data = File.read!("test/fixtures/mastodon-vote.json") - |> Poison.decode!() + |> Jason.decode!() |> Kernel.put_in(["to"], user.ap_id) |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"]) |> Kernel.put_in(["object", "to"], user.ap_id) diff --git a/test/pleroma/web/activity_pub/transmogrifier/audio_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/audio_handling_test.exs index 6eeb1c863..7a2ac5d4d 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/audio_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/audio_handling_test.exs @@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do } end) - data = File.read!("test/fixtures/tesla_mock/funkwhale_create_audio.json") |> Poison.decode!() + data = File.read!("test/fixtures/tesla_mock/funkwhale_create_audio.json") |> Jason.decode!() {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) diff --git a/test/pleroma/web/activity_pub/transmogrifier/block_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/block_handling_test.exs index 71f1a0ed5..b8e4ad827 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/block_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/block_handling_test.exs @@ -16,7 +16,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.BlockHandlingTest do data = File.read!("test/fixtures/mastodon-block-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) blocker = insert(:user, ap_id: data["actor"]) @@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.BlockHandlingTest do data = File.read!("test/fixtures/mastodon-block-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", blocked.ap_id) |> Map.put("actor", blocker.ap_id) diff --git a/test/pleroma/web/activity_pub/transmogrifier/chat_message_test.exs b/test/pleroma/web/activity_pub/transmogrifier/chat_message_test.exs index 31274c067..2adaa1ade 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/chat_message_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/chat_message_test.exs @@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do test "it rejects messages that don't contain content" do data = File.read!("test/fixtures/create-chat-message.json") - |> Poison.decode!() + |> Jason.decode!() object = data["object"] @@ -79,7 +79,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do test "it rejects messages that don't concern local users" do data = File.read!("test/fixtures/create-chat-message.json") - |> Poison.decode!() + |> Jason.decode!() _author = insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now()) @@ -97,7 +97,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do test "it rejects messages where the `to` field of activity and object don't match" do data = File.read!("test/fixtures/create-chat-message.json") - |> Poison.decode!() + |> Jason.decode!() author = insert(:user, ap_id: data["actor"]) _recipient = insert(:user, ap_id: List.first(data["to"])) @@ -115,7 +115,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do data = File.read!("test/fixtures/create-chat-message.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", "http://mastodon.example.org/users/admin") |> put_in(["object", "actor"], "http://mastodon.example.org/users/admin") @@ -127,7 +127,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do test "it doesn't work for deactivated users" do data = File.read!("test/fixtures/create-chat-message.json") - |> Poison.decode!() + |> Jason.decode!() _author = insert(:user, @@ -145,7 +145,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do test "it inserts it and creates a chat" do data = File.read!("test/fixtures/create-chat-message.json") - |> Poison.decode!() + |> Jason.decode!() author = insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now()) diff --git a/test/pleroma/web/activity_pub/transmogrifier/delete_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/delete_handling_test.exs index c9a53918c..cffaa7c44 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/delete_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/delete_handling_test.exs @@ -25,7 +25,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do data = File.read!("test/fixtures/mastodon-delete.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", deleting_user.ap_id) |> put_in(["object", "id"], activity.data["object"]) @@ -57,7 +57,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do data = File.read!("test/fixtures/mastodon-delete.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", deleting_user.ap_id) |> put_in(["object", "id"], activity.data["object"]) @@ -78,7 +78,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do data = File.read!("test/fixtures/mastodon-delete.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", ap_id) |> put_in(["object", "id"], activity.data["object"]) @@ -91,7 +91,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do data = File.read!("test/fixtures/mastodon-delete-user.json") - |> Poison.decode!() + |> Jason.decode!() {:ok, _} = Transmogrifier.handle_incoming(data) ObanHelpers.perform_all() @@ -104,7 +104,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do data = File.read!("test/fixtures/mastodon-delete-user.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", ap_id) assert match?({:error, _}, Transmogrifier.handle_incoming(data)) diff --git a/test/pleroma/web/activity_pub/transmogrifier/emoji_react_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/emoji_react_handling_test.exs index 0fb056b50..aea4ed6f8 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/emoji_react_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/emoji_react_handling_test.exs @@ -19,7 +19,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do data = File.read!("test/fixtures/emoji-reaction.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) |> Map.put("actor", other_user.ap_id) @@ -44,7 +44,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do data = File.read!("test/fixtures/emoji-reaction-too-long.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) |> Map.put("actor", other_user.ap_id) @@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do data = File.read!("test/fixtures/emoji-reaction-no-emoji.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) |> Map.put("actor", other_user.ap_id) diff --git a/test/pleroma/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/follow_handling_test.exs index 4ef8210ad..985c26def 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -28,7 +28,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/osada-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data) @@ -47,7 +47,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data) @@ -69,7 +69,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) @@ -100,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data) @@ -116,7 +116,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("id", String.replace(data["id"], "2", "3")) |> Map.put("object", user.ap_id) @@ -142,7 +142,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) {:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data) @@ -157,7 +157,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) with_mock Pleroma.User, [:passthrough], follow: fn _, _, _ -> {:error, :testing} end do @@ -174,7 +174,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/hubzilla-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) |> Utils.normalize_params() @@ -192,7 +192,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) diff --git a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs index 53fe1d550..967bad151 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs @@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do data = File.read!("test/fixtures/mastodon-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) _actor = insert(:user, ap_id: data["actor"], local: false) @@ -40,7 +40,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do data = File.read!("test/fixtures/misskey-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) _actor = insert(:user, ap_id: data["actor"], local: false) @@ -61,7 +61,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do data = File.read!("test/fixtures/misskey-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) |> Map.put("_misskey_reaction", "โญ") diff --git a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs new file mode 100644 index 000000000..b4a006aec --- /dev/null +++ b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs @@ -0,0 +1,749 @@ +# 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.NoteHandlingTest do + use Oban.Testing, repo: Pleroma.Repo + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.User + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.CommonAPI + + import Mock + import Pleroma.Factory + import ExUnit.CaptureLog + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + :ok + end + + setup do: clear_config([:instance, :max_remote_account_fields]) + + describe "handle_incoming" do + test "it works for incoming notices with tag not being an array (kroeg)" do + data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + object = Object.normalize(data["object"]) + + assert object.data["emoji"] == %{ + "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png" + } + + data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + object = Object.normalize(data["object"]) + + assert "test" in object.data["tag"] + end + + test "it cleans up incoming notices which are not really DMs" do + user = insert(:user) + other_user = insert(:user) + + to = [user.ap_id, other_user.ap_id] + + data = + File.read!("test/fixtures/mastodon-post-activity.json") + |> Jason.decode!() + |> Map.put("to", to) + |> Map.put("cc", []) + + object = + data["object"] + |> Map.put("to", to) + |> Map.put("cc", []) + + data = Map.put(data, "object", object) + + {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data) + + assert data["to"] == [] + assert data["cc"] == to + + object_data = Object.normalize(activity).data + + assert object_data["to"] == [] + assert object_data["cc"] == to + end + + test "it ignores an incoming notice if we already have it" do + activity = insert(:note_activity) + + data = + File.read!("test/fixtures/mastodon-post-activity.json") + |> Jason.decode!() + |> Map.put("object", Object.normalize(activity).data) + + {:ok, returned_activity} = Transmogrifier.handle_incoming(data) + + assert activity == returned_activity + end + + @tag capture_log: true + test "it fetches reply-to activities if we don't have them" do + data = + File.read!("test/fixtures/mastodon-post-activity.json") + |> Jason.decode!() + + object = + data["object"] + |> Map.put("inReplyTo", "https://mstdn.io/users/mayuutann/statuses/99568293732299394") + + data = Map.put(data, "object", object) + {:ok, returned_activity} = Transmogrifier.handle_incoming(data) + returned_object = Object.normalize(returned_activity, false) + + assert %Activity{} = + Activity.get_create_by_object_ap_id( + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" + ) + + assert returned_object.data["inReplyTo"] == + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" + end + + test "it does not fetch reply-to activities beyond max replies depth limit" do + data = + File.read!("test/fixtures/mastodon-post-activity.json") + |> Jason.decode!() + + object = + data["object"] + |> Map.put("inReplyTo", "https://shitposter.club/notice/2827873") + + data = Map.put(data, "object", object) + + with_mock Pleroma.Web.Federator, + allowed_thread_distance?: fn _ -> false end do + {:ok, returned_activity} = Transmogrifier.handle_incoming(data) + + returned_object = Object.normalize(returned_activity, false) + + refute Activity.get_create_by_object_ap_id( + "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" + ) + + assert returned_object.data["inReplyTo"] == "https://shitposter.club/notice/2827873" + end + end + + test "it does not crash if the object in inReplyTo can't be fetched" do + data = + File.read!("test/fixtures/mastodon-post-activity.json") + |> Jason.decode!() + + object = + data["object"] + |> Map.put("inReplyTo", "https://404.site/whatever") + + data = + data + |> Map.put("object", object) + + assert capture_log(fn -> + {:ok, _returned_activity} = Transmogrifier.handle_incoming(data) + end) =~ "[warn] Couldn't fetch \"https://404.site/whatever\", error: nil" + end + + test "it does not work for deactivated users" do + data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() + + insert(:user, ap_id: data["actor"], deactivated: true) + + assert {:error, _} = Transmogrifier.handle_incoming(data) + end + + test "it works for incoming notices" do + data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + assert data["id"] == + "http://mastodon.example.org/users/admin/statuses/99512778738411822/activity" + + assert data["context"] == + "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation" + + assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"] + + assert data["cc"] == [ + "http://mastodon.example.org/users/admin/followers", + "http://localtesting.pleroma.lol/users/lain" + ] + + assert data["actor"] == "http://mastodon.example.org/users/admin" + + object_data = Object.normalize(data["object"]).data + + assert object_data["id"] == + "http://mastodon.example.org/users/admin/statuses/99512778738411822" + + assert object_data["to"] == ["https://www.w3.org/ns/activitystreams#Public"] + + assert object_data["cc"] == [ + "http://mastodon.example.org/users/admin/followers", + "http://localtesting.pleroma.lol/users/lain" + ] + + assert object_data["actor"] == "http://mastodon.example.org/users/admin" + assert object_data["attributedTo"] == "http://mastodon.example.org/users/admin" + + assert object_data["context"] == + "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation" + + assert object_data["sensitive"] == true + + user = User.get_cached_by_ap_id(object_data["actor"]) + + assert user.note_count == 1 + end + + test "it works for incoming notices without the sensitive property but an nsfw hashtag" do + data = File.read!("test/fixtures/mastodon-post-activity-nsfw.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + object_data = Object.normalize(data["object"], false).data + + assert object_data["sensitive"] == true + end + + test "it works for incoming notices with hashtags" do + data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + object = Object.normalize(data["object"]) + + assert Enum.at(object.data["tag"], 2) == "moo" + end + + test "it works for incoming notices with contentMap" do + data = File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + object = Object.normalize(data["object"]) + + assert object.data["content"] == + "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>" + end + + test "it works for incoming notices with to/cc not being an array (kroeg)" do + data = File.read!("test/fixtures/kroeg-post-activity.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + object = Object.normalize(data["object"]) + + assert object.data["content"] == + "<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>" + end + + test "it ensures that as:Public activities make it to their followers collection" do + user = insert(:user) + + data = + File.read!("test/fixtures/mastodon-post-activity.json") + |> Jason.decode!() + |> Map.put("actor", user.ap_id) + |> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"]) + |> Map.put("cc", []) + + object = + data["object"] + |> Map.put("attributedTo", user.ap_id) + |> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"]) + |> Map.put("cc", []) + |> Map.put("id", user.ap_id <> "/activities/12345678") + + data = Map.put(data, "object", object) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + assert data["cc"] == [User.ap_followers(user)] + end + + test "it ensures that address fields become lists" do + user = insert(:user) + + data = + File.read!("test/fixtures/mastodon-post-activity.json") + |> Jason.decode!() + |> Map.put("actor", user.ap_id) + |> Map.put("to", nil) + |> Map.put("cc", nil) + + object = + data["object"] + |> Map.put("attributedTo", user.ap_id) + |> Map.put("to", nil) + |> Map.put("cc", nil) + |> Map.put("id", user.ap_id <> "/activities/12345678") + + data = Map.put(data, "object", object) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + assert !is_nil(data["to"]) + assert !is_nil(data["cc"]) + end + + test "it strips internal likes" do + data = + File.read!("test/fixtures/mastodon-post-activity.json") + |> Jason.decode!() + + likes = %{ + "first" => + "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes?page=1", + "id" => "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes", + "totalItems" => 3, + "type" => "OrderedCollection" + } + + object = Map.put(data["object"], "likes", likes) + data = Map.put(data, "object", object) + + {:ok, %Activity{object: object}} = Transmogrifier.handle_incoming(data) + + refute Map.has_key?(object.data, "likes") + end + + test "it strips internal reactions" do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) + {:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "๐ข") + + %{object: object} = Activity.get_by_id_with_object(activity.id) + assert Map.has_key?(object.data, "reactions") + assert Map.has_key?(object.data, "reaction_count") + + object_data = Transmogrifier.strip_internal_fields(object.data) + refute Map.has_key?(object_data, "reactions") + refute Map.has_key?(object_data, "reaction_count") + end + + test "it correctly processes messages with non-array to field" do + user = insert(:user) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => "https://www.w3.org/ns/activitystreams#Public", + "type" => "Create", + "object" => %{ + "content" => "blah blah blah", + "type" => "Note", + "attributedTo" => user.ap_id, + "inReplyTo" => nil + }, + "actor" => user.ap_id + } + + assert {:ok, activity} = Transmogrifier.handle_incoming(message) + + assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["to"] + end + + test "it correctly processes messages with non-array cc field" do + user = insert(:user) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => user.follower_address, + "cc" => "https://www.w3.org/ns/activitystreams#Public", + "type" => "Create", + "object" => %{ + "content" => "blah blah blah", + "type" => "Note", + "attributedTo" => user.ap_id, + "inReplyTo" => nil + }, + "actor" => user.ap_id + } + + assert {:ok, activity} = Transmogrifier.handle_incoming(message) + + assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"] + assert [user.follower_address] == activity.data["to"] + end + + test "it correctly processes messages with weirdness in address fields" do + user = insert(:user) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [nil, user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public", ["ยฟ"]], + "type" => "Create", + "object" => %{ + "content" => "โฆ", + "type" => "Note", + "attributedTo" => user.ap_id, + "inReplyTo" => nil + }, + "actor" => user.ap_id + } + + assert {:ok, activity} = Transmogrifier.handle_incoming(message) + + assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"] + assert [user.follower_address] == activity.data["to"] + end + end + + describe "`handle_incoming/2`, Mastodon format `replies` handling" do + setup do: clear_config([:activitypub, :note_replies_output_limit], 5) + setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) + + setup do + data = + "test/fixtures/mastodon-post-activity.json" + |> File.read!() + |> Jason.decode!() + + items = get_in(data, ["object", "replies", "first", "items"]) + assert length(items) > 0 + + %{data: data, items: items} + end + + test "schedules background fetching of `replies` items if max thread depth limit allows", %{ + data: data, + items: items + } do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10) + + {:ok, _activity} = Transmogrifier.handle_incoming(data) + + for id <- items do + job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1} + assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args) + end + end + + test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows", + %{data: data} do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + + {:ok, _activity} = Transmogrifier.handle_incoming(data) + + assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == [] + end + end + + describe "`handle_incoming/2`, Pleroma format `replies` handling" do + setup do: clear_config([:activitypub, :note_replies_output_limit], 5) + setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) + + setup do + user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{status: "post1"}) + + {:ok, reply1} = + CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: activity.id}) + + {:ok, reply2} = + CommonAPI.post(user, %{status: "reply2", in_reply_to_status_id: activity.id}) + + replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end) + + {:ok, federation_output} = Transmogrifier.prepare_outgoing(activity.data) + + Repo.delete(activity.object) + Repo.delete(activity) + + %{federation_output: federation_output, replies_uris: replies_uris} + end + + test "schedules background fetching of `replies` items if max thread depth limit allows", %{ + federation_output: federation_output, + replies_uris: replies_uris + } do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 1) + + {:ok, _activity} = Transmogrifier.handle_incoming(federation_output) + + for id <- replies_uris do + job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1} + assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args) + end + end + + test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows", + %{federation_output: federation_output} do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + + {:ok, _activity} = Transmogrifier.handle_incoming(federation_output) + + assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == [] + end + end + + describe "reserialization" do + test "successfully reserializes a message with inReplyTo == nil" do + user = insert(:user) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => ["https://www.w3.org/ns/activitystreams#Public"], + "cc" => [], + "type" => "Create", + "object" => %{ + "to" => ["https://www.w3.org/ns/activitystreams#Public"], + "cc" => [], + "type" => "Note", + "content" => "Hi", + "inReplyTo" => nil, + "attributedTo" => user.ap_id + }, + "actor" => user.ap_id + } + + {:ok, activity} = Transmogrifier.handle_incoming(message) + + {:ok, _} = Transmogrifier.prepare_outgoing(activity.data) + end + + test "successfully reserializes a message with AS2 objects in IR" do + user = insert(:user) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => ["https://www.w3.org/ns/activitystreams#Public"], + "cc" => [], + "type" => "Create", + "object" => %{ + "to" => ["https://www.w3.org/ns/activitystreams#Public"], + "cc" => [], + "type" => "Note", + "content" => "Hi", + "inReplyTo" => nil, + "attributedTo" => user.ap_id, + "tag" => [ + %{"name" => "#2hu", "href" => "http://example.com/2hu", "type" => "Hashtag"}, + %{"name" => "Bob", "href" => "http://example.com/bob", "type" => "Mention"} + ] + }, + "actor" => user.ap_id + } + + {:ok, activity} = Transmogrifier.handle_incoming(message) + + {:ok, _} = Transmogrifier.prepare_outgoing(activity.data) + end + end + + describe "fix_in_reply_to/2" do + setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) + + setup do + data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) + [data: data] + end + + test "returns not modified object when hasn't containts inReplyTo field", %{data: data} do + assert Transmogrifier.fix_in_reply_to(data) == data + end + + test "returns object with inReplyTo when denied incoming reply", %{data: data} do + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + + object_with_reply = + Map.put(data["object"], "inReplyTo", "https://shitposter.club/notice/2827873") + + modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) + assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873" + + object_with_reply = + Map.put(data["object"], "inReplyTo", %{"id" => "https://shitposter.club/notice/2827873"}) + + modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) + assert modified_object["inReplyTo"] == %{"id" => "https://shitposter.club/notice/2827873"} + + object_with_reply = + Map.put(data["object"], "inReplyTo", ["https://shitposter.club/notice/2827873"]) + + modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) + assert modified_object["inReplyTo"] == ["https://shitposter.club/notice/2827873"] + + object_with_reply = Map.put(data["object"], "inReplyTo", []) + modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) + assert modified_object["inReplyTo"] == [] + end + + @tag capture_log: true + test "returns modified object when allowed incoming reply", %{data: data} do + object_with_reply = + Map.put( + data["object"], + "inReplyTo", + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" + ) + + Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 5) + modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) + + assert modified_object["inReplyTo"] == + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" + + assert modified_object["context"] == + "tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4" + end + end + + describe "fix_attachments/1" do + test "returns not modified object" do + data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) + assert Transmogrifier.fix_attachments(data) == data + end + + test "returns modified object when attachment is map" do + assert Transmogrifier.fix_attachments(%{ + "attachment" => %{ + "mediaType" => "video/mp4", + "url" => "https://peertube.moe/stat-480.mp4" + } + }) == %{ + "attachment" => [ + %{ + "mediaType" => "video/mp4", + "type" => "Document", + "url" => [ + %{ + "href" => "https://peertube.moe/stat-480.mp4", + "mediaType" => "video/mp4", + "type" => "Link" + } + ] + } + ] + } + end + + test "returns modified object when attachment is list" do + assert Transmogrifier.fix_attachments(%{ + "attachment" => [ + %{"mediaType" => "video/mp4", "url" => "https://pe.er/stat-480.mp4"}, + %{"mimeType" => "video/mp4", "href" => "https://pe.er/stat-480.mp4"} + ] + }) == %{ + "attachment" => [ + %{ + "mediaType" => "video/mp4", + "type" => "Document", + "url" => [ + %{ + "href" => "https://pe.er/stat-480.mp4", + "mediaType" => "video/mp4", + "type" => "Link" + } + ] + }, + %{ + "mediaType" => "video/mp4", + "type" => "Document", + "url" => [ + %{ + "href" => "https://pe.er/stat-480.mp4", + "mediaType" => "video/mp4", + "type" => "Link" + } + ] + } + ] + } + end + end + + describe "fix_emoji/1" do + test "returns not modified object when object not contains tags" do + data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) + assert Transmogrifier.fix_emoji(data) == data + end + + test "returns object with emoji when object contains list tags" do + assert Transmogrifier.fix_emoji(%{ + "tag" => [ + %{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}}, + %{"type" => "Hashtag"} + ] + }) == %{ + "emoji" => %{"bib" => "/test"}, + "tag" => [ + %{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"}, + %{"type" => "Hashtag"} + ] + } + end + + test "returns object with emoji when object contains map tag" do + assert Transmogrifier.fix_emoji(%{ + "tag" => %{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}} + }) == %{ + "emoji" => %{"bib" => "/test"}, + "tag" => %{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"} + } + end + end + + describe "set_replies/1" do + setup do: clear_config([:activitypub, :note_replies_output_limit], 2) + + test "returns unmodified object if activity doesn't have self-replies" do + data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) + assert Transmogrifier.set_replies(data) == data + end + + test "sets `replies` collection with a limited number of self-replies" do + [user, another_user] = insert_list(2, :user) + + {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{status: "1"}) + + {:ok, %{id: id2} = self_reply1} = + CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: id1}) + + {:ok, self_reply2} = + CommonAPI.post(user, %{status: "self-reply 2", in_reply_to_status_id: id1}) + + # Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2 + {:ok, _} = CommonAPI.post(user, %{status: "self-reply 3", in_reply_to_status_id: id1}) + + {:ok, _} = + CommonAPI.post(user, %{ + status: "self-reply to self-reply", + in_reply_to_status_id: id2 + }) + + {:ok, _} = + CommonAPI.post(another_user, %{ + status: "another user's reply", + in_reply_to_status_id: id1 + }) + + object = Object.normalize(activity) + replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end) + + assert %{"type" => "Collection", "items" => ^replies_uris} = + Transmogrifier.set_replies(object.data)["replies"] + end + end + + test "take_emoji_tags/1" do + user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}}) + + assert Transmogrifier.take_emoji_tags(user) == [ + %{ + "icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"}, + "id" => "https://example.org/firefox.png", + "name" => ":firefox:", + "type" => "Emoji", + "updated" => "1970-01-01T00:00:00Z" + } + ] + end +end diff --git a/test/pleroma/web/activity_pub/transmogrifier/question_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/question_handling_test.exs index d2822ce75..47f92cf4d 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/question_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/question_handling_test.exs @@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do end test "Mastodon Question activity" do - data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() + data = File.read!("test/fixtures/mastodon-question-activity.json") |> Jason.decode!() {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) @@ -97,7 +97,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do data = File.read!("test/fixtures/mastodon-question-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Kernel.put_in(["object", "oneOf"], options) {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) @@ -142,7 +142,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do data = File.read!("test/fixtures/mastodon-question-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Kernel.put_in(["object", "oneOf"], options) |> Kernel.put_in(["object", "tag"], tag) @@ -158,7 +158,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do end test "returns same activity if received a second time" do - data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() + data = File.read!("test/fixtures/mastodon-question-activity.json") |> Jason.decode!() assert {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) @@ -168,7 +168,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do test "accepts a Question with no content" do data = File.read!("test/fixtures/mastodon-question-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Kernel.put_in(["object", "content"], "") assert {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data) diff --git a/test/pleroma/web/activity_pub/transmogrifier/reject_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/reject_handling_test.exs index 5c1451def..cc28eb7ef 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/reject_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/reject_handling_test.exs @@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.RejectHandlingTest do accept_data = File.read!("test/fixtures/mastodon-reject-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", followed.ap_id) accept_data = @@ -42,7 +42,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.RejectHandlingTest do reject_data = File.read!("test/fixtures/mastodon-reject-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", followed.ap_id) |> Map.put("object", follow_activity.data["id"]) @@ -58,7 +58,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.RejectHandlingTest do data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) |> Map.put("id", "") diff --git a/test/pleroma/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/undo_handling_test.exs index 8683f7135..fcfc7b4b6 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/undo_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/undo_handling_test.exs @@ -21,7 +21,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do data = File.read!("test/fixtures/mastodon-undo-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", reaction_activity.data["id"]) |> Map.put("actor", user.ap_id) @@ -38,7 +38,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do data = File.read!("test/fixtures/mastodon-undo-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) assert Transmogrifier.handle_incoming(data) == :error @@ -50,7 +50,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do like_data = File.read!("test/fixtures/mastodon-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) _liker = insert(:user, ap_id: like_data["actor"], local: false) @@ -59,7 +59,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do data = File.read!("test/fixtures/mastodon-undo-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", like_data) |> Map.put("actor", like_data["actor"]) @@ -81,7 +81,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do like_data = File.read!("test/fixtures/mastodon-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) _liker = insert(:user, ap_id: like_data["actor"], local: false) @@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do data = File.read!("test/fixtures/mastodon-undo-like.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", like_data["id"]) |> Map.put("actor", like_data["actor"]) @@ -108,7 +108,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do announce_data = File.read!("test/fixtures/mastodon-announce.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) _announcer = insert(:user, ap_id: announce_data["actor"], local: false) @@ -118,7 +118,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do data = File.read!("test/fixtures/mastodon-undo-announce.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", announce_data) |> Map.put("actor", announce_data["actor"]) @@ -135,7 +135,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do follow_data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) _follower = insert(:user, ap_id: follow_data["actor"], local: false) @@ -144,7 +144,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do data = File.read!("test/fixtures/mastodon-unfollow-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", follow_data) {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) @@ -162,7 +162,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do block_data = File.read!("test/fixtures/mastodon-block-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", user.ap_id) _blocker = insert(:user, ap_id: block_data["actor"], local: false) @@ -171,7 +171,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do data = File.read!("test/fixtures/mastodon-unblock-activity.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", block_data) {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) diff --git a/test/pleroma/web/activity_pub/transmogrifier/user_update_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/user_update_handling_test.exs index 7c4d16db7..c62d5e139 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/user_update_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/user_update_handling_test.exs @@ -14,7 +14,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UserUpdateHandlingTest do test "it works for incoming update activities" do user = insert(:user, local: false) - update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!() + update_data = File.read!("test/fixtures/mastodon-update.json") |> Jason.decode!() object = update_data["object"] @@ -58,7 +58,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UserUpdateHandlingTest do {:ok, _activity} = "test/fixtures/mastodon-update.json" |> File.read!() - |> Poison.decode!() + |> Jason.decode!() |> Map.put("actor", actor) |> Map.update!("object", fn object -> object @@ -82,7 +82,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UserUpdateHandlingTest do assert user.fields == [] - update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!() + update_data = File.read!("test/fixtures/mastodon-update.json") |> Jason.decode!() object = update_data["object"] @@ -138,7 +138,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UserUpdateHandlingTest do test "it works for incoming update activities which lock the account" do user = insert(:user, local: false) - update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!() + update_data = File.read!("test/fixtures/mastodon-update.json") |> Jason.decode!() object = update_data["object"] diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs index e39af1dfc..66ea7664a 100644 --- a/test/pleroma/web/activity_pub/transmogrifier_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs @@ -26,323 +26,19 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do setup do: clear_config([:instance, :max_remote_account_fields]) describe "handle_incoming" do - test "it works for incoming notices with tag not being an array (kroeg)" do - data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Poison.decode!() - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - object = Object.normalize(data["object"]) - - assert object.data["emoji"] == %{ - "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png" - } - - data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Poison.decode!() - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - object = Object.normalize(data["object"]) - - assert "test" in object.data["tag"] - end - - test "it cleans up incoming notices which are not really DMs" do - user = insert(:user) - other_user = insert(:user) - - to = [user.ap_id, other_user.ap_id] - - data = - File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() - |> Map.put("to", to) - |> Map.put("cc", []) - - object = - data["object"] - |> Map.put("to", to) - |> Map.put("cc", []) - - data = Map.put(data, "object", object) - - {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data) - - assert data["to"] == [] - assert data["cc"] == to - - object_data = Object.normalize(activity).data - - assert object_data["to"] == [] - assert object_data["cc"] == to - end - - test "it ignores an incoming notice if we already have it" do - activity = insert(:note_activity) - - data = - File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() - |> Map.put("object", Object.normalize(activity).data) - - {:ok, returned_activity} = Transmogrifier.handle_incoming(data) - - assert activity == returned_activity - end - - @tag capture_log: true - test "it fetches reply-to activities if we don't have them" do - data = - File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() - - object = - data["object"] - |> Map.put("inReplyTo", "https://mstdn.io/users/mayuutann/statuses/99568293732299394") - - data = Map.put(data, "object", object) - {:ok, returned_activity} = Transmogrifier.handle_incoming(data) - returned_object = Object.normalize(returned_activity, false) - - assert %Activity{} = - Activity.get_create_by_object_ap_id( - "https://mstdn.io/users/mayuutann/statuses/99568293732299394" - ) - - assert returned_object.data["inReplyTo"] == - "https://mstdn.io/users/mayuutann/statuses/99568293732299394" - end - - test "it does not fetch reply-to activities beyond max replies depth limit" do - data = - File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() - - object = - data["object"] - |> Map.put("inReplyTo", "https://shitposter.club/notice/2827873") - - data = Map.put(data, "object", object) - - with_mock Pleroma.Web.Federator, - allowed_thread_distance?: fn _ -> false end do - {:ok, returned_activity} = Transmogrifier.handle_incoming(data) - - returned_object = Object.normalize(returned_activity, false) - - refute Activity.get_create_by_object_ap_id( - "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" - ) - - assert returned_object.data["inReplyTo"] == "https://shitposter.club/notice/2827873" - end - end - - test "it does not crash if the object in inReplyTo can't be fetched" do - data = - File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() - - object = - data["object"] - |> Map.put("inReplyTo", "https://404.site/whatever") - - data = - data - |> Map.put("object", object) - - assert capture_log(fn -> - {:ok, _returned_activity} = Transmogrifier.handle_incoming(data) - end) =~ "[warn] Couldn't fetch \"https://404.site/whatever\", error: nil" - end - - test "it does not work for deactivated users" do - data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() - - insert(:user, ap_id: data["actor"], deactivated: true) - - assert {:error, _} = Transmogrifier.handle_incoming(data) - end - - test "it works for incoming notices" do - data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["id"] == - "http://mastodon.example.org/users/admin/statuses/99512778738411822/activity" - - assert data["context"] == - "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation" - - assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"] - - assert data["cc"] == [ - "http://mastodon.example.org/users/admin/followers", - "http://localtesting.pleroma.lol/users/lain" - ] - - assert data["actor"] == "http://mastodon.example.org/users/admin" - - object_data = Object.normalize(data["object"]).data - - assert object_data["id"] == - "http://mastodon.example.org/users/admin/statuses/99512778738411822" - - assert object_data["to"] == ["https://www.w3.org/ns/activitystreams#Public"] - - assert object_data["cc"] == [ - "http://mastodon.example.org/users/admin/followers", - "http://localtesting.pleroma.lol/users/lain" - ] - - assert object_data["actor"] == "http://mastodon.example.org/users/admin" - assert object_data["attributedTo"] == "http://mastodon.example.org/users/admin" - - assert object_data["context"] == - "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation" - - assert object_data["sensitive"] == true - - user = User.get_cached_by_ap_id(object_data["actor"]) - - assert user.note_count == 1 - end - - test "it works for incoming notices without the sensitive property but an nsfw hashtag" do - data = File.read!("test/fixtures/mastodon-post-activity-nsfw.json") |> Poison.decode!() - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - object_data = Object.normalize(data["object"], false).data - - assert object_data["sensitive"] == true - end - - test "it works for incoming notices with hashtags" do - data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Poison.decode!() - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - object = Object.normalize(data["object"]) - - assert Enum.at(object.data["tag"], 2) == "moo" - end - - test "it works for incoming notices with contentMap" do - data = - File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!() - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - object = Object.normalize(data["object"]) - - assert object.data["content"] == - "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>" - end - - test "it works for incoming notices with to/cc not being an array (kroeg)" do - data = File.read!("test/fixtures/kroeg-post-activity.json") |> Poison.decode!() - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - object = Object.normalize(data["object"]) - - assert object.data["content"] == - "<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>" - end - - test "it ensures that as:Public activities make it to their followers collection" do - user = insert(:user) - - data = - File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() - |> Map.put("actor", user.ap_id) - |> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"]) - |> Map.put("cc", []) - - object = - data["object"] - |> Map.put("attributedTo", user.ap_id) - |> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"]) - |> Map.put("cc", []) - |> Map.put("id", user.ap_id <> "/activities/12345678") - - data = Map.put(data, "object", object) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["cc"] == [User.ap_followers(user)] - end - - test "it ensures that address fields become lists" do - user = insert(:user) - - data = - File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() - |> Map.put("actor", user.ap_id) - |> Map.put("to", nil) - |> Map.put("cc", nil) - - object = - data["object"] - |> Map.put("attributedTo", user.ap_id) - |> Map.put("to", nil) - |> Map.put("cc", nil) - |> Map.put("id", user.ap_id <> "/activities/12345678") - - data = Map.put(data, "object", object) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert !is_nil(data["to"]) - assert !is_nil(data["cc"]) - end - - test "it strips internal likes" do - data = - File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() - - likes = %{ - "first" => - "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes?page=1", - "id" => "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes", - "totalItems" => 3, - "type" => "OrderedCollection" - } - - object = Map.put(data["object"], "likes", likes) - data = Map.put(data, "object", object) - - {:ok, %Activity{object: object}} = Transmogrifier.handle_incoming(data) - - refute Map.has_key?(object.data, "likes") - end - - test "it strips internal reactions" do - user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) - {:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "๐ข") - - %{object: object} = Activity.get_by_id_with_object(activity.id) - assert Map.has_key?(object.data, "reactions") - assert Map.has_key?(object.data, "reaction_count") - - object_data = Transmogrifier.strip_internal_fields(object.data) - refute Map.has_key?(object_data, "reactions") - refute Map.has_key?(object_data, "reaction_count") - end - test "it works for incoming unfollows with an existing follow" do user = insert(:user) follow_data = File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() + |> Jason.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!() + |> Jason.decode!() |> Map.put("object", follow_data) {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) @@ -387,73 +83,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert activity.data["cc"] == [user.ap_id] end - test "it correctly processes messages with non-array to field" do - user = insert(:user) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => "https://www.w3.org/ns/activitystreams#Public", - "type" => "Create", - "object" => %{ - "content" => "blah blah blah", - "type" => "Note", - "attributedTo" => user.ap_id, - "inReplyTo" => nil - }, - "actor" => user.ap_id - } - - assert {:ok, activity} = Transmogrifier.handle_incoming(message) - - assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["to"] - end - - test "it correctly processes messages with non-array cc field" do - user = insert(:user) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => user.follower_address, - "cc" => "https://www.w3.org/ns/activitystreams#Public", - "type" => "Create", - "object" => %{ - "content" => "blah blah blah", - "type" => "Note", - "attributedTo" => user.ap_id, - "inReplyTo" => nil - }, - "actor" => user.ap_id - } - - assert {:ok, activity} = Transmogrifier.handle_incoming(message) - - assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"] - assert [user.follower_address] == activity.data["to"] - end - - test "it correctly processes messages with weirdness in address fields" do - user = insert(:user) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => [nil, user.follower_address], - "cc" => ["https://www.w3.org/ns/activitystreams#Public", ["ยฟ"]], - "type" => "Create", - "object" => %{ - "content" => "โฆ", - "type" => "Note", - "attributedTo" => user.ap_id, - "inReplyTo" => nil - }, - "actor" => user.ap_id - } - - assert {:ok, activity} = Transmogrifier.handle_incoming(message) - - assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"] - assert [user.follower_address] == activity.data["to"] - end - test "it accepts Move activities" do old_user = insert(:user) new_user = insert(:user) @@ -479,95 +108,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do end end - describe "`handle_incoming/2`, Mastodon format `replies` handling" do - setup do: clear_config([:activitypub, :note_replies_output_limit], 5) - setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) - - setup do - data = - "test/fixtures/mastodon-post-activity.json" - |> File.read!() - |> Poison.decode!() - - items = get_in(data, ["object", "replies", "first", "items"]) - assert length(items) > 0 - - %{data: data, items: items} - end - - test "schedules background fetching of `replies` items if max thread depth limit allows", %{ - data: data, - items: items - } do - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10) - - {:ok, _activity} = Transmogrifier.handle_incoming(data) - - for id <- items do - job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1} - assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args) - end - end - - test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows", - %{data: data} do - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) - - {:ok, _activity} = Transmogrifier.handle_incoming(data) - - assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == [] - end - end - - describe "`handle_incoming/2`, Pleroma format `replies` handling" do - setup do: clear_config([:activitypub, :note_replies_output_limit], 5) - setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) - - setup do - user = insert(:user) - - {:ok, activity} = CommonAPI.post(user, %{status: "post1"}) - - {:ok, reply1} = - CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: activity.id}) - - {:ok, reply2} = - CommonAPI.post(user, %{status: "reply2", in_reply_to_status_id: activity.id}) - - replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end) - - {:ok, federation_output} = Transmogrifier.prepare_outgoing(activity.data) - - Repo.delete(activity.object) - Repo.delete(activity) - - %{federation_output: federation_output, replies_uris: replies_uris} - end - - test "schedules background fetching of `replies` items if max thread depth limit allows", %{ - federation_output: federation_output, - replies_uris: replies_uris - } do - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 1) - - {:ok, _activity} = Transmogrifier.handle_incoming(federation_output) - - for id <- replies_uris do - job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1} - assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args) - end - end - - test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows", - %{federation_output: federation_output} do - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) - - {:ok, _activity} = Transmogrifier.handle_incoming(federation_output) - - assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == [] - end - end - describe "prepare outgoing" do test "it inlines private announced objects" do user = insert(:user) @@ -864,60 +404,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do end end - describe "reserialization" do - test "successfully reserializes a message with inReplyTo == nil" do - user = insert(:user) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "type" => "Create", - "object" => %{ - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "type" => "Note", - "content" => "Hi", - "inReplyTo" => nil, - "attributedTo" => user.ap_id - }, - "actor" => user.ap_id - } - - {:ok, activity} = Transmogrifier.handle_incoming(message) - - {:ok, _} = Transmogrifier.prepare_outgoing(activity.data) - end - - test "successfully reserializes a message with AS2 objects in IR" do - user = insert(:user) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "type" => "Create", - "object" => %{ - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "type" => "Note", - "content" => "Hi", - "inReplyTo" => nil, - "attributedTo" => user.ap_id, - "tag" => [ - %{"name" => "#2hu", "href" => "http://example.com/2hu", "type" => "Hashtag"}, - %{"name" => "Bob", "href" => "http://example.com/bob", "type" => "Mention"} - ] - }, - "actor" => user.ap_id - } - - {:ok, activity} = Transmogrifier.handle_incoming(message) - - {:ok, _} = Transmogrifier.prepare_outgoing(activity.data) - end - end - describe "fix_explicit_addressing" do setup do user = insert(:user) @@ -983,64 +469,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do end end - describe "fix_in_reply_to/2" do - setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) - - setup do - data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) - [data: data] - end - - test "returns not modified object when hasn't containts inReplyTo field", %{data: data} do - assert Transmogrifier.fix_in_reply_to(data) == data - end - - test "returns object with inReplyTo when denied incoming reply", %{data: data} do - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) - - object_with_reply = - Map.put(data["object"], "inReplyTo", "https://shitposter.club/notice/2827873") - - modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) - assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873" - - object_with_reply = - Map.put(data["object"], "inReplyTo", %{"id" => "https://shitposter.club/notice/2827873"}) - - modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) - assert modified_object["inReplyTo"] == %{"id" => "https://shitposter.club/notice/2827873"} - - object_with_reply = - Map.put(data["object"], "inReplyTo", ["https://shitposter.club/notice/2827873"]) - - modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) - assert modified_object["inReplyTo"] == ["https://shitposter.club/notice/2827873"] - - object_with_reply = Map.put(data["object"], "inReplyTo", []) - modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) - assert modified_object["inReplyTo"] == [] - end - - @tag capture_log: true - test "returns modified object when allowed incoming reply", %{data: data} do - object_with_reply = - Map.put( - data["object"], - "inReplyTo", - "https://mstdn.io/users/mayuutann/statuses/99568293732299394" - ) - - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 5) - modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) - - assert modified_object["inReplyTo"] == - "https://mstdn.io/users/mayuutann/statuses/99568293732299394" - - assert modified_object["context"] == - "tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4" - end - end - describe "fix_url/1" do test "fixes data for object when url is map" do object = %{ @@ -1076,155 +504,4 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do ) end end - - describe "fix_attachments/1" do - test "returns not modified object" do - data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) - assert Transmogrifier.fix_attachments(data) == data - end - - test "returns modified object when attachment is map" do - assert Transmogrifier.fix_attachments(%{ - "attachment" => %{ - "mediaType" => "video/mp4", - "url" => "https://peertube.moe/stat-480.mp4" - } - }) == %{ - "attachment" => [ - %{ - "mediaType" => "video/mp4", - "type" => "Document", - "url" => [ - %{ - "href" => "https://peertube.moe/stat-480.mp4", - "mediaType" => "video/mp4", - "type" => "Link" - } - ] - } - ] - } - end - - test "returns modified object when attachment is list" do - assert Transmogrifier.fix_attachments(%{ - "attachment" => [ - %{"mediaType" => "video/mp4", "url" => "https://pe.er/stat-480.mp4"}, - %{"mimeType" => "video/mp4", "href" => "https://pe.er/stat-480.mp4"} - ] - }) == %{ - "attachment" => [ - %{ - "mediaType" => "video/mp4", - "type" => "Document", - "url" => [ - %{ - "href" => "https://pe.er/stat-480.mp4", - "mediaType" => "video/mp4", - "type" => "Link" - } - ] - }, - %{ - "mediaType" => "video/mp4", - "type" => "Document", - "url" => [ - %{ - "href" => "https://pe.er/stat-480.mp4", - "mediaType" => "video/mp4", - "type" => "Link" - } - ] - } - ] - } - end - end - - describe "fix_emoji/1" do - test "returns not modified object when object not contains tags" do - data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) - assert Transmogrifier.fix_emoji(data) == data - end - - test "returns object with emoji when object contains list tags" do - assert Transmogrifier.fix_emoji(%{ - "tag" => [ - %{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}}, - %{"type" => "Hashtag"} - ] - }) == %{ - "emoji" => %{"bib" => "/test"}, - "tag" => [ - %{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"}, - %{"type" => "Hashtag"} - ] - } - end - - test "returns object with emoji when object contains map tag" do - assert Transmogrifier.fix_emoji(%{ - "tag" => %{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}} - }) == %{ - "emoji" => %{"bib" => "/test"}, - "tag" => %{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"} - } - end - end - - describe "set_replies/1" do - setup do: clear_config([:activitypub, :note_replies_output_limit], 2) - - test "returns unmodified object if activity doesn't have self-replies" do - data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) - assert Transmogrifier.set_replies(data) == data - end - - test "sets `replies` collection with a limited number of self-replies" do - [user, another_user] = insert_list(2, :user) - - {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{status: "1"}) - - {:ok, %{id: id2} = self_reply1} = - CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: id1}) - - {:ok, self_reply2} = - CommonAPI.post(user, %{status: "self-reply 2", in_reply_to_status_id: id1}) - - # Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2 - {:ok, _} = CommonAPI.post(user, %{status: "self-reply 3", in_reply_to_status_id: id1}) - - {:ok, _} = - CommonAPI.post(user, %{ - status: "self-reply to self-reply", - in_reply_to_status_id: id2 - }) - - {:ok, _} = - CommonAPI.post(another_user, %{ - status: "another user's reply", - in_reply_to_status_id: id1 - }) - - object = Object.normalize(activity) - replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end) - - assert %{"type" => "Collection", "items" => ^replies_uris} = - Transmogrifier.set_replies(object.data)["replies"] - end - end - - test "take_emoji_tags/1" do - user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}}) - - assert Transmogrifier.take_emoji_tags(user) == [ - %{ - "icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"}, - "id" => "https://example.org/firefox.png", - "name" => ":firefox:", - "type" => "Emoji", - "updated" => "1970-01-01T00:00:00Z" - } - ] - end end diff --git a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs new file mode 100644 index 000000000..94873f6db --- /dev/null +++ b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs @@ -0,0 +1,141 @@ +# Pleroma: A lightweight social networking server +# Copyright ยฉ 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do + use Pleroma.Web.ConnCase + + import Pleroma.Factory + + alias Pleroma.Config + + @dir "test/frontend_static_test" + + setup do + clear_config([:instance, :static_dir], @dir) + File.mkdir_p!(Pleroma.Frontend.dir()) + + on_exit(fn -> + File.rm_rf(@dir) + end) + + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + + {:ok, %{admin: admin, token: token, conn: conn}} + end + + describe "GET /api/pleroma/admin/frontends" do + test "it lists available frontends", %{conn: conn} do + response = + conn + |> get("/api/pleroma/admin/frontends") + |> json_response_and_validate_schema(:ok) + + assert Enum.map(response, & &1["name"]) == + Enum.map(Config.get([:frontends, :available]), fn {_, map} -> map["name"] end) + + refute Enum.any?(response, fn frontend -> frontend["installed"] == true end) + end + end + + describe "POST /api/pleroma/admin/frontends/install" do + test "from available frontends", %{conn: conn} do + clear_config([:frontends, :available], %{ + "pleroma" => %{ + "ref" => "fantasy", + "name" => "pleroma", + "build_url" => "http://gensokyo.2hu/builds/${ref}" + } + }) + + Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")} + end) + + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/frontends/install", %{name: "pleroma"}) + |> json_response_and_validate_schema(:ok) + + assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"])) + + response = + conn + |> get("/api/pleroma/admin/frontends") + |> json_response_and_validate_schema(:ok) + + assert response == [ + %{ + "build_url" => "http://gensokyo.2hu/builds/${ref}", + "git" => nil, + "installed" => true, + "name" => "pleroma", + "ref" => "fantasy" + } + ] + end + + test "from a file", %{conn: conn} do + clear_config([:frontends, :available], %{ + "pleroma" => %{ + "ref" => "fantasy", + "name" => "pleroma", + "build_dir" => "" + } + }) + + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/frontends/install", %{ + name: "pleroma", + file: "test/fixtures/tesla_mock/frontend.zip" + }) + |> json_response_and_validate_schema(:ok) + + assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"])) + end + + test "from an URL", %{conn: conn} do + Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend.zip")} + end) + + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/frontends/install", %{ + name: "unknown", + ref: "baka", + build_url: "http://gensokyo.2hu/madeup.zip", + build_dir: "" + }) + |> json_response_and_validate_schema(:ok) + + assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"])) + end + + test "failing returns an error", %{conn: conn} do + Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} -> + %Tesla.Env{status: 404, body: ""} + end) + + result = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/frontends/install", %{ + name: "unknown", + ref: "baka", + build_url: "http://gensokyo.2hu/madeup.zip", + build_dir: "" + }) + |> json_response_and_validate_schema(400) + + assert result == %{"error" => "Could not download or unzip the frontend"} + end + end +end diff --git a/test/pleroma/web/admin_api/controllers/report_controller_test.exs b/test/pleroma/web/admin_api/controllers/report_controller_test.exs index 958e1d3ab..cbfc2e7b0 100644 --- a/test/pleroma/web/admin_api/controllers/report_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/report_controller_test.exs @@ -122,13 +122,13 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do }) |> json_response_and_validate_schema(:no_content) - activity = Activity.get_by_id(id) + activity = Activity.get_by_id_with_user_actor(id) assert activity.data["state"] == "resolved" log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} updated report ##{id} with 'resolved' state" + "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'resolved' state" end test "closes report", %{conn: conn, id: id, admin: admin} do @@ -141,13 +141,13 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do }) |> json_response_and_validate_schema(:no_content) - activity = Activity.get_by_id(id) + activity = Activity.get_by_id_with_user_actor(id) assert activity.data["state"] == "closed" log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} updated report ##{id} with 'closed' state" + "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'closed' state" end test "returns 400 when state is unknown", %{conn: conn, id: id} do @@ -193,18 +193,20 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do }) |> json_response_and_validate_schema(:no_content) - activity = Activity.get_by_id(id) - second_activity = Activity.get_by_id(second_report_id) + activity = Activity.get_by_id_with_user_actor(id) + second_activity = Activity.get_by_id_with_user_actor(second_report_id) assert activity.data["state"] == "resolved" assert second_activity.data["state"] == "closed" [first_log_entry, second_log_entry] = Repo.all(ModerationLog) assert ModerationLog.get_log_entry_message(first_log_entry) == - "@#{admin.nickname} updated report ##{id} with 'resolved' state" + "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'resolved' state" assert ModerationLog.get_log_entry_message(second_log_entry) == - "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state" + "@#{admin.nickname} updated report ##{second_report_id} (on user @#{ + second_activity.user_actor.nickname + }) with 'closed' state" end end diff --git a/test/pleroma/web/admin_api/search_test.exs b/test/pleroma/web/admin_api/search_test.exs index 92a116c65..9bc58640c 100644 --- a/test/pleroma/web/admin_api/search_test.exs +++ b/test/pleroma/web/admin_api/search_test.exs @@ -203,6 +203,7 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do assert count == 1 end + # Note: as in Mastodon, `is_discoverable` doesn't anyhow relate to user searchability test "it returns non-discoverable users" do insert(:user) insert(:user, is_discoverable: false) diff --git a/test/pleroma/web/admin_api/views/moderation_log_view_test.exs b/test/pleroma/web/admin_api/views/moderation_log_view_test.exs new file mode 100644 index 000000000..e6c5aaa7f --- /dev/null +++ b/test/pleroma/web/admin_api/views/moderation_log_view_test.exs @@ -0,0 +1,98 @@ +# Pleroma: A lightweight social networking server +# Copyright ยฉ 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only +defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do + use Pleroma.DataCase + + alias Pleroma.Web.AdminAPI.ModerationLogView + + describe "renders `report_note_delete` log messages" do + setup do + log1 = %Pleroma.ModerationLog{ + data: %{ + "action" => "report_note_delete", + "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, + "message" => "@admin deleted note 'mistake' from report #A1I7be on user @b-612", + "subject" => %{"id" => "A1I7be", "state" => "open", "type" => "report"}, + "subject_actor" => %{"id" => "A1I7G8", "nickname" => "b-612", "type" => "user"}, + "text" => "mistake" + }, + inserted_at: ~N[2020-11-17 14:13:20] + } + + log2 = %Pleroma.ModerationLog{ + data: %{ + "action" => "report_note_delete", + "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, + "message" => "@admin deleted note 'fake user' from report #A1I7be on user @j-612", + "subject" => %{"id" => "A1I7be", "state" => "open", "type" => "report"}, + "subject_actor" => %{"id" => "A1I7G8", "nickname" => "j-612", "type" => "user"}, + "text" => "fake user" + }, + inserted_at: ~N[2020-11-17 14:13:20] + } + + {:ok, %{log1: log1, log2: log2}} + end + + test "renders `report_note_delete` log messages", %{log1: log1, log2: log2} do + assert ModerationLogView.render( + "index.json", + %{log: %{items: [log1, log2], count: 2}} + ) == %{ + items: [ + %{ + data: %{ + "action" => "report_note_delete", + "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, + "message" => + "@admin deleted note 'mistake' from report #A1I7be on user @b-612", + "subject" => %{"id" => "A1I7be", "state" => "open", "type" => "report"}, + "subject_actor" => %{ + "id" => "A1I7G8", + "nickname" => "b-612", + "type" => "user" + }, + "text" => "mistake" + }, + message: "@admin deleted note 'mistake' from report #A1I7be on user @b-612", + time: 1_605_622_400 + }, + %{ + data: %{ + "action" => "report_note_delete", + "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, + "message" => + "@admin deleted note 'fake user' from report #A1I7be on user @j-612", + "subject" => %{"id" => "A1I7be", "state" => "open", "type" => "report"}, + "subject_actor" => %{ + "id" => "A1I7G8", + "nickname" => "j-612", + "type" => "user" + }, + "text" => "fake user" + }, + message: "@admin deleted note 'fake user' from report #A1I7be on user @j-612", + time: 1_605_622_400 + } + ], + total: 2 + } + end + + test "renders `report_note_delete` log message", %{log1: log} do + assert ModerationLogView.render("show.json", %{log_entry: log}) == %{ + data: %{ + "action" => "report_note_delete", + "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, + "message" => "@admin deleted note 'mistake' from report #A1I7be on user @b-612", + "subject" => %{"id" => "A1I7be", "state" => "open", "type" => "report"}, + "subject_actor" => %{"id" => "A1I7G8", "nickname" => "b-612", "type" => "user"}, + "text" => "mistake" + }, + message: "@admin deleted note 'mistake' from report #A1I7be on user @b-612", + time: 1_605_622_400 + } + end + end +end diff --git a/test/pleroma/web/common_api/utils_test.exs b/test/pleroma/web/common_api/utils_test.exs index e67c10b93..4d6c9ea26 100644 --- a/test/pleroma/web/common_api/utils_test.exs +++ b/test/pleroma/web/common_api/utils_test.exs @@ -6,6 +6,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do alias Pleroma.Builders.UserBuilder alias Pleroma.Object alias Pleroma.Web.CommonAPI + alias Pleroma.Web.CommonAPI.ActivityDraft alias Pleroma.Web.CommonAPI.Utils use Pleroma.DataCase @@ -235,9 +236,9 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do test "for public posts, not a reply" do user = insert(:user) mentioned_user = insert(:user) - mentions = [mentioned_user.ap_id] + draft = %ActivityDraft{user: user, mentions: [mentioned_user.ap_id], visibility: "public"} - {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "public", nil) + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 2 assert length(cc) == 1 @@ -252,9 +253,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do mentioned_user = insert(:user) third_user = insert(:user) {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"}) - mentions = [mentioned_user.ap_id] - {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public", nil) + draft = %ActivityDraft{ + user: user, + mentions: [mentioned_user.ap_id], + visibility: "public", + in_reply_to: activity + } + + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 3 assert length(cc) == 1 @@ -268,9 +275,9 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do test "for unlisted posts, not a reply" do user = insert(:user) mentioned_user = insert(:user) - mentions = [mentioned_user.ap_id] + draft = %ActivityDraft{user: user, mentions: [mentioned_user.ap_id], visibility: "unlisted"} - {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "unlisted", nil) + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 2 assert length(cc) == 1 @@ -285,9 +292,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do mentioned_user = insert(:user) third_user = insert(:user) {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"}) - mentions = [mentioned_user.ap_id] - {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted", nil) + draft = %ActivityDraft{ + user: user, + mentions: [mentioned_user.ap_id], + visibility: "unlisted", + in_reply_to: activity + } + + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 3 assert length(cc) == 1 @@ -301,9 +314,9 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do test "for private posts, not a reply" do user = insert(:user) mentioned_user = insert(:user) - mentions = [mentioned_user.ap_id] + draft = %ActivityDraft{user: user, mentions: [mentioned_user.ap_id], visibility: "private"} - {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "private", nil) + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 2 assert Enum.empty?(cc) @@ -316,9 +329,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do mentioned_user = insert(:user) third_user = insert(:user) {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"}) - mentions = [mentioned_user.ap_id] - {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private", nil) + draft = %ActivityDraft{ + user: user, + mentions: [mentioned_user.ap_id], + visibility: "private", + in_reply_to: activity + } + + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 2 assert Enum.empty?(cc) @@ -330,9 +349,9 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do test "for direct posts, not a reply" do user = insert(:user) mentioned_user = insert(:user) - mentions = [mentioned_user.ap_id] + draft = %ActivityDraft{user: user, mentions: [mentioned_user.ap_id], visibility: "direct"} - {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "direct", nil) + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 1 assert Enum.empty?(cc) @@ -345,9 +364,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do mentioned_user = insert(:user) third_user = insert(:user) {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"}) - mentions = [mentioned_user.ap_id] - {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct", nil) + draft = %ActivityDraft{ + user: user, + mentions: [mentioned_user.ap_id], + visibility: "direct", + in_reply_to: activity + } + + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 1 assert Enum.empty?(cc) @@ -356,7 +381,14 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do {:ok, direct_activity} = CommonAPI.post(third_user, %{status: "uguu", visibility: "direct"}) - {to, cc} = Utils.get_to_and_cc(user, mentions, direct_activity, "direct", nil) + draft = %ActivityDraft{ + user: user, + mentions: [mentioned_user.ap_id], + visibility: "direct", + in_reply_to: direct_activity + } + + {to, cc} = Utils.get_to_and_cc(draft) assert length(to) == 2 assert Enum.empty?(cc) @@ -532,26 +564,26 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do end end - describe "make_note_data/11" do + describe "make_note_data/1" do test "returns note data" do user = insert(:user) note = insert(:note) user2 = insert(:user) user3 = insert(:user) - assert Utils.make_note_data( - user.ap_id, - [user2.ap_id], - "2hu", - "<h1>This is :moominmamma: note</h1>", - [], - note.id, - [name: "jimm"], - "test summary", - [user3.ap_id], - false, - %{"custom_tag" => "test"} - ) == %{ + draft = %ActivityDraft{ + user: user, + to: [user2.ap_id], + context: "2hu", + content_html: "<h1>This is :moominmamma: note</h1>", + in_reply_to: note.id, + tags: [name: "jimm"], + summary: "test summary", + cc: [user3.ap_id], + extra: %{"custom_tag" => "test"} + } + + assert Utils.make_note_data(draft) == %{ "actor" => user.ap_id, "attachment" => [], "cc" => [user3.ap_id], diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index 8e87e69fe..585b2c174 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -1277,4 +1277,128 @@ defmodule Pleroma.Web.CommonAPITest do } = CommonAPI.get_user("") end end + + describe "with `local` visibility" do + setup do: clear_config([:instance, :federating], true) + + test "post" do + user = insert(:user) + + with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do + {:ok, activity} = CommonAPI.post(user, %{status: "#2hu #2HU", visibility: "local"}) + + assert Visibility.is_local_public?(activity) + assert_not_called(Pleroma.Web.Federator.publish(activity)) + end + end + + test "delete" do + user = insert(:user) + + {:ok, %Activity{id: activity_id}} = + CommonAPI.post(user, %{status: "#2hu #2HU", visibility: "local"}) + + with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do + assert {:ok, %Activity{data: %{"deleted_activity_id" => ^activity_id}} = activity} = + CommonAPI.delete(activity_id, user) + + assert Visibility.is_local_public?(activity) + assert_not_called(Pleroma.Web.Federator.publish(activity)) + end + end + + test "repeat" do + user = insert(:user) + other_user = insert(:user) + + {:ok, %Activity{id: activity_id}} = + CommonAPI.post(other_user, %{status: "cofe", visibility: "local"}) + + with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do + assert {:ok, %Activity{data: %{"type" => "Announce"}} = activity} = + CommonAPI.repeat(activity_id, user) + + assert Visibility.is_local_public?(activity) + refute called(Pleroma.Web.Federator.publish(activity)) + end + end + + test "unrepeat" do + user = insert(:user) + other_user = insert(:user) + + {:ok, %Activity{id: activity_id}} = + CommonAPI.post(other_user, %{status: "cofe", visibility: "local"}) + + assert {:ok, _} = CommonAPI.repeat(activity_id, user) + + with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do + assert {:ok, %Activity{data: %{"type" => "Undo"}} = activity} = + CommonAPI.unrepeat(activity_id, user) + + assert Visibility.is_local_public?(activity) + refute called(Pleroma.Web.Federator.publish(activity)) + end + end + + test "favorite" do + user = insert(:user) + other_user = insert(:user) + + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"}) + + with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do + assert {:ok, %Activity{data: %{"type" => "Like"}} = activity} = + CommonAPI.favorite(user, activity.id) + + assert Visibility.is_local_public?(activity) + refute called(Pleroma.Web.Federator.publish(activity)) + end + end + + test "unfavorite" do + user = insert(:user) + other_user = insert(:user) + + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"}) + + {:ok, %Activity{}} = CommonAPI.favorite(user, activity.id) + + with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do + assert {:ok, activity} = CommonAPI.unfavorite(activity.id, user) + assert Visibility.is_local_public?(activity) + refute called(Pleroma.Web.Federator.publish(activity)) + end + end + + test "react_with_emoji" do + user = insert(:user) + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"}) + + with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do + assert {:ok, %Activity{data: %{"type" => "EmojiReact"}} = activity} = + CommonAPI.react_with_emoji(activity.id, user, "๐") + + assert Visibility.is_local_public?(activity) + refute called(Pleroma.Web.Federator.publish(activity)) + end + end + + test "unreact_with_emoji" do + user = insert(:user) + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"}) + + {:ok, _reaction} = CommonAPI.react_with_emoji(activity.id, user, "๐") + + with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do + assert {:ok, %Activity{data: %{"type" => "Undo"}} = activity} = + CommonAPI.unreact_with_emoji(activity.id, user, "๐") + + assert Visibility.is_local_public?(activity) + refute called(Pleroma.Web.Federator.publish(activity)) + end + end + end end diff --git a/test/pleroma/web/fed_sockets/fed_registry_test.exs b/test/pleroma/web/fed_sockets/fed_registry_test.exs deleted file mode 100644 index 73aaced46..000000000 --- a/test/pleroma/web/fed_sockets/fed_registry_test.exs +++ /dev/null @@ -1,124 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright ยฉ 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.FedSockets.FedRegistryTest do - use ExUnit.Case - - alias Pleroma.Web.FedSockets - alias Pleroma.Web.FedSockets.FedRegistry - alias Pleroma.Web.FedSockets.SocketInfo - - @good_domain "http://good.domain" - @good_domain_origin "good.domain:80" - - setup do - start_supervised({Pleroma.Web.FedSockets.Supervisor, []}) - build_test_socket(@good_domain) - Process.sleep(10) - - :ok - end - - describe "add_fed_socket/1 without conflicting sockets" do - test "can be added" do - Process.sleep(10) - assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin) - assert origin == "good.domain:80" - end - - test "multiple origins can be added" do - build_test_socket("http://anothergood.domain") - Process.sleep(10) - - assert {:ok, %SocketInfo{origin: origin_1}} = - FedRegistry.get_fed_socket(@good_domain_origin) - - assert {:ok, %SocketInfo{origin: origin_2}} = - FedRegistry.get_fed_socket("anothergood.domain:80") - - assert origin_1 == "good.domain:80" - assert origin_2 == "anothergood.domain:80" - assert FedRegistry.list_all() |> Enum.count() == 2 - end - end - - describe "add_fed_socket/1 when duplicate sockets conflict" do - setup do - build_test_socket(@good_domain) - build_test_socket(@good_domain) - Process.sleep(10) - :ok - end - - test "will be ignored" do - assert {:ok, %SocketInfo{origin: origin, pid: _pid_one}} = - FedRegistry.get_fed_socket(@good_domain_origin) - - assert origin == "good.domain:80" - - assert FedRegistry.list_all() |> Enum.count() == 1 - end - - test "the newer process will be closed" do - pid_two = build_test_socket(@good_domain) - - assert {:ok, %SocketInfo{origin: origin, pid: _pid_one}} = - FedRegistry.get_fed_socket(@good_domain_origin) - - assert origin == "good.domain:80" - Process.sleep(10) - - refute Process.alive?(pid_two) - - assert FedRegistry.list_all() |> Enum.count() == 1 - end - end - - describe "get_fed_socket/1" do - test "returns missing for unknown hosts" do - assert {:error, :missing} = FedRegistry.get_fed_socket("not_a_dmoain") - end - - test "returns rejected for hosts previously rejected" do - "rejected.domain:80" - |> FedSockets.uri_for_origin() - |> FedRegistry.set_host_rejected() - - assert {:error, :rejected} = FedRegistry.get_fed_socket("rejected.domain:80") - end - - test "can retrieve a previously added SocketInfo" do - build_test_socket(@good_domain) - Process.sleep(10) - assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin) - assert origin == "good.domain:80" - end - - test "removes references to SocketInfos when the process crashes" do - assert {:ok, %SocketInfo{origin: origin, pid: pid}} = - FedRegistry.get_fed_socket(@good_domain_origin) - - assert origin == "good.domain:80" - - Process.exit(pid, :testing) - Process.sleep(100) - assert {:error, :missing} = FedRegistry.get_fed_socket(@good_domain_origin) - end - end - - def build_test_socket(uri) do - Kernel.spawn(fn -> fed_socket_almost(uri) end) - end - - def fed_socket_almost(origin) do - FedRegistry.add_fed_socket(origin) - - receive do - :close -> - :ok - after - 5_000 -> :timeout - end - end -end diff --git a/test/pleroma/web/fed_sockets/fetch_registry_test.exs b/test/pleroma/web/fed_sockets/fetch_registry_test.exs deleted file mode 100644 index 7bd2d995a..000000000 --- a/test/pleroma/web/fed_sockets/fetch_registry_test.exs +++ /dev/null @@ -1,67 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright ยฉ 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.FedSockets.FetchRegistryTest do - use ExUnit.Case - - alias Pleroma.Web.FedSockets.FetchRegistry - alias Pleroma.Web.FedSockets.FetchRegistry.FetchRegistryData - - @json_message "hello" - @json_reply "hello back" - - setup do - start_supervised( - {Pleroma.Web.FedSockets.Supervisor, - [ - ping_interval: 8, - connection_duration: 15, - rejection_duration: 5, - fed_socket_fetches: [default: 10, interval: 10] - ]} - ) - - :ok - end - - test "fetches can be stored" do - uuid = FetchRegistry.register_fetch(@json_message) - - assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) - end - - test "fetches can return" do - uuid = FetchRegistry.register_fetch(@json_message) - task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end) - - assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) - Task.await(task) - - assert {:ok, %FetchRegistryData{received_json: received_json}} = - FetchRegistry.check_fetch(uuid) - - assert received_json == @json_reply - end - - test "fetches are deleted once popped from stack" do - uuid = FetchRegistry.register_fetch(@json_message) - task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end) - Task.await(task) - - assert {:ok, %FetchRegistryData{received_json: received_json}} = - FetchRegistry.check_fetch(uuid) - - assert received_json == @json_reply - assert {:ok, @json_reply} = FetchRegistry.pop_fetch(uuid) - - assert {:error, :missing} = FetchRegistry.check_fetch(uuid) - end - - test "fetches can time out" do - uuid = FetchRegistry.register_fetch(@json_message) - assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) - Process.sleep(500) - assert {:error, :missing} = FetchRegistry.check_fetch(uuid) - end -end diff --git a/test/pleroma/web/fed_sockets/socket_info_test.exs b/test/pleroma/web/fed_sockets/socket_info_test.exs deleted file mode 100644 index db3d6edcd..000000000 --- a/test/pleroma/web/fed_sockets/socket_info_test.exs +++ /dev/null @@ -1,118 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright ยฉ 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.FedSockets.SocketInfoTest do - use ExUnit.Case - - alias Pleroma.Web.FedSockets - alias Pleroma.Web.FedSockets.SocketInfo - - describe "uri_for_origin" do - test "provides the fed_socket URL given the origin information" do - endpoint = "example.com:4000" - assert FedSockets.uri_for_origin(endpoint) =~ "ws://" - assert FedSockets.uri_for_origin(endpoint) =~ endpoint - end - end - - describe "origin" do - test "will provide the origin field given a url" do - endpoint = "example.com:4000" - assert SocketInfo.origin("ws://#{endpoint}") == endpoint - assert SocketInfo.origin("http://#{endpoint}") == endpoint - assert SocketInfo.origin("https://#{endpoint}") == endpoint - end - - test "will proide the origin field given a uri" do - endpoint = "example.com:4000" - uri = URI.parse("http://#{endpoint}") - - assert SocketInfo.origin(uri) == endpoint - end - end - - describe "touch" do - test "will update the TTL" do - endpoint = "example.com:4000" - socket = SocketInfo.build("ws://#{endpoint}") - Process.sleep(2) - touched_socket = SocketInfo.touch(socket) - - assert socket.connected_until < touched_socket.connected_until - end - end - - describe "expired?" do - setup do - start_supervised( - {Pleroma.Web.FedSockets.Supervisor, - [ - ping_interval: 8, - connection_duration: 5, - rejection_duration: 5, - fed_socket_rejections: [lazy: true] - ]} - ) - - :ok - end - - test "tests if the TTL is exceeded" do - endpoint = "example.com:4000" - socket = SocketInfo.build("ws://#{endpoint}") - refute SocketInfo.expired?(socket) - Process.sleep(10) - - assert SocketInfo.expired?(socket) - end - end - - describe "creating outgoing connection records" do - test "can be passed a string" do - assert %{conn_pid: :pid, origin: _origin} = SocketInfo.build("example.com:4000", :pid) - end - - test "can be passed a URI" do - uri = URI.parse("http://example.com:4000") - assert %{conn_pid: :pid, origin: origin} = SocketInfo.build(uri, :pid) - assert origin =~ "example.com:4000" - end - - test "will include the port number" do - assert %{conn_pid: :pid, origin: origin} = SocketInfo.build("http://example.com:4000", :pid) - - assert origin =~ ":4000" - end - - test "will provide the port if missing" do - assert %{conn_pid: :pid, origin: "example.com:80"} = - SocketInfo.build("http://example.com", :pid) - - assert %{conn_pid: :pid, origin: "example.com:443"} = - SocketInfo.build("https://example.com", :pid) - end - end - - describe "creating incoming connection records" do - test "can be passed a string" do - assert %{pid: _, origin: _origin} = SocketInfo.build("example.com:4000") - end - - test "can be passed a URI" do - uri = URI.parse("example.com:4000") - assert %{pid: _, origin: _origin} = SocketInfo.build(uri) - end - - test "will include the port number" do - assert %{pid: _, origin: origin} = SocketInfo.build("http://example.com:4000") - - assert origin =~ ":4000" - end - - test "will provide the port if missing" do - assert %{pid: _, origin: "example.com:80"} = SocketInfo.build("http://example.com") - assert %{pid: _, origin: "example.com:443"} = SocketInfo.build("https://example.com") - end - end -end diff --git a/test/pleroma/web/federator_test.exs b/test/pleroma/web/federator_test.exs index 592fdccd1..67001add7 100644 --- a/test/pleroma/web/federator_test.exs +++ b/test/pleroma/web/federator_test.exs @@ -164,7 +164,7 @@ defmodule Pleroma.Web.FederatorTest do params = File.read!("test/fixtures/mastodon-post-activity.json") - |> Poison.decode!() + |> Jason.decode!() assert {:ok, job} = Federator.incoming_ap_doc(params) assert {:error, _} = ObanHelpers.perform(job) diff --git a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs index 58ce76ab8..e8a00dd6b 100644 --- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs @@ -436,6 +436,39 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_visibilities[]=direct") assert [%{"id" => ^public_activity_id}] = json_response_and_validate_schema(conn, 200) end + + test "muted reactions", %{user: user, conn: conn} do + user2 = insert(:user) + User.mute(user, user2) + {:ok, activity} = CommonAPI.post(user, %{status: "."}) + {:ok, _} = CommonAPI.react_with_emoji(activity.id, user2, "๐
") + + result = + conn + |> get("/api/v1/accounts/#{user.id}/statuses") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [] + } + } + ] = result + + result = + conn + |> get("/api/v1/accounts/#{user.id}/statuses?with_muted=true") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "๐
"}] + } + } + ] = result + end end defp local_and_remote_activities(%{local: local, remote: remote}) do diff --git a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs index 6a9ccd979..605df6ed6 100644 --- a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs @@ -13,6 +13,9 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do assert result = json_response_and_validate_schema(conn, 200) email = Pleroma.Config.get([:instance, :email]) + thumbnail = Pleroma.Web.base_url() <> Pleroma.Config.get([:instance, :instance_thumbnail]) + background = Pleroma.Web.base_url() <> Pleroma.Config.get([:instance, :background_image]) + # Note: not checking for "max_toot_chars" since it's optional assert %{ "uri" => _, @@ -24,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do "streaming_api" => _ }, "stats" => _, - "thumbnail" => _, + "thumbnail" => from_config_thumbnail, "languages" => _, "registrations" => _, "approval_required" => _, @@ -33,7 +36,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do "avatar_upload_limit" => _, "background_upload_limit" => _, "banner_upload_limit" => _, - "background_image" => _, + "background_image" => from_config_background, "chat_limit" => _, "description_limit" => _ } = result @@ -45,6 +48,8 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do assert result["pleroma"]["vapid_public_key"] assert email == from_config_email + assert thumbnail == from_config_thumbnail + assert background == from_config_background end test "get instance stats", %{conn: conn} do diff --git a/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs index 5fd518c60..9ac8488f6 100644 --- a/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs @@ -75,6 +75,34 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do assert [_] = result end + test "by default, does not contain pleroma:report" do + %{user: user, conn: conn} = oauth_access(["read:notifications"]) + other_user = insert(:user) + third_user = insert(:user) + + user + |> User.admin_api_update(%{is_moderator: true}) + + {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) + + {:ok, _report} = + CommonAPI.report(third_user, %{account_id: other_user.id, status_ids: [activity.id]}) + + result = + conn + |> get("/api/v1/notifications") + |> json_response_and_validate_schema(200) + + assert [] == result + + result = + conn + |> get("/api/v1/notifications?include_types[]=pleroma:report") + |> json_response_and_validate_schema(200) + + assert [_] = result + end + test "getting a single notification" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) diff --git a/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs index 04dc6f445..1045ab265 100644 --- a/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs @@ -279,6 +279,10 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do end test "search fetches remote statuses and prefers them over other results", %{conn: conn} do + old_version = :persistent_term.get({Pleroma.Repo, :postgres_version}) + :persistent_term.put({Pleroma.Repo, :postgres_version}, 10.0) + on_exit(fn -> :persistent_term.put({Pleroma.Repo, :postgres_version}, old_version) end) + capture_log(fn -> {:ok, %{id: activity_id}} = CommonAPI.post(insert(:user), %{ diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs index 436608e51..30d542dfa 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -328,7 +328,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do end test "posting a status with OGP link preview", %{conn: conn} do - Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) clear_config([:rich_media, :enabled], true) conn = @@ -1197,7 +1197,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do end test "returns rich-media card", %{conn: conn, user: user} do - Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) {:ok, activity} = CommonAPI.post(user, %{status: "https://example.com/ogp"}) @@ -1242,7 +1242,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do end test "replaces missing description with an empty string", %{conn: conn, user: user} do - Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) {:ok, activity} = CommonAPI.post(user, %{status: "https://example.com/ogp-missing-data"}) @@ -1740,4 +1740,94 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do |> get("/api/v1/statuses/#{activity.id}") |> json_response_and_validate_schema(:ok) end + + test "posting a local only status" do + %{user: _user, conn: conn} = oauth_access(["write:statuses"]) + + conn_one = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "visibility" => "local" + }) + + local = Pleroma.Constants.as_local_public() + + assert %{"content" => "cofe", "id" => id, "visibility" => "local"} = + json_response(conn_one, 200) + + assert %Activity{id: ^id, data: %{"to" => [^local]}} = Activity.get_by_id(id) + end + + describe "muted reactions" do + test "index" do + %{conn: conn, user: user} = oauth_access(["read:statuses"]) + + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{status: "test"}) + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "๐
") + User.mute(user, other_user) + + result = + conn + |> get("/api/v1/statuses/?ids[]=#{activity.id}") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [] + } + } + ] = result + + result = + conn + |> get("/api/v1/statuses/?ids[]=#{activity.id}&with_muted=true") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "๐
"}] + } + } + ] = result + end + + test "show" do + # %{conn: conn, user: user, token: token} = oauth_access(["read:statuses"]) + %{conn: conn, user: user, token: _token} = oauth_access(["read:statuses"]) + + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{status: "test"}) + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "๐
") + User.mute(user, other_user) + + result = + conn + |> get("/api/v1/statuses/#{activity.id}") + |> json_response_and_validate_schema(200) + + assert %{ + "pleroma" => %{ + "emoji_reactions" => [] + } + } = result + + result = + conn + |> get("/api/v1/statuses/#{activity.id}?with_muted=true") + |> json_response_and_validate_schema(200) + + assert %{ + "pleroma" => %{ + "emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "๐
"}] + } + } = result + end + end end diff --git a/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs index d36bb1ae8..5ef39bdb2 100644 --- a/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs @@ -45,21 +45,77 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do end end - describe "creates push subscription" do - test "returns error when push disabled ", %{conn: conn} do + describe "when disabled" do + test "POST returns error", %{conn: conn} do + assert_error_when_disable_push do + conn + |> post("/api/v1/push/subscription", %{ + "data" => %{"alerts" => %{"mention" => true}}, + "subscription" => @sub + }) + |> json_response_and_validate_schema(403) + end + end + + test "GET returns error", %{conn: conn} do assert_error_when_disable_push do conn - |> post("/api/v1/push/subscription", %{subscription: @sub}) + |> get("/api/v1/push/subscription", %{}) |> json_response_and_validate_schema(403) end end + test "PUT returns error", %{conn: conn} do + assert_error_when_disable_push do + conn + |> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}}) + |> json_response_and_validate_schema(403) + end + end + + test "DELETE returns error", %{conn: conn} do + assert_error_when_disable_push do + conn + |> delete("/api/v1/push/subscription", %{}) + |> json_response_and_validate_schema(403) + end + end + end + + describe "creates push subscription" do + test "ignores unsupported types", %{conn: conn} do + result = + conn + |> post("/api/v1/push/subscription", %{ + "data" => %{ + "alerts" => %{ + "fake_unsupported_type" => true + } + }, + "subscription" => @sub + }) + |> json_response_and_validate_schema(200) + + refute %{ + "alerts" => %{ + "fake_unsupported_type" => true + } + } == result + end + test "successful creation", %{conn: conn} do result = conn |> post("/api/v1/push/subscription", %{ "data" => %{ - "alerts" => %{"mention" => true, "test" => true, "pleroma:chat_mention" => true} + "alerts" => %{ + "mention" => true, + "favourite" => true, + "follow" => true, + "reblog" => true, + "pleroma:chat_mention" => true, + "pleroma:emoji_reaction" => true + } }, "subscription" => @sub }) @@ -68,7 +124,14 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do [subscription] = Pleroma.Repo.all(Subscription) assert %{ - "alerts" => %{"mention" => true, "pleroma:chat_mention" => true}, + "alerts" => %{ + "mention" => true, + "favourite" => true, + "follow" => true, + "reblog" => true, + "pleroma:chat_mention" => true, + "pleroma:emoji_reaction" => true + }, "endpoint" => subscription.endpoint, "id" => to_string(subscription.id), "server_key" => @server_key @@ -77,14 +140,6 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do end describe "gets a user subscription" do - test "returns error when push disabled ", %{conn: conn} do - assert_error_when_disable_push do - conn - |> get("/api/v1/push/subscription", %{}) - |> json_response_and_validate_schema(403) - end - end - test "returns error when user hasn't subscription", %{conn: conn} do res = conn @@ -124,30 +179,47 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do insert(:push_subscription, user: user, token: token, - data: %{"alerts" => %{"mention" => true}} + data: %{ + "alerts" => %{ + "mention" => true, + "favourite" => true, + "follow" => true, + "reblog" => true, + "pleroma:chat_mention" => true, + "pleroma:emoji_reaction" => true + } + } ) %{conn: conn, user: user, token: token, subscription: subscription} end - test "returns error when push disabled ", %{conn: conn} do - assert_error_when_disable_push do - conn - |> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}}) - |> json_response_and_validate_schema(403) - end - end - test "returns updated subsciption", %{conn: conn, subscription: subscription} do res = conn |> put("/api/v1/push/subscription", %{ - data: %{"alerts" => %{"mention" => false, "follow" => true}} + data: %{ + "alerts" => %{ + "mention" => false, + "favourite" => false, + "follow" => false, + "reblog" => false, + "pleroma:chat_mention" => false, + "pleroma:emoji_reaction" => false + } + } }) |> json_response_and_validate_schema(200) expect = %{ - "alerts" => %{"follow" => true, "mention" => false}, + "alerts" => %{ + "mention" => false, + "favourite" => false, + "follow" => false, + "reblog" => false, + "pleroma:chat_mention" => false, + "pleroma:emoji_reaction" => false + }, "endpoint" => "https://example.com/example/1234", "id" => to_string(subscription.id), "server_key" => @server_key @@ -158,14 +230,6 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do end describe "deletes the user subscription" do - test "returns error when push disabled ", %{conn: conn} do - assert_error_when_disable_push do - conn - |> delete("/api/v1/push/subscription", %{}) - |> json_response_and_validate_schema(403) - end - end - test "returns error when user hasn't subscription", %{conn: conn} do res = conn diff --git a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs index 4c08ad60a..8356b64d3 100644 --- a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs @@ -54,6 +54,42 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do assert private_activity.id in status_ids refute direct_activity.id in status_ids end + + test "muted emotions", %{user: user, conn: conn} do + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{status: "."}) + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "๐
") + User.mute(user, other_user) + + result = + conn + |> assign(:user, user) + |> get("/api/v1/timelines/home") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [] + } + } + ] = result + + result = + conn + |> assign(:user, user) + |> get("/api/v1/timelines/home?with_muted=true") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "๐
"}] + } + } + ] = result + end end describe "public" do @@ -159,6 +195,48 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do assert length(json_response_and_validate_schema(conn, :ok)) == 1 end + + test "muted emotions", %{conn: conn} do + user = insert(:user) + token = insert(:oauth_token, user: user, scopes: ["read:statuses"]) + + conn = + conn + |> assign(:user, user) + |> assign(:token, token) + + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{status: "."}) + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "๐
") + User.mute(user, other_user) + + result = + conn + |> get("/api/v1/timelines/public") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [] + } + } + ] = result + + result = + conn + |> get("/api/v1/timelines/public?with_muted=true") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "๐
"}] + } + } + ] = result + end end defp local_and_remote_activities do @@ -428,6 +506,44 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do assert id == to_string(activity_one.id) end + + test "muted emotions", %{user: user, conn: conn} do + user2 = insert(:user) + user3 = insert(:user) + {:ok, activity} = CommonAPI.post(user2, %{status: "."}) + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, user3, "๐
") + User.mute(user, user3) + + {:ok, list} = Pleroma.List.create("name", user) + {:ok, list} = Pleroma.List.follow(list, user2) + + result = + conn + |> get("/api/v1/timelines/list/#{list.id}") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [] + } + } + ] = result + + result = + conn + |> get("/api/v1/timelines/list/#{list.id}?with_muted=true") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "๐
"}] + } + } + ] = result + end end describe "hashtag" do @@ -476,6 +592,48 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do assert [status_none] == json_response_and_validate_schema(all_test, :ok) end + + test "muted emotions", %{conn: conn} do + user = insert(:user) + token = insert(:oauth_token, user: user, scopes: ["read:statuses"]) + + conn = + conn + |> assign(:user, user) + |> assign(:token, token) + + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{status: "test #2hu"}) + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "๐
") + User.mute(user, other_user) + + result = + conn + |> get("/api/v1/timelines/tag/2hu") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [] + } + } + ] = result + + result = + conn + |> get("/api/v1/timelines/tag/2hu?with_muted=true") + |> json_response_and_validate_schema(200) + + assert [ + %{ + "pleroma" => %{ + "emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "๐
"}] + } + } + ] = result + end end describe "hashtag timeline handling of :restrict_unauthenticated setting" do diff --git a/test/pleroma/web/mastodon_api/views/notification_view_test.exs b/test/pleroma/web/mastodon_api/views/notification_view_test.exs index 2f6a808f1..9de11a87e 100644 --- a/test/pleroma/web/mastodon_api/views/notification_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/notification_view_test.exs @@ -12,6 +12,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User + alias Pleroma.Web.AdminAPI.Report + alias Pleroma.Web.AdminAPI.ReportView alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.MastodonAPI.AccountView @@ -207,6 +209,26 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do test_notifications_rendering([notification], user, [expected]) end + test "Report notification" do + reporting_user = insert(:user) + reported_user = insert(:user) + {:ok, moderator_user} = insert(:user) |> User.admin_api_update(%{is_moderator: true}) + + {:ok, activity} = CommonAPI.report(reporting_user, %{account_id: reported_user.id}) + {:ok, [notification]} = Notification.create_notifications(activity) + + expected = %{ + id: to_string(notification.id), + pleroma: %{is_seen: false, is_muted: false}, + type: "pleroma:report", + account: AccountView.render("show.json", %{user: reporting_user, for: moderator_user}), + created_at: Utils.to_masto_date(notification.inserted_at), + report: ReportView.render("show.json", Report.extract_report_info(activity)) + } + + test_notifications_rendering([notification], moderator_user, [expected]) + end + test "muted notification" do user = insert(:user) another_user = insert(:user) diff --git a/test/pleroma/web/mastodon_api/views/status_view_test.exs b/test/pleroma/web/mastodon_api/views/status_view_test.exs index 665199f97..f2a7469ed 100644 --- a/test/pleroma/web/mastodon_api/views/status_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/status_view_test.exs @@ -73,6 +73,50 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do ] end + test "doesn't show reactions from muted and blocked users" do + user = insert(:user) + other_user = insert(:user) + third_user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{status: "dae cofe??"}) + + {:ok, _} = User.mute(user, other_user) + {:ok, _} = User.block(other_user, third_user) + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "โ") + + activity = Repo.get(Activity, activity.id) + status = StatusView.render("show.json", activity: activity) + + assert status[:pleroma][:emoji_reactions] == [ + %{name: "โ", count: 1, me: false} + ] + + status = StatusView.render("show.json", activity: activity, for: user) + + assert status[:pleroma][:emoji_reactions] == [] + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, third_user, "โ") + + status = StatusView.render("show.json", activity: activity) + + assert status[:pleroma][:emoji_reactions] == [ + %{name: "โ", count: 2, me: false} + ] + + status = StatusView.render("show.json", activity: activity, for: user) + + assert status[:pleroma][:emoji_reactions] == [ + %{name: "โ", count: 1, me: false} + ] + + status = StatusView.render("show.json", activity: activity, for: other_user) + + assert status[:pleroma][:emoji_reactions] == [ + %{name: "โ", count: 1, me: true} + ] + end + test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do user = insert(:user) diff --git a/test/pleroma/web/metadata/providers/restrict_indexing_test.exs b/test/pleroma/web/metadata/providers/restrict_indexing_test.exs index 282d132c8..52399fdc8 100644 --- a/test/pleroma/web/metadata/providers/restrict_indexing_test.exs +++ b/test/pleroma/web/metadata/providers/restrict_indexing_test.exs @@ -18,7 +18,7 @@ defmodule Pleroma.Web.Metadata.Providers.RestrictIndexingTest do }) == [] end - test "for local user when discoverable is false" do + test "for local user when `is_discoverable` is false" do assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ user: %Pleroma.User{local: true, is_discoverable: false} }) == [{:meta, [name: "robots", content: "noindex, noarchive"], []}] diff --git a/test/pleroma/web/metadata_test.exs b/test/pleroma/web/metadata_test.exs deleted file mode 100644 index 8fb946540..000000000 --- a/test/pleroma/web/metadata_test.exs +++ /dev/null @@ -1,49 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright ยฉ 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.MetadataTest do - use Pleroma.DataCase, async: true - - import Pleroma.Factory - - describe "restrict indexing remote users" do - test "for remote user" do - user = insert(:user, local: false) - - assert Pleroma.Web.Metadata.build_tags(%{user: user}) =~ - "<meta content=\"noindex, noarchive\" name=\"robots\">" - end - - test "for local user" do - user = insert(:user, is_discoverable: false) - - assert Pleroma.Web.Metadata.build_tags(%{user: user}) =~ - "<meta content=\"noindex, noarchive\" name=\"robots\">" - end - - test "for local user set to discoverable" do - user = insert(:user, is_discoverable: true) - - refute Pleroma.Web.Metadata.build_tags(%{user: user}) =~ - "<meta content=\"noindex, noarchive\" name=\"robots\">" - end - end - - describe "no metadata for private instances" do - test "for local user set to discoverable" do - clear_config([:instance, :public], false) - user = insert(:user, bio: "This is my secret fedi account bio", is_discoverable: true) - - assert "" = Pleroma.Web.Metadata.build_tags(%{user: user}) - end - - test "search exclusion metadata is included" do - clear_config([:instance, :public], false) - user = insert(:user, bio: "This is my secret fedi account bio", is_discoverable: false) - - assert ~s(<meta content="noindex, noarchive" name="robots">) == - Pleroma.Web.Metadata.build_tags(%{user: user}) - end - end -end diff --git a/test/pleroma/web/o_auth/o_auth_controller_test.exs b/test/pleroma/web/o_auth/o_auth_controller_test.exs index a00df8cc7..c6526d8c9 100644 --- a/test/pleroma/web/o_auth/o_auth_controller_test.exs +++ b/test/pleroma/web/o_auth/o_auth_controller_test.exs @@ -81,7 +81,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do redirect_query = URI.parse(redirected_to(conn)).query assert %{"state" => state_param} = URI.decode_query(redirect_query) - assert {:ok, state_components} = Poison.decode(state_param) + assert {:ok, state_components} = Jason.decode(state_param) expected_client_id = app.client_id expected_redirect_uri = app.redirect_uris @@ -115,7 +115,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM", "oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs", "provider" => "twitter", - "state" => Poison.encode!(state_params) + "state" => Jason.encode!(state_params) } ) @@ -147,7 +147,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM", "oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs", "provider" => "twitter", - "state" => Poison.encode!(state_params) + "state" => Jason.encode!(state_params) } ) @@ -178,7 +178,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM", "oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs", "provider" => "twitter", - "state" => Poison.encode!(state_params) + "state" => Jason.encode!(state_params) } ) diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs index 3deab30d1..bda9c20c6 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs @@ -106,6 +106,48 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionControllerTest do result end + test "GET /api/v1/pleroma/statuses/:id/reactions?with_muted=true", %{conn: conn} do + user = insert(:user) + user2 = insert(:user) + user3 = insert(:user) + + token = insert(:oauth_token, user: user, scopes: ["read:statuses"]) + + {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) + + {:ok, _} = CommonAPI.react_with_emoji(activity.id, user2, "๐
") + {:ok, _} = CommonAPI.react_with_emoji(activity.id, user3, "๐
") + + result = + conn + |> assign(:user, user) + |> assign(:token, token) + |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions") + |> json_response_and_validate_schema(200) + + assert [%{"name" => "๐
", "count" => 2}] = result + + User.mute(user, user3) + + result = + conn + |> assign(:user, user) + |> assign(:token, token) + |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions") + |> json_response_and_validate_schema(200) + + assert [%{"name" => "๐
", "count" => 1}] = result + + result = + conn + |> assign(:user, user) + |> assign(:token, token) + |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions?with_muted=true") + |> json_response_and_validate_schema(200) + + assert [%{"name" => "๐
", "count" => 2}] = result + end + test "GET /api/v1/pleroma/statuses/:id/reactions with :show_reactions disabled", %{conn: conn} do clear_config([:instance, :show_reactions], false) diff --git a/test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs b/test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs index ae8257870..93eef00a2 100644 --- a/test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs +++ b/test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs @@ -48,7 +48,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatMessageReferenceViewTest do clear_config([:rich_media, :enabled], true) - Tesla.Mock.mock(fn + Tesla.Mock.mock_global(fn %{url: "https://example.com/ogp"} -> %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/ogp.html")} end) diff --git a/test/pleroma/web/plugs/digest_plug_test.exs b/test/pleroma/web/plugs/digest_plug_test.exs new file mode 100644 index 000000000..629c28c93 --- /dev/null +++ b/test/pleroma/web/plugs/digest_plug_test.exs @@ -0,0 +1,48 @@ +defmodule Pleroma.Web.Plugs.DigestPlugTest do + use ExUnit.Case, async: true + use Plug.Test + + test "digest algorithm is taken from digest header" do + body = "{\"hello\": \"world\"}" + digest = "X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=" + + {:ok, ^body, conn} = + :get + |> conn("/", body) + |> put_req_header("content-type", "application/json") + |> put_req_header("digest", "sha-256=" <> digest) + |> Pleroma.Web.Plugs.DigestPlug.read_body([]) + + assert conn.assigns[:digest] == "sha-256=" <> digest + + {:ok, ^body, conn} = + :get + |> conn("/", body) + |> put_req_header("content-type", "application/json") + |> put_req_header("digest", "SHA-256=" <> digest) + |> Pleroma.Web.Plugs.DigestPlug.read_body([]) + + assert conn.assigns[:digest] == "SHA-256=" <> digest + end + + test "error if digest algorithm is invalid" do + body = "{\"hello\": \"world\"}" + digest = "X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=" + + assert_raise ArgumentError, "invalid value for digest algorithm, got: MD5", fn -> + :get + |> conn("/", body) + |> put_req_header("content-type", "application/json") + |> put_req_header("digest", "MD5=" <> digest) + |> Pleroma.Web.Plugs.DigestPlug.read_body([]) + end + + assert_raise ArgumentError, "invalid value for digest algorithm, got: md5", fn -> + :get + |> conn("/", body) + |> put_req_header("content-type", "application/json") + |> put_req_header("digest", "md5=" <> digest) + |> Pleroma.Web.Plugs.DigestPlug.read_body([]) + end + end +end diff --git a/test/pleroma/web/push/impl_test.exs b/test/pleroma/web/push/impl_test.exs index 7d8cc999a..2a4a8fd06 100644 --- a/test/pleroma/web/push/impl_test.exs +++ b/test/pleroma/web/push/impl_test.exs @@ -184,6 +184,24 @@ defmodule Pleroma.Web.Push.ImplTest do "New Favorite" end + test "renders title and body for pleroma:emoji_reaction activity" do + user = insert(:user, nickname: "Bob") + + {:ok, activity} = + CommonAPI.post(user, %{ + status: "This post is a really good post!" + }) + + {:ok, activity} = CommonAPI.react_with_emoji(activity.id, user, "๐") + object = Object.normalize(activity) + + assert Impl.format_body(%{activity: activity, type: "pleroma:emoji_reaction"}, user, object) == + "@Bob reacted with ๐" + + assert Impl.format_title(%{activity: activity, type: "pleroma:emoji_reaction"}) == + "New Reaction" + end + test "renders title for create activity with direct visibility" do user = insert(:user, nickname: "Bob") diff --git a/test/pleroma/web/streamer_test.exs b/test/pleroma/web/streamer_test.exs index 0d89e01d0..dd210c3b5 100644 --- a/test/pleroma/web/streamer_test.exs +++ b/test/pleroma/web/streamer_test.exs @@ -222,7 +222,7 @@ defmodule Pleroma.Web.StreamerTest do data = File.read!("test/fixtures/mastodon-announce.json") - |> Poison.decode!() + |> Jason.decode!() |> Map.put("object", activity.data["object"]) |> Map.put("actor", user.ap_id) diff --git a/test/pleroma/web/twitter_api/password_controller_test.exs b/test/pleroma/web/twitter_api/password_controller_test.exs index a5e9e2178..6d08075cc 100644 --- a/test/pleroma/web/twitter_api/password_controller_test.exs +++ b/test/pleroma/web/twitter_api/password_controller_test.exs @@ -31,9 +31,48 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do assert response =~ "<h2>Password Reset for #{user.nickname}</h2>" end + + test "it returns an error when the token has expired", %{conn: conn} do + clear_config([:instance, :password_reset_token_validity], 0) + + user = insert(:user) + {:ok, token} = PasswordResetToken.create_token(user) + + :timer.sleep(2000) + + response = + conn + |> get("/api/pleroma/password_reset/#{token.token}") + |> html_response(:ok) + + assert response =~ "<h2>Invalid Token</h2>" + end end describe "POST /api/pleroma/password_reset" do + test "it fails for an expired token", %{conn: conn} do + clear_config([:instance, :password_reset_token_validity], 0) + + user = insert(:user) + {:ok, token} = PasswordResetToken.create_token(user) + :timer.sleep(2000) + {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{}) + + params = %{ + "password" => "test", + password_confirmation: "test", + token: token.token + } + + response = + conn + |> assign(:user, user) + |> post("/api/pleroma/password_reset", %{data: params}) + |> html_response(:ok) + + refute response =~ "<h2>Password changed!</h2>" + end + test "it returns HTTP 200", %{conn: conn} do user = insert(:user) {:ok, token} = PasswordResetToken.create_token(user) diff --git a/test/support/factory.ex b/test/support/factory.ex index 80b882ee4..8eb07dc3c 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -24,7 +24,7 @@ defmodule Pleroma.Factory do } end - def user_factory do + def user_factory(attrs \\ %{}) do user = %User{ name: sequence(:name, &"Test ใในใ User #{&1}"), email: sequence(:email, &"user#{&1}@example.com"), @@ -39,13 +39,29 @@ defmodule Pleroma.Factory do ap_enabled: true } - %{ - user - | ap_id: User.ap_id(user), - follower_address: User.ap_followers(user), - following_address: User.ap_following(user), - raw_bio: user.bio - } + urls = + if attrs[:local] == false do + base_domain = Enum.random(["domain1.com", "domain2.com", "domain3.com"]) + + ap_id = "https://#{base_domain}/users/#{user.nickname}" + + %{ + ap_id: ap_id, + follower_address: ap_id <> "/followers", + following_address: ap_id <> "/following" + } + else + %{ + ap_id: User.ap_id(user), + follower_address: User.ap_followers(user), + following_address: User.ap_following(user) + } + end + + user + |> Map.put(:raw_bio, user.bio) + |> Map.merge(urls) + |> merge_attributes(attrs) end def user_relationship_factory(attrs \\ %{}) do diff --git a/test/support/helpers.ex b/test/support/helpers.ex index ecd4b1e18..224034521 100644 --- a/test/support/helpers.ex +++ b/test/support/helpers.ex @@ -85,8 +85,8 @@ defmodule Pleroma.Tests.Helpers do assigns = Map.new(assigns) view.render(template, assigns) - |> Poison.encode!() - |> Poison.decode!() + |> Jason.encode!() + |> Jason.decode!() end def stringify_keys(nil), do: nil |