diff options
Diffstat (limited to 'test')
70 files changed, 3258 insertions, 1101 deletions
| diff --git a/test/config/deprecation_warnings_test.exs b/test/config/deprecation_warnings_test.exs index e22052404..f81a7b580 100644 --- a/test/config/deprecation_warnings_test.exs +++ b/test/config/deprecation_warnings_test.exs @@ -1,5 +1,5 @@  defmodule Pleroma.Config.DeprecationWarningsTest do -  use ExUnit.Case, async: true +  use ExUnit.Case    use Pleroma.Tests.Helpers    import ExUnit.CaptureLog @@ -66,6 +66,30 @@ defmodule Pleroma.Config.DeprecationWarningsTest do             end) =~ "Your config is using old format (only domain) for MediaProxy whitelist option"    end +  test "check_welcome_message_config/0" do +    clear_config([:instance, :welcome_user_nickname], "LainChan") + +    assert capture_log(fn -> +             DeprecationWarnings.check_welcome_message_config() +           end) =~ "Your config is using the old namespace for Welcome messages configuration." +  end + +  test "check_hellthread_threshold/0" do +    clear_config([:mrf_hellthread, :threshold], 16) + +    assert capture_log(fn -> +             DeprecationWarnings.check_hellthread_threshold() +           end) =~ "You are using the old configuration mechanism for the hellthread filter." +  end + +  test "check_activity_expiration_config/0" do +    clear_config([Pleroma.ActivityExpiration, :enabled], true) + +    assert capture_log(fn -> +             DeprecationWarnings.check_activity_expiration_config() +           end) =~ "Your config is using old namespace for activity expiration configuration." +  end +    describe "check_gun_pool_options/0" do      test "await_up_timeout" do        config = Config.get(:connections_pool) @@ -74,7 +98,7 @@ defmodule Pleroma.Config.DeprecationWarningsTest do        assert capture_log(fn ->                 DeprecationWarnings.check_gun_pool_options()               end) =~ -               "Your config is using old setting name `await_up_timeout` instead of `connect_timeout`" +               "Your config is using old setting `config :pleroma, :connections_pool, await_up_timeout`."      end      test "pool timeout" do diff --git a/test/emoji/pack_test.exs b/test/emoji/pack_test.exs new file mode 100644 index 000000000..70d1eaa1b --- /dev/null +++ b/test/emoji/pack_test.exs @@ -0,0 +1,93 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Emoji.PackTest do +  use ExUnit.Case, async: true +  alias Pleroma.Emoji.Pack + +  @emoji_path Path.join( +                Pleroma.Config.get!([:instance, :static_dir]), +                "emoji" +              ) + +  setup do +    pack_path = Path.join(@emoji_path, "dump_pack") +    File.mkdir(pack_path) + +    File.write!(Path.join(pack_path, "pack.json"), """ +    { +    "files": { }, +    "pack": { +    "description": "Dump pack", "homepage": "https://pleroma.social", +    "license": "Test license", "share-files": true +    }} +    """) + +    {:ok, pack} = Pleroma.Emoji.Pack.load_pack("dump_pack") + +    on_exit(fn -> +      File.rm_rf!(pack_path) +    end) + +    {:ok, pack: pack} +  end + +  describe "add_file/4" do +    test "add emojies from zip file", %{pack: pack} do +      file = %Plug.Upload{ +        content_type: "application/zip", +        filename: "emojis.zip", +        path: Path.absname("test/fixtures/emojis.zip") +      } + +      {:ok, updated_pack} = Pack.add_file(pack, nil, nil, file) + +      assert updated_pack.files == %{ +               "a_trusted_friend-128" => "128px/a_trusted_friend-128.png", +               "auroraborealis" => "auroraborealis.png", +               "baby_in_a_box" => "1000px/baby_in_a_box.png", +               "bear" => "1000px/bear.png", +               "bear-128" => "128px/bear-128.png" +             } + +      assert updated_pack.files_count == 5 +    end +  end + +  test "returns error when zip file is bad", %{pack: pack} do +    file = %Plug.Upload{ +      content_type: "application/zip", +      filename: "emojis.zip", +      path: Path.absname("test/instance_static/emoji/test_pack/blank.png") +    } + +    assert Pack.add_file(pack, nil, nil, file) == {:error, :einval} +  end + +  test "returns pack when zip file is empty", %{pack: pack} do +    file = %Plug.Upload{ +      content_type: "application/zip", +      filename: "emojis.zip", +      path: Path.absname("test/fixtures/empty.zip") +    } + +    {:ok, updated_pack} = Pack.add_file(pack, nil, nil, file) +    assert updated_pack == pack +  end + +  test "add emoji file", %{pack: pack} do +    file = %Plug.Upload{ +      filename: "blank.png", +      path: "#{@emoji_path}/test_pack/blank.png" +    } + +    {:ok, updated_pack} = Pack.add_file(pack, "test_blank", "test_blank.png", file) + +    assert updated_pack.files == %{ +             "test_blank" => "test_blank.png" +           } + +    assert updated_pack.files_count == 1 +  end +end diff --git a/test/emoji_test.exs b/test/emoji_test.exs index b36047578..1dd3c58c6 100644 --- a/test/emoji_test.exs +++ b/test/emoji_test.exs @@ -3,7 +3,7 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.EmojiTest do -  use ExUnit.Case, async: true +  use ExUnit.Case    alias Pleroma.Emoji    describe "is_unicode_emoji?/1" do diff --git a/test/fixtures/custom_instance_panel.html b/test/fixtures/custom_instance_panel.html new file mode 100644 index 000000000..6371a1e43 --- /dev/null +++ b/test/fixtures/custom_instance_panel.html @@ -0,0 +1 @@ +<h2>Custom instance panel</h2>
\ No newline at end of file diff --git a/test/fixtures/emojis.zip b/test/fixtures/emojis.zipBinary files differ new file mode 100644 index 000000000..d7fc4732b --- /dev/null +++ b/test/fixtures/emojis.zip diff --git a/test/fixtures/empty.zip b/test/fixtures/empty.zipBinary files differ new file mode 100644 index 000000000..15cb0ecb3 --- /dev/null +++ b/test/fixtures/empty.zip diff --git a/test/fixtures/image.gif b/test/fixtures/image.gifBinary files differ new file mode 100755 index 000000000..9df64778b --- /dev/null +++ b/test/fixtures/image.gif diff --git a/test/fixtures/image.png b/test/fixtures/image.pngBinary files differ new file mode 100755 index 000000000..e999e8800 --- /dev/null +++ b/test/fixtures/image.png diff --git a/test/fixtures/tesla_mock/admin@mastdon.example.org.json b/test/fixtures/tesla_mock/admin@mastdon.example.org.json index a911b979a..f961ccb36 100644 --- a/test/fixtures/tesla_mock/admin@mastdon.example.org.json +++ b/test/fixtures/tesla_mock/admin@mastdon.example.org.json @@ -1,20 +1,24 @@  { -  "@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", { -    "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", -    "sensitive": "as:sensitive", -    "movedTo": "as:movedTo", -    "Hashtag": "as:Hashtag", -    "ostatus": "http://ostatus.org#", -    "atomUri": "ostatus:atomUri", -    "inReplyToAtomUri": "ostatus:inReplyToAtomUri", -    "conversation": "ostatus:conversation", -    "toot": "http://joinmastodon.org/ns#", -    "Emoji": "toot:Emoji", -    "alsoKnownAs": { -      "@id": "as:alsoKnownAs", -      "@type": "@id" +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +      "sensitive": "as:sensitive", +      "movedTo": "as:movedTo", +      "Hashtag": "as:Hashtag", +      "ostatus": "http://ostatus.org#", +      "atomUri": "ostatus:atomUri", +      "inReplyToAtomUri": "ostatus:inReplyToAtomUri", +      "conversation": "ostatus:conversation", +      "toot": "http://joinmastodon.org/ns#", +      "Emoji": "toot:Emoji", +      "alsoKnownAs": { +        "@id": "as:alsoKnownAs", +        "@type": "@id" +      }      } -  }], +  ],    "id": "http://mastodon.example.org/users/admin",    "type": "Person",    "following": "http://mastodon.example.org/users/admin/following", @@ -23,6 +27,7 @@    "outbox": "http://mastodon.example.org/users/admin/outbox",    "preferredUsername": "admin",    "name": null, +  "discoverable": "true",    "summary": "\u003cp\u003e\u003c/p\u003e",    "url": "http://mastodon.example.org/@admin",    "manuallyApprovesFollowers": false, @@ -34,7 +39,8 @@      "owner": "http://mastodon.example.org/users/admin",      "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtc4Tir+3ADhSNF6VKrtW\nOU32T01w7V0yshmQei38YyiVwVvFu8XOP6ACchkdxbJ+C9mZud8qWaRJKVbFTMUG\nNX4+6Q+FobyuKrwN7CEwhDALZtaN2IPbaPd6uG1B7QhWorrY+yFa8f2TBM3BxnUy\nI4T+bMIZIEYG7KtljCBoQXuTQmGtuffO0UwJksidg2ffCF5Q+K//JfQagJ3UzrR+\nZXbKMJdAw4bCVJYs4Z5EhHYBwQWiXCyMGTd7BGlmMkY6Av7ZqHKC/owp3/0EWDNz\nNqF09Wcpr3y3e8nA10X40MJqp/wR+1xtxp+YGbq/Cj5hZGBG7etFOmIpVBrDOhry\nBwIDAQAB\n-----END PUBLIC KEY-----\n"    }, -  "attachment": [{ +  "attachment": [ +    {        "type": "PropertyValue",        "name": "foo",        "value": "bar" @@ -58,5 +64,7 @@      "mediaType": "image/png",      "url": "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"    }, -  "alsoKnownAs": ["http://example.org/users/foo"] -} +  "alsoKnownAs": [ +    "http://example.org/users/foo" +  ] +}
\ No newline at end of file diff --git a/test/fixtures/tesla_mock/framatube.org-video.json b/test/fixtures/tesla_mock/framatube.org-video.json index 3d53f0c97..1fa529886 100644 --- a/test/fixtures/tesla_mock/framatube.org-video.json +++ b/test/fixtures/tesla_mock/framatube.org-video.json @@ -1 +1 @@ -{"type":"Video","id":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206","name":"Déframasoftisons Internet [Framasoft]","duration":"PT3622S","uuid":"6050732a-8a7a-43d4-a6cd-809525a1d206","tag":[{"type":"Hashtag","name":"déframasoftisons"},{"type":"Hashtag","name":"EPN23"},{"type":"Hashtag","name":"framaconf"},{"type":"Hashtag","name":"Framasoft"},{"type":"Hashtag","name":"pyg"}],"category":{"identifier":"15","name":"Science & Technology"},"views":122,"sensitive":false,"waitTranscoding":false,"state":1,"commentsEnabled":true,"downloadEnabled":true,"published":"2020-05-24T18:34:31.569Z","originallyPublishedAt":"2019-11-30T23:00:00.000Z","updated":"2020-07-05T09:01:01.720Z","mediaType":"text/markdown","content":"Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?\r\n\r\nTranscription par @april...","support":null,"subtitleLanguage":[],"icon":{"type":"Image","url":"https://framatube.org/static/thumbnails/6050732a-8a7a-43d4-a6cd-809525a1d206.jpg","mediaType":"image/jpeg","width":223,"height":122},"url":[{"type":"Link","mediaType":"text/html","href":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080,"size":1157359410,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309939","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent&xt=urn:btih:381c9429900552e23a4eb506318f1fa01e4d63a8&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480,"size":250095131,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309941","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent&xt=urn:btih:a181dcbb5368ab5c31cc9ff07634becb72c344ee&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360,"size":171357733,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309942","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent&xt=urn:btih:aedfa9479ea04a175eee0b0bd0bda64076308746&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720,"size":497100839,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309943","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent&xt=urn:btih:71971668f82a3b24ac71bc3a982848dd8dc5a5f5&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240,"size":113038439,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309944","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent&xt=urn:btih:c42aa6c95efb28d9f114ebd98537f7b00fa72246&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240},{"type":"Link","mediaType":"application/x-mpegURL","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/master.m3u8","tag":[{"type":"Infohash","name":"f7428214539626e062f300f2ca4cf9154575144e"},{"type":"Infohash","name":"46e236dffb1ea6b9123a5396cbe88e97dd94cc6c"},{"type":"Infohash","name":"11f1045830b5d786c788f2594d19f128764e7d87"},{"type":"Infohash","name":"4327ad3e0d84de100130a27e9ab6fe40c4284f0e"},{"type":"Infohash","name":"41e2eee8e7b23a63c23a77c40a46de11492a4831"},{"type":"Link","name":"sha256","mediaType":"application/json","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/segments-sha256.json"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080,"size":1156777472,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309940","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent&xt=urn:btih:0204d780ebfab0d5d9d3476a038e812ad792deeb&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480,"size":249562889,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309945","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent&xt=urn:btih:5d14f38ded29de629668fe1cfc61a75f4cce2628&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360,"size":170836415,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309946","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent&xt=urn:btih:30125488789080ad405ebcee6c214945f31b8f30&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720,"size":496533741,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309947","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent&xt=urn:btih:8ed1e8bccde709901c26e315fc8f53bfd26d1ba6&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240,"size":112529249,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309948","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent&xt=urn:btih:8b452bf4e70b9078d4e74ca8b5523cc9dc70d10a&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240}]}],"likes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/likes","dislikes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/dislikes","shares":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/announces","comments":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/comments","attributedTo":[{"type":"Person","id":"https://framatube.org/accounts/framasoft"},{"type":"Group","id":"https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8"}],"to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://framatube.org/accounts/framasoft/followers"],"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"RsaSignature2017":"https://w3id.org/security#RsaSignature2017"},{"pt":"https://joinpeertube.org/ns#","sc":"http://schema.org#","Hashtag":"as:Hashtag","uuid":"sc:identifier","category":"sc:category","licence":"sc:license","subtitleLanguage":"sc:subtitleLanguage","sensitive":"as:sensitive","language":"sc:inLanguage","Infohash":"pt:Infohash","Playlist":"pt:Playlist","PlaylistElement":"pt:PlaylistElement","originallyPublishedAt":"sc:datePublished","views":{"@type":"sc:Number","@id":"pt:views"},"state":{"@type":"sc:Number","@id":"pt:state"},"size":{"@type":"sc:Number","@id":"pt:size"},"fps":{"@type":"sc:Number","@id":"pt:fps"},"startTimestamp":{"@type":"sc:Number","@id":"pt:startTimestamp"},"stopTimestamp":{"@type":"sc:Number","@id":"pt:stopTimestamp"},"position":{"@type":"sc:Number","@id":"pt:position"},"commentsEnabled":{"@type":"sc:Boolean","@id":"pt:commentsEnabled"},"downloadEnabled":{"@type":"sc:Boolean","@id":"pt:downloadEnabled"},"waitTranscoding":{"@type":"sc:Boolean","@id":"pt:waitTranscoding"},"support":{"@type":"sc:Text","@id":"pt:support"},"likes":{"@id":"as:likes","@type":"@id"},"dislikes":{"@id":"as:dislikes","@type":"@id"},"playlists":{"@id":"pt:playlists","@type":"@id"},"shares":{"@id":"as:shares","@type":"@id"},"comments":{"@id":"as:comments","@type":"@id"}}]}
\ No newline at end of file +{"type":"Create","id":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/activity","actor":"https://framatube.org/accounts/framasoft","object":{"type":"Video","id":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206","name":"Déframasoftisons Internet [Framasoft]","duration":"PT3622S","uuid":"6050732a-8a7a-43d4-a6cd-809525a1d206","tag":[{"type":"Hashtag","name":"déframasoftisons"},{"type":"Hashtag","name":"EPN23"},{"type":"Hashtag","name":"framaconf"},{"type":"Hashtag","name":"Framasoft"},{"type":"Hashtag","name":"pyg"}],"category":{"identifier":"15","name":"Science & Technology"},"views":154,"sensitive":false,"waitTranscoding":false,"state":1,"commentsEnabled":true,"downloadEnabled":true,"published":"2020-05-24T18:34:31.569Z","originallyPublishedAt":"2019-11-30T23:00:00.000Z","updated":"2020-08-17T11:01:02.994Z","mediaType":"text/markdown","content":"Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?\r\n\r\nTranscription par @aprilorg ici : https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft","support":null,"subtitleLanguage":[],"icon":[{"type":"Image","url":"https://framatube.org/static/thumbnails/6050732a-8a7a-43d4-a6cd-809525a1d206.jpg","mediaType":"image/jpeg","width":223,"height":122},{"type":"Image","url":"https://framatube.org/static/previews/6050732a-8a7a-43d4-a6cd-809525a1d206.jpg","mediaType":"image/jpeg","width":850,"height":480}],"url":[{"type":"Link","mediaType":"text/html","href":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080,"size":1157359410,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309939","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent&xt=urn:btih:381c9429900552e23a4eb506318f1fa01e4d63a8&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720,"size":497100839,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309943","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent&xt=urn:btih:71971668f82a3b24ac71bc3a982848dd8dc5a5f5&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480,"size":250095131,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309941","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent&xt=urn:btih:a181dcbb5368ab5c31cc9ff07634becb72c344ee&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360,"size":171357733,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309942","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent&xt=urn:btih:aedfa9479ea04a175eee0b0bd0bda64076308746&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240,"size":113038439,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309944","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent&xt=urn:btih:c42aa6c95efb28d9f114ebd98537f7b00fa72246&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240},{"type":"Link","mediaType":"application/x-mpegURL","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/master.m3u8","tag":[{"type":"Infohash","name":"f7428214539626e062f300f2ca4cf9154575144e"},{"type":"Infohash","name":"46e236dffb1ea6b9123a5396cbe88e97dd94cc6c"},{"type":"Infohash","name":"11f1045830b5d786c788f2594d19f128764e7d87"},{"type":"Infohash","name":"4327ad3e0d84de100130a27e9ab6fe40c4284f0e"},{"type":"Infohash","name":"41e2eee8e7b23a63c23a77c40a46de11492a4831"},{"type":"Link","name":"sha256","mediaType":"application/json","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/segments-sha256.json"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080,"size":1156777472,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309940","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent&xt=urn:btih:0204d780ebfab0d5d9d3476a038e812ad792deeb&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720,"size":496533741,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309947","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent&xt=urn:btih:8ed1e8bccde709901c26e315fc8f53bfd26d1ba6&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480,"size":249562889,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309945","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent&xt=urn:btih:5d14f38ded29de629668fe1cfc61a75f4cce2628&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360,"size":170836415,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309946","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent&xt=urn:btih:30125488789080ad405ebcee6c214945f31b8f30&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240,"size":112529249,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309948","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent&xt=urn:btih:8b452bf4e70b9078d4e74ca8b5523cc9dc70d10a&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240}]}],"likes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/likes","dislikes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/dislikes","shares":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/announces","comments":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/comments","attributedTo":[{"type":"Person","id":"https://framatube.org/accounts/framasoft"},{"type":"Group","id":"https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8"}],"to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://framatube.org/accounts/framasoft/followers"]},"to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://framatube.org/accounts/framasoft/followers"],"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"RsaSignature2017":"https://w3id.org/security#RsaSignature2017"},{"pt":"https://joinpeertube.org/ns#","sc":"http://schema.org#","Hashtag":"as:Hashtag","uuid":"sc:identifier","category":"sc:category","licence":"sc:license","subtitleLanguage":"sc:subtitleLanguage","sensitive":"as:sensitive","language":"sc:inLanguage","Infohash":"pt:Infohash","Playlist":"pt:Playlist","PlaylistElement":"pt:PlaylistElement","originallyPublishedAt":"sc:datePublished","views":{"@type":"sc:Number","@id":"pt:views"},"state":{"@type":"sc:Number","@id":"pt:state"},"size":{"@type":"sc:Number","@id":"pt:size"},"fps":{"@type":"sc:Number","@id":"pt:fps"},"startTimestamp":{"@type":"sc:Number","@id":"pt:startTimestamp"},"stopTimestamp":{"@type":"sc:Number","@id":"pt:stopTimestamp"},"position":{"@type":"sc:Number","@id":"pt:position"},"commentsEnabled":{"@type":"sc:Boolean","@id":"pt:commentsEnabled"},"downloadEnabled":{"@type":"sc:Boolean","@id":"pt:downloadEnabled"},"waitTranscoding":{"@type":"sc:Boolean","@id":"pt:waitTranscoding"},"support":{"@type":"sc:Text","@id":"pt:support"},"likes":{"@id":"as:likes","@type":"@id"},"dislikes":{"@id":"as:dislikes","@type":"@id"},"playlists":{"@id":"pt:playlists","@type":"@id"},"shares":{"@id":"as:shares","@type":"@id"},"comments":{"@id":"as:comments","@type":"@id"}}]}
\ No newline at end of file diff --git a/test/fixtures/tesla_mock/https___osada.macgirvin.com_channel_mike.json b/test/fixtures/tesla_mock/https___osada.macgirvin.com_channel_mike.json index c42f3a53c..ca76d6e17 100644 --- a/test/fixtures/tesla_mock/https___osada.macgirvin.com_channel_mike.json +++ b/test/fixtures/tesla_mock/https___osada.macgirvin.com_channel_mike.json @@ -8,6 +8,7 @@      "preferredUsername": "mike",      "name": "Mike Macgirvin (Osada)",      "updated": "2018-08-29T03:09:11Z", +    "discoverable": "true",      "icon": {          "type": "Image",          "mediaType": "image/jpeg", @@ -51,4 +52,4 @@          "created": "2018-10-17T07:16:28Z",          "signatureValue": "WbfFVIPImkd3yNu6brz0CvZaeV242rwAbH0vy8DM4vfnXCxLr5Uv/Wj9gwP+tbooTxGaahAKBeqlGkQp8RLEo37LATrKMRLA/0V6DeeV+C5ORWR9B4WxyWiD3s/9Wf+KesFMtktNLAcMZ5PfnOS/xNYerhnpkp/gWPxtkglmLIWJv+w18A5zZ01JCxsO4QljHbhYaEUPHUfQ97abrkLECeam+FThVwdO6BFCtbjoNXHfzjpSZL/oKyBpi5/fpnqMqOLOQPs5WgBBZJvjEYYkQcoPTyxYI5NGpNbzIjGHPQNuACnOelH16A7L+q4swLWDIaEFeXQ2/5bmqVKZDZZ6usNP4QyTVszwd8jqo27qcDTNibXDUTsTdKpNQvM/3UncBuzuzmUV3FczhtGshIU1/pRVZiQycpVqPlGLvXhP/yZCe+1siyqDd+3uMaS2vkHTObSl5r+VYof+c+TcjrZXHSWnQTg8/X3zkoBWosrQ93VZcwjzMxQoARYv6rphbOoTz7RPmGAXYUt3/PDWkqDlmQDwCpLNNkJo1EidyefZBdD9HXQpCBO0ZU0NHb0JmPvg/+zU0krxlv70bm3RHA/maBETVjroIWzt7EwQEg5pL2hVnvSBG+1wF3BtRVe77etkPOHxLnYYIcAMLlVKCcgDd89DPIziQyruvkx1busHI08="      } -} +}
\ No newline at end of file diff --git a/test/fixtures/tesla_mock/wedistribute-create-article.json b/test/fixtures/tesla_mock/wedistribute-create-article.json new file mode 100644 index 000000000..3cfef8b99 --- /dev/null +++ b/test/fixtures/tesla_mock/wedistribute-create-article.json @@ -0,0 +1 @@ +{"@context":["https:\/\/www.w3.org\/ns\/activitystreams"],"type":"Create","actor":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/actor\/-blog","object":{"@context":["https:\/\/www.w3.org\/ns\/activitystreams"],"type":"Article","name":"The end is near: Mastodon plans to drop OStatus support","content":"<!-- wp:paragraph {\"dropCap\":true} -->\n<p class=\"has-drop-cap\">The days of OStatus are numbered. The venerable protocol has served as a glue between many different types of servers since the early days of the Fediverse, connecting StatusNet (now GNU Social) to Friendica, Hubzilla, Mastodon, and Pleroma.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>Now that many fediverse platforms support ActivityPub as a successor protocol, Mastodon appears to be drawing a line in the sand. In <a href=\"https:\/\/www.patreon.com\/posts\/mastodon-2-9-and-28121681\">a Patreon update<\/a>, Eugen Rochko writes:<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:quote -->\n<blockquote class=\"wp-block-quote\"><p>...OStatus...has overstayed its welcome in the code...and now that most of the network uses ActivityPub, it's time for it to go. <\/p><cite>Eugen Rochko, Mastodon creator<\/cite><\/blockquote>\n<!-- \/wp:quote -->\n\n<!-- wp:paragraph -->\n<p>The <a href=\"https:\/\/github.com\/tootsuite\/mastodon\/pull\/11205\">pull request<\/a> to remove Pubsubhubbub and Salmon, two of the main components of OStatus, has already been merged into Mastodon's master branch.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>Some projects will be left in the dark as a side effect of this. GNU Social and PostActiv, for example, both only communicate using OStatus. While <a href=\"https:\/\/mastodon.social\/@dansup\/102076573310057902\">some discussion<\/a> exists regarding adopting ActivityPub for GNU Social, and <a href=\"https:\/\/notabug.org\/diogo\/gnu-social\/src\/activitypub\/plugins\/ActivityPub\">a plugin is in development<\/a>, it hasn't been formally adopted yet. We just hope that the <a href=\"https:\/\/status.fsf.org\/main\/public\">Free Software Foundation's instance<\/a> gets updated in time!<\/p>\n<!-- \/wp:paragraph -->","summary":"One of the largest platforms in the federated social web is dropping the protocol that it started with.","attributedTo":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/actor\/-blog","url":"https:\/\/wedistribute.org\/2019\/07\/mastodon-drops-ostatus\/","to":["https:\/\/www.w3.org\/ns\/activitystreams#Public","https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/actor\/-blog\/followers"],"id":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/object\/85810","likes":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/object\/85810\/likes","shares":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/object\/85810\/shares"},"to":["https:\/\/www.w3.org\/ns\/activitystreams#Public","https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/actor\/-blog\/followers"],"id":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/object\/85809"}
\ No newline at end of file diff --git a/test/instance_static/emoji/blobs.gg/blank.png b/test/instance_static/emoji/blobs.gg/blank.pngBinary files differ new file mode 100644 index 000000000..8f50fa023 --- /dev/null +++ b/test/instance_static/emoji/blobs.gg/blank.png diff --git a/test/instance_static/emoji/blobs.gg/pack.json b/test/instance_static/emoji/blobs.gg/pack.json new file mode 100644 index 000000000..481891b08 --- /dev/null +++ b/test/instance_static/emoji/blobs.gg/pack.json @@ -0,0 +1,11 @@ +{ +    "files": { +        "blank": "blank.png" +    }, +    "pack": { +        "description": "Test description", +        "homepage": "https://pleroma.social", +        "license": "Test license", +        "share-files": true +    } +}
\ No newline at end of file diff --git a/test/integration/mastodon_websocket_test.exs b/test/integration/mastodon_websocket_test.exs index 76fbc8bda..0f2e6cc2b 100644 --- a/test/integration/mastodon_websocket_test.exs +++ b/test/integration/mastodon_websocket_test.exs @@ -78,7 +78,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do          Pleroma.Repo.insert(            OAuth.App.register_changeset(%OAuth.App{}, %{              client_name: "client", -            scopes: ["scope"], +            scopes: ["read"],              redirect_uris: "url"            })          ) diff --git a/test/marker_test.exs b/test/marker_test.exs index 5b6d0b4a4..7b3943c7b 100644 --- a/test/marker_test.exs +++ b/test/marker_test.exs @@ -33,8 +33,8 @@ defmodule Pleroma.MarkerTest do      test "returns user markers" do        user = insert(:user)        marker = insert(:marker, user: user) -      insert(:notification, user: user) -      insert(:notification, user: user) +      insert(:notification, user: user, activity: insert(:note_activity)) +      insert(:notification, user: user, activity: insert(:note_activity))        insert(:marker, timeline: "home", user: user)        assert Marker.get_markers( diff --git a/test/notification_test.exs b/test/notification_test.exs index a09b08675..f2e0f0b0d 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -179,17 +179,19 @@ defmodule Pleroma.NotificationTest do    describe "create_notification" do      @tag needs_streamer: true      test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do -      user = insert(:user) +      %{user: user, token: oauth_token} = oauth_access(["read"])        task =          Task.async(fn -> -          Streamer.get_topic_and_add_socket("user", user) +          {:ok, _topic} = Streamer.get_topic_and_add_socket("user", user, oauth_token)            assert_receive {:render_with_user, _, _, _}, 4_000          end)        task_user_notification =          Task.async(fn -> -          Streamer.get_topic_and_add_socket("user:notification", user) +          {:ok, _topic} = +            Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) +            assert_receive {:render_with_user, _, _, _}, 4_000          end) diff --git a/test/object/fetcher_test.exs b/test/object/fetcher_test.exs index 16cfa7f5c..14d2c645f 100644 --- a/test/object/fetcher_test.exs +++ b/test/object/fetcher_test.exs @@ -6,10 +6,12 @@ defmodule Pleroma.Object.FetcherTest do    use Pleroma.DataCase    alias Pleroma.Activity +  alias Pleroma.Config    alias Pleroma.Object    alias Pleroma.Object.Fetcher -  import Tesla.Mock +    import Mock +  import Tesla.Mock    setup do      mock(fn @@ -71,20 +73,20 @@ defmodule Pleroma.Object.FetcherTest do      setup do: clear_config([:instance, :federation_incoming_replies_max_depth])      test "it returns thread depth exceeded error if thread depth is exceeded" do -      Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) +      Config.put([:instance, :federation_incoming_replies_max_depth], 0)        assert {:error, "Max thread distance exceeded."} =                 Fetcher.fetch_object_from_id(@ap_id, depth: 1)      end      test "it fetches object if max thread depth is restricted to 0 and depth is not specified" do -      Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) +      Config.put([:instance, :federation_incoming_replies_max_depth], 0)        assert {:ok, _} = Fetcher.fetch_object_from_id(@ap_id)      end      test "it fetches object if requested depth does not exceed max thread depth" do -      Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10) +      Config.put([:instance, :federation_incoming_replies_max_depth], 10)        assert {:ok, _} = Fetcher.fetch_object_from_id(@ap_id, depth: 10)      end @@ -120,6 +122,16 @@ defmodule Pleroma.Object.FetcherTest do        assert object == object_again      end + +    test "Return MRF reason when fetched status is rejected by one" do +      clear_config([:mrf_keyword, :reject], ["yeah"]) +      clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) + +      assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} == +               Fetcher.fetch_object_from_id( +                 "http://mastodon.example.org/@admin/99541947525187367" +               ) +    end    end    describe "implementation quirks" do @@ -212,7 +224,7 @@ defmodule Pleroma.Object.FetcherTest do                     Pleroma.Signature,                     [:passthrough],                     [] do -      Pleroma.Config.put([:activitypub, :sign_object_fetches], true) +      Config.put([:activitypub, :sign_object_fetches], true)        Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367") @@ -223,7 +235,7 @@ defmodule Pleroma.Object.FetcherTest do                     Pleroma.Signature,                     [:passthrough],                     [] do -      Pleroma.Config.put([:activitypub, :sign_object_fetches], false) +      Config.put([:activitypub, :sign_object_fetches], false)        Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367") diff --git a/test/plugs/remote_ip_test.exs b/test/plugs/remote_ip_test.exs index 752ab32e7..6d01c812d 100644 --- a/test/plugs/remote_ip_test.exs +++ b/test/plugs/remote_ip_test.exs @@ -3,13 +3,27 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Plugs.RemoteIpTest do -  use ExUnit.Case, async: true +  use ExUnit.Case    use Plug.Test    alias Pleroma.Plugs.RemoteIp -  import Pleroma.Tests.Helpers, only: [clear_config: 1, clear_config: 2] -  setup do: clear_config(RemoteIp) +  import Pleroma.Tests.Helpers, only: [clear_config: 2] + +  setup do: +          clear_config(RemoteIp, +            enabled: true, +            headers: ["x-forwarded-for"], +            proxies: [], +            reserved: [ +              "127.0.0.0/8", +              "::1/128", +              "fc00::/7", +              "10.0.0.0/8", +              "172.16.0.0/12", +              "192.168.0.0/16" +            ] +          )    test "disabled" do      Pleroma.Config.put(RemoteIp, enabled: false) @@ -25,8 +39,6 @@ defmodule Pleroma.Plugs.RemoteIpTest do    end    test "enabled" do -    Pleroma.Config.put(RemoteIp, enabled: true) -      conn =        conn(:get, "/")        |> put_req_header("x-forwarded-for", "1.1.1.1") @@ -54,8 +66,6 @@ defmodule Pleroma.Plugs.RemoteIpTest do    end    test "custom proxies" do -    Pleroma.Config.put(RemoteIp, enabled: true) -      conn =        conn(:get, "/")        |> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1, 173.245.48.2") @@ -72,4 +82,27 @@ defmodule Pleroma.Plugs.RemoteIpTest do      assert conn.remote_ip == {1, 1, 1, 1}    end + +  test "proxies set without CIDR format" do +    Pleroma.Config.put([RemoteIp, :proxies], ["173.245.48.1"]) + +    conn = +      conn(:get, "/") +      |> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1") +      |> RemoteIp.call(nil) + +    assert conn.remote_ip == {1, 1, 1, 1} +  end + +  test "proxies set `nonsensical` CIDR" do +    Pleroma.Config.put([RemoteIp, :reserved], ["127.0.0.0/8"]) +    Pleroma.Config.put([RemoteIp, :proxies], ["10.0.0.3/24"]) + +    conn = +      conn(:get, "/") +      |> put_req_header("x-forwarded-for", "10.0.0.3, 1.1.1.1") +      |> RemoteIp.call(nil) + +    assert conn.remote_ip == {1, 1, 1, 1} +  end  end diff --git a/test/repo_test.exs b/test/repo_test.exs index 92e827c95..155791be2 100644 --- a/test/repo_test.exs +++ b/test/repo_test.exs @@ -37,7 +37,9 @@ defmodule Pleroma.RepoTest do      test "get one-to-many assoc from repo" do        user = insert(:user) -      notification = refresh_record(insert(:notification, user: user)) + +      notification = +        refresh_record(insert(:notification, user: user, activity: insert(:note_activity)))        assert Repo.get_assoc(user, :notifications) == {:ok, [notification]}      end @@ -47,4 +49,32 @@ defmodule Pleroma.RepoTest do        assert Repo.get_assoc(token, :user) == {:error, :not_found}      end    end + +  describe "chunk_stream/3" do +    test "fetch records one-by-one" do +      users = insert_list(50, :user) + +      {fetch_users, 50} = +        from(t in User) +        |> Repo.chunk_stream(5) +        |> Enum.reduce({[], 0}, fn %User{} = user, {acc, count} -> +          {acc ++ [user], count + 1} +        end) + +      assert users == fetch_users +    end + +    test "fetch records in bulk" do +      users = insert_list(50, :user) + +      {fetch_users, 10} = +        from(t in User) +        |> Repo.chunk_stream(5, :batches) +        |> Enum.reduce({[], 0}, fn users, {acc, count} -> +          {acc ++ users, count + 1} +        end) + +      assert users == fetch_users +    end +  end  end diff --git a/test/support/data_case.ex b/test/support/data_case.ex index ba8848952..d5456521c 100644 --- a/test/support/data_case.ex +++ b/test/support/data_case.ex @@ -27,6 +27,21 @@ defmodule Pleroma.DataCase do        import Ecto.Query        import Pleroma.DataCase        use Pleroma.Tests.Helpers + +      # Sets up OAuth access with specified scopes +      defp oauth_access(scopes, opts \\ []) do +        user = +          Keyword.get_lazy(opts, :user, fn -> +            Pleroma.Factory.insert(:user) +          end) + +        token = +          Keyword.get_lazy(opts, :oauth_token, fn -> +            Pleroma.Factory.insert(:oauth_token, user: user, scopes: scopes) +          end) + +        %{user: user, token: token} +      end      end    end diff --git a/test/support/factory.ex b/test/support/factory.ex index 2fdfabbc5..fb82be0c4 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -31,6 +31,7 @@ defmodule Pleroma.Factory do        nickname: sequence(:nickname, &"nick#{&1}"),        password_hash: Pbkdf2.hash_pwd_salt("test"),        bio: sequence(:bio, &"Tester Number #{&1}"), +      discoverable: true,        last_digest_emailed_at: NaiveDateTime.utc_now(),        last_refreshed_at: NaiveDateTime.utc_now(),        notification_settings: %Pleroma.User.NotificationSetting{}, diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 344e27f13..cb022333f 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -1262,4 +1262,21 @@ defmodule HttpRequestMock do         inspect(headers)       }"}    end + +  # Most of the rich media mocks are missing HEAD requests, so we just return 404. +  @rich_media_mocks [ +    "https://example.com/ogp", +    "https://example.com/ogp-missing-data", +    "https://example.com/twitter-card" +  ] +  def head(url, _query, _body, _headers) when url in @rich_media_mocks do +    {:ok, %Tesla.Env{status: 404, body: ""}} +  end + +  def head(url, query, body, headers) do +    {:error, +     "Mock response not implemented for HEAD #{inspect(url)}, #{query}, #{inspect(body)}, #{ +       inspect(headers) +     }"} +  end  end diff --git a/test/support/web_push_http_client_mock.ex b/test/support/web_push_http_client_mock.ex deleted file mode 100644 index 3cd12957d..000000000 --- a/test/support/web_push_http_client_mock.ex +++ /dev/null @@ -1,23 +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.WebPushHttpClientMock do -  def get(url, headers \\ [], options \\ []) do -    { -      res, -      %Tesla.Env{status: status} -    } = Pleroma.HTTP.request(:get, url, "", headers, options) - -    {res, %{status_code: status}} -  end - -  def post(url, body, headers \\ [], options \\ []) do -    { -      res, -      %Tesla.Env{status: status} -    } = Pleroma.HTTP.request(:post, url, body, headers, options) - -    {res, %{status_code: status}} -  end -end diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs index fb12e7fb3..f36648829 100644 --- a/test/tasks/config_test.exs +++ b/test/tasks/config_test.exs @@ -40,6 +40,19 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do        on_exit(fn -> Application.put_env(:quack, :level, initial) end)      end +    @tag capture_log: true +    test "config migration refused when deprecated settings are found" do +      clear_config([:media_proxy, :whitelist], ["domain_without_scheme.com"]) +      assert Repo.all(ConfigDB) == [] + +      Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs") + +      assert_received {:mix_shell, :error, [message]} + +      assert message =~ +               "Migration is not allowed until all deprecation warnings have been resolved." +    end +      test "filtered settings are migrated to db" do        assert Repo.all(ConfigDB) == [] diff --git a/test/tasks/email_test.exs b/test/tasks/email_test.exs index c3af7ef68..5393e3573 100644 --- a/test/tasks/email_test.exs +++ b/test/tasks/email_test.exs @@ -6,6 +6,8 @@ defmodule Mix.Tasks.Pleroma.EmailTest do    alias Pleroma.Config    alias Pleroma.Tests.ObanHelpers +  import Pleroma.Factory +    setup_all do      Mix.shell(Mix.Shell.Process) @@ -17,6 +19,7 @@ defmodule Mix.Tasks.Pleroma.EmailTest do    end    setup do: clear_config([Pleroma.Emails.Mailer, :enabled], true) +  setup do: clear_config([:instance, :account_activation_required], true)    describe "pleroma.email test" do      test "Sends test email with no given address" do @@ -50,5 +53,71 @@ defmodule Mix.Tasks.Pleroma.EmailTest do          html_body: ~r/a test email was requested./i        )      end + +    test "Sends confirmation emails" do +      local_user1 = +        insert(:user, %{ +          confirmation_pending: true, +          confirmation_token: "mytoken", +          deactivated: false, +          email: "local1@pleroma.com", +          local: true +        }) + +      local_user2 = +        insert(:user, %{ +          confirmation_pending: true, +          confirmation_token: "mytoken", +          deactivated: false, +          email: "local2@pleroma.com", +          local: true +        }) + +      :ok = Mix.Tasks.Pleroma.Email.run(["resend_confirmation_emails"]) + +      ObanHelpers.perform_all() + +      assert_email_sent(to: {local_user1.name, local_user1.email}) +      assert_email_sent(to: {local_user2.name, local_user2.email}) +    end + +    test "Does not send confirmation email to inappropriate users" do +      # confirmed user +      insert(:user, %{ +        confirmation_pending: false, +        confirmation_token: "mytoken", +        deactivated: false, +        email: "confirmed@pleroma.com", +        local: true +      }) + +      # remote user +      insert(:user, %{ +        deactivated: false, +        email: "remote@not-pleroma.com", +        local: false +      }) + +      # deactivated user = +      insert(:user, %{ +        deactivated: true, +        email: "deactivated@pleroma.com", +        local: false +      }) + +      # invisible user +      insert(:user, %{ +        deactivated: false, +        email: "invisible@pleroma.com", +        local: true, +        invisible: true +      }) + +      :ok = Mix.Tasks.Pleroma.Email.run(["resend_confirmation_emails"]) + +      ObanHelpers.perform_all() + +      refute_email_sent() +    end    end  end diff --git a/test/tasks/relay_test.exs b/test/tasks/relay_test.exs index e5225b64c..cf48e7dda 100644 --- a/test/tasks/relay_test.exs +++ b/test/tasks/relay_test.exs @@ -81,6 +81,80 @@ defmodule Mix.Tasks.Pleroma.RelayTest do        assert undo_activity.data["object"]["id"] == cancelled_activity.data["id"]        refute "#{target_instance}/followers" in User.following(local_user)      end + +    test "unfollow when relay is dead" do +      user = insert(:user) +      target_instance = user.ap_id + +      Mix.Tasks.Pleroma.Relay.run(["follow", target_instance]) + +      %User{ap_id: follower_id} = local_user = Relay.get_actor() +      target_user = User.get_cached_by_ap_id(target_instance) +      follow_activity = Utils.fetch_latest_follow(local_user, target_user) +      User.follow(local_user, target_user) + +      assert "#{target_instance}/followers" in User.following(local_user) + +      Tesla.Mock.mock(fn %{method: :get, url: ^target_instance} -> +        %Tesla.Env{status: 404} +      end) + +      Pleroma.Repo.delete(user) +      Cachex.clear(:user_cache) + +      Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance]) + +      cancelled_activity = Activity.get_by_ap_id(follow_activity.data["id"]) +      assert cancelled_activity.data["state"] == "accept" + +      assert [] == +               ActivityPub.fetch_activities( +                 [], +                 %{ +                   type: "Undo", +                   actor_id: follower_id, +                   skip_preload: true, +                   invisible_actors: true +                 } +               ) +    end + +    test "force unfollow when relay is dead" do +      user = insert(:user) +      target_instance = user.ap_id + +      Mix.Tasks.Pleroma.Relay.run(["follow", target_instance]) + +      %User{ap_id: follower_id} = local_user = Relay.get_actor() +      target_user = User.get_cached_by_ap_id(target_instance) +      follow_activity = Utils.fetch_latest_follow(local_user, target_user) +      User.follow(local_user, target_user) + +      assert "#{target_instance}/followers" in User.following(local_user) + +      Tesla.Mock.mock(fn %{method: :get, url: ^target_instance} -> +        %Tesla.Env{status: 404} +      end) + +      Pleroma.Repo.delete(user) +      Cachex.clear(:user_cache) + +      Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance, "--force"]) + +      cancelled_activity = Activity.get_by_ap_id(follow_activity.data["id"]) +      assert cancelled_activity.data["state"] == "cancelled" + +      [undo_activity] = +        ActivityPub.fetch_activities( +          [], +          %{type: "Undo", actor_id: follower_id, skip_preload: true, invisible_actors: true} +        ) + +      assert undo_activity.data["type"] == "Undo" +      assert undo_activity.data["actor"] == local_user.ap_id +      assert undo_activity.data["object"]["id"] == cancelled_activity.data["id"] +      refute "#{target_instance}/followers" in User.following(local_user) +    end    end    describe "mix pleroma.relay list" do diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs index ce43a9cc7..b8c423c48 100644 --- a/test/tasks/user_test.exs +++ b/test/tasks/user_test.exs @@ -225,47 +225,64 @@ defmodule Mix.Tasks.Pleroma.UserTest do      test "All statuses set" do        user = insert(:user) -      Mix.Tasks.Pleroma.User.run(["set", user.nickname, "--moderator", "--admin", "--locked"]) +      Mix.Tasks.Pleroma.User.run([ +        "set", +        user.nickname, +        "--admin", +        "--confirmed", +        "--locked", +        "--moderator" +      ])        assert_received {:mix_shell, :info, [message]} -      assert message =~ ~r/Moderator status .* true/ +      assert message =~ ~r/Admin status .* true/ + +      assert_received {:mix_shell, :info, [message]} +      assert message =~ ~r/Confirmation pending .* false/        assert_received {:mix_shell, :info, [message]}        assert message =~ ~r/Locked status .* true/        assert_received {:mix_shell, :info, [message]} -      assert message =~ ~r/Admin status .* true/ +      assert message =~ ~r/Moderator status .* true/        user = User.get_cached_by_nickname(user.nickname)        assert user.is_moderator        assert user.locked        assert user.is_admin +      refute user.confirmation_pending      end      test "All statuses unset" do -      user = insert(:user, locked: true, is_moderator: true, is_admin: true) +      user = +        insert(:user, locked: true, is_moderator: true, is_admin: true, confirmation_pending: true)        Mix.Tasks.Pleroma.User.run([          "set",          user.nickname, -        "--no-moderator",          "--no-admin", -        "--no-locked" +        "--no-confirmed", +        "--no-locked", +        "--no-moderator"        ])        assert_received {:mix_shell, :info, [message]} -      assert message =~ ~r/Moderator status .* false/ +      assert message =~ ~r/Admin status .* false/ + +      assert_received {:mix_shell, :info, [message]} +      assert message =~ ~r/Confirmation pending .* true/        assert_received {:mix_shell, :info, [message]}        assert message =~ ~r/Locked status .* false/        assert_received {:mix_shell, :info, [message]} -      assert message =~ ~r/Admin status .* false/ +      assert message =~ ~r/Moderator status .* false/        user = User.get_cached_by_nickname(user.nickname)        refute user.is_moderator        refute user.locked        refute user.is_admin +      assert user.confirmation_pending      end      test "no user to set status" do @@ -554,4 +571,44 @@ defmodule Mix.Tasks.Pleroma.UserTest do        assert message =~ "Could not change user tags"      end    end + +  describe "bulk confirm and unconfirm" do +    test "confirm all" do +      user1 = insert(:user, confirmation_pending: true) +      user2 = insert(:user, confirmation_pending: true) + +      assert user1.confirmation_pending +      assert user2.confirmation_pending + +      Mix.Tasks.Pleroma.User.run(["confirm_all"]) + +      user1 = User.get_cached_by_nickname(user1.nickname) +      user2 = User.get_cached_by_nickname(user2.nickname) + +      refute user1.confirmation_pending +      refute user2.confirmation_pending +    end + +    test "unconfirm all" do +      user1 = insert(:user, confirmation_pending: false) +      user2 = insert(:user, confirmation_pending: false) +      admin = insert(:user, is_admin: true, confirmation_pending: false) +      mod = insert(:user, is_moderator: true, confirmation_pending: false) + +      refute user1.confirmation_pending +      refute user2.confirmation_pending + +      Mix.Tasks.Pleroma.User.run(["unconfirm_all"]) + +      user1 = User.get_cached_by_nickname(user1.nickname) +      user2 = User.get_cached_by_nickname(user2.nickname) +      admin = User.get_cached_by_nickname(admin.nickname) +      mod = User.get_cached_by_nickname(mod.nickname) + +      assert user1.confirmation_pending +      assert user2.confirmation_pending +      refute admin.confirmation_pending +      refute mod.confirmation_pending +    end +  end  end diff --git a/test/user/import_test.exs b/test/user/import_test.exs new file mode 100644 index 000000000..e404deeb5 --- /dev/null +++ b/test/user/import_test.exs @@ -0,0 +1,76 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.User.ImportTest do +  alias Pleroma.Repo +  alias Pleroma.Tests.ObanHelpers +  alias Pleroma.User + +  use Pleroma.DataCase +  use Oban.Testing, repo: Pleroma.Repo + +  import Pleroma.Factory + +  setup_all do +    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  describe "follow_import" do +    test "it imports user followings from list" do +      [user1, user2, user3] = insert_list(3, :user) + +      identifiers = [ +        user2.ap_id, +        user3.nickname +      ] + +      {:ok, job} = User.Import.follow_import(user1, identifiers) + +      assert {:ok, result} = ObanHelpers.perform(job) +      assert is_list(result) +      assert result == [user2, user3] +      assert User.following?(user1, user2) +      assert User.following?(user1, user3) +    end +  end + +  describe "blocks_import" do +    test "it imports user blocks from list" do +      [user1, user2, user3] = insert_list(3, :user) + +      identifiers = [ +        user2.ap_id, +        user3.nickname +      ] + +      {:ok, job} = User.Import.blocks_import(user1, identifiers) + +      assert {:ok, result} = ObanHelpers.perform(job) +      assert is_list(result) +      assert result == [user2, user3] +      assert User.blocks?(user1, user2) +      assert User.blocks?(user1, user3) +    end +  end + +  describe "mutes_import" do +    test "it imports user mutes from list" do +      [user1, user2, user3] = insert_list(3, :user) + +      identifiers = [ +        user2.ap_id, +        user3.nickname +      ] + +      {:ok, job} = User.Import.mutes_import(user1, identifiers) + +      assert {:ok, result} = ObanHelpers.perform(job) +      assert is_list(result) +      assert result == [user2, user3] +      assert User.mutes?(user1, user2) +      assert User.mutes?(user1, user3) +    end +  end +end diff --git a/test/user/query_test.exs b/test/user/query_test.exs new file mode 100644 index 000000000..e2f5c7d81 --- /dev/null +++ b/test/user/query_test.exs @@ -0,0 +1,37 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.User.QueryTest do +  use Pleroma.DataCase, async: true + +  alias Pleroma.Repo +  alias Pleroma.User +  alias Pleroma.User.Query +  alias Pleroma.Web.ActivityPub.InternalFetchActor + +  import Pleroma.Factory + +  describe "internal users" do +    test "it filters out internal users by default" do +      %User{nickname: "internal.fetch"} = InternalFetchActor.get_actor() + +      assert [_user] = User |> Repo.all() +      assert [] == %{} |> Query.build() |> Repo.all() +    end + +    test "it filters out users without nickname by default" do +      insert(:user, %{nickname: nil}) + +      assert [_user] = User |> Repo.all() +      assert [] == %{} |> Query.build() |> Repo.all() +    end + +    test "it returns internal users when enabled" do +      %User{nickname: "internal.fetch"} = InternalFetchActor.get_actor() +      insert(:user, %{nickname: nil}) + +      assert %{internal: true} |> Query.build() |> Repo.aggregate(:count) == 2 +    end +  end +end diff --git a/test/user_search_test.exs b/test/user_search_test.exs index 01976bf58..c4b805005 100644 --- a/test/user_search_test.exs +++ b/test/user_search_test.exs @@ -17,6 +17,46 @@ defmodule Pleroma.UserSearchTest do    describe "User.search" do      setup do: clear_config([:instance, :limit_to_local_content]) +    test "returns a resolved user as the first result" do +      Pleroma.Config.put([:instance, :limit_to_local_content], false) +      user = insert(:user, %{nickname: "no_relation", ap_id: "https://lain.com/users/lain"}) +      _user = insert(:user, %{nickname: "com_user"}) + +      [first_user, _second_user] = User.search("https://lain.com/users/lain", resolve: true) + +      assert first_user.id == user.id +    end + +    test "returns a user with matching ap_id as the first result" do +      user = insert(:user, %{nickname: "no_relation", ap_id: "https://lain.com/users/lain"}) +      _user = insert(:user, %{nickname: "com_user"}) + +      [first_user, _second_user] = User.search("https://lain.com/users/lain") + +      assert first_user.id == user.id +    end + +    test "doesn't die if two users have the same uri" do +      insert(:user, %{uri: "https://gensokyo.2hu/@raymoo"}) +      insert(:user, %{uri: "https://gensokyo.2hu/@raymoo"}) +      assert [_first_user, _second_user] = User.search("https://gensokyo.2hu/@raymoo") +    end + +    test "returns a user with matching uri as the first result" do +      user = +        insert(:user, %{ +          nickname: "no_relation", +          ap_id: "https://lain.com/users/lain", +          uri: "https://lain.com/@lain" +        }) + +      _user = insert(:user, %{nickname: "com_user"}) + +      [first_user, _second_user] = User.search("https://lain.com/@lain") + +      assert first_user.id == user.id +    end +      test "excludes invisible users from results" do        user = insert(:user, %{nickname: "john t1000"})        insert(:user, %{invisible: true, nickname: "john t800"}) @@ -25,6 +65,14 @@ defmodule Pleroma.UserSearchTest do        assert found_user.id == user.id      end +    test "excludes users when discoverable is false" do +      insert(:user, %{nickname: "john 3000", discoverable: false}) +      insert(:user, %{nickname: "john 3001"}) + +      users = User.search("john") +      assert Enum.count(users) == 1 +    end +      test "excludes service actors from results" do        insert(:user, actor_type: "Application", nickname: "user1")        service = insert(:user, actor_type: "Service", nickname: "user2") diff --git a/test/user_test.exs b/test/user_test.exs index 50f72549e..d506f7047 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -440,6 +440,45 @@ defmodule Pleroma.UserTest do        assert activity.actor == welcome_user.ap_id      end +    setup do: +            clear_config(:mrf_simple, +              media_removal: [], +              media_nsfw: [], +              federated_timeline_removal: [], +              report_removal: [], +              reject: [], +              followers_only: [], +              accept: [], +              avatar_removal: [], +              banner_removal: [], +              reject_deletes: [] +            ) + +    setup do: +            clear_config(:mrf, +              policies: [ +                Pleroma.Web.ActivityPub.MRF.SimplePolicy +              ] +            ) + +    test "it sends a welcome chat message when Simple policy applied to local instance" do +      Pleroma.Config.put([:mrf_simple, :media_nsfw], ["localhost"]) + +      welcome_user = insert(:user) +      Pleroma.Config.put([:welcome, :chat_message, :enabled], true) +      Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname) +      Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message") + +      cng = User.register_changeset(%User{}, @full_user_data) +      {:ok, registered_user} = User.register(cng) +      ObanHelpers.perform_all() + +      activity = Repo.one(Pleroma.Activity) +      assert registered_user.ap_id in activity.recipients +      assert Object.normalize(activity).data["content"] =~ "chat message" +      assert activity.actor == welcome_user.ap_id +    end +      test "it sends a welcome email message if it is set" do        welcome_user = insert(:user)        Pleroma.Config.put([:welcome, :email, :enabled], true) @@ -470,7 +509,12 @@ defmodule Pleroma.UserTest do        cng = User.register_changeset(%User{}, @full_user_data)        {:ok, registered_user} = User.register(cng)        ObanHelpers.perform_all() -      assert_email_sent(Pleroma.Emails.UserEmail.account_confirmation_email(registered_user)) + +      Pleroma.Emails.UserEmail.account_confirmation_email(registered_user) +      # temporary hackney fix until hackney max_connections bug is fixed +      # https://git.pleroma.social/pleroma/pleroma/-/issues/2101 +      |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]]) +      |> assert_email_sent()      end      test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do @@ -932,23 +976,6 @@ defmodule Pleroma.UserTest do      end    end -  describe "follow_import" do -    test "it imports user followings from list" do -      [user1, user2, user3] = insert_list(3, :user) - -      identifiers = [ -        user2.ap_id, -        user3.nickname -      ] - -      {:ok, job} = User.follow_import(user1, identifiers) - -      assert {:ok, result} = ObanHelpers.perform(job) -      assert is_list(result) -      assert result == [user2, user3] -    end -  end -    describe "mutes" do      test "it mutes people" do        user = insert(:user) @@ -1155,23 +1182,6 @@ defmodule Pleroma.UserTest do      end    end -  describe "blocks_import" do -    test "it imports user blocks from list" do -      [user1, user2, user3] = insert_list(3, :user) - -      identifiers = [ -        user2.ap_id, -        user3.nickname -      ] - -      {:ok, job} = User.blocks_import(user1, identifiers) - -      assert {:ok, result} = ObanHelpers.perform(job) -      assert is_list(result) -      assert result == [user2, user3] -    end -  end -    describe "get_recipients_from_activity" do      test "works for announces" do        actor = insert(:user) @@ -1637,7 +1647,7 @@ defmodule Pleroma.UserTest do        assert User.visible_for(user, user) == :visible      end -    test "returns false when the account is unauthenticated and auth is required" do +    test "returns false when the account is unconfirmed and confirmation is required" do        Pleroma.Config.put([:instance, :account_activation_required], true)        user = insert(:user, local: true, confirmation_pending: true) @@ -1646,14 +1656,23 @@ defmodule Pleroma.UserTest do        refute User.visible_for(user, other_user) == :visible      end -    test "returns true when the account is unauthenticated and auth is not required" do +    test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do +      Pleroma.Config.put([:instance, :account_activation_required], true) + +      user = insert(:user, local: false, confirmation_pending: true) +      other_user = insert(:user, local: true) + +      assert User.visible_for(user, other_user) == :visible +    end + +    test "returns true when the account is unconfirmed and confirmation is not required" do        user = insert(:user, local: true, confirmation_pending: true)        other_user = insert(:user, local: true)        assert User.visible_for(user, other_user) == :visible      end -    test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do +    test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do        Pleroma.Config.put([:instance, :account_activation_required], true)        user = insert(:user, local: true, confirmation_pending: true) diff --git a/test/utils_test.exs b/test/utils_test.exs new file mode 100644 index 000000000..460f7e0b5 --- /dev/null +++ b/test/utils_test.exs @@ -0,0 +1,15 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.UtilsTest do +  use ExUnit.Case, async: true + +  describe "tmp_dir/1" do +    test "returns unique temporary directory" do +      {:ok, path} = Pleroma.Utils.tmp_dir("emoji") +      assert path =~ ~r/\/emoji-(.*)-#{:os.getpid()}-(.*)/ +      File.rm_rf(path) +    end +  end +end diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index d8caa0b00..804305a13 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -1810,6 +1810,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do          |> Enum.map(& &1.id)        assert activities_ids == [] + +      activities_ids = +        %{} +        |> Map.put(:reply_visibility, "self") +        |> Map.put(:reply_filtering_user, nil) +        |> ActivityPub.fetch_public_activities() + +      assert activities_ids == []      end      test "home timeline", %{users: %{u1: user}} do @@ -2169,4 +2177,84 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert user.nickname == orig_user.nickname      end    end + +  describe "reply filtering" do +    test "`following` still contains announcements by friends" do +      user = insert(:user) +      followed = insert(:user) +      not_followed = insert(:user) + +      User.follow(user, followed) + +      {:ok, followed_post} = CommonAPI.post(followed, %{status: "Hello"}) + +      {:ok, not_followed_to_followed} = +        CommonAPI.post(not_followed, %{ +          status: "Also hello", +          in_reply_to_status_id: followed_post.id +        }) + +      {:ok, retoot} = CommonAPI.repeat(not_followed_to_followed.id, followed) + +      params = +        %{} +        |> Map.put(:type, ["Create", "Announce"]) +        |> Map.put(:blocking_user, user) +        |> Map.put(:muting_user, user) +        |> Map.put(:reply_filtering_user, user) +        |> Map.put(:reply_visibility, "following") +        |> Map.put(:announce_filtering_user, user) +        |> Map.put(:user, user) + +      activities = +        [user.ap_id | User.following(user)] +        |> ActivityPub.fetch_activities(params) + +      followed_post_id = followed_post.id +      retoot_id = retoot.id + +      assert [%{id: ^followed_post_id}, %{id: ^retoot_id}] = activities + +      assert length(activities) == 2 +    end + +    # This test is skipped because, while this is the desired behavior, +    # there seems to be no good way to achieve it with the method that +    # we currently use for detecting to who a reply is directed. +    # This is a TODO and should be fixed by a later rewrite of the code +    # in question. +    @tag skip: true +    test "`following` still contains self-replies by friends" do +      user = insert(:user) +      followed = insert(:user) +      not_followed = insert(:user) + +      User.follow(user, followed) + +      {:ok, followed_post} = CommonAPI.post(followed, %{status: "Hello"}) +      {:ok, not_followed_post} = CommonAPI.post(not_followed, %{status: "Also hello"}) + +      {:ok, _followed_to_not_followed} = +        CommonAPI.post(followed, %{status: "sup", in_reply_to_status_id: not_followed_post.id}) + +      {:ok, _followed_self_reply} = +        CommonAPI.post(followed, %{status: "Also cofe", in_reply_to_status_id: followed_post.id}) + +      params = +        %{} +        |> Map.put(:type, ["Create", "Announce"]) +        |> Map.put(:blocking_user, user) +        |> Map.put(:muting_user, user) +        |> Map.put(:reply_filtering_user, user) +        |> Map.put(:reply_visibility, "following") +        |> Map.put(:announce_filtering_user, user) +        |> Map.put(:user, user) + +      activities = +        [user.ap_id | User.following(user)] +        |> ActivityPub.fetch_activities(params) + +      assert length(activities) == 2 +    end +  end  end diff --git a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs b/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs index 313d59a66..1710c4d2a 100644 --- a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs +++ b/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs @@ -22,6 +22,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do      }    } +  setup do: clear_config([:media_proxy, :enabled], true) +    test "it prefetches media proxy URIs" do      with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do        MediaProxyWarmingPolicy.filter(@message) diff --git a/test/web/activity_pub/mrf/mrf_test.exs b/test/web/activity_pub/mrf/mrf_test.exs index a63b25423..e82c8afa6 100644 --- a/test/web/activity_pub/mrf/mrf_test.exs +++ b/test/web/activity_pub/mrf/mrf_test.exs @@ -61,6 +61,8 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do    describe "describe/0" do      test "it works as expected with noop policy" do +      clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.NoOpPolicy]) +        expected = %{          mrf_policies: ["NoOpPolicy"],          exclusions: false diff --git a/test/web/activity_pub/object_validators/note_validator_test.exs b/test/web/activity_pub/object_validators/article_note_validator_test.exs index 30c481ffb..cc6dab872 100644 --- a/test/web/activity_pub/object_validators/note_validator_test.exs +++ b/test/web/activity_pub/object_validators/article_note_validator_test.exs @@ -2,10 +2,10 @@  # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only -defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidatorTest do +defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidatorTest do    use Pleroma.DataCase -  alias Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator +  alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator    alias Pleroma.Web.ActivityPub.Utils    import Pleroma.Factory @@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidatorTest do      end      test "a basic note validates", %{note: note} do -      %{valid?: true} = NoteValidator.cast_and_validate(note) +      %{valid?: true} = ArticleNoteValidator.cast_and_validate(note)      end    end  end diff --git a/test/web/activity_pub/pipeline_test.exs b/test/web/activity_pub/pipeline_test.exs index f2a231eaf..210a06563 100644 --- a/test/web/activity_pub/pipeline_test.exs +++ b/test/web/activity_pub/pipeline_test.exs @@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do          {            Pleroma.Web.ActivityPub.MRF,            [], -          [filter: fn o -> {:ok, o} end] +          [pipeline_filter: fn o, m -> {:ok, o, m} end]          },          {            Pleroma.Web.ActivityPub.ActivityPub, @@ -51,7 +51,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do                   Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)          assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) -        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))          assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))          assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))          refute called(Pleroma.Web.Federator.publish(activity)) @@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do          {            Pleroma.Web.ActivityPub.MRF,            [], -          [filter: fn o -> {:ok, o} end] +          [pipeline_filter: fn o, m -> {:ok, o, m} end]          },          {            Pleroma.Web.ActivityPub.ActivityPub, @@ -93,7 +93,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do                   Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)          assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) -        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))          assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))          assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))          assert_called(Pleroma.Web.Federator.publish(activity)) @@ -109,7 +109,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do          {            Pleroma.Web.ActivityPub.MRF,            [], -          [filter: fn o -> {:ok, o} end] +          [pipeline_filter: fn o, m -> {:ok, o, m} end]          },          {            Pleroma.Web.ActivityPub.ActivityPub, @@ -131,7 +131,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do                   Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)          assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) -        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))          assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))          assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))        end @@ -148,7 +148,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do          {            Pleroma.Web.ActivityPub.MRF,            [], -          [filter: fn o -> {:ok, o} end] +          [pipeline_filter: fn o, m -> {:ok, o, m} end]          },          {            Pleroma.Web.ActivityPub.ActivityPub, @@ -170,7 +170,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do                   Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)          assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) -        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))          assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))          assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))        end diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs index 9d657ac4f..3284980f7 100644 --- a/test/web/activity_pub/relay_test.exs +++ b/test/web/activity_pub/relay_test.exs @@ -63,6 +63,46 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do        assert activity.data["to"] == [user.ap_id]        refute "#{user.ap_id}/followers" in User.following(service_actor)      end + +    test "force unfollow when target service is dead" do +      user = insert(:user) +      user_ap_id = user.ap_id +      user_id = user.id + +      Tesla.Mock.mock(fn %{method: :get, url: ^user_ap_id} -> +        %Tesla.Env{status: 404} +      end) + +      service_actor = Relay.get_actor() +      CommonAPI.follow(service_actor, user) +      assert "#{user.ap_id}/followers" in User.following(service_actor) + +      assert Pleroma.Repo.get_by( +               Pleroma.FollowingRelationship, +               follower_id: service_actor.id, +               following_id: user_id +             ) + +      Pleroma.Repo.delete(user) +      Cachex.clear(:user_cache) + +      assert {:ok, %Activity{} = activity} = Relay.unfollow(user_ap_id, %{force: true}) + +      assert refresh_record(service_actor).following_count == 0 + +      refute Pleroma.Repo.get_by( +               Pleroma.FollowingRelationship, +               follower_id: service_actor.id, +               following_id: user_id +             ) + +      assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay" +      assert user.ap_id in activity.recipients +      assert activity.data["type"] == "Undo" +      assert activity.data["actor"] == service_actor.ap_id +      assert activity.data["to"] == [user_ap_id] +      refute "#{user.ap_id}/followers" in User.following(service_actor) +    end    end    describe "publish/1" do diff --git a/test/web/activity_pub/transmogrifier/article_handling_test.exs b/test/web/activity_pub/transmogrifier/article_handling_test.exs new file mode 100644 index 000000000..9b12a470a --- /dev/null +++ b/test/web/activity_pub/transmogrifier/article_handling_test.exs @@ -0,0 +1,75 @@ +# 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.ArticleHandlingTest do +  use Oban.Testing, repo: Pleroma.Repo +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Object.Fetcher +  alias Pleroma.Web.ActivityPub.Transmogrifier + +  test "Pterotype (Wordpress Plugin) Article" do +    Tesla.Mock.mock(fn %{url: "https://wedistribute.org/wp-json/pterotype/v1/actor/-blog"} -> +      %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/wedistribute-user.json")} +    end) + +    data = +      File.read!("test/fixtures/tesla_mock/wedistribute-create-article.json") |> Jason.decode!() + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    object = Object.normalize(data["object"]) + +    assert object.data["name"] == "The end is near: Mastodon plans to drop OStatus support" + +    assert object.data["summary"] == +             "One of the largest platforms in the federated social web is dropping the protocol that it started with." + +    assert object.data["url"] == "https://wedistribute.org/2019/07/mastodon-drops-ostatus/" +  end + +  test "Plume Article" do +    Tesla.Mock.mock(fn +      %{url: "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"} -> +        %Tesla.Env{ +          status: 200, +          body: File.read!("test/fixtures/tesla_mock/baptiste.gelex.xyz-article.json") +        } + +      %{url: "https://baptiste.gelez.xyz/@/BaptisteGelez"} -> +        %Tesla.Env{ +          status: 200, +          body: File.read!("test/fixtures/tesla_mock/baptiste.gelex.xyz-user.json") +        } +    end) + +    {:ok, object} = +      Fetcher.fetch_object_from_id( +        "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" +      ) + +    assert object.data["name"] == "This Month in Plume: June 2018" + +    assert object.data["url"] == +             "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" +  end + +  test "Prismo Article" do +    Tesla.Mock.mock(fn %{url: "https://prismo.news/@mxb"} -> +      %Tesla.Env{ +        status: 200, +        body: File.read!("test/fixtures/tesla_mock/https___prismo.news__mxb.json") +      } +    end) + +    data = File.read!("test/fixtures/prismo-url-map.json") |> Jason.decode!() + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) +    object = Object.normalize(data["object"]) + +    assert object.data["url"] == "https://prismo.news/posts/83" +  end +end diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs index 74ee79543..d2822ce75 100644 --- a/test/web/activity_pub/transmogrifier/question_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/question_handling_test.exs @@ -157,12 +157,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do             }    end -  test "returns an error if received a second time" do +  test "returns same activity if received a second time" do      data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!()      assert {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) -    assert {:error, {:validate_object, {:error, _}}} = Transmogrifier.handle_incoming(data) +    assert {:ok, ^activity} = Transmogrifier.handle_incoming(data)    end    test "accepts a Question with no content" do diff --git a/test/web/activity_pub/transmogrifier/video_handling_test.exs b/test/web/activity_pub/transmogrifier/video_handling_test.exs new file mode 100644 index 000000000..69c953a2e --- /dev/null +++ b/test/web/activity_pub/transmogrifier/video_handling_test.exs @@ -0,0 +1,93 @@ +# 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.VideoHandlingTest do +  use Oban.Testing, repo: Pleroma.Repo +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Object.Fetcher +  alias Pleroma.Web.ActivityPub.Transmogrifier + +  setup_all do +    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  test "skip converting the content when it is nil" do +    data = +      File.read!("test/fixtures/tesla_mock/framatube.org-video.json") +      |> Jason.decode!() +      |> Kernel.put_in(["object", "content"], nil) + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    assert object = Object.normalize(activity, false) + +    assert object.data["content"] == nil +  end + +  test "it converts content of object to html" do +    data = File.read!("test/fixtures/tesla_mock/framatube.org-video.json") |> Jason.decode!() + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    assert object = Object.normalize(activity, false) + +    assert object.data["content"] == +             "<p>Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?</p><p>Transcription par @aprilorg ici : <a href=\"https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft\">https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft</a></p>" +  end + +  test "it remaps video URLs as attachments if necessary" do +    {:ok, object} = +      Fetcher.fetch_object_from_id( +        "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" +      ) + +    assert object.data["url"] == +             "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" + +    assert object.data["attachment"] == [ +             %{ +               "type" => "Link", +               "mediaType" => "video/mp4", +               "name" => nil, +               "url" => [ +                 %{ +                   "href" => +                     "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", +                   "mediaType" => "video/mp4", +                   "type" => "Link" +                 } +               ] +             } +           ] + +    data = File.read!("test/fixtures/tesla_mock/framatube.org-video.json") |> Jason.decode!() + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    assert object = Object.normalize(activity, false) + +    assert object.data["attachment"] == [ +             %{ +               "type" => "Link", +               "mediaType" => "video/mp4", +               "name" => nil, +               "url" => [ +                 %{ +                   "href" => +                     "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", +                   "mediaType" => "video/mp4", +                   "type" => "Link" +                 } +               ] +             } +           ] + +    assert object.data["url"] == +             "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" +  end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index cc55a7be7..561674f01 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do    alias Pleroma.Activity    alias Pleroma.Object -  alias Pleroma.Object.Fetcher    alias Pleroma.Tests.ObanHelpers    alias Pleroma.User    alias Pleroma.Web.ActivityPub.Transmogrifier @@ -45,15 +44,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert "test" in object.data["tag"]      end -    test "it works for incoming notices with url not being a string (prismo)" do -      data = File.read!("test/fixtures/prismo-url-map.json") |> Poison.decode!() - -      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) -      object = Object.normalize(data["object"]) - -      assert object.data["url"] == "https://prismo.news/posts/83" -    end -      test "it cleans up incoming notices which are not really DMs" do        user = insert(:user)        other_user = insert(:user) @@ -355,83 +345,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)      end -    test "skip converting the content when it is nil" do -      object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe" - -      {:ok, object} = Fetcher.fetch_and_contain_remote_object_from_id(object_id) - -      result = -        Pleroma.Web.ActivityPub.Transmogrifier.fix_object(Map.merge(object, %{"content" => nil})) - -      assert result["content"] == nil -    end - -    test "it converts content of object to html" do -      object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe" - -      {:ok, %{"content" => content_markdown}} = -        Fetcher.fetch_and_contain_remote_object_from_id(object_id) - -      {:ok, %Pleroma.Object{data: %{"content" => content}} = object} = -        Fetcher.fetch_object_from_id(object_id) - -      assert content_markdown == -               "Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership\n\nTwenty Years in Jail: FreeBSD's Jails, Then and Now\n\nJails started as a limited virtualization system, but over the last two years they've..." - -      assert content == -               "<p>Support this and our other Michigan!/usr/group videos and meetings. Learn more at <a href=\"http://mug.org/membership\">http://mug.org/membership</a></p><p>Twenty Years in Jail: FreeBSD’s Jails, Then and Now</p><p>Jails started as a limited virtualization system, but over the last two years they’ve…</p>" - -      assert object.data["mediaType"] == "text/html" -    end - -    test "it remaps video URLs as attachments if necessary" do -      {:ok, object} = -        Fetcher.fetch_object_from_id( -          "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" -        ) - -      assert object.data["url"] == -               "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" - -      assert object.data["attachment"] == [ -               %{ -                 "type" => "Link", -                 "mediaType" => "video/mp4", -                 "url" => [ -                   %{ -                     "href" => -                       "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", -                     "mediaType" => "video/mp4", -                     "type" => "Link" -                   } -                 ] -               } -             ] - -      {:ok, object} = -        Fetcher.fetch_object_from_id( -          "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" -        ) - -      assert object.data["attachment"] == [ -               %{ -                 "type" => "Link", -                 "mediaType" => "video/mp4", -                 "url" => [ -                   %{ -                     "href" => -                       "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", -                     "mediaType" => "video/mp4", -                     "type" => "Link" -                   } -                 ] -               } -             ] - -      assert object.data["url"] == -               "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" -    end -      test "it accepts Flag activities" do        user = insert(:user)        other_user = insert(:user) @@ -1133,75 +1046,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do               }      end -    test "fixes data for video object" do -      object = %{ -        "type" => "Video", -        "url" => [ -          %{ -            "type" => "Link", -            "mimeType" => "video/mp4", -            "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4" -          }, -          %{ -            "type" => "Link", -            "mimeType" => "video/mp4", -            "href" => "https://peertube46fb-ad81-2d4c2d1630e3-240.mp4" -          }, -          %{ -            "type" => "Link", -            "mimeType" => "text/html", -            "href" => "https://peertube.-2d4c2d1630e3" -          }, -          %{ -            "type" => "Link", -            "mimeType" => "text/html", -            "href" => "https://peertube.-2d4c2d16377-42" -          } -        ] -      } - -      assert Transmogrifier.fix_url(object) == %{ -               "attachment" => [ -                 %{ -                   "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4", -                   "mimeType" => "video/mp4", -                   "type" => "Link" -                 } -               ], -               "type" => "Video", -               "url" => "https://peertube.-2d4c2d1630e3" -             } -    end - -    test "fixes url for not Video object" do -      object = %{ -        "type" => "Text", -        "url" => [ -          %{ -            "type" => "Link", -            "mimeType" => "text/html", -            "href" => "https://peertube.-2d4c2d1630e3" -          }, -          %{ -            "type" => "Link", -            "mimeType" => "text/html", -            "href" => "https://peertube.-2d4c2d16377-42" -          } -        ] -      } - -      assert Transmogrifier.fix_url(object) == %{ -               "type" => "Text", -               "url" => "https://peertube.-2d4c2d1630e3" -             } - -      assert Transmogrifier.fix_url(%{"type" => "Text", "url" => []}) == %{ -               "type" => "Text", -               "url" => "" -             } -    end - -    test "retunrs not modified object" do +    test "returns non-modified object" do        assert Transmogrifier.fix_url(%{"type" => "Text"}) == %{"type" => "Text"}      end    end diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index 3bc88c6a9..cba6b43d3 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -1510,6 +1510,56 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end +  describe "GET /api/pleroma/admin/users/:nickname/chats" do +    setup do +      user = insert(:user) +      recipients = insert_list(3, :user) + +      Enum.each(recipients, fn recipient -> +        CommonAPI.post_chat_message(user, recipient, "yo") +      end) + +      %{user: user} +    end + +    test "renders user's chats", %{conn: conn, user: user} do +      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/chats") + +      assert json_response(conn, 200) |> length() == 3 +    end +  end + +  describe "GET /api/pleroma/admin/users/:nickname/chats unauthorized" do +    setup do +      user = insert(:user) +      recipient = insert(:user) +      CommonAPI.post_chat_message(user, recipient, "yo") +      %{conn: conn} = oauth_access(["read:chats"]) +      %{conn: conn, user: user} +    end + +    test "returns 403", %{conn: conn, user: user} do +      conn +      |> get("/api/pleroma/admin/users/#{user.nickname}/chats") +      |> json_response(403) +    end +  end + +  describe "GET /api/pleroma/admin/users/:nickname/chats unauthenticated" do +    setup do +      user = insert(:user) +      recipient = insert(:user) +      CommonAPI.post_chat_message(user, recipient, "yo") +      %{conn: build_conn(), user: user} +    end + +    test "returns 403", %{conn: conn, user: user} do +      conn +      |> get("/api/pleroma/admin/users/#{user.nickname}/chats") +      |> json_response(403) +    end +  end +    describe "GET /api/pleroma/admin/moderation_log" do      setup do        moderator = insert(:user, is_moderator: true) @@ -1927,7 +1977,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 }"        ObanHelpers.perform_all() -      assert_email_sent(Pleroma.Emails.UserEmail.account_confirmation_email(first_user)) + +      Pleroma.Emails.UserEmail.account_confirmation_email(first_user) +      # temporary hackney fix until hackney max_connections bug is fixed +      # https://git.pleroma.social/pleroma/pleroma/-/issues/2101 +      |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]]) +      |> assert_email_sent()      end    end diff --git a/test/web/admin_api/controllers/chat_controller_test.exs b/test/web/admin_api/controllers/chat_controller_test.exs new file mode 100644 index 000000000..bd4c9c9d1 --- /dev/null +++ b/test/web/admin_api/controllers/chat_controller_test.exs @@ -0,0 +1,219 @@ +# 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.ChatControllerTest do +  use Pleroma.Web.ConnCase + +  import Pleroma.Factory + +  alias Pleroma.Chat +  alias Pleroma.Chat.MessageReference +  alias Pleroma.Config +  alias Pleroma.ModerationLog +  alias Pleroma.Object +  alias Pleroma.Repo +  alias Pleroma.Web.CommonAPI + +  defp admin_setup do +    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 "DELETE /api/pleroma/admin/chats/:id/messages/:message_id" do +    setup do: admin_setup() + +    test "it deletes a message from the chat", %{conn: conn, admin: admin} do +      user = insert(:user) +      recipient = insert(:user) + +      {:ok, message} = +        CommonAPI.post_chat_message(user, recipient, "Hello darkness my old friend") + +      object = Object.normalize(message, false) + +      chat = Chat.get(user.id, recipient.ap_id) +      recipient_chat = Chat.get(recipient.id, user.ap_id) + +      cm_ref = MessageReference.for_chat_and_object(chat, object) +      recipient_cm_ref = MessageReference.for_chat_and_object(recipient_chat, object) + +      result = +        conn +        |> put_req_header("content-type", "application/json") +        |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") +        |> json_response_and_validate_schema(200) + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} deleted chat message ##{cm_ref.id}" + +      assert result["id"] == cm_ref.id +      refute MessageReference.get_by_id(cm_ref.id) +      refute MessageReference.get_by_id(recipient_cm_ref.id) +      assert %{data: %{"type" => "Tombstone"}} = Object.get_by_id(object.id) +    end +  end + +  describe "GET /api/pleroma/admin/chats/:id/messages" do +    setup do: admin_setup() + +    test "it paginates", %{conn: conn} do +      user = insert(:user) +      recipient = insert(:user) + +      Enum.each(1..30, fn _ -> +        {:ok, _} = CommonAPI.post_chat_message(user, recipient, "hey") +      end) + +      chat = Chat.get(user.id, recipient.ap_id) + +      result = +        conn +        |> get("/api/pleroma/admin/chats/#{chat.id}/messages") +        |> json_response_and_validate_schema(200) + +      assert length(result) == 20 + +      result = +        conn +        |> get("/api/pleroma/admin/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}") +        |> json_response_and_validate_schema(200) + +      assert length(result) == 10 +    end + +    test "it returns the messages for a given chat", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) +      third_user = insert(:user) + +      {:ok, _} = CommonAPI.post_chat_message(user, other_user, "hey") +      {:ok, _} = CommonAPI.post_chat_message(user, third_user, "hey") +      {:ok, _} = CommonAPI.post_chat_message(user, other_user, "how are you?") +      {:ok, _} = CommonAPI.post_chat_message(other_user, user, "fine, how about you?") + +      chat = Chat.get(user.id, other_user.ap_id) + +      result = +        conn +        |> get("/api/pleroma/admin/chats/#{chat.id}/messages") +        |> json_response_and_validate_schema(200) + +      result +      |> Enum.each(fn message -> +        assert message["chat_id"] == chat.id |> to_string() +      end) + +      assert length(result) == 3 +    end +  end + +  describe "GET /api/pleroma/admin/chats/:id" do +    setup do: admin_setup() + +    test "it returns a chat", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + +      result = +        conn +        |> get("/api/pleroma/admin/chats/#{chat.id}") +        |> json_response_and_validate_schema(200) + +      assert result["id"] == to_string(chat.id) +      assert %{} = result["sender"] +      assert %{} = result["receiver"] +      refute result["account"] +    end +  end + +  describe "unauthorized chat moderation" do +    setup do +      user = insert(:user) +      recipient = insert(:user) + +      {:ok, message} = CommonAPI.post_chat_message(user, recipient, "Yo") +      object = Object.normalize(message, false) +      chat = Chat.get(user.id, recipient.ap_id) +      cm_ref = MessageReference.for_chat_and_object(chat, object) + +      %{conn: conn} = oauth_access(["read:chats", "write:chats"]) +      %{conn: conn, chat: chat, cm_ref: cm_ref} +    end + +    test "DELETE /api/pleroma/admin/chats/:id/messages/:message_id", %{ +      conn: conn, +      chat: chat, +      cm_ref: cm_ref +    } do +      conn +      |> put_req_header("content-type", "application/json") +      |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") +      |> json_response(403) + +      assert MessageReference.get_by_id(cm_ref.id) == cm_ref +    end + +    test "GET /api/pleroma/admin/chats/:id/messages", %{conn: conn, chat: chat} do +      conn +      |> get("/api/pleroma/admin/chats/#{chat.id}/messages") +      |> json_response(403) +    end + +    test "GET /api/pleroma/admin/chats/:id", %{conn: conn, chat: chat} do +      conn +      |> get("/api/pleroma/admin/chats/#{chat.id}") +      |> json_response(403) +    end +  end + +  describe "unauthenticated chat moderation" do +    setup do +      user = insert(:user) +      recipient = insert(:user) + +      {:ok, message} = CommonAPI.post_chat_message(user, recipient, "Yo") +      object = Object.normalize(message, false) +      chat = Chat.get(user.id, recipient.ap_id) +      cm_ref = MessageReference.for_chat_and_object(chat, object) + +      %{conn: build_conn(), chat: chat, cm_ref: cm_ref} +    end + +    test "DELETE /api/pleroma/admin/chats/:id/messages/:message_id", %{ +      conn: conn, +      chat: chat, +      cm_ref: cm_ref +    } do +      conn +      |> put_req_header("content-type", "application/json") +      |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") +      |> json_response(403) + +      assert MessageReference.get_by_id(cm_ref.id) == cm_ref +    end + +    test "GET /api/pleroma/admin/chats/:id/messages", %{conn: conn, chat: chat} do +      conn +      |> get("/api/pleroma/admin/chats/#{chat.id}/messages") +      |> json_response(403) +    end + +    test "GET /api/pleroma/admin/chats/:id", %{conn: conn, chat: chat} do +      conn +      |> get("/api/pleroma/admin/chats/#{chat.id}") +      |> json_response(403) +    end +  end +end diff --git a/test/web/admin_api/controllers/instance_document_controller_test.exs b/test/web/admin_api/controllers/instance_document_controller_test.exs new file mode 100644 index 000000000..5f7b042f6 --- /dev/null +++ b/test/web/admin_api/controllers/instance_document_controller_test.exs @@ -0,0 +1,106 @@ +# 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.InstanceDocumentControllerTest do +  use Pleroma.Web.ConnCase, async: true +  import Pleroma.Factory +  alias Pleroma.Config + +  @dir "test/tmp/instance_static" +  @default_instance_panel ~s(<p>Welcome to <a href="https://pleroma.social" target="_blank">Pleroma!</a></p>) + +  setup do +    File.mkdir_p!(@dir) +    on_exit(fn -> File.rm_rf(@dir) end) +  end + +  setup do: clear_config([:instance, :static_dir], @dir) + +  setup do +    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/instance_document/:name" do +    test "return the instance document url", %{conn: conn} do +      conn = get(conn, "/api/pleroma/admin/instance_document/instance-panel") + +      assert content = html_response(conn, 200) +      assert String.contains?(content, @default_instance_panel) +    end + +    test "it returns 403 if requested by a non-admin" do +      non_admin_user = insert(:user) +      token = insert(:oauth_token, user: non_admin_user) + +      conn = +        build_conn() +        |> assign(:user, non_admin_user) +        |> assign(:token, token) +        |> get("/api/pleroma/admin/instance_document/instance-panel") + +      assert json_response(conn, :forbidden) +    end + +    test "it returns 404 if the instance document with the given name doesn't exist", %{ +      conn: conn +    } do +      conn = get(conn, "/api/pleroma/admin/instance_document/1234") + +      assert json_response_and_validate_schema(conn, 404) +    end +  end + +  describe "PATCH /api/pleroma/admin/instance_document/:name" do +    test "uploads the instance document", %{conn: conn} do +      image = %Plug.Upload{ +        content_type: "text/html", +        path: Path.absname("test/fixtures/custom_instance_panel.html"), +        filename: "custom_instance_panel.html" +      } + +      conn = +        conn +        |> put_req_header("content-type", "multipart/form-data") +        |> patch("/api/pleroma/admin/instance_document/instance-panel", %{ +          "file" => image +        }) + +      assert %{"url" => url} = json_response_and_validate_schema(conn, 200) +      index = get(build_conn(), url) +      assert html_response(index, 200) == "<h2>Custom instance panel</h2>" +    end +  end + +  describe "DELETE /api/pleroma/admin/instance_document/:name" do +    test "deletes the instance document", %{conn: conn} do +      File.mkdir!(@dir <> "/instance/") +      File.write!(@dir <> "/instance/panel.html", "Custom instance panel") + +      conn_resp = +        conn +        |> get("/api/pleroma/admin/instance_document/instance-panel") + +      assert html_response(conn_resp, 200) == "Custom instance panel" + +      conn +      |> delete("/api/pleroma/admin/instance_document/instance-panel") +      |> json_response_and_validate_schema(200) + +      conn_resp = +        conn +        |> get("/api/pleroma/admin/instance_document/instance-panel") + +      assert content = html_response(conn_resp, 200) +      assert String.contains?(content, @default_instance_panel) +    end +  end +end diff --git a/test/web/admin_api/search_test.exs b/test/web/admin_api/search_test.exs index b974cedd5..d88867c52 100644 --- a/test/web/admin_api/search_test.exs +++ b/test/web/admin_api/search_test.exs @@ -177,5 +177,14 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do        assert total == 3        assert count == 1      end + +    test "it returns non-discoverable users" do +      insert(:user) +      insert(:user, discoverable: false) + +      {:ok, _results, total} = Search.user() + +      assert total == 2 +    end    end  end diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index 5afb0a6dc..e34f5a49b 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -29,6 +29,23 @@ defmodule Pleroma.Web.CommonAPITest do    setup do: clear_config([:instance, :limit])    setup do: clear_config([:instance, :max_pinned_statuses]) +  describe "posting polls" do +    test "it posts a poll" do +      user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{ +          status: "who is the best", +          poll: %{expires_in: 600, options: ["reimu", "marisa"]} +        }) + +      object = Object.normalize(activity) + +      assert object.data["type"] == "Question" +      assert object.data["oneOf"] |> length() == 2 +    end +  end +    describe "blocking" do      setup do        blocker = insert(:user) @@ -217,6 +234,17 @@ defmodule Pleroma.Web.CommonAPITest do        assert message == :content_too_long      end + +    test "it reject messages via MRF" do +      clear_config([:mrf_keyword, :reject], ["GNO"]) +      clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) + +      author = insert(:user) +      recipient = insert(:user) + +      assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} == +               CommonAPI.post_chat_message(author, recipient, "GNO/Linux") +    end    end    describe "unblocking" do @@ -1193,4 +1221,24 @@ defmodule Pleroma.Web.CommonAPITest do        assert Visibility.get_visibility(activity) == "private"      end    end + +  describe "get_user/1" do +    test "gets user by ap_id" do +      user = insert(:user) +      assert CommonAPI.get_user(user.ap_id) == user +    end + +    test "gets user by guessed nickname" do +      user = insert(:user, ap_id: "", nickname: "mario@mushroom.kingdom") +      assert CommonAPI.get_user("https://mushroom.kingdom/users/mario") == user +    end + +    test "fallback" do +      assert %User{ +               name: "", +               ap_id: "", +               nickname: "erroruser@example.com" +             } = CommonAPI.get_user("") +    end +  end  end diff --git a/test/web/fed_sockets/fed_registry_test.exs b/test/web/fed_sockets/fed_registry_test.exs new file mode 100644 index 000000000..19ac874d6 --- /dev/null +++ b/test/web/fed_sockets/fed_registry_test.exs @@ -0,0 +1,124 @@ +# 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/web/fed_sockets/fetch_registry_test.exs b/test/web/fed_sockets/fetch_registry_test.exs new file mode 100644 index 000000000..7bd2d995a --- /dev/null +++ b/test/web/fed_sockets/fetch_registry_test.exs @@ -0,0 +1,67 @@ +# 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/web/fed_sockets/socket_info_test.exs b/test/web/fed_sockets/socket_info_test.exs new file mode 100644 index 000000000..db3d6edcd --- /dev/null +++ b/test/web/fed_sockets/socket_info_test.exs @@ -0,0 +1,118 @@ +# 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/web/instances/instance_test.exs b/test/web/instances/instance_test.exs index dc6ace843..4f0805100 100644 --- a/test/web/instances/instance_test.exs +++ b/test/web/instances/instance_test.exs @@ -99,35 +99,54 @@ defmodule Pleroma.Instances.InstanceTest do      end    end -  test "Scrapes favicon URLs" do -    Tesla.Mock.mock(fn %{url: "https://favicon.example.org/"} -> -      %Tesla.Env{ -        status: 200, -        body: ~s[<html><head><link rel="icon" href="/favicon.png"></head></html>] -      } -    end) - -    assert "https://favicon.example.org/favicon.png" == -             Instance.get_or_update_favicon(URI.parse("https://favicon.example.org/")) -  end +  describe "get_or_update_favicon/1" do +    test "Scrapes favicon URLs" do +      Tesla.Mock.mock(fn %{url: "https://favicon.example.org/"} -> +        %Tesla.Env{ +          status: 200, +          body: ~s[<html><head><link rel="icon" href="/favicon.png"></head></html>] +        } +      end) + +      assert "https://favicon.example.org/favicon.png" == +               Instance.get_or_update_favicon(URI.parse("https://favicon.example.org/")) +    end -  test "Returns nil on too long favicon URLs" do -    long_favicon_url = -      "https://Lorem.ipsum.dolor.sit.amet/consecteturadipiscingelit/Praesentpharetrapurusutaliquamtempus/Mauriseulaoreetarcu/atfacilisisorci/Nullamporttitor/nequesedfeugiatmollis/dolormagnaefficiturlorem/nonpretiumsapienorcieurisus/Nullamveleratsem/Maecenassedaccumsanexnam/favicon.png" - -    Tesla.Mock.mock(fn %{url: "https://long-favicon.example.org/"} -> -      %Tesla.Env{ -        status: 200, -        body: ~s[<html><head><link rel="icon" href="] <> long_favicon_url <> ~s["></head></html>] -      } -    end) - -    assert capture_log(fn -> -             assert nil == -                      Instance.get_or_update_favicon( -                        URI.parse("https://long-favicon.example.org/") -                      ) -           end) =~ -             "Instance.get_or_update_favicon(\"long-favicon.example.org\") error: %Postgrex.Error{" +    test "Returns nil on too long favicon URLs" do +      long_favicon_url = +        "https://Lorem.ipsum.dolor.sit.amet/consecteturadipiscingelit/Praesentpharetrapurusutaliquamtempus/Mauriseulaoreetarcu/atfacilisisorci/Nullamporttitor/nequesedfeugiatmollis/dolormagnaefficiturlorem/nonpretiumsapienorcieurisus/Nullamveleratsem/Maecenassedaccumsanexnam/favicon.png" + +      Tesla.Mock.mock(fn %{url: "https://long-favicon.example.org/"} -> +        %Tesla.Env{ +          status: 200, +          body: +            ~s[<html><head><link rel="icon" href="] <> long_favicon_url <> ~s["></head></html>] +        } +      end) + +      assert capture_log(fn -> +               assert nil == +                        Instance.get_or_update_favicon( +                          URI.parse("https://long-favicon.example.org/") +                        ) +             end) =~ +               "Instance.get_or_update_favicon(\"long-favicon.example.org\") error: %Postgrex.Error{" +    end + +    test "Handles not getting a favicon URL properly" do +      Tesla.Mock.mock(fn %{url: "https://no-favicon.example.org/"} -> +        %Tesla.Env{ +          status: 200, +          body: ~s[<html><head><h1>I wil look down and whisper "GNO.."</h1></head></html>] +        } +      end) + +      refute capture_log(fn -> +               assert nil == +                        Instance.get_or_update_favicon( +                          URI.parse("https://no-favicon.example.org/") +                        ) +             end) =~ "Instance.scrape_favicon(\"https://no-favicon.example.org/\") error: " +    end    end  end diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index 17a1e7d66..f7f1369e4 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -1442,7 +1442,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do    describe "verify_credentials" do      test "verify_credentials" do        %{user: user, conn: conn} = oauth_access(["read:accounts"]) -      [notification | _] = insert_list(7, :notification, user: user) + +      [notification | _] = +        insert_list(7, :notification, user: user, activity: insert(:note_activity)) +        Pleroma.Notification.set_read_up_to(user, notification.id)        conn = get(conn, "/api/v1/accounts/verify_credentials") diff --git a/test/web/mastodon_api/controllers/auth_controller_test.exs b/test/web/mastodon_api/controllers/auth_controller_test.exs index 4fa95fce1..bf2438fe2 100644 --- a/test/web/mastodon_api/controllers/auth_controller_test.exs +++ b/test/web/mastodon_api/controllers/auth_controller_test.exs @@ -61,7 +61,7 @@ defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do      end      test "it returns 204", %{conn: conn} do -      assert json_response(conn, :no_content) +      assert empty_json_response(conn)      end      test "it creates a PasswordResetToken record for user", %{user: user} do @@ -91,7 +91,7 @@ defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do        assert conn               |> post("/auth/password?nickname=#{user.nickname}") -             |> json_response(:no_content) +             |> empty_json_response()        ObanHelpers.perform_all()        token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) @@ -112,7 +112,7 @@ defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do        assert conn               |> post("/auth/password?nickname=#{user.nickname}") -             |> json_response(:no_content) +             |> empty_json_response()      end    end @@ -125,24 +125,21 @@ defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do      test "it returns 204 when user is not found", %{conn: conn, user: user} do        conn = post(conn, "/auth/password?email=nonexisting_#{user.email}") -      assert conn -             |> json_response(:no_content) +      assert empty_json_response(conn)      end      test "it returns 204 when user is not local", %{conn: conn, user: user} do        {:ok, user} = Repo.update(Ecto.Changeset.change(user, local: false))        conn = post(conn, "/auth/password?email=#{user.email}") -      assert conn -             |> json_response(:no_content) +      assert empty_json_response(conn)      end      test "it returns 204 when user is deactivated", %{conn: conn, user: user} do        {:ok, user} = Repo.update(Ecto.Changeset.change(user, deactivated: true, local: true))        conn = post(conn, "/auth/password?email=#{user.email}") -      assert conn -             |> json_response(:no_content) +      assert empty_json_response(conn)      end    end diff --git a/test/web/mastodon_api/controllers/marker_controller_test.exs b/test/web/mastodon_api/controllers/marker_controller_test.exs index 6dd40fb4a..9f0481120 100644 --- a/test/web/mastodon_api/controllers/marker_controller_test.exs +++ b/test/web/mastodon_api/controllers/marker_controller_test.exs @@ -11,7 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do      test "gets markers with correct scopes", %{conn: conn} do        user = insert(:user)        token = insert(:oauth_token, user: user, scopes: ["read:statuses"]) -      insert_list(7, :notification, user: user) +      insert_list(7, :notification, user: user, activity: insert(:note_activity))        {:ok, %{"notifications" => marker}} =          Pleroma.Marker.upsert( diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs index 517cabcff..c6e0268fd 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -114,8 +114,16 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do        {:ok, _reply_from_friend} =          CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee}) -      res_conn = get(conn, "/api/v1/timelines/public") -      [%{"id" => ^activity_id}] = json_response_and_validate_schema(res_conn, 200) +      # Still shows replies from yourself +      {:ok, %{id: reply_from_me}} = +        CommonAPI.post(blocker, %{status: "status", in_reply_to_status_id: reply_from_blockee}) + +      response = +        get(conn, "/api/v1/timelines/public") +        |> json_response_and_validate_schema(200) + +      assert length(response) == 2 +      [%{"id" => ^reply_from_me}, %{"id" => ^activity_id}] = response      end      test "doesn't return replies if follow is posting with users from blocked domain" do diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 9f22f9dcf..a5f39b215 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -5,6 +5,7 @@  defmodule Pleroma.Web.MastodonAPI.AccountViewTest do    use Pleroma.DataCase +  alias Pleroma.Config    alias Pleroma.User    alias Pleroma.UserRelationship    alias Pleroma.Web.CommonAPI @@ -68,7 +69,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do          sensitive: false,          pleroma: %{            actor_type: "Person", -          discoverable: false +          discoverable: true          },          fields: []        }, @@ -166,7 +167,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do          sensitive: false,          pleroma: %{            actor_type: "Service", -          discoverable: false +          discoverable: true          },          fields: []        }, @@ -448,7 +449,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do      test "shows unread_count only to the account owner" do        user = insert(:user) -      insert_list(7, :notification, user: user) +      insert_list(7, :notification, user: user, activity: insert(:note_activity))        other_user = insert(:user)        user = User.get_cached_by_ap_id(user.ap_id) @@ -540,8 +541,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do      end    end -  test "uses mediaproxy urls when it's enabled" do +  test "uses mediaproxy urls when it's enabled (regardless of media preview proxy state)" do      clear_config([:media_proxy, :enabled], true) +    clear_config([:media_preview_proxy, :enabled])      user =        insert(:user, @@ -550,20 +552,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do          emoji: %{"joker_smile" => "https://evil.website/society.png"}        ) -    AccountView.render("show.json", %{user: user, skip_visibility_check: true}) -    |> Enum.all?(fn -      {key, url} when key in [:avatar, :avatar_static, :header, :header_static] -> -        String.starts_with?(url, Pleroma.Web.base_url()) - -      {:emojis, emojis} -> -        Enum.all?(emojis, fn %{url: url, static_url: static_url} -> -          String.starts_with?(url, Pleroma.Web.base_url()) && -            String.starts_with?(static_url, Pleroma.Web.base_url()) -        end) - -      _ -> -        true -    end) -    |> assert() +    with media_preview_enabled <- [false, true] do +      Config.put([:media_preview_proxy, :enabled], media_preview_enabled) + +      AccountView.render("show.json", %{user: user, skip_visibility_check: true}) +      |> Enum.all?(fn +        {key, url} when key in [:avatar, :avatar_static, :header, :header_static] -> +          String.starts_with?(url, Pleroma.Web.base_url()) + +        {:emojis, emojis} -> +          Enum.all?(emojis, fn %{url: url, static_url: static_url} -> +            String.starts_with?(url, Pleroma.Web.base_url()) && +              String.starts_with?(static_url, Pleroma.Web.base_url()) +          end) + +        _ -> +          true +      end) +      |> assert() +    end    end  end diff --git a/test/web/media_proxy/media_proxy_controller_test.exs b/test/web/media_proxy/media_proxy_controller_test.exs index d4db44c63..e9b584822 100644 --- a/test/web/media_proxy/media_proxy_controller_test.exs +++ b/test/web/media_proxy/media_proxy_controller_test.exs @@ -8,34 +8,34 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do    import Mock    alias Pleroma.Web.MediaProxy -  alias Pleroma.Web.MediaProxy.MediaProxyController    alias Plug.Conn    setup do      on_exit(fn -> Cachex.clear(:banned_urls_cache) end)    end -  test "it returns 404 when MediaProxy disabled", %{conn: conn} do -    clear_config([:media_proxy, :enabled], false) - -    assert %Conn{ -             status: 404, -             resp_body: "Not Found" -           } = get(conn, "/proxy/hhgfh/eeeee") - -    assert %Conn{ -             status: 404, -             resp_body: "Not Found" -           } = get(conn, "/proxy/hhgfh/eeee/fff") -  end - -  describe "" do +  describe "Media Proxy" do      setup do        clear_config([:media_proxy, :enabled], true)        clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") +        [url: MediaProxy.encode_url("https://google.fn/test.png")]      end +    test "it returns 404 when disabled", %{conn: conn} do +      clear_config([:media_proxy, :enabled], false) + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/hhgfh/eeeee") + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/hhgfh/eeee/fff") +    end +      test "it returns 403 for invalid signature", %{conn: conn, url: url} do        Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")        %{path: path} = URI.parse(url) @@ -56,7 +56,7 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do               } = get(conn, "/proxy/hhgfh/eeee/fff")      end -    test "redirects on valid url when filename is invalidated", %{conn: conn, url: url} do +    test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do        invalid_url = String.replace(url, "test.png", "test-file.png")        response = get(conn, invalid_url)        assert response.status == 302 @@ -80,42 +80,263 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do      end    end -  describe "filename_matches/3" do -    test "preserves the encoded or decoded path" do -      assert MediaProxyController.filename_matches( -               %{"filename" => "/Hello world.jpg"}, -               "/Hello world.jpg", -               "http://pleroma.social/Hello world.jpg" -             ) == :ok - -      assert MediaProxyController.filename_matches( -               %{"filename" => "/Hello%20world.jpg"}, -               "/Hello%20world.jpg", -               "http://pleroma.social/Hello%20world.jpg" -             ) == :ok - -      assert MediaProxyController.filename_matches( -               %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"}, -               "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", -               "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg" -             ) == :ok - -      assert MediaProxyController.filename_matches( -               %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jp"}, -               "/my%2Flong%2Furl%2F2019%2F07%2FS.jp", -               "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg" -             ) == {:wrong_filename, "my%2Flong%2Furl%2F2019%2F07%2FS.jpg"} -    end - -    test "encoded url are tried to match for proxy as `conn.request_path` encodes the url" do -      # conn.request_path will return encoded url -      request_path = "/ANALYSE-DAI-_-LE-STABLECOIN-100-D%C3%89CENTRALIS%C3%89-BQ.jpg" - -      assert MediaProxyController.filename_matches( -               true, -               request_path, -               "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg" -             ) == :ok +  describe "Media Preview Proxy" do +    def assert_dependencies_installed do +      missing_dependencies = Pleroma.Helpers.MediaHelper.missing_dependencies() + +      assert missing_dependencies == [], +             "Error: missing dependencies (please refer to `docs/installation`): #{ +               inspect(missing_dependencies) +             }" +    end + +    setup do +      clear_config([:media_proxy, :enabled], true) +      clear_config([:media_preview_proxy, :enabled], true) +      clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") + +      original_url = "https://google.fn/test.png" + +      [ +        url: MediaProxy.encode_preview_url(original_url), +        media_proxy_url: MediaProxy.encode_url(original_url) +      ] +    end + +    test "returns 404 when media proxy is disabled", %{conn: conn} do +      clear_config([:media_proxy, :enabled], false) + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/preview/hhgfh/eeeee") + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/preview/hhgfh/fff") +    end + +    test "returns 404 when disabled", %{conn: conn} do +      clear_config([:media_preview_proxy, :enabled], false) + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/preview/hhgfh/eeeee") + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/preview/hhgfh/fff") +    end + +    test "it returns 403 for invalid signature", %{conn: conn, url: url} do +      Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000") +      %{path: path} = URI.parse(url) + +      assert %Conn{ +               status: 403, +               resp_body: "Forbidden" +             } = get(conn, path) + +      assert %Conn{ +               status: 403, +               resp_body: "Forbidden" +             } = get(conn, "/proxy/preview/hhgfh/eeee") + +      assert %Conn{ +               status: 403, +               resp_body: "Forbidden" +             } = get(conn, "/proxy/preview/hhgfh/eeee/fff") +    end + +    test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do +      invalid_url = String.replace(url, "test.png", "test-file.png") +      response = get(conn, invalid_url) +      assert response.status == 302 +      assert redirected_to(response) == url +    end + +    test "responds with 424 Failed Dependency if HEAD request to media proxy fails", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 500, body: ""} +      end) + +      response = get(conn, url) +      assert response.status == 424 +      assert response.resp_body == "Can't fetch HTTP headers (HTTP 500)." +    end + +    test "redirects to media proxy URI on unsupported content type", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "application/pdf"}]} +      end) + +      response = get(conn, url) +      assert response.status == 302 +      assert redirected_to(response) == media_proxy_url +    end + +    test "with `static=true` and GIF image preview requested, responds with JPEG image", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      assert_dependencies_installed() + +      # Setting a high :min_content_length to ensure this scenario is not affected by its logic +      clear_config([:media_preview_proxy, :min_content_length], 1_000_000_000) + +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{ +            status: 200, +            body: "", +            headers: [{"content-type", "image/gif"}, {"content-length", "1001718"}] +          } + +        %{method: :get, url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.gif")} +      end) + +      response = get(conn, url <> "?static=true") + +      assert response.status == 200 +      assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"] +      assert response.resp_body != "" +    end + +    test "with GIF image preview requested and no `static` param, redirects to media proxy URI", +         %{ +           conn: conn, +           url: url, +           media_proxy_url: media_proxy_url +         } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/gif"}]} +      end) + +      response = get(conn, url) + +      assert response.status == 302 +      assert redirected_to(response) == media_proxy_url +    end + +    test "with `static` param and non-GIF image preview requested, " <> +           "redirects to media preview proxy URI without `static` param", +         %{ +           conn: conn, +           url: url, +           media_proxy_url: media_proxy_url +         } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} +      end) + +      response = get(conn, url <> "?static=true") + +      assert response.status == 302 +      assert redirected_to(response) == url +    end + +    test "with :min_content_length setting not matched by Content-Length header, " <> +           "redirects to media proxy URI", +         %{ +           conn: conn, +           url: url, +           media_proxy_url: media_proxy_url +         } do +      clear_config([:media_preview_proxy, :min_content_length], 100_000) + +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{ +            status: 200, +            body: "", +            headers: [{"content-type", "image/gif"}, {"content-length", "5000"}] +          } +      end) + +      response = get(conn, url) + +      assert response.status == 302 +      assert redirected_to(response) == media_proxy_url +    end + +    test "thumbnails PNG images into PNG", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      assert_dependencies_installed() + +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/png"}]} + +        %{method: :get, url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.png")} +      end) + +      response = get(conn, url) + +      assert response.status == 200 +      assert Conn.get_resp_header(response, "content-type") == ["image/png"] +      assert response.resp_body != "" +    end + +    test "thumbnails JPEG images into JPEG", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      assert_dependencies_installed() + +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} + +        %{method: :get, url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")} +      end) + +      response = get(conn, url) + +      assert response.status == 200 +      assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"] +      assert response.resp_body != "" +    end + +    test "redirects to media proxy URI in case of thumbnailing error", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} + +        %{method: :get, url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "<html><body>error</body></html>"} +      end) + +      response = get(conn, url) + +      assert response.status == 302 +      assert redirected_to(response) == media_proxy_url      end    end  end diff --git a/test/web/media_proxy/media_proxy_test.exs b/test/web/media_proxy/media_proxy_test.exs index 72885cfdd..0e6df826c 100644 --- a/test/web/media_proxy/media_proxy_test.exs +++ b/test/web/media_proxy/media_proxy_test.exs @@ -6,9 +6,16 @@ defmodule Pleroma.Web.MediaProxyTest do    use ExUnit.Case    use Pleroma.Tests.Helpers +  alias Pleroma.Config    alias Pleroma.Web.Endpoint    alias Pleroma.Web.MediaProxy +  defp decode_result(encoded) do +    [_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/") +    {:ok, decoded} = MediaProxy.decode_url(sig, base64) +    decoded +  end +    describe "when enabled" do      setup do: clear_config([:media_proxy, :enabled], true) @@ -35,7 +42,7 @@ defmodule Pleroma.Web.MediaProxyTest do        assert String.starts_with?(                 encoded, -               Pleroma.Config.get([:media_proxy, :base_url], Pleroma.Web.base_url()) +               Config.get([:media_proxy, :base_url], Pleroma.Web.base_url())               )        assert String.ends_with?(encoded, "/logo.png") @@ -75,6 +82,64 @@ defmodule Pleroma.Web.MediaProxyTest do        assert MediaProxy.decode_url(sig, base64) == {:error, :invalid_signature}      end +    def test_verify_request_path_and_url(request_path, url, expected_result) do +      assert MediaProxy.verify_request_path_and_url(request_path, url) == expected_result + +      assert MediaProxy.verify_request_path_and_url( +               %Plug.Conn{ +                 params: %{"filename" => Path.basename(request_path)}, +                 request_path: request_path +               }, +               url +             ) == expected_result +    end + +    test "if first arg of `verify_request_path_and_url/2` is a Plug.Conn without \"filename\" " <> +           "parameter, `verify_request_path_and_url/2` returns :ok " do +      assert MediaProxy.verify_request_path_and_url( +               %Plug.Conn{params: %{}, request_path: "/some/path"}, +               "https://instance.com/file.jpg" +             ) == :ok + +      assert MediaProxy.verify_request_path_and_url( +               %Plug.Conn{params: %{}, request_path: "/path/to/file.jpg"}, +               "https://instance.com/file.jpg" +             ) == :ok +    end + +    test "`verify_request_path_and_url/2` preserves the encoded or decoded path" do +      test_verify_request_path_and_url( +        "/Hello world.jpg", +        "http://pleroma.social/Hello world.jpg", +        :ok +      ) + +      test_verify_request_path_and_url( +        "/Hello%20world.jpg", +        "http://pleroma.social/Hello%20world.jpg", +        :ok +      ) + +      test_verify_request_path_and_url( +        "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", +        "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", +        :ok +      ) + +      test_verify_request_path_and_url( +        # Note: `conn.request_path` returns encoded url +        "/ANALYSE-DAI-_-LE-STABLECOIN-100-D%C3%89CENTRALIS%C3%89-BQ.jpg", +        "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg", +        :ok +      ) + +      test_verify_request_path_and_url( +        "/my%2Flong%2Furl%2F2019%2F07%2FS", +        "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", +        {:wrong_filename, "my%2Flong%2Furl%2F2019%2F07%2FS.jpg"} +      ) +    end +      test "uses the configured base_url" do        base_url = "https://cache.pleroma.social"        clear_config([:media_proxy, :base_url], base_url) @@ -124,12 +189,6 @@ defmodule Pleroma.Web.MediaProxyTest do      end    end -  defp decode_result(encoded) do -    [_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/") -    {:ok, decoded} = MediaProxy.decode_url(sig, base64) -    decoded -  end -    describe "whitelist" do      setup do: clear_config([:media_proxy, :enabled], true) diff --git a/test/web/metadata/metadata_test.exs b/test/web/metadata/metadata_test.exs index 9d3121b7b..ca6cbe67f 100644 --- a/test/web/metadata/metadata_test.exs +++ b/test/web/metadata/metadata_test.exs @@ -16,7 +16,14 @@ defmodule Pleroma.Web.MetadataTest do      end      test "for local user" do -      user = insert(:user) +      user = insert(:user, 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, discoverable: true)        refute Pleroma.Web.Metadata.build_tags(%{user: user}) =~                 "<meta content=\"noindex, noarchive\" name=\"robots\">" @@ -24,11 +31,19 @@ defmodule Pleroma.Web.MetadataTest do    end    describe "no metadata for private instances" do -    test "for local user" 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") +      user = insert(:user, bio: "This is my secret fedi account bio", 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", discoverable: false) + +      assert ~s(<meta content="noindex, noarchive" name="robots">) == +               Pleroma.Web.Metadata.build_tags(%{user: user}) +    end    end  end diff --git a/test/web/metadata/restrict_indexing_test.exs b/test/web/metadata/restrict_indexing_test.exs index aad0bac42..6b3a65372 100644 --- a/test/web/metadata/restrict_indexing_test.exs +++ b/test/web/metadata/restrict_indexing_test.exs @@ -14,8 +14,14 @@ defmodule Pleroma.Web.Metadata.Providers.RestrictIndexingTest do      test "for local user" do        assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ -               user: %Pleroma.User{local: true} +               user: %Pleroma.User{local: true, discoverable: true}               }) == []      end + +    test "for local user when discoverable is false" do +      assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ +               user: %Pleroma.User{local: true, discoverable: false} +             }) == [{:meta, [name: "robots", content: "noindex, noarchive"], []}] +    end    end  end diff --git a/test/web/pleroma_api/controllers/chat_controller_test.exs b/test/web/pleroma_api/controllers/chat_controller_test.exs index 7be5fe09c..11d5ba373 100644 --- a/test/web/pleroma_api/controllers/chat_controller_test.exs +++ b/test/web/pleroma_api/controllers/chat_controller_test.exs @@ -2,7 +2,7 @@  # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do -  use Pleroma.Web.ConnCase, async: true +  use Pleroma.Web.ConnCase    alias Pleroma.Chat    alias Pleroma.Chat.MessageReference @@ -100,7 +100,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do          |> post("/api/v1/pleroma/chats/#{chat.id}/messages")          |> json_response_and_validate_schema(400) -      assert result +      assert %{"error" => "no_content"} == result      end      test "it works with an attachment", %{conn: conn, user: user} do @@ -126,6 +126,23 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do        assert result["attachment"]      end + +    test "gets MRF reason when rejected", %{conn: conn, user: user} do +      clear_config([:mrf_keyword, :reject], ["GNO"]) +      clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) + +      other_user = insert(:user) + +      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + +      result = +        conn +        |> put_req_header("content-type", "application/json") +        |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "GNO/Linux"}) +        |> json_response_and_validate_schema(422) + +      assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} == result +    end    end    describe "DELETE /api/v1/pleroma/chats/:id/messages/:message_id" do @@ -184,17 +201,39 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do        chat = Chat.get(user.id, recipient.ap_id) -      result = -        conn -        |> get("/api/v1/pleroma/chats/#{chat.id}/messages") -        |> json_response_and_validate_schema(200) +      response = get(conn, "/api/v1/pleroma/chats/#{chat.id}/messages") +      result = json_response_and_validate_schema(response, 200) + +      [next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ") +      api_endpoint = "/api/v1/pleroma/chats/" + +      assert String.match?( +               next, +               ~r(#{api_endpoint}.*/messages\?id=.*&limit=\d+&max_id=.*; rel=\"next\"$) +             ) + +      assert String.match?( +               prev, +               ~r(#{api_endpoint}.*/messages\?id=.*&limit=\d+&min_id=.*; rel=\"prev\"$) +             )        assert length(result) == 20 -      result = -        conn -        |> get("/api/v1/pleroma/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}") -        |> json_response_and_validate_schema(200) +      response = +        get(conn, "/api/v1/pleroma/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}") + +      result = json_response_and_validate_schema(response, 200) +      [next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ") + +      assert String.match?( +               next, +               ~r(#{api_endpoint}.*/messages\?id=.*&limit=\d+&max_id=.*; rel=\"next\"$) +             ) + +      assert String.match?( +               prev, +               ~r(#{api_endpoint}.*/messages\?id=.*&limit=\d+&max_id=.*&min_id=.*; rel=\"prev\"$) +             )        assert length(result) == 10      end @@ -223,12 +262,10 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do        assert length(result) == 3        # Trying to get the chat of a different user -      result = -        conn -        |> assign(:user, other_user) -        |> get("/api/v1/pleroma/chats/#{chat.id}/messages") - -      assert result |> json_response(404) +      conn +      |> assign(:user, other_user) +      |> get("/api/v1/pleroma/chats/#{chat.id}/messages") +      |> json_response_and_validate_schema(404)      end    end diff --git a/test/web/pleroma_api/controllers/emoji_file_controller_test.exs b/test/web/pleroma_api/controllers/emoji_file_controller_test.exs new file mode 100644 index 000000000..82de86ee3 --- /dev/null +++ b/test/web/pleroma_api/controllers/emoji_file_controller_test.exs @@ -0,0 +1,357 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.EmojiFileControllerTest do +  use Pleroma.Web.ConnCase + +  import Tesla.Mock +  import Pleroma.Factory + +  @emoji_path Path.join( +                Pleroma.Config.get!([:instance, :static_dir]), +                "emoji" +              ) +  setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false) + +  setup do: clear_config([:instance, :public], true) + +  setup do +    admin = insert(:user, is_admin: true) +    token = insert(:oauth_admin_token, user: admin) + +    admin_conn = +      build_conn() +      |> assign(:user, admin) +      |> assign(:token, token) + +    Pleroma.Emoji.reload() +    {:ok, %{admin_conn: admin_conn}} +  end + +  describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/files?name=:name" do +    setup do +      pack_file = "#{@emoji_path}/test_pack/pack.json" +      original_content = File.read!(pack_file) + +      on_exit(fn -> +        File.write!(pack_file, original_content) +      end) + +      :ok +    end + +    test "upload zip file with emojies", %{admin_conn: admin_conn} do +      on_exit(fn -> +        [ +          "128px/a_trusted_friend-128.png", +          "auroraborealis.png", +          "1000px/baby_in_a_box.png", +          "1000px/bear.png", +          "128px/bear-128.png" +        ] +        |> Enum.each(fn path -> File.rm_rf!("#{@emoji_path}/test_pack/#{path}") end) +      end) + +      resp = +        admin_conn +        |> put_req_header("content-type", "multipart/form-data") +        |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ +          file: %Plug.Upload{ +            content_type: "application/zip", +            filename: "emojis.zip", +            path: Path.absname("test/fixtures/emojis.zip") +          } +        }) +        |> json_response_and_validate_schema(200) + +      assert resp == %{ +               "a_trusted_friend-128" => "128px/a_trusted_friend-128.png", +               "auroraborealis" => "auroraborealis.png", +               "baby_in_a_box" => "1000px/baby_in_a_box.png", +               "bear" => "1000px/bear.png", +               "bear-128" => "128px/bear-128.png", +               "blank" => "blank.png", +               "blank2" => "blank2.png" +             } + +      Enum.each(Map.values(resp), fn path -> +        assert File.exists?("#{@emoji_path}/test_pack/#{path}") +      end) +    end + +    test "create shortcode exists", %{admin_conn: admin_conn} do +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response_and_validate_schema(:conflict) == %{ +               "error" => "An emoji with the \"blank\" shortcode already exists" +             } +    end + +    test "don't rewrite old emoji", %{admin_conn: admin_conn} do +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir/") end) + +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank3", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response_and_validate_schema(200) == %{ +               "blank" => "blank.png", +               "blank2" => "blank2.png", +               "blank3" => "dir/blank.png" +             } + +      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") + +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank", +               new_shortcode: "blank2", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response_and_validate_schema(:conflict) == %{ +               "error" => +                 "New shortcode \"blank2\" is already used. If you want to override emoji use 'force' option" +             } +    end + +    test "rewrite old emoji with force option", %{admin_conn: admin_conn} do +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir_2/") end) + +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank3", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response_and_validate_schema(200) == %{ +               "blank" => "blank.png", +               "blank2" => "blank2.png", +               "blank3" => "dir/blank.png" +             } + +      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") + +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank3", +               new_shortcode: "blank4", +               new_filename: "dir_2/blank_3.png", +               force: true +             }) +             |> json_response_and_validate_schema(200) == %{ +               "blank" => "blank.png", +               "blank2" => "blank2.png", +               "blank4" => "dir_2/blank_3.png" +             } + +      assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png") +    end + +    test "with empty filename", %{admin_conn: admin_conn} do +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank2", +               filename: "", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response_and_validate_schema(422) == %{ +               "error" => "pack name, shortcode or filename cannot be empty" +             } +    end + +    test "add file with not loaded pack", %{admin_conn: admin_conn} do +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> post("/api/pleroma/emoji/packs/files?name=not_loaded", %{ +               shortcode: "blank3", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response_and_validate_schema(:not_found) == %{ +               "error" => "pack \"not_loaded\" is not found" +             } +    end + +    test "remove file with not loaded pack", %{admin_conn: admin_conn} do +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/files?name=not_loaded&shortcode=blank3") +             |> json_response_and_validate_schema(:not_found) == %{ +               "error" => "pack \"not_loaded\" is not found" +             } +    end + +    test "remove file with empty shortcode", %{admin_conn: admin_conn} do +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/files?name=not_loaded&shortcode=") +             |> json_response_and_validate_schema(:not_found) == %{ +               "error" => "pack \"not_loaded\" is not found" +             } +    end + +    test "update file with not loaded pack", %{admin_conn: admin_conn} do +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> patch("/api/pleroma/emoji/packs/files?name=not_loaded", %{ +               shortcode: "blank4", +               new_shortcode: "blank3", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response_and_validate_schema(:not_found) == %{ +               "error" => "pack \"not_loaded\" is not found" +             } +    end + +    test "new with shortcode as file with update", %{admin_conn: admin_conn} do +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank4", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response_and_validate_schema(200) == %{ +               "blank" => "blank.png", +               "blank4" => "dir/blank.png", +               "blank2" => "blank2.png" +             } + +      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") + +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank4", +               new_shortcode: "blank3", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response_and_validate_schema(200) == %{ +               "blank3" => "dir_2/blank_3.png", +               "blank" => "blank.png", +               "blank2" => "blank2.png" +             } + +      refute File.exists?("#{@emoji_path}/test_pack/dir/") +      assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png") + +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/files?name=test_pack&shortcode=blank3") +             |> json_response_and_validate_schema(200) == %{ +               "blank" => "blank.png", +               "blank2" => "blank2.png" +             } + +      refute File.exists?("#{@emoji_path}/test_pack/dir_2/") + +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir") end) +    end + +    test "new with shortcode from url", %{admin_conn: admin_conn} do +      mock(fn +        %{ +          method: :get, +          url: "https://test-blank/blank_url.png" +        } -> +          text(File.read!("#{@emoji_path}/test_pack/blank.png")) +      end) + +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank_url", +               file: "https://test-blank/blank_url.png" +             }) +             |> json_response_and_validate_schema(200) == %{ +               "blank_url" => "blank_url.png", +               "blank" => "blank.png", +               "blank2" => "blank2.png" +             } + +      assert File.exists?("#{@emoji_path}/test_pack/blank_url.png") + +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/blank_url.png") end) +    end + +    test "new without shortcode", %{admin_conn: admin_conn} do +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/shortcode.png") end) + +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               file: %Plug.Upload{ +                 filename: "shortcode.png", +                 path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png" +               } +             }) +             |> json_response_and_validate_schema(200) == %{ +               "shortcode" => "shortcode.png", +               "blank" => "blank.png", +               "blank2" => "blank2.png" +             } +    end + +    test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/files?name=test_pack&shortcode=blank3") +             |> json_response_and_validate_schema(:bad_request) == %{ +               "error" => "Emoji \"blank3\" does not exist" +             } +    end + +    test "update non existing emoji", %{admin_conn: admin_conn} do +      assert admin_conn +             |> put_req_header("content-type", "multipart/form-data") +             |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ +               shortcode: "blank3", +               new_shortcode: "blank4", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response_and_validate_schema(:bad_request) == %{ +               "error" => "Emoji \"blank3\" does not exist" +             } +    end + +    test "update with empty shortcode", %{admin_conn: admin_conn} do +      assert %{ +               "error" => "Missing field: new_shortcode." +             } = +               admin_conn +               |> put_req_header("content-type", "multipart/form-data") +               |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ +                 shortcode: "blank", +                 new_filename: "dir_2/blank_3.png" +               }) +               |> json_response_and_validate_schema(:bad_request) +    end +  end +end diff --git a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs index e113bb15f..386ad8634 100644 --- a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs +++ b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs @@ -37,11 +37,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do    test "GET /api/pleroma/emoji/packs", %{conn: conn} do      resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200) -    assert resp["count"] == 3 +    assert resp["count"] == 4      assert resp["packs"]             |> Map.keys() -           |> length() == 3 +           |> length() == 4      shared = resp["packs"]["test_pack"]      assert shared["files"] == %{"blank" => "blank.png", "blank2" => "blank2.png"} @@ -58,7 +58,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do        |> get("/api/pleroma/emoji/packs?page_size=1")        |> json_response_and_validate_schema(200) -    assert resp["count"] == 3 +    assert resp["count"] == 4      packs = Map.keys(resp["packs"]) @@ -71,7 +71,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do        |> get("/api/pleroma/emoji/packs?page_size=1&page=2")        |> json_response_and_validate_schema(200) -    assert resp["count"] == 3 +    assert resp["count"] == 4      packs = Map.keys(resp["packs"])      assert length(packs) == 1      [pack2] = packs @@ -81,18 +81,28 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do        |> get("/api/pleroma/emoji/packs?page_size=1&page=3")        |> json_response_and_validate_schema(200) -    assert resp["count"] == 3 +    assert resp["count"] == 4      packs = Map.keys(resp["packs"])      assert length(packs) == 1      [pack3] = packs -    assert [pack1, pack2, pack3] |> Enum.uniq() |> length() == 3 + +    resp = +      conn +      |> get("/api/pleroma/emoji/packs?page_size=1&page=4") +      |> json_response_and_validate_schema(200) + +    assert resp["count"] == 4 +    packs = Map.keys(resp["packs"]) +    assert length(packs) == 1 +    [pack4] = packs +    assert [pack1, pack2, pack3, pack4] |> Enum.uniq() |> length() == 4    end    describe "GET /api/pleroma/emoji/packs/remote" do      test "shareable instance", %{admin_conn: admin_conn, conn: conn} do        resp =          conn -        |> get("/api/pleroma/emoji/packs") +        |> get("/api/pleroma/emoji/packs?page=2&page_size=1")          |> json_response_and_validate_schema(200)        mock(fn @@ -102,12 +112,12 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do          %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->            json(%{metadata: %{features: ["shareable_emoji_packs"]}}) -        %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} -> +        %{method: :get, url: "https://example.com/api/pleroma/emoji/packs?page=2&page_size=1"} ->            json(resp)        end)        assert admin_conn -             |> get("/api/pleroma/emoji/packs/remote?url=https://example.com") +             |> get("/api/pleroma/emoji/packs/remote?url=https://example.com&page=2&page_size=1")               |> json_response_and_validate_schema(200) == resp      end @@ -128,11 +138,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      end    end -  describe "GET /api/pleroma/emoji/packs/:name/archive" do +  describe "GET /api/pleroma/emoji/packs/archive?name=:name" do      test "download shared pack", %{conn: conn} do        resp =          conn -        |> get("/api/pleroma/emoji/packs/test_pack/archive") +        |> get("/api/pleroma/emoji/packs/archive?name=test_pack")          |> response(200)        {:ok, arch} = :zip.unzip(resp, [:memory]) @@ -143,7 +153,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      test "non existing pack", %{conn: conn} do        assert conn -             |> get("/api/pleroma/emoji/packs/test_pack_for_import/archive") +             |> get("/api/pleroma/emoji/packs/archive?name=test_pack_for_import")               |> json_response_and_validate_schema(:not_found) == %{                 "error" => "Pack test_pack_for_import does not exist"               } @@ -151,7 +161,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      test "non downloadable pack", %{conn: conn} do        assert conn -             |> get("/api/pleroma/emoji/packs/test_pack_nonshared/archive") +             |> get("/api/pleroma/emoji/packs/archive?name=test_pack_nonshared")               |> json_response_and_validate_schema(:forbidden) == %{                 "error" =>                   "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing" @@ -173,28 +183,28 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do          %{            method: :get, -          url: "https://example.com/api/pleroma/emoji/packs/test_pack" +          url: "https://example.com/api/pleroma/emoji/pack?name=test_pack"          } ->            conn -          |> get("/api/pleroma/emoji/packs/test_pack") +          |> get("/api/pleroma/emoji/pack?name=test_pack")            |> json_response_and_validate_schema(200)            |> json()          %{            method: :get, -          url: "https://example.com/api/pleroma/emoji/packs/test_pack/archive" +          url: "https://example.com/api/pleroma/emoji/packs/archive?name=test_pack"          } ->            conn -          |> get("/api/pleroma/emoji/packs/test_pack/archive") +          |> get("/api/pleroma/emoji/packs/archive?name=test_pack")            |> response(200)            |> text()          %{            method: :get, -          url: "https://example.com/api/pleroma/emoji/packs/test_pack_nonshared" +          url: "https://example.com/api/pleroma/emoji/pack?name=test_pack_nonshared"          } ->            conn -          |> get("/api/pleroma/emoji/packs/test_pack_nonshared") +          |> get("/api/pleroma/emoji/pack?name=test_pack_nonshared")            |> json_response_and_validate_schema(200)            |> json() @@ -218,7 +228,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do        assert File.exists?("#{@emoji_path}/test_pack2/blank.png")        assert admin_conn -             |> delete("/api/pleroma/emoji/packs/test_pack2") +             |> delete("/api/pleroma/emoji/pack?name=test_pack2")               |> json_response_and_validate_schema(200) == "ok"        refute File.exists?("#{@emoji_path}/test_pack2") @@ -239,7 +249,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do        assert File.exists?("#{@emoji_path}/test_pack_nonshared2/blank.png")        assert admin_conn -             |> delete("/api/pleroma/emoji/packs/test_pack_nonshared2") +             |> delete("/api/pleroma/emoji/pack?name=test_pack_nonshared2")               |> json_response_and_validate_schema(200) == "ok"        refute File.exists?("#{@emoji_path}/test_pack_nonshared2") @@ -279,14 +289,14 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do          %{            method: :get, -          url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha" +          url: "https://example.com/api/pleroma/emoji/pack?name=pack_bad_sha"          } ->            {:ok, pack} = Pleroma.Emoji.Pack.load_pack("pack_bad_sha")            %Tesla.Env{status: 200, body: Jason.encode!(pack)}          %{            method: :get, -          url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha/archive" +          url: "https://example.com/api/pleroma/emoji/packs/archive?name=pack_bad_sha"          } ->            %Tesla.Env{              status: 200, @@ -316,7 +326,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do          %{            method: :get, -          url: "https://example.com/api/pleroma/emoji/packs/test_pack" +          url: "https://example.com/api/pleroma/emoji/pack?name=test_pack"          } ->            {:ok, pack} = Pleroma.Emoji.Pack.load_pack("test_pack")            %Tesla.Env{status: 200, body: Jason.encode!(pack)} @@ -336,7 +346,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      end    end -  describe "PATCH /api/pleroma/emoji/packs/:name" do +  describe "PATCH /api/pleroma/emoji/pack?name=:name" do      setup do        pack_file = "#{@emoji_path}/test_pack/pack.json"        original_content = File.read!(pack_file) @@ -358,7 +368,9 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      test "for a pack without a fallback source", ctx do        assert ctx[:admin_conn]               |> put_req_header("content-type", "multipart/form-data") -             |> patch("/api/pleroma/emoji/packs/test_pack", %{"metadata" => ctx[:new_data]}) +             |> patch("/api/pleroma/emoji/pack?name=test_pack", %{ +               "metadata" => ctx[:new_data] +             })               |> json_response_and_validate_schema(200) == ctx[:new_data]        assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data] @@ -384,7 +396,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do        assert ctx[:admin_conn]               |> put_req_header("content-type", "multipart/form-data") -             |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data}) +             |> patch("/api/pleroma/emoji/pack?name=test_pack", %{metadata: new_data})               |> json_response_and_validate_schema(200) == new_data_with_sha        assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha @@ -404,304 +416,17 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do        assert ctx[:admin_conn]               |> put_req_header("content-type", "multipart/form-data") -             |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data}) +             |> patch("/api/pleroma/emoji/pack?name=test_pack", %{metadata: new_data})               |> json_response_and_validate_schema(:bad_request) == %{                 "error" => "The fallback archive does not have all files specified in pack.json"               }      end    end -  describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/:name/files" do -    setup do -      pack_file = "#{@emoji_path}/test_pack/pack.json" -      original_content = File.read!(pack_file) - -      on_exit(fn -> -        File.write!(pack_file, original_content) -      end) - -      :ok -    end - -    test "create shortcode exists", %{admin_conn: admin_conn} do -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank", -               filename: "dir/blank.png", -               file: %Plug.Upload{ -                 filename: "blank.png", -                 path: "#{@emoji_path}/test_pack/blank.png" -               } -             }) -             |> json_response_and_validate_schema(:conflict) == %{ -               "error" => "An emoji with the \"blank\" shortcode already exists" -             } -    end - -    test "don't rewrite old emoji", %{admin_conn: admin_conn} do -      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir/") end) - -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank3", -               filename: "dir/blank.png", -               file: %Plug.Upload{ -                 filename: "blank.png", -                 path: "#{@emoji_path}/test_pack/blank.png" -               } -             }) -             |> json_response_and_validate_schema(200) == %{ -               "blank" => "blank.png", -               "blank2" => "blank2.png", -               "blank3" => "dir/blank.png" -             } - -      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") - -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank", -               new_shortcode: "blank2", -               new_filename: "dir_2/blank_3.png" -             }) -             |> json_response_and_validate_schema(:conflict) == %{ -               "error" => -                 "New shortcode \"blank2\" is already used. If you want to override emoji use 'force' option" -             } -    end - -    test "rewrite old emoji with force option", %{admin_conn: admin_conn} do -      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir_2/") end) - -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank3", -               filename: "dir/blank.png", -               file: %Plug.Upload{ -                 filename: "blank.png", -                 path: "#{@emoji_path}/test_pack/blank.png" -               } -             }) -             |> json_response_and_validate_schema(200) == %{ -               "blank" => "blank.png", -               "blank2" => "blank2.png", -               "blank3" => "dir/blank.png" -             } - -      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") - -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank3", -               new_shortcode: "blank4", -               new_filename: "dir_2/blank_3.png", -               force: true -             }) -             |> json_response_and_validate_schema(200) == %{ -               "blank" => "blank.png", -               "blank2" => "blank2.png", -               "blank4" => "dir_2/blank_3.png" -             } - -      assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png") -    end - -    test "with empty filename", %{admin_conn: admin_conn} do -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank2", -               filename: "", -               file: %Plug.Upload{ -                 filename: "blank.png", -                 path: "#{@emoji_path}/test_pack/blank.png" -               } -             }) -             |> json_response_and_validate_schema(:bad_request) == %{ -               "error" => "pack name, shortcode or filename cannot be empty" -             } -    end - -    test "add file with not loaded pack", %{admin_conn: admin_conn} do -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> post("/api/pleroma/emoji/packs/not_loaded/files", %{ -               shortcode: "blank3", -               filename: "dir/blank.png", -               file: %Plug.Upload{ -                 filename: "blank.png", -                 path: "#{@emoji_path}/test_pack/blank.png" -               } -             }) -             |> json_response_and_validate_schema(:bad_request) == %{ -               "error" => "pack \"not_loaded\" is not found" -             } -    end - -    test "remove file with not loaded pack", %{admin_conn: admin_conn} do -      assert admin_conn -             |> delete("/api/pleroma/emoji/packs/not_loaded/files?shortcode=blank3") -             |> json_response_and_validate_schema(:bad_request) == %{ -               "error" => "pack \"not_loaded\" is not found" -             } -    end - -    test "remove file with empty shortcode", %{admin_conn: admin_conn} do -      assert admin_conn -             |> delete("/api/pleroma/emoji/packs/not_loaded/files?shortcode=") -             |> json_response_and_validate_schema(:bad_request) == %{ -               "error" => "pack name or shortcode cannot be empty" -             } -    end - -    test "update file with not loaded pack", %{admin_conn: admin_conn} do -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> patch("/api/pleroma/emoji/packs/not_loaded/files", %{ -               shortcode: "blank4", -               new_shortcode: "blank3", -               new_filename: "dir_2/blank_3.png" -             }) -             |> json_response_and_validate_schema(:bad_request) == %{ -               "error" => "pack \"not_loaded\" is not found" -             } -    end - -    test "new with shortcode as file with update", %{admin_conn: admin_conn} do -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank4", -               filename: "dir/blank.png", -               file: %Plug.Upload{ -                 filename: "blank.png", -                 path: "#{@emoji_path}/test_pack/blank.png" -               } -             }) -             |> json_response_and_validate_schema(200) == %{ -               "blank" => "blank.png", -               "blank4" => "dir/blank.png", -               "blank2" => "blank2.png" -             } - -      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") - -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank4", -               new_shortcode: "blank3", -               new_filename: "dir_2/blank_3.png" -             }) -             |> json_response_and_validate_schema(200) == %{ -               "blank3" => "dir_2/blank_3.png", -               "blank" => "blank.png", -               "blank2" => "blank2.png" -             } - -      refute File.exists?("#{@emoji_path}/test_pack/dir/") -      assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png") - -      assert admin_conn -             |> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank3") -             |> json_response_and_validate_schema(200) == %{ -               "blank" => "blank.png", -               "blank2" => "blank2.png" -             } - -      refute File.exists?("#{@emoji_path}/test_pack/dir_2/") - -      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir") end) -    end - -    test "new with shortcode from url", %{admin_conn: admin_conn} do -      mock(fn -        %{ -          method: :get, -          url: "https://test-blank/blank_url.png" -        } -> -          text(File.read!("#{@emoji_path}/test_pack/blank.png")) -      end) - -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank_url", -               file: "https://test-blank/blank_url.png" -             }) -             |> json_response_and_validate_schema(200) == %{ -               "blank_url" => "blank_url.png", -               "blank" => "blank.png", -               "blank2" => "blank2.png" -             } - -      assert File.exists?("#{@emoji_path}/test_pack/blank_url.png") - -      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/blank_url.png") end) -    end - -    test "new without shortcode", %{admin_conn: admin_conn} do -      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/shortcode.png") end) - -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ -               file: %Plug.Upload{ -                 filename: "shortcode.png", -                 path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png" -               } -             }) -             |> json_response_and_validate_schema(200) == %{ -               "shortcode" => "shortcode.png", -               "blank" => "blank.png", -               "blank2" => "blank2.png" -             } -    end - -    test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do -      assert admin_conn -             |> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank3") -             |> json_response_and_validate_schema(:bad_request) == %{ -               "error" => "Emoji \"blank3\" does not exist" -             } -    end - -    test "update non existing emoji", %{admin_conn: admin_conn} do -      assert admin_conn -             |> put_req_header("content-type", "multipart/form-data") -             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ -               shortcode: "blank3", -               new_shortcode: "blank4", -               new_filename: "dir_2/blank_3.png" -             }) -             |> json_response_and_validate_schema(:bad_request) == %{ -               "error" => "Emoji \"blank3\" does not exist" -             } -    end - -    test "update with empty shortcode", %{admin_conn: admin_conn} do -      assert %{ -               "error" => "Missing field: new_shortcode." -             } = -               admin_conn -               |> put_req_header("content-type", "multipart/form-data") -               |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ -                 shortcode: "blank", -                 new_filename: "dir_2/blank_3.png" -               }) -               |> json_response_and_validate_schema(:bad_request) -    end -  end - -  describe "POST/DELETE /api/pleroma/emoji/packs/:name" do +  describe "POST/DELETE /api/pleroma/emoji/pack?name=:name" do      test "creating and deleting a pack", %{admin_conn: admin_conn} do        assert admin_conn -             |> post("/api/pleroma/emoji/packs/test_created") +             |> post("/api/pleroma/emoji/pack?name=test_created")               |> json_response_and_validate_schema(200) == "ok"        assert File.exists?("#{@emoji_path}/test_created/pack.json") @@ -713,7 +438,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do               }        assert admin_conn -             |> delete("/api/pleroma/emoji/packs/test_created") +             |> delete("/api/pleroma/emoji/pack?name=test_created")               |> json_response_and_validate_schema(200) == "ok"        refute File.exists?("#{@emoji_path}/test_created/pack.json") @@ -726,7 +451,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do        File.write!(Path.join(path, "pack.json"), pack_file)        assert admin_conn -             |> post("/api/pleroma/emoji/packs/test_created") +             |> post("/api/pleroma/emoji/pack?name=test_created")               |> json_response_and_validate_schema(:conflict) == %{                 "error" => "A pack named \"test_created\" already exists"               } @@ -736,7 +461,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      test "with empty name", %{admin_conn: admin_conn} do        assert admin_conn -             |> post("/api/pleroma/emoji/packs/ ") +             |> post("/api/pleroma/emoji/pack?name= ")               |> json_response_and_validate_schema(:bad_request) == %{                 "error" => "pack name cannot be empty"               } @@ -745,7 +470,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do    test "deleting nonexisting pack", %{admin_conn: admin_conn} do      assert admin_conn -           |> delete("/api/pleroma/emoji/packs/non_existing") +           |> delete("/api/pleroma/emoji/pack?name=non_existing")             |> json_response_and_validate_schema(:not_found) == %{               "error" => "Pack non_existing does not exist"             } @@ -753,7 +478,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do    test "deleting with empty name", %{admin_conn: admin_conn} do      assert admin_conn -           |> delete("/api/pleroma/emoji/packs/ ") +           |> delete("/api/pleroma/emoji/pack?name= ")             |> json_response_and_validate_schema(:bad_request) == %{               "error" => "pack name cannot be empty"             } @@ -801,7 +526,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do             }    end -  describe "GET /api/pleroma/emoji/packs/:name" do +  describe "GET /api/pleroma/emoji/pack?name=:name" do      test "shows pack.json", %{conn: conn} do        assert %{                 "files" => files, @@ -816,7 +541,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do                 }               } =                 conn -               |> get("/api/pleroma/emoji/packs/test_pack") +               |> get("/api/pleroma/emoji/pack?name=test_pack")                 |> json_response_and_validate_schema(200)        assert files == %{"blank" => "blank.png", "blank2" => "blank2.png"} @@ -826,7 +551,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do                 "files_count" => 2               } =                 conn -               |> get("/api/pleroma/emoji/packs/test_pack?page_size=1") +               |> get("/api/pleroma/emoji/pack?name=test_pack&page_size=1")                 |> json_response_and_validate_schema(200)        assert files |> Map.keys() |> length() == 1 @@ -836,15 +561,33 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do                 "files_count" => 2               } =                 conn -               |> get("/api/pleroma/emoji/packs/test_pack?page_size=1&page=2") +               |> get("/api/pleroma/emoji/pack?name=test_pack&page_size=1&page=2")                 |> json_response_and_validate_schema(200)        assert files |> Map.keys() |> length() == 1      end +    test "for pack name with special chars", %{conn: conn} do +      assert %{ +               "files" => files, +               "files_count" => 1, +               "pack" => %{ +                 "can-download" => true, +                 "description" => "Test description", +                 "download-sha256" => _, +                 "homepage" => "https://pleroma.social", +                 "license" => "Test license", +                 "share-files" => true +               } +             } = +               conn +               |> get("/api/pleroma/emoji/pack?name=blobs.gg") +               |> json_response_and_validate_schema(200) +    end +      test "non existing pack", %{conn: conn} do        assert conn -             |> get("/api/pleroma/emoji/packs/non_existing") +             |> get("/api/pleroma/emoji/pack?name=non_existing")               |> json_response_and_validate_schema(:not_found) == %{                 "error" => "Pack non_existing does not exist"               } @@ -852,7 +595,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      test "error name", %{conn: conn} do        assert conn -             |> get("/api/pleroma/emoji/packs/ ") +             |> get("/api/pleroma/emoji/pack?name= ")               |> json_response_and_validate_schema(:bad_request) == %{                 "error" => "pack name cannot be empty"               } diff --git a/test/web/pleroma_api/controllers/user_import_controller_test.exs b/test/web/pleroma_api/controllers/user_import_controller_test.exs new file mode 100644 index 000000000..433c97e81 --- /dev/null +++ b/test/web/pleroma_api/controllers/user_import_controller_test.exs @@ -0,0 +1,235 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do +  use Pleroma.Web.ConnCase +  use Oban.Testing, repo: Pleroma.Repo + +  alias Pleroma.Config +  alias Pleroma.Tests.ObanHelpers + +  import Pleroma.Factory +  import Mock + +  setup do +    Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  describe "POST /api/pleroma/follow_import" do +    setup do: oauth_access(["follow"]) + +    test "it returns HTTP 200", %{conn: conn} do +      user2 = insert(:user) + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"}) +               |> json_response_and_validate_schema(200) +    end + +    test "it imports follow lists from file", %{conn: conn} do +      user2 = insert(:user) + +      with_mocks([ +        {File, [], +         read!: fn "follow_list.txt" -> +           "Account address,Show boosts\n#{user2.ap_id},true" +         end} +      ]) do +        assert "job started" == +                 conn +                 |> put_req_header("content-type", "application/json") +                 |> post("/api/pleroma/follow_import", %{ +                   "list" => %Plug.Upload{path: "follow_list.txt"} +                 }) +                 |> json_response_and_validate_schema(200) + +        assert [{:ok, job_result}] = ObanHelpers.perform_all() +        assert job_result == [user2] +      end +    end + +    test "it imports new-style mastodon follow lists", %{conn: conn} do +      user2 = insert(:user) + +      response = +        conn +        |> put_req_header("content-type", "application/json") +        |> post("/api/pleroma/follow_import", %{ +          "list" => "Account address,Show boosts\n#{user2.ap_id},true" +        }) +        |> json_response_and_validate_schema(200) + +      assert response == "job started" +    end + +    test "requires 'follow' or 'write:follows' permissions" do +      token1 = insert(:oauth_token, scopes: ["read", "write"]) +      token2 = insert(:oauth_token, scopes: ["follow"]) +      token3 = insert(:oauth_token, scopes: ["something"]) +      another_user = insert(:user) + +      for token <- [token1, token2, token3] do +        conn = +          build_conn() +          |> put_req_header("authorization", "Bearer #{token.token}") +          |> put_req_header("content-type", "application/json") +          |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"}) + +        if token == token3 do +          assert %{"error" => "Insufficient permissions: follow | write:follows."} == +                   json_response(conn, 403) +        else +          assert json_response(conn, 200) +        end +      end +    end + +    test "it imports follows with different nickname variations", %{conn: conn} do +      users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + +      identifiers = +        [ +          user2.ap_id, +          user3.nickname, +          "  ", +          "@" <> user4.nickname, +          user5.nickname <> "@localhost", +          "@" <> user6.nickname <> "@localhost" +        ] +        |> Enum.join("\n") + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/follow_import", %{"list" => identifiers}) +               |> json_response_and_validate_schema(200) + +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == users +    end +  end + +  describe "POST /api/pleroma/blocks_import" do +    # Note: "follow" or "write:blocks" permission is required +    setup do: oauth_access(["write:blocks"]) + +    test "it returns HTTP 200", %{conn: conn} do +      user2 = insert(:user) + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"}) +               |> json_response_and_validate_schema(200) +    end + +    test "it imports blocks users from file", %{conn: conn} do +      users = [user2, user3] = insert_list(2, :user) + +      with_mocks([ +        {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} +      ]) do +        assert "job started" == +                 conn +                 |> put_req_header("content-type", "application/json") +                 |> post("/api/pleroma/blocks_import", %{ +                   "list" => %Plug.Upload{path: "blocks_list.txt"} +                 }) +                 |> json_response_and_validate_schema(200) + +        assert [{:ok, job_result}] = ObanHelpers.perform_all() +        assert job_result == users +      end +    end + +    test "it imports blocks with different nickname variations", %{conn: conn} do +      users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + +      identifiers = +        [ +          user2.ap_id, +          user3.nickname, +          "@" <> user4.nickname, +          user5.nickname <> "@localhost", +          "@" <> user6.nickname <> "@localhost" +        ] +        |> Enum.join(" ") + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/blocks_import", %{"list" => identifiers}) +               |> json_response_and_validate_schema(200) + +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == users +    end +  end + +  describe "POST /api/pleroma/mutes_import" do +    # Note: "follow" or "write:mutes" permission is required +    setup do: oauth_access(["write:mutes"]) + +    test "it returns HTTP 200", %{user: user, conn: conn} do +      user2 = insert(:user) + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/mutes_import", %{"list" => "#{user2.ap_id}"}) +               |> json_response_and_validate_schema(200) + +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == [user2] +      assert Pleroma.User.mutes?(user, user2) +    end + +    test "it imports mutes users from file", %{user: user, conn: conn} do +      users = [user2, user3] = insert_list(2, :user) + +      with_mocks([ +        {File, [], read!: fn "mutes_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} +      ]) do +        assert "job started" == +                 conn +                 |> put_req_header("content-type", "application/json") +                 |> post("/api/pleroma/mutes_import", %{ +                   "list" => %Plug.Upload{path: "mutes_list.txt"} +                 }) +                 |> json_response_and_validate_schema(200) + +        assert [{:ok, job_result}] = ObanHelpers.perform_all() +        assert job_result == users +        assert Enum.all?(users, &Pleroma.User.mutes?(user, &1)) +      end +    end + +    test "it imports mutes with different nickname variations", %{user: user, conn: conn} do +      users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + +      identifiers = +        [ +          user2.ap_id, +          user3.nickname, +          "@" <> user4.nickname, +          user5.nickname <> "@localhost", +          "@" <> user6.nickname <> "@localhost" +        ] +        |> Enum.join(" ") + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/mutes_import", %{"list" => identifiers}) +               |> json_response_and_validate_schema(200) + +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == users +      assert Enum.all?(users, &Pleroma.User.mutes?(user, &1)) +    end +  end +end diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index aeb5c1fbd..6cab46696 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -5,6 +5,8 @@  defmodule Pleroma.Web.Push.ImplTest do    use Pleroma.DataCase +  import Pleroma.Factory +    alias Pleroma.Notification    alias Pleroma.Object    alias Pleroma.User @@ -13,8 +15,6 @@ defmodule Pleroma.Web.Push.ImplTest do    alias Pleroma.Web.Push.Impl    alias Pleroma.Web.Push.Subscription -  import Pleroma.Factory -    setup do      Tesla.Mock.mock(fn        %{method: :post, url: "https://example.com/example/1234"} -> diff --git a/test/web/rich_media/helpers_test.exs b/test/web/rich_media/helpers_test.exs index 8264a9c41..4b97bd66b 100644 --- a/test/web/rich_media/helpers_test.exs +++ b/test/web/rich_media/helpers_test.exs @@ -64,41 +64,6 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do               Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)    end -  test "refuses to crawl URLs from posts marked sensitive" do -    user = insert(:user) - -    {:ok, activity} = -      CommonAPI.post(user, %{ -        status: "http://example.com/ogp", -        sensitive: true -      }) - -    %Object{} = object = Object.normalize(activity) - -    assert object.data["sensitive"] - -    Config.put([:rich_media, :enabled], true) - -    assert %{} = Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) -  end - -  test "refuses to crawl URLs from posts tagged NSFW" do -    user = insert(:user) - -    {:ok, activity} = -      CommonAPI.post(user, %{ -        status: "http://example.com/ogp #nsfw" -      }) - -    %Object{} = object = Object.normalize(activity) - -    assert object.data["sensitive"] - -    Config.put([:rich_media, :enabled], true) - -    assert %{} = Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) -  end -    test "refuses to crawl URLs of private network from posts" do      user = insert(:user) diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs index 21ae35f8b..6d00c2af5 100644 --- a/test/web/rich_media/parser_test.exs +++ b/test/web/rich_media/parser_test.exs @@ -56,6 +56,27 @@ defmodule Pleroma.Web.RichMedia.ParserTest do        %{method: :get, url: "http://example.com/error"} ->          {:error, :overload} + +      %{ +        method: :head, +        url: "http://example.com/huge-page" +      } -> +        %Tesla.Env{ +          status: 200, +          headers: [{"content-length", "2000001"}, {"content-type", "text/html"}] +        } + +      %{ +        method: :head, +        url: "http://example.com/pdf-file" +      } -> +        %Tesla.Env{ +          status: 200, +          headers: [{"content-length", "1000000"}, {"content-type", "application/pdf"}] +        } + +      %{method: :head} -> +        %Tesla.Env{status: 404, body: "", headers: []}      end)      :ok @@ -144,4 +165,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do    test "returns error if getting page was not successful" do      assert {:error, :overload} = Parser.parse("http://example.com/error")    end + +  test "does a HEAD request to check if the body is too large" do +    assert {:error, :body_too_large} = Parser.parse("http://example.com/huge-page") +  end + +  test "does a HEAD request to check if the body is html" do +    assert {:error, {:content_type, _}} = Parser.parse("http://example.com/pdf-file") +  end  end diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index d56d74464..185724a9f 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -21,92 +21,148 @@ defmodule Pleroma.Web.StreamerTest do    setup do: clear_config([:instance, :skip_thread_containment]) -  describe "get_topic without an user" do +  describe "get_topic/_ (unauthenticated)" do      test "allows public" do -      assert {:ok, "public"} = Streamer.get_topic("public", nil) -      assert {:ok, "public:local"} = Streamer.get_topic("public:local", nil) -      assert {:ok, "public:media"} = Streamer.get_topic("public:media", nil) -      assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil) +      assert {:ok, "public"} = Streamer.get_topic("public", nil, nil) +      assert {:ok, "public:local"} = Streamer.get_topic("public:local", nil, nil) +      assert {:ok, "public:media"} = Streamer.get_topic("public:media", nil, nil) +      assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil, nil)      end      test "allows hashtag streams" do -      assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", nil, %{"tag" => "cofe"}) +      assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", nil, nil, %{"tag" => "cofe"})      end      test "disallows user streams" do -      assert {:error, _} = Streamer.get_topic("user", nil) -      assert {:error, _} = Streamer.get_topic("user:notification", nil) -      assert {:error, _} = Streamer.get_topic("direct", nil) +      assert {:error, _} = Streamer.get_topic("user", nil, nil) +      assert {:error, _} = Streamer.get_topic("user:notification", nil, nil) +      assert {:error, _} = Streamer.get_topic("direct", nil, nil)      end      test "disallows list streams" do -      assert {:error, _} = Streamer.get_topic("list", nil, %{"list" => 42}) +      assert {:error, _} = Streamer.get_topic("list", nil, nil, %{"list" => 42})      end    end -  describe "get_topic with an user" do -    setup do -      user = insert(:user) -      {:ok, %{user: user}} -    end +  describe "get_topic/_ (authenticated)" do +    setup do: oauth_access(["read"]) + +    test "allows public streams (regardless of OAuth token scopes)", %{ +      user: user, +      token: read_oauth_token +    } do +      with oauth_token <- [nil, read_oauth_token] do +        assert {:ok, "public"} = Streamer.get_topic("public", user, oauth_token) +        assert {:ok, "public:local"} = Streamer.get_topic("public:local", user, oauth_token) +        assert {:ok, "public:media"} = Streamer.get_topic("public:media", user, oauth_token) -    test "allows public streams", %{user: user} do -      assert {:ok, "public"} = Streamer.get_topic("public", user) -      assert {:ok, "public:local"} = Streamer.get_topic("public:local", user) -      assert {:ok, "public:media"} = Streamer.get_topic("public:media", user) -      assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", user) +        assert {:ok, "public:local:media"} = +                 Streamer.get_topic("public:local:media", user, oauth_token) +      end      end -    test "allows user streams", %{user: user} do +    test "allows user streams (with proper OAuth token scopes)", %{ +      user: user, +      token: read_oauth_token +    } do +      %{token: read_notifications_token} = oauth_access(["read:notifications"], user: user) +      %{token: read_statuses_token} = oauth_access(["read:statuses"], user: user) +      %{token: badly_scoped_token} = oauth_access(["irrelevant:scope"], user: user) +        expected_user_topic = "user:#{user.id}" -      expected_notif_topic = "user:notification:#{user.id}" +      expected_notification_topic = "user:notification:#{user.id}"        expected_direct_topic = "direct:#{user.id}" -      assert {:ok, ^expected_user_topic} = Streamer.get_topic("user", user) -      assert {:ok, ^expected_notif_topic} = Streamer.get_topic("user:notification", user) -      assert {:ok, ^expected_direct_topic} = Streamer.get_topic("direct", user) +      expected_pleroma_chat_topic = "user:pleroma_chat:#{user.id}" + +      for valid_user_token <- [read_oauth_token, read_statuses_token] do +        assert {:ok, ^expected_user_topic} = Streamer.get_topic("user", user, valid_user_token) + +        assert {:ok, ^expected_direct_topic} = +                 Streamer.get_topic("direct", user, valid_user_token) + +        assert {:ok, ^expected_pleroma_chat_topic} = +                 Streamer.get_topic("user:pleroma_chat", user, valid_user_token) +      end + +      for invalid_user_token <- [read_notifications_token, badly_scoped_token], +          user_topic <- ["user", "direct", "user:pleroma_chat"] do +        assert {:error, :unauthorized} = Streamer.get_topic(user_topic, user, invalid_user_token) +      end + +      for valid_notification_token <- [read_oauth_token, read_notifications_token] do +        assert {:ok, ^expected_notification_topic} = +                 Streamer.get_topic("user:notification", user, valid_notification_token) +      end + +      for invalid_notification_token <- [read_statuses_token, badly_scoped_token] do +        assert {:error, :unauthorized} = +                 Streamer.get_topic("user:notification", user, invalid_notification_token) +      end      end -    test "allows hashtag streams", %{user: user} do -      assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", user, %{"tag" => "cofe"}) +    test "allows hashtag streams (regardless of OAuth token scopes)", %{ +      user: user, +      token: read_oauth_token +    } do +      for oauth_token <- [nil, read_oauth_token] do +        assert {:ok, "hashtag:cofe"} = +                 Streamer.get_topic("hashtag", user, oauth_token, %{"tag" => "cofe"}) +      end      end -    test "disallows registering to an user stream", %{user: user} do +    test "disallows registering to another user's stream", %{user: user, token: read_oauth_token} do        another_user = insert(:user) -      assert {:error, _} = Streamer.get_topic("user:#{another_user.id}", user) -      assert {:error, _} = Streamer.get_topic("user:notification:#{another_user.id}", user) -      assert {:error, _} = Streamer.get_topic("direct:#{another_user.id}", user) +      assert {:error, _} = Streamer.get_topic("user:#{another_user.id}", user, read_oauth_token) + +      assert {:error, _} = +               Streamer.get_topic("user:notification:#{another_user.id}", user, read_oauth_token) + +      assert {:error, _} = Streamer.get_topic("direct:#{another_user.id}", user, read_oauth_token)      end -    test "allows list stream that are owned by the user", %{user: user} do +    test "allows list stream that are owned by the user (with `read` or `read:lists` scopes)", %{ +      user: user, +      token: read_oauth_token +    } do +      %{token: read_lists_token} = oauth_access(["read:lists"], user: user) +      %{token: invalid_token} = oauth_access(["irrelevant:scope"], user: user)        {:ok, list} = List.create("Test", user) -      assert {:error, _} = Streamer.get_topic("list:#{list.id}", user) -      assert {:ok, _} = Streamer.get_topic("list", user, %{"list" => list.id}) + +      assert {:error, _} = Streamer.get_topic("list:#{list.id}", user, read_oauth_token) + +      for valid_token <- [read_oauth_token, read_lists_token] do +        assert {:ok, _} = Streamer.get_topic("list", user, valid_token, %{"list" => list.id}) +      end + +      assert {:error, _} = Streamer.get_topic("list", user, invalid_token, %{"list" => list.id})      end -    test "disallows list stream that are not owned by the user", %{user: user} do +    test "disallows list stream that are not owned by the user", %{user: user, token: oauth_token} do        another_user = insert(:user)        {:ok, list} = List.create("Test", another_user) -      assert {:error, _} = Streamer.get_topic("list:#{list.id}", user) -      assert {:error, _} = Streamer.get_topic("list", user, %{"list" => list.id}) + +      assert {:error, _} = Streamer.get_topic("list:#{list.id}", user, oauth_token) +      assert {:error, _} = Streamer.get_topic("list", user, oauth_token, %{"list" => list.id})      end    end    describe "user streams" do      setup do -      user = insert(:user) +      %{user: user, token: token} = oauth_access(["read"])        notify = insert(:notification, user: user, activity: build(:note_activity)) -      {:ok, %{user: user, notify: notify}} +      {:ok, %{user: user, notify: notify, token: token}}      end -    test "it streams the user's post in the 'user' stream", %{user: user} do -      Streamer.get_topic_and_add_socket("user", user) +    test "it streams the user's post in the 'user' stream", %{user: user, token: oauth_token} do +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) +        assert_receive {:render_with_user, _, _, ^activity}        refute Streamer.filtered_by_user?(user, activity)      end -    test "it streams boosts of the user in the 'user' stream", %{user: user} do -      Streamer.get_topic_and_add_socket("user", user) +    test "it streams boosts of the user in the 'user' stream", %{user: user, token: oauth_token} do +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) @@ -117,9 +173,10 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it does not stream announces of the user's own posts in the 'user' stream", %{ -      user: user +      user: user, +      token: oauth_token      } do -      Streamer.get_topic_and_add_socket("user", user) +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) @@ -129,9 +186,10 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it does stream notifications announces of the user's own posts in the 'user' stream", %{ -      user: user +      user: user, +      token: oauth_token      } do -      Streamer.get_topic_and_add_socket("user", user) +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) @@ -145,8 +203,11 @@ defmodule Pleroma.Web.StreamerTest do        refute Streamer.filtered_by_user?(user, notification)      end -    test "it streams boosts of mastodon user in the 'user' stream", %{user: user} do -      Streamer.get_topic_and_add_socket("user", user) +    test "it streams boosts of mastodon user in the 'user' stream", %{ +      user: user, +      token: oauth_token +    } do +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) @@ -164,21 +225,34 @@ defmodule Pleroma.Web.StreamerTest do        refute Streamer.filtered_by_user?(user, announce)      end -    test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do -      Streamer.get_topic_and_add_socket("user", user) +    test "it sends notify to in the 'user' stream", %{ +      user: user, +      token: oauth_token, +      notify: notify +    } do +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        Streamer.stream("user", notify) +        assert_receive {:render_with_user, _, _, ^notify}        refute Streamer.filtered_by_user?(user, notify)      end -    test "it sends notify to in the 'user:notification' stream", %{user: user, notify: notify} do -      Streamer.get_topic_and_add_socket("user:notification", user) +    test "it sends notify to in the 'user:notification' stream", %{ +      user: user, +      token: oauth_token, +      notify: notify +    } do +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        Streamer.stream("user:notification", notify) +        assert_receive {:render_with_user, _, _, ^notify}        refute Streamer.filtered_by_user?(user, notify)      end -    test "it sends chat messages to the 'user:pleroma_chat' stream", %{user: user} do +    test "it sends chat messages to the 'user:pleroma_chat' stream", %{ +      user: user, +      token: oauth_token +    } do        other_user = insert(:user)        {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") @@ -187,7 +261,7 @@ defmodule Pleroma.Web.StreamerTest do        cm_ref = MessageReference.for_chat_and_object(chat, object)        cm_ref = %{cm_ref | chat: chat, object: object} -      Streamer.get_topic_and_add_socket("user:pleroma_chat", user) +      Streamer.get_topic_and_add_socket("user:pleroma_chat", user, oauth_token)        Streamer.stream("user:pleroma_chat", {user, cm_ref})        text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}) @@ -196,7 +270,7 @@ defmodule Pleroma.Web.StreamerTest do        assert_receive {:text, ^text}      end -    test "it sends chat messages to the 'user' stream", %{user: user} do +    test "it sends chat messages to the 'user' stream", %{user: user, token: oauth_token} do        other_user = insert(:user)        {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") @@ -205,7 +279,7 @@ defmodule Pleroma.Web.StreamerTest do        cm_ref = MessageReference.for_chat_and_object(chat, object)        cm_ref = %{cm_ref | chat: chat, object: object} -      Streamer.get_topic_and_add_socket("user", user) +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        Streamer.stream("user", {user, cm_ref})        text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}) @@ -214,7 +288,10 @@ defmodule Pleroma.Web.StreamerTest do        assert_receive {:text, ^text}      end -    test "it sends chat message notifications to the 'user:notification' stream", %{user: user} do +    test "it sends chat message notifications to the 'user:notification' stream", %{ +      user: user, +      token: oauth_token +    } do        other_user = insert(:user)        {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey") @@ -223,19 +300,21 @@ defmodule Pleroma.Web.StreamerTest do          Repo.get_by(Pleroma.Notification, user_id: user.id, activity_id: create_activity.id)          |> Repo.preload(:activity) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        Streamer.stream("user:notification", notify) +        assert_receive {:render_with_user, _, _, ^notify}        refute Streamer.filtered_by_user?(user, notify)      end      test "it doesn't send notify to the 'user:notification' stream when a user is blocked", %{ -      user: user +      user: user, +      token: oauth_token      } do        blocked = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, activity} = CommonAPI.post(user, %{status: ":("})        {:ok, _} = CommonAPI.favorite(blocked, activity.id) @@ -244,14 +323,15 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it doesn't send notify to the 'user:notification' stream when a thread is muted", %{ -      user: user +      user: user, +      token: oauth_token      } do        user2 = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"})        {:ok, _} = CommonAPI.add_mute(user, activity) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id) @@ -260,12 +340,13 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it sends favorite to 'user:notification' stream'", %{ -      user: user +      user: user, +      token: oauth_token      } do        user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})        {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id)        assert_receive {:render_with_user, _, "notification.json", notif} @@ -274,13 +355,14 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it doesn't send the 'user:notification' stream' when a domain is blocked", %{ -      user: user +      user: user, +      token: oauth_token      } do        user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})        {:ok, user} = User.block_domain(user, "hecking-lewd-place.com")        {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id)        refute_receive _ @@ -288,7 +370,8 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it sends follow activities to the 'user:notification' stream", %{ -      user: user +      user: user, +      token: oauth_token      } do        user_url = user.ap_id        user2 = insert(:user) @@ -303,7 +386,7 @@ defmodule Pleroma.Web.StreamerTest do            %Tesla.Env{status: 200, body: body}        end) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, _follower, _followed, follow_activity} = CommonAPI.follow(user2, user)        assert_receive {:render_with_user, _, "notification.json", notif} @@ -312,51 +395,53 @@ defmodule Pleroma.Web.StreamerTest do      end    end -  test "it sends to public authenticated" do -    user = insert(:user) -    other_user = insert(:user) +  describe "public streams" do +    test "it sends to public (authenticated)" do +      %{user: user, token: oauth_token} = oauth_access(["read"]) +      other_user = insert(:user) -    Streamer.get_topic_and_add_socket("public", other_user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token) -    {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) -    assert_receive {:render_with_user, _, _, ^activity} -    refute Streamer.filtered_by_user?(user, activity) -  end +      {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) +      assert_receive {:render_with_user, _, _, ^activity} +      refute Streamer.filtered_by_user?(other_user, activity) +    end -  test "works for deletions" do -    user = insert(:user) -    other_user = insert(:user) -    {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) +    test "it sends to public (unauthenticated)" do +      user = insert(:user) -    Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", nil, nil) -    {:ok, _} = CommonAPI.delete(activity.id, other_user) -    activity_id = activity.id -    assert_receive {:text, event} -    assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) -  end +      {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) +      activity_id = activity.id +      assert_receive {:text, event} +      assert %{"event" => "update", "payload" => payload} = Jason.decode!(event) +      assert %{"id" => ^activity_id} = Jason.decode!(payload) -  test "it sends to public unauthenticated" do -    user = insert(:user) +      {:ok, _} = CommonAPI.delete(activity.id, user) +      assert_receive {:text, event} +      assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) +    end -    Streamer.get_topic_and_add_socket("public", nil) +    test "handles deletions" do +      %{user: user, token: oauth_token} = oauth_access(["read"]) +      other_user = insert(:user) +      {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) -    {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) -    activity_id = activity.id -    assert_receive {:text, event} -    assert %{"event" => "update", "payload" => payload} = Jason.decode!(event) -    assert %{"id" => ^activity_id} = Jason.decode!(payload) +      Streamer.get_topic_and_add_socket("public", user, oauth_token) -    {:ok, _} = CommonAPI.delete(activity.id, user) -    assert_receive {:text, event} -    assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) +      {:ok, _} = CommonAPI.delete(activity.id, other_user) +      activity_id = activity.id +      assert_receive {:text, event} +      assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) +    end    end -  describe "thread_containment" do +  describe "thread_containment/2" do      test "it filters to user if recipients invalid and thread containment is enabled" do        Pleroma.Config.put([:instance, :skip_thread_containment], false)        author = insert(:user) -      user = insert(:user) +      %{user: user, token: oauth_token} = oauth_access(["read"])        User.follow(user, author, :follow_accept)        activity = @@ -368,7 +453,7 @@ defmodule Pleroma.Web.StreamerTest do              )          ) -      Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token)        Streamer.stream("public", activity)        assert_receive {:render_with_user, _, _, ^activity}        assert Streamer.filtered_by_user?(user, activity) @@ -377,7 +462,7 @@ defmodule Pleroma.Web.StreamerTest do      test "it sends message if recipients invalid and thread containment is disabled" do        Pleroma.Config.put([:instance, :skip_thread_containment], true)        author = insert(:user) -      user = insert(:user) +      %{user: user, token: oauth_token} = oauth_access(["read"])        User.follow(user, author, :follow_accept)        activity = @@ -389,7 +474,7 @@ defmodule Pleroma.Web.StreamerTest do              )          ) -      Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token)        Streamer.stream("public", activity)        assert_receive {:render_with_user, _, _, ^activity} @@ -400,6 +485,7 @@ defmodule Pleroma.Web.StreamerTest do        Pleroma.Config.put([:instance, :skip_thread_containment], false)        author = insert(:user)        user = insert(:user, skip_thread_containment: true) +      %{token: oauth_token} = oauth_access(["read"], user: user)        User.follow(user, author, :follow_accept)        activity = @@ -411,7 +497,7 @@ defmodule Pleroma.Web.StreamerTest do              )          ) -      Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token)        Streamer.stream("public", activity)        assert_receive {:render_with_user, _, _, ^activity} @@ -420,23 +506,26 @@ defmodule Pleroma.Web.StreamerTest do    end    describe "blocks" do -    test "it filters messages involving blocked users" do -      user = insert(:user) +    setup do: oauth_access(["read"]) + +    test "it filters messages involving blocked users", %{user: user, token: oauth_token} do        blocked_user = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked_user) -      Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token)        {:ok, activity} = CommonAPI.post(blocked_user, %{status: "Test"})        assert_receive {:render_with_user, _, _, ^activity}        assert Streamer.filtered_by_user?(user, activity)      end -    test "it filters messages transitively involving blocked users" do -      blocker = insert(:user) +    test "it filters messages transitively involving blocked users", %{ +      user: blocker, +      token: blocker_token +    } do        blockee = insert(:user)        friend = insert(:user) -      Streamer.get_topic_and_add_socket("public", blocker) +      Streamer.get_topic_and_add_socket("public", blocker, blocker_token)        {:ok, _user_relationship} = User.block(blocker, blockee) @@ -458,8 +547,9 @@ defmodule Pleroma.Web.StreamerTest do    end    describe "lists" do -    test "it doesn't send unwanted DMs to list" do -      user_a = insert(:user) +    setup do: oauth_access(["read"]) + +    test "it doesn't send unwanted DMs to list", %{user: user_a, token: user_a_token} do        user_b = insert(:user)        user_c = insert(:user) @@ -468,7 +558,7 @@ defmodule Pleroma.Web.StreamerTest do        {:ok, list} = List.create("Test", user_a)        {:ok, list} = List.follow(list, user_b) -      Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) +      Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id})        {:ok, _activity} =          CommonAPI.post(user_b, %{ @@ -479,14 +569,13 @@ defmodule Pleroma.Web.StreamerTest do        refute_receive _      end -    test "it doesn't send unwanted private posts to list" do -      user_a = insert(:user) +    test "it doesn't send unwanted private posts to list", %{user: user_a, token: user_a_token} do        user_b = insert(:user)        {:ok, list} = List.create("Test", user_a)        {:ok, list} = List.follow(list, user_b) -      Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) +      Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id})        {:ok, _activity} =          CommonAPI.post(user_b, %{ @@ -497,8 +586,7 @@ defmodule Pleroma.Web.StreamerTest do        refute_receive _      end -    test "it sends wanted private posts to list" do -      user_a = insert(:user) +    test "it sends wanted private posts to list", %{user: user_a, token: user_a_token} do        user_b = insert(:user)        {:ok, user_a} = User.follow(user_a, user_b) @@ -506,7 +594,7 @@ defmodule Pleroma.Web.StreamerTest do        {:ok, list} = List.create("Test", user_a)        {:ok, list} = List.follow(list, user_b) -      Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) +      Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id})        {:ok, activity} =          CommonAPI.post(user_b, %{ @@ -520,8 +608,9 @@ defmodule Pleroma.Web.StreamerTest do    end    describe "muted reblogs" do -    test "it filters muted reblogs" do -      user1 = insert(:user) +    setup do: oauth_access(["read"]) + +    test "it filters muted reblogs", %{user: user1, token: user1_token} do        user2 = insert(:user)        user3 = insert(:user)        CommonAPI.follow(user1, user2) @@ -529,34 +618,38 @@ defmodule Pleroma.Web.StreamerTest do        {:ok, create_activity} = CommonAPI.post(user3, %{status: "I'm kawen"}) -      Streamer.get_topic_and_add_socket("user", user1) +      Streamer.get_topic_and_add_socket("user", user1, user1_token)        {:ok, announce_activity} = CommonAPI.repeat(create_activity.id, user2)        assert_receive {:render_with_user, _, _, ^announce_activity}        assert Streamer.filtered_by_user?(user1, announce_activity)      end -    test "it filters reblog notification for reblog-muted actors" do -      user1 = insert(:user) +    test "it filters reblog notification for reblog-muted actors", %{ +      user: user1, +      token: user1_token +    } do        user2 = insert(:user)        CommonAPI.follow(user1, user2)        CommonAPI.hide_reblogs(user1, user2)        {:ok, create_activity} = CommonAPI.post(user1, %{status: "I'm kawen"}) -      Streamer.get_topic_and_add_socket("user", user1) +      Streamer.get_topic_and_add_socket("user", user1, user1_token)        {:ok, _announce_activity} = CommonAPI.repeat(create_activity.id, user2)        assert_receive {:render_with_user, _, "notification.json", notif}        assert Streamer.filtered_by_user?(user1, notif)      end -    test "it send non-reblog notification for reblog-muted actors" do -      user1 = insert(:user) +    test "it send non-reblog notification for reblog-muted actors", %{ +      user: user1, +      token: user1_token +    } do        user2 = insert(:user)        CommonAPI.follow(user1, user2)        CommonAPI.hide_reblogs(user1, user2)        {:ok, create_activity} = CommonAPI.post(user1, %{status: "I'm kawen"}) -      Streamer.get_topic_and_add_socket("user", user1) +      Streamer.get_topic_and_add_socket("user", user1, user1_token)        {:ok, _favorite_activity} = CommonAPI.favorite(user2, create_activity.id)        assert_receive {:render_with_user, _, "notification.json", notif} @@ -564,27 +657,28 @@ defmodule Pleroma.Web.StreamerTest do      end    end -  test "it filters posts from muted threads" do -    user = insert(:user) -    user2 = insert(:user) -    Streamer.get_topic_and_add_socket("user", user2) -    {:ok, user2, user, _activity} = CommonAPI.follow(user2, user) -    {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) -    {:ok, _} = CommonAPI.add_mute(user2, activity) -    assert_receive {:render_with_user, _, _, ^activity} -    assert Streamer.filtered_by_user?(user2, activity) +  describe "muted threads" do +    test "it filters posts from muted threads" do +      user = insert(:user) +      %{user: user2, token: user2_token} = oauth_access(["read"]) +      Streamer.get_topic_and_add_socket("user", user2, user2_token) + +      {:ok, user2, user, _activity} = CommonAPI.follow(user2, user) +      {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) +      {:ok, _} = CommonAPI.add_mute(user2, activity) + +      assert_receive {:render_with_user, _, _, ^activity} +      assert Streamer.filtered_by_user?(user2, activity) +    end    end    describe "direct streams" do -    setup do -      :ok -    end +    setup do: oauth_access(["read"]) -    test "it sends conversation update to the 'direct' stream", %{} do -      user = insert(:user) +    test "it sends conversation update to the 'direct' stream", %{user: user, token: oauth_token} do        another_user = insert(:user) -      Streamer.get_topic_and_add_socket("direct", user) +      Streamer.get_topic_and_add_socket("direct", user, oauth_token)        {:ok, _create_activity} =          CommonAPI.post(another_user, %{ @@ -602,11 +696,11 @@ defmodule Pleroma.Web.StreamerTest do        assert last_status["pleroma"]["direct_conversation_id"] == participation.id      end -    test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted" do -      user = insert(:user) +    test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted", +         %{user: user, token: oauth_token} do        another_user = insert(:user) -      Streamer.get_topic_and_add_socket("direct", user) +      Streamer.get_topic_and_add_socket("direct", user, oauth_token)        {:ok, create_activity} =          CommonAPI.post(another_user, %{ @@ -629,10 +723,12 @@ defmodule Pleroma.Web.StreamerTest do        refute_receive _      end -    test "it sends conversation update to the 'direct' stream when a message is deleted" do -      user = insert(:user) +    test "it sends conversation update to the 'direct' stream when a message is deleted", %{ +      user: user, +      token: oauth_token +    } do        another_user = insert(:user) -      Streamer.get_topic_and_add_socket("direct", user) +      Streamer.get_topic_and_add_socket("direct", user, oauth_token)        {:ok, create_activity} =          CommonAPI.post(another_user, %{ diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs index d164127ee..60f2fb052 100644 --- a/test/web/twitter_api/util_controller_test.exs +++ b/test/web/twitter_api/util_controller_test.exs @@ -21,170 +21,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do    setup do: clear_config([:instance])    setup do: clear_config([:frontend_configurations, :pleroma_fe]) -  describe "POST /api/pleroma/follow_import" do -    setup do: oauth_access(["follow"]) - -    test "it returns HTTP 200", %{conn: conn} do -      user2 = insert(:user) - -      response = -        conn -        |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"}) -        |> json_response(:ok) - -      assert response == "job started" -    end - -    test "it imports follow lists from file", %{user: user1, conn: conn} do -      user2 = insert(:user) - -      with_mocks([ -        {File, [], -         read!: fn "follow_list.txt" -> -           "Account address,Show boosts\n#{user2.ap_id},true" -         end} -      ]) do -        response = -          conn -          |> post("/api/pleroma/follow_import", %{"list" => %Plug.Upload{path: "follow_list.txt"}}) -          |> json_response(:ok) - -        assert response == "job started" - -        assert ObanHelpers.member?( -                 %{ -                   "op" => "follow_import", -                   "follower_id" => user1.id, -                   "followed_identifiers" => [user2.ap_id] -                 }, -                 all_enqueued(worker: Pleroma.Workers.BackgroundWorker) -               ) -      end -    end - -    test "it imports new-style mastodon follow lists", %{conn: conn} do -      user2 = insert(:user) - -      response = -        conn -        |> post("/api/pleroma/follow_import", %{ -          "list" => "Account address,Show boosts\n#{user2.ap_id},true" -        }) -        |> json_response(:ok) - -      assert response == "job started" -    end - -    test "requires 'follow' or 'write:follows' permissions" do -      token1 = insert(:oauth_token, scopes: ["read", "write"]) -      token2 = insert(:oauth_token, scopes: ["follow"]) -      token3 = insert(:oauth_token, scopes: ["something"]) -      another_user = insert(:user) - -      for token <- [token1, token2, token3] do -        conn = -          build_conn() -          |> put_req_header("authorization", "Bearer #{token.token}") -          |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"}) - -        if token == token3 do -          assert %{"error" => "Insufficient permissions: follow | write:follows."} == -                   json_response(conn, 403) -        else -          assert json_response(conn, 200) -        end -      end -    end - -    test "it imports follows with different nickname variations", %{conn: conn} do -      [user2, user3, user4, user5, user6] = insert_list(5, :user) - -      identifiers = -        [ -          user2.ap_id, -          user3.nickname, -          "  ", -          "@" <> user4.nickname, -          user5.nickname <> "@localhost", -          "@" <> user6.nickname <> "@localhost" -        ] -        |> Enum.join("\n") - -      response = -        conn -        |> post("/api/pleroma/follow_import", %{"list" => identifiers}) -        |> json_response(:ok) - -      assert response == "job started" -      assert [{:ok, job_result}] = ObanHelpers.perform_all() -      assert job_result == [user2, user3, user4, user5, user6] -    end -  end - -  describe "POST /api/pleroma/blocks_import" do -    # Note: "follow" or "write:blocks" permission is required -    setup do: oauth_access(["write:blocks"]) - -    test "it returns HTTP 200", %{conn: conn} do -      user2 = insert(:user) - -      response = -        conn -        |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"}) -        |> json_response(:ok) - -      assert response == "job started" -    end - -    test "it imports blocks users from file", %{user: user1, conn: conn} do -      user2 = insert(:user) -      user3 = insert(:user) - -      with_mocks([ -        {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} -      ]) do -        response = -          conn -          |> post("/api/pleroma/blocks_import", %{"list" => %Plug.Upload{path: "blocks_list.txt"}}) -          |> json_response(:ok) - -        assert response == "job started" - -        assert ObanHelpers.member?( -                 %{ -                   "op" => "blocks_import", -                   "blocker_id" => user1.id, -                   "blocked_identifiers" => [user2.ap_id, user3.ap_id] -                 }, -                 all_enqueued(worker: Pleroma.Workers.BackgroundWorker) -               ) -      end -    end - -    test "it imports blocks with different nickname variations", %{conn: conn} do -      [user2, user3, user4, user5, user6] = insert_list(5, :user) - -      identifiers = -        [ -          user2.ap_id, -          user3.nickname, -          "@" <> user4.nickname, -          user5.nickname <> "@localhost", -          "@" <> user6.nickname <> "@localhost" -        ] -        |> Enum.join(" ") - -      response = -        conn -        |> post("/api/pleroma/blocks_import", %{"list" => identifiers}) -        |> json_response(:ok) - -      assert response == "job started" -      assert [{:ok, job_result}] = ObanHelpers.perform_all() -      assert job_result == [user2, user3, user4, user5, user6] -    end -  end -    describe "PUT /api/pleroma/notification_settings" do      setup do: oauth_access(["write:accounts"]) | 
