diff options
| author | Ivan Tashkinov <ivantashkinov@gmail.com> | 2020-07-19 20:05:37 +0300 | 
|---|---|---|
| committer | Ivan Tashkinov <ivantashkinov@gmail.com> | 2020-07-19 20:05:37 +0300 | 
| commit | bdf57b8ef438f32999ef917777b13161320644a8 (patch) | |
| tree | b72dc8ce2621eeb25e14504d6ce73c6657fac571 /test | |
| parent | 9faa63203717e71d666afb6755ff0b781b491823 (diff) | |
| parent | f0d13fc3f7d0e9b58cfe1cd8918072d45d656a31 (diff) | |
| download | pleroma-bdf57b8ef438f32999ef917777b13161320644a8.tar.gz pleroma-bdf57b8ef438f32999ef917777b13161320644a8.zip | |
Merge remote-tracking branch 'remotes/origin/develop' into 2168-media-preview-proxy
# Conflicts:
#	config/config.exs
#	lib/pleroma/web/media_proxy/media_proxy.ex
#	mix.lock
#	test/web/media_proxy/media_proxy_test.exs
Diffstat (limited to 'test')
87 files changed, 2473 insertions, 2453 deletions
| diff --git a/test/activity_expiration_test.exs b/test/activity_expiration_test.exs index e899d4509..d75c06cc7 100644 --- a/test/activity_expiration_test.exs +++ b/test/activity_expiration_test.exs @@ -44,7 +44,7 @@ defmodule Pleroma.ActivityExpirationTest do          %{activity_id: activity.id, scheduled_at: naive_datetime}        ) -    Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(:ops, :pid) +    Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{})      refute Pleroma.Repo.get(Pleroma.Activity, activity.id)      refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id) diff --git a/test/config/deprecation_warnings_test.exs b/test/config/deprecation_warnings_test.exs index 548ee87b0..555661a71 100644 --- a/test/config/deprecation_warnings_test.exs +++ b/test/config/deprecation_warnings_test.exs @@ -54,4 +54,12 @@ defmodule Pleroma.Config.DeprecationWarningsTest do      assert Pleroma.Config.get(new_group2) == 2      assert Pleroma.Config.get(new_group3) == 3    end + +  test "check_media_proxy_whitelist_config/0" do +    clear_config([:media_proxy, :whitelist], ["https://example.com", "example2.com"]) + +    assert capture_log(fn -> +             Pleroma.Config.DeprecationWarnings.check_media_proxy_whitelist_config() +           end) =~ "Your config is using old format (only domain) for MediaProxy whitelist option" +  end  end diff --git a/test/config/holder_test.exs b/test/config/holder_test.exs index 15d48b5c7..abcaa27dd 100644 --- a/test/config/holder_test.exs +++ b/test/config/holder_test.exs @@ -10,7 +10,6 @@ defmodule Pleroma.Config.HolderTest do    test "default_config/0" do      config = Holder.default_config()      assert config[:pleroma][Pleroma.Uploaders.Local][:uploads] == "test/uploads" -    assert config[:tesla][:adapter] == Tesla.Mock      refute config[:pleroma][Pleroma.Repo]      refute config[:pleroma][Pleroma.Web.Endpoint] @@ -18,17 +17,15 @@ defmodule Pleroma.Config.HolderTest do      refute config[:pleroma][:configurable_from_database]      refute config[:pleroma][:database]      refute config[:phoenix][:serve_endpoints] +    refute config[:tesla][:adapter]    end    test "default_config/1" do      pleroma_config = Holder.default_config(:pleroma)      assert pleroma_config[Pleroma.Uploaders.Local][:uploads] == "test/uploads" -    tesla_config = Holder.default_config(:tesla) -    assert tesla_config[:adapter] == Tesla.Mock    end    test "default_config/2" do      assert Holder.default_config(:pleroma, Pleroma.Uploaders.Local) == [uploads: "test/uploads"] -    assert Holder.default_config(:tesla, :adapter) == Tesla.Mock    end  end diff --git a/test/docs/generator_test.exs b/test/docs/generator_test.exs index 9c9f4357b..b32918a69 100644 --- a/test/docs/generator_test.exs +++ b/test/docs/generator_test.exs @@ -13,21 +13,13 @@ defmodule Pleroma.Docs.GeneratorTest do            key: :uploader,            type: :module,            description: "", -          suggestions: -            Generator.list_modules_in_dir( -              "lib/pleroma/upload/filter", -              "Elixir.Pleroma.Upload.Filter." -            ) +          suggestions: {:list_behaviour_implementations, Pleroma.Upload.Filter}          },          %{            key: :filters,            type: {:list, :module},            description: "", -          suggestions: -            Generator.list_modules_in_dir( -              "lib/pleroma/web/activity_pub/mrf", -              "Elixir.Pleroma.Web.ActivityPub.MRF." -            ) +          suggestions: {:list_behaviour_implementations, Pleroma.Web.ActivityPub.MRF}          },          %{            key: Pleroma.Upload, diff --git a/test/emails/admin_email_test.exs b/test/emails/admin_email_test.exs index bc871a0a9..9082ae5a7 100644 --- a/test/emails/admin_email_test.exs +++ b/test/emails/admin_email_test.exs @@ -31,7 +31,7 @@ defmodule Pleroma.Emails.AdminEmailTest do                 account_url               }\">#{account.nickname}</a></p>\n<p>Comment: Test comment\n<p> Statuses:\n  <ul>\n    <li><a href=\"#{                 status_url -             }\">#{status_url}</li>\n  </ul>\n</p>\n\n" +             }\">#{status_url}</li>\n  </ul>\n</p>\n\n<p>\n<a href=\"http://localhost:4001/pleroma/admin/#/reports/index\">View Reports in AdminFE</a>\n"    end    test "it works when the reporter is a remote user without email" do diff --git a/test/filter_test.exs b/test/filter_test.exs index 63a30c736..0a5c4426a 100644 --- a/test/filter_test.exs +++ b/test/filter_test.exs @@ -3,37 +3,39 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.FilterTest do -  alias Pleroma.Repo    use Pleroma.DataCase    import Pleroma.Factory +  alias Pleroma.Filter +  alias Pleroma.Repo +    describe "creating filters" do      test "creating one filter" do        user = insert(:user) -      query = %Pleroma.Filter{ +      query = %Filter{          user_id: user.id,          filter_id: 42,          phrase: "knights",          context: ["home"]        } -      {:ok, %Pleroma.Filter{} = filter} = Pleroma.Filter.create(query) -      result = Pleroma.Filter.get(filter.filter_id, user) +      {:ok, %Filter{} = filter} = Filter.create(query) +      result = Filter.get(filter.filter_id, user)        assert query.phrase == result.phrase      end      test "creating one filter without a pre-defined filter_id" do        user = insert(:user) -      query = %Pleroma.Filter{ +      query = %Filter{          user_id: user.id,          phrase: "knights",          context: ["home"]        } -      {:ok, %Pleroma.Filter{} = filter} = Pleroma.Filter.create(query) +      {:ok, %Filter{} = filter} = Filter.create(query)        # Should start at 1        assert filter.filter_id == 1      end @@ -41,23 +43,23 @@ defmodule Pleroma.FilterTest do      test "creating additional filters uses previous highest filter_id + 1" do        user = insert(:user) -      query_one = %Pleroma.Filter{ +      query_one = %Filter{          user_id: user.id,          filter_id: 42,          phrase: "knights",          context: ["home"]        } -      {:ok, %Pleroma.Filter{} = filter_one} = Pleroma.Filter.create(query_one) +      {:ok, %Filter{} = filter_one} = Filter.create(query_one) -      query_two = %Pleroma.Filter{ +      query_two = %Filter{          user_id: user.id,          # No filter_id          phrase: "who",          context: ["home"]        } -      {:ok, %Pleroma.Filter{} = filter_two} = Pleroma.Filter.create(query_two) +      {:ok, %Filter{} = filter_two} = Filter.create(query_two)        assert filter_two.filter_id == filter_one.filter_id + 1      end @@ -65,29 +67,29 @@ defmodule Pleroma.FilterTest do        user_one = insert(:user)        user_two = insert(:user) -      query_one = %Pleroma.Filter{ +      query_one = %Filter{          user_id: user_one.id,          phrase: "knights",          context: ["home"]        } -      {:ok, %Pleroma.Filter{} = filter_one} = Pleroma.Filter.create(query_one) +      {:ok, %Filter{} = filter_one} = Filter.create(query_one) -      query_two = %Pleroma.Filter{ +      query_two = %Filter{          user_id: user_two.id,          phrase: "who",          context: ["home"]        } -      {:ok, %Pleroma.Filter{} = filter_two} = Pleroma.Filter.create(query_two) +      {:ok, %Filter{} = filter_two} = Filter.create(query_two)        assert filter_one.filter_id == 1        assert filter_two.filter_id == 1 -      result_one = Pleroma.Filter.get(filter_one.filter_id, user_one) +      result_one = Filter.get(filter_one.filter_id, user_one)        assert result_one.phrase == filter_one.phrase -      result_two = Pleroma.Filter.get(filter_two.filter_id, user_two) +      result_two = Filter.get(filter_two.filter_id, user_two)        assert result_two.phrase == filter_two.phrase      end    end @@ -95,38 +97,38 @@ defmodule Pleroma.FilterTest do    test "deleting a filter" do      user = insert(:user) -    query = %Pleroma.Filter{ +    query = %Filter{        user_id: user.id,        filter_id: 0,        phrase: "knights",        context: ["home"]      } -    {:ok, _filter} = Pleroma.Filter.create(query) -    {:ok, filter} = Pleroma.Filter.delete(query) -    assert is_nil(Repo.get(Pleroma.Filter, filter.filter_id)) +    {:ok, _filter} = Filter.create(query) +    {:ok, filter} = Filter.delete(query) +    assert is_nil(Repo.get(Filter, filter.filter_id))    end    test "getting all filters by an user" do      user = insert(:user) -    query_one = %Pleroma.Filter{ +    query_one = %Filter{        user_id: user.id,        filter_id: 1,        phrase: "knights",        context: ["home"]      } -    query_two = %Pleroma.Filter{ +    query_two = %Filter{        user_id: user.id,        filter_id: 2,        phrase: "who",        context: ["home"]      } -    {:ok, filter_one} = Pleroma.Filter.create(query_one) -    {:ok, filter_two} = Pleroma.Filter.create(query_two) -    filters = Pleroma.Filter.get_filters(user) +    {:ok, filter_one} = Filter.create(query_one) +    {:ok, filter_two} = Filter.create(query_two) +    filters = Filter.get_filters(user)      assert filter_one in filters      assert filter_two in filters    end @@ -134,7 +136,7 @@ defmodule Pleroma.FilterTest do    test "updating a filter" do      user = insert(:user) -    query_one = %Pleroma.Filter{ +    query_one = %Filter{        user_id: user.id,        filter_id: 1,        phrase: "knights", @@ -146,8 +148,9 @@ defmodule Pleroma.FilterTest do        context: ["home", "timeline"]      } -    {:ok, filter_one} = Pleroma.Filter.create(query_one) -    {:ok, filter_two} = Pleroma.Filter.update(filter_one, changes) +    {:ok, filter_one} = Filter.create(query_one) +    {:ok, filter_two} = Filter.update(filter_one, changes) +      assert filter_one != filter_two      assert filter_two.phrase == changes.phrase      assert filter_two.context == changes.context diff --git a/test/fixtures/DSCN0010.jpg b/test/fixtures/DSCN0010.jpgBinary files differ new file mode 100644 index 000000000..4a2c1552b --- /dev/null +++ b/test/fixtures/DSCN0010.jpg diff --git a/test/fixtures/tesla_mock/admin@mastdon.example.org.json b/test/fixtures/tesla_mock/admin@mastdon.example.org.json index 9fdd6557c..a911b979a 100644 --- a/test/fixtures/tesla_mock/admin@mastdon.example.org.json +++ b/test/fixtures/tesla_mock/admin@mastdon.example.org.json @@ -26,6 +26,9 @@    "summary": "\u003cp\u003e\u003c/p\u003e",    "url": "http://mastodon.example.org/@admin",    "manuallyApprovesFollowers": false, +  "capabilities": { +    "acceptsChatMessages": true +  },    "publicKey": {      "id": "http://mastodon.example.org/users/admin#main-key",      "owner": "http://mastodon.example.org/users/admin", diff --git a/test/fixtures/tesla_mock/framatube.org-video.json b/test/fixtures/tesla_mock/framatube.org-video.json new file mode 100644 index 000000000..3d53f0c97 --- /dev/null +++ b/test/fixtures/tesla_mock/framatube.org-video.json @@ -0,0 +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 diff --git a/test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json b/test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json new file mode 100644 index 000000000..1c3f779b3 --- /dev/null +++ b/test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json @@ -0,0 +1 @@ +{"type":"Person","id":"https://framatube.org/accounts/framasoft","following":"https://framatube.org/accounts/framasoft/following","followers":"https://framatube.org/accounts/framasoft/followers","playlists":"https://framatube.org/accounts/framasoft/playlists","inbox":"https://framatube.org/accounts/framasoft/inbox","outbox":"https://framatube.org/accounts/framasoft/outbox","preferredUsername":"framasoft","url":"https://framatube.org/accounts/framasoft","name":"Framasoft","endpoints":{"sharedInbox":"https://framatube.org/inbox"},"publicKey":{"id":"https://framatube.org/accounts/framasoft#main-key","owner":"https://framatube.org/accounts/framasoft","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuRh3frgIg866D0y0FThp\nSUkJImMcHGkUvpYQYv2iUgarZZtEbwT8PfQf0bJazy+cP8KqQmMDf5PBhT7dfdny\nf/GKGMw9Olc+QISeKDj3sqZ3Csrm4KV4avMGCfth6eSU7LozojeSGCXdUFz/8UgE\nfhV4mJjEX/FbwRYoKlagv5rY9mkX5XomzZU+z9j6ZVXyofwOwJvmI1hq0SYDv2bc\neB/RgIh/H0nyMtF8o+0CT42FNEET9j9m1BKOBtPzwZHmitKRkEmui5cK256s1laB\nT61KHpcD9gQKkQ+I3sFEzCBUJYfVo6fUe+GehBZuAfq4qDhd15SfE4K9veDscDFI\nTwIDAQAB\n-----END PUBLIC KEY-----"},"icon":{"type":"Image","mediaType":"image/png","url":"https://framatube.org/lazy-static/avatars/f73876f5-1d45-4f8a-942a-d3d5d5ac5dc1.png"},"@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","expires":"sc:expires","CacheFile":"pt:CacheFile","Infohash":"pt:Infohash","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"}}],"summary":null}
\ No newline at end of file diff --git a/test/fixtures/tesla_mock/https___osada.macgirvin.com.html b/test/fixtures/tesla_mock/https___osada.macgirvin.com.html new file mode 100644 index 000000000..880273d74 --- /dev/null +++ b/test/fixtures/tesla_mock/https___osada.macgirvin.com.html @@ -0,0 +1,301 @@ +<!DOCTYPE html > +<html prefix="og: http://ogp.me/ns#"> +<head> +  <title>Osada</title> +  <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> +<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, user-scalable=0"/> +<meta property="generator" content="osada"/> +<link rel="stylesheet" href="http://osada.macgirvin.com/library/fork-awesome/css/fork-awesome.min.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/vendor/twbs/bootstrap/dist/css/bootstrap.min.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/library/bootstrap-tagsinput/bootstrap-tagsinput.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/view/css/bootstrap-red.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/library/datetimepicker/jquery.datetimepicker.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/library/bootstrap-colorpicker/dist/css/bootstrap-colorpicker.min.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/library/tiptip/tipTip.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/library/jgrowl/jquery.jgrowl.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/library/jRange/jquery.range.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/view/css/conversation.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/view/css/widgets.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/view/css/colorbox.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/library/justifiedGallery/justifiedGallery.min.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/view/css/default.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/view/css/mod_home.css?v=2.3" type="text/css" media="screen"> +<link rel="stylesheet" href="http://osada.macgirvin.com/view/theme/redbasic/php/style.pcss?v=2.3" type="text/css" media="screen"> + +<script> + +	var aStr = { + +		'delitem'     : "Delete this item?", +		'comment'     : "Comment", +		'showmore'    : "<i class='fa fa-chevron-down'></i> show all", +		'showfewer'   : "<i class='fa fa-chevron-up'></i> show less", +		'divgrowmore' : "<i class='fa fa-chevron-down'></i> expand", +		'divgrowless' : "<i class='fa fa-chevron-up'></i> collapse", +		'pwshort'     : "Password too short", +		'pwnomatch'   : "Passwords do not match", +		'everybody'   : "everybody", +		'passphrase'  : "Secret Passphrase", +		'passhint'    : "Passphrase hint", +		'permschange' : "Notice: Permissions have changed but have not yet been submitted.", +		'closeAll'    : "close all", +		'nothingnew'  : "Nothing new here", +		'rating_desc' : "Rate This Channel (this is public)", +		'rating_val'  : "Rating", +		'rating_text' : "Describe (optional)", +		'submit'      : "Submit", +		'linkurl'     : "Please enter a link URL", +		'leavethispage' : "Unsaved changes. Are you sure you wish to leave this page?", +		'location'    : "Location", +		'lovely'      : "lovely", +		'wonderful'   : "wonderful", +		'fantastic'   : "fantastic", +		'great'       : "great", +		'nick_invld1' : "Your chosen nickname was either already taken or not valid. Please use our suggestion (", +		'nick_invld2' : ") or enter a new one.", +		'nick_valid'  : "Thank you, this nickname is valid.", +		'name_empty'  : "A channel name is required.", +		'name_ok1'    : "This is a ", +		'name_ok2'    : " channel name", + + + +		't01' : "", +		't02' : "", +		't03' : "ago", +		't04' : "from now", +		't05' : "less than a minute", +		't06' : "about a minute", +		't07' : "%d minutes", +		't08' : "about an hour", +		't09' : "about %d hours", +		't10' : "a day", +		't11' : "%d days", +		't12' : "about a month", +		't13' : "%d months", +		't14' : "about a year", +		't15' : "%d years", +		't16' : " ", +		't17' : "[]", + +		'monthNames' : [ "January","February","March","April","May","June","July","August","September","October","November","December" ], +		'monthNamesShort' : [ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" ], +		'dayNames' : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], +		'dayNamesShort' : ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], +		'today' : "today", +		'month' : "month", +		'week' : "week", +		'day' : "day", +		'allday' : "All day" +	}; + +</script> +		 + +<script src="http://osada.macgirvin.com/view/js/jquery.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/justifiedGallery/jquery.justifiedGallery.min.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/sprintf.js/dist/sprintf.min.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/textcomplete/textcomplete.min.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/view/js/autocomplete.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/jquery.timeago.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/readmore.js/readmore.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/sticky-kit/sticky-kit.min.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/jgrowl/jquery.jgrowl_minimized.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/view/js/acl.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/view/js/webtoolkit.base64.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/jRange/jquery.range.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/colorbox/jquery.colorbox-min.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/jquery.AreYouSure/jquery.are-you-sure.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/tableofcontents/jquery.toc.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/imagesloaded/imagesloaded.pkgd.min.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/vendor/twbs/bootstrap/dist/js/bootstrap.bundle.min.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/bootbox/bootbox.min.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/bootstrap-tagsinput/bootstrap-tagsinput.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/datetimepicker/jquery.datetimepicker.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/library/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.js?v=2.3"></script> +<script src="http://osada.macgirvin.com/view/theme/redbasic/js/redbasic.js?v=2.3"></script> + + + +<script> +	var updateInterval = 80000; +	var localUser = false; +	var zid = null; +	var justifiedGalleryActive = false; +			var preloadImages = 0; +</script> + + + +<script>$(document).ready(function() { $("#nav-search-text").search_autocomplete('https://osada.macgirvin.com/acl');});</script><script src="http://osada.macgirvin.com/view/js/main.js?v=2.3"></script> +</head> +<body> +		<header></header> +	<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark"><div class="project-banner" title="Powered by Osada"><a href="https://osada.macgirvin.com/">☸</a></div> +<div class="d-lg-none pt-1 pb-1"> +		<a class="btn btn-primary btn-sm text-white" href="#" title="Sign in" id="login_nav_btn_collapse" data-toggle="modal" data-target="#nav-login"> +		Login +	</a> +		</div> +<div class="navbar-toggler-right"> +		<button id="expand-aside" type="button" class="d-lg-none navbar-toggler border-0" data-toggle="offcanvas" data-target="#region_1"> +		<i class="fa fa-arrow-circle-right" id="expand-aside-icon"></i> +	</button> +		<button id="menu-btn" class="navbar-toggler border-0" type="button" data-toggle="collapse" data-target="#navbar-collapse-2"> +		<i class="fa fa-bars"></i> +	</button> +</div> +<div class="collapse navbar-collapse" id="navbar-collapse-1"> +	<ul class="navbar-nav mr-auto"> +				<li class="nav-item d-lg-flex"> +						<a class="nav-link" href="#" title="Sign in" id="login_nav_btn" data-toggle="modal" data-target="#nav-login"> +			Login +			</a> +					</li> +							</ul> + +	<div id="banner" class="navbar-text"></div> + +	<ul id="nav-right" class="navbar-nav ml-auto"> +		<li class="nav-item collapse clearfix" id="nav-search"> +			<form class="form-inline" method="get" action="search" role="search"> +				<input class="form-control form-control-sm mt-1 mr-2" id="nav-search-text" type="text" value="" placeholder="@name, !forum, #tag, content" name="search" title="Search site @name, !forum, #tag, ?docs, content" onclick="this.submit();" onblur="closeMenu('nav-search'); openMenu('nav-search-btn');"/> +			</form> +			<div id="nav-search-spinner" class="spinner-wrapper"> +				<div class="spinner s"></div> +			</div> +		</li> +		<li class="nav-item" id="nav-search-btn"> +			<a class="nav-link" href="#nav-search" title="Search site @name, !forum, #tag, ?docs, content" onclick="openMenu('nav-search'); closeMenu('nav-search-btn'); $('#nav-search-text').focus(); return false;"><i class="fa fa-fw fa-search"></i></a> +		</li> +										<li class="nav-item dropdown" id="app-menu"> +			<a class="nav-link" href="#" data-toggle="dropdown"><i class="fa fa-fw fa-bars"></i></a> +			<div id="dropdown-menu" class="dropdown-menu dropdown-menu-right"> +												<a class="dropdown-item" href="https://osada.macgirvin.com/directory"><i class="generic-icons-nav fa fa-fw fa-sitemap"></i>Directory</a> + + +								<a class="dropdown-item" href="https://osada.macgirvin.com/lang"><i class="generic-icons-nav fa fa-fw fa-language"></i>Language</a> + + +								<a class="dropdown-item" href="https://osada.macgirvin.com/search"><i class="generic-icons-nav fa fa-fw fa-search"></i>Search</a> + + +															</div> +		</li> +	</ul> +</div> +<div class="collapse d-lg-none" id="navbar-collapse-2"> +	<div class="navbar-nav mr-auto"> +								<a class="nav-link" href="https://osada.macgirvin.com/directory"><i class="generic-icons-nav fa fa-fw fa-sitemap"></i>Directory</a> + + +				<a class="nav-link" href="https://osada.macgirvin.com/lang"><i class="generic-icons-nav fa fa-fw fa-language"></i>Language</a> + + +				<a class="nav-link" href="https://osada.macgirvin.com/search"><i class="generic-icons-nav fa fa-fw fa-search"></i>Search</a> + + +							</div> +</div> +</nav> +	<main> +		<aside id="region_1"><div class="aside_spacer"><div id="left_aside_wrapper"></div></div></aside> +		<section id="region_2"><h1 class="home-welcome">Welcome to Osada</h1><form action="https://osada.macgirvin.com/" id="main-login" method="post"> +	<input type="hidden" name="auth-params" value="login"/> +	<div id="login-main"> +		<div id="login-input" class="form-group"> +				<div id="id_username_wrapper" class="form-group"> +		<label for="id_username" id="label_username">Login/Email</label> +		<input class="form-control" name="username" id="id_username" type="text" value=""> +		<small id="help_username" class="form-text text-muted"></small> +	</div> +				<div class="form-group"> +		<label for="id_password">Password</label> +		<input class="form-control" type="password" name="password" id="id_password" value="">		<small id="help_password" class="form-text text-muted"></small> +	</div> +				<div id="remember_container" class="clearfix form-group checkbox"> +		<label for="id_remember">Remember me</label> +		<div class="float-right"><input type="checkbox" name="remember" id="id_remember" value="1"/><label class="switchlabel" for="id_remember"> <span class="onoffswitch-inner" data-on="Yes" data-off="No"></span><span class="onoffswitch-switch"></span></label></div> +		<small class="form-text text-muted"></small> +	</div> +			<button type="submit" name="submit" class="btn btn-block btn-primary">Login</button> +		</div> +		<div id="login-extra-links"> +			<a href="https://osada.macgirvin.com/pubsites" title="Create an account to access services and applications" id="register-link" class="pull-right">Register</a>			<a href="lostpass" title="Forgot your password?" id="lost-password-link">Password Reset</a> +		</div> +		<hr> +		<a href="rmagic" class="btn btn-block btn-outline-success rmagic-button">Remote Authentication</a> +	</div> +			<input type="hidden" name="0" value=""/> +	</form> +<script type="text/javascript"> $(document).ready(function() { $("#id_username").focus();} );</script> +<div id="nav-login" class="modal" tabindex="-1" role="dialog"> +	<div class="modal-dialog" role="document"> +		<div class="modal-content"> +			<div class="modal-header"> +				<h4 class="modal-title">Login</h4> +				<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> +			</div> +			<div class="modal-body"> +				<div class="form-group"> +					<form action="https://osada.macgirvin.com/" id="main-login" method="post"> +	<input type="hidden" name="auth-params" value="login"/> +	<div id="login-main"> +		<div id="login-input" class="form-group"> +				<div id="id_username_wrapper" class="form-group"> +		<label for="id_username" id="label_username">Login/Email</label> +		<input class="form-control" name="username" id="id_username" type="text" value=""> +		<small id="help_username" class="form-text text-muted"></small> +	</div> +				<div class="form-group"> +		<label for="id_password">Password</label> +		<input class="form-control" type="password" name="password" id="id_password" value="">		<small id="help_password" class="form-text text-muted"></small> +	</div> +				<div id="remember_me_container" class="clearfix form-group checkbox"> +		<label for="id_remember_me">Remember me</label> +		<div class="float-right"><input type="checkbox" name="remember_me" id="id_remember_me" value="1"/><label class="switchlabel" for="id_remember_me"> <span class="onoffswitch-inner" data-on="Yes" data-off="No"></span><span class="onoffswitch-switch"></span></label></div> +		<small class="form-text text-muted"></small> +	</div> +			<button type="submit" name="submit" class="btn btn-block btn-primary">Login</button> +		</div> +		<div id="login-extra-links"> +			<a href="https://osada.macgirvin.com/pubsites" title="Create an account to access services and applications" id="register-link" class="pull-right">Register</a>			<a href="lostpass" title="Forgot your password?" id="lost-password-link">Password Reset</a> +		</div> +		<hr> +		<a href="rmagic" class="btn btn-block btn-outline-success rmagic-button">Remote Authentication</a> +	</div> +			<input type="hidden" name="0" value=""/> +	</form> + +				</div> +			</div> +		</div> +	</div> +</div> +					<div id="page-footer"></div> +			<div id="pause"></div> +		</section> +		<aside id="region_3" class="d-none d-xl-table-cell"><div class="aside_spacer"><div id="right_aside_wrapper"></div></div></aside> +	</main> +	<footer></footer> +</body> +</html> +<!-- +     FILE ARCHIVED ON 11:49:38 Jan 26, 2019 AND RETRIEVED FROM THE +     INTERNET ARCHIVE ON 04:27:56 Mar 02, 2020. + +     CONTENT MAY BE PROTECTED BY COPYRIGHT (17 U.S.C. SECTION 108(a)(3)). +--> +<!-- +playback timings (ms): +  exclusion.robots: 0.217 +  CDXLines.iter: 14.7 (3) +  LoadShardBlock: 165.298 (3) +  esindex: 0.01 +  PetaboxLoader3.datanode: 72.599 (4) +  exclusion.robots.policy: 0.208 +  RedisCDXSource: 16.804 +  PetaboxLoader3.resolve: 146.316 (4) +  captures_list: 199.59 +  load_resource: 56.473 +-->
\ No newline at end of file diff --git a/test/gun/conneciton_pool_test.exs b/test/gun/conneciton_pool_test.exs new file mode 100644 index 000000000..aea908fac --- /dev/null +++ b/test/gun/conneciton_pool_test.exs @@ -0,0 +1,101 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Gun.ConnectionPoolTest do +  use Pleroma.DataCase + +  import Mox +  import ExUnit.CaptureLog +  alias Pleroma.Config +  alias Pleroma.Gun.ConnectionPool + +  defp gun_mock(_) do +    Pleroma.GunMock +    |> stub(:open, fn _, _, _ -> Task.start_link(fn -> Process.sleep(100) end) end) +    |> stub(:await_up, fn _, _ -> {:ok, :http} end) +    |> stub(:set_owner, fn _, _ -> :ok end) + +    :ok +  end + +  setup :set_mox_from_context +  setup :gun_mock + +  test "gives the same connection to 2 concurrent requests" do +    Enum.map( +      [ +        "http://www.korean-books.com.kp/KBMbooks/en/periodic/pictorial/20200530163914.pdf", +        "http://www.korean-books.com.kp/KBMbooks/en/periodic/pictorial/20200528183427.pdf" +      ], +      fn uri -> +        uri = URI.parse(uri) +        task_parent = self() + +        Task.start_link(fn -> +          {:ok, conn} = ConnectionPool.get_conn(uri, []) +          ConnectionPool.release_conn(conn) +          send(task_parent, conn) +        end) +      end +    ) + +    [pid, pid] = +      for _ <- 1..2 do +        receive do +          pid -> pid +        end +      end +  end + +  test "connection limit is respected with concurrent requests" do +    clear_config([:connections_pool, :max_connections]) do +      Config.put([:connections_pool, :max_connections], 1) +      # The supervisor needs a reboot to apply the new config setting +      Process.exit(Process.whereis(Pleroma.Gun.ConnectionPool.WorkerSupervisor), :kill) + +      on_exit(fn -> +        Process.exit(Process.whereis(Pleroma.Gun.ConnectionPool.WorkerSupervisor), :kill) +      end) +    end + +    capture_log(fn -> +      Enum.map( +        [ +          "https://ninenines.eu/", +          "https://youtu.be/PFGwMiDJKNY" +        ], +        fn uri -> +          uri = URI.parse(uri) +          task_parent = self() + +          Task.start_link(fn -> +            result = ConnectionPool.get_conn(uri, []) +            # Sleep so that we don't end up with a situation, +            # where request from the second process gets processed +            # only after the first process already released the connection +            Process.sleep(50) + +            case result do +              {:ok, pid} -> +                ConnectionPool.release_conn(pid) + +              _ -> +                nil +            end + +            send(task_parent, result) +          end) +        end +      ) + +      [{:error, :pool_full}, {:ok, _pid}] = +        for _ <- 1..2 do +          receive do +            result -> result +          end +        end +        |> Enum.sort() +    end) +  end +end diff --git a/test/http/adapter_helper/gun_test.exs b/test/http/adapter_helper/gun_test.exs index 2e961826e..80589c73d 100644 --- a/test/http/adapter_helper/gun_test.exs +++ b/test/http/adapter_helper/gun_test.exs @@ -9,24 +9,10 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do    import Mox    alias Pleroma.Config -  alias Pleroma.Gun.Conn    alias Pleroma.HTTP.AdapterHelper.Gun -  alias Pleroma.Pool.Connections    setup :verify_on_exit! -  defp gun_mock(_) do -    gun_mock() -    :ok -  end - -  defp gun_mock do -    Pleroma.GunMock -    |> stub(:open, fn _, _, _ -> Task.start_link(fn -> Process.sleep(1000) end) end) -    |> stub(:await_up, fn _, _ -> {:ok, :http} end) -    |> stub(:set_owner, fn _, _ -> :ok end) -  end -    describe "options/1" do      setup do: clear_config([:http, :adapter], a: 1, b: 2) @@ -35,7 +21,6 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do        opts = Gun.options([receive_conn: false], uri)        assert opts[:certificates_verification] -      assert opts[:tls_opts][:log_level] == :warning      end      test "https ipv4 with default port" do @@ -43,7 +28,6 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do        opts = Gun.options([receive_conn: false], uri)        assert opts[:certificates_verification] -      assert opts[:tls_opts][:log_level] == :warning      end      test "https ipv6 with default port" do @@ -51,7 +35,6 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do        opts = Gun.options([receive_conn: false], uri)        assert opts[:certificates_verification] -      assert opts[:tls_opts][:log_level] == :warning      end      test "https url with non standart port" do @@ -62,46 +45,12 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do        assert opts[:certificates_verification]      end -    test "get conn on next request" do -      gun_mock() -      level = Application.get_env(:logger, :level) -      Logger.configure(level: :debug) -      on_exit(fn -> Logger.configure(level: level) end) -      uri = URI.parse("http://some-domain2.com") - -      opts = Gun.options(uri) - -      assert opts[:conn] == nil -      assert opts[:close_conn] == nil - -      Process.sleep(50) -      opts = Gun.options(uri) - -      assert is_pid(opts[:conn]) -      assert opts[:close_conn] == false -    end -      test "merges with defaul http adapter config" do        defaults = Gun.options([receive_conn: false], URI.parse("https://example.com"))        assert Keyword.has_key?(defaults, :a)        assert Keyword.has_key?(defaults, :b)      end -    test "default ssl adapter opts with connection" do -      gun_mock() -      uri = URI.parse("https://some-domain.com") - -      :ok = Conn.open(uri, :gun_connections) - -      opts = Gun.options(uri) - -      assert opts[:certificates_verification] -      refute opts[:tls_opts] == [] - -      assert opts[:close_conn] == false -      assert is_pid(opts[:conn]) -    end -      test "parses string proxy host & port" do        proxy = Config.get([:http, :proxy_url])        Config.put([:http, :proxy_url], "localhost:8123") @@ -132,127 +81,4 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do        assert opts[:proxy] == {'example.com', 4321}      end    end - -  describe "options/1 with receive_conn parameter" do -    setup :gun_mock - -    test "receive conn by default" do -      uri = URI.parse("http://another-domain.com") -      :ok = Conn.open(uri, :gun_connections) - -      received_opts = Gun.options(uri) -      assert received_opts[:close_conn] == false -      assert is_pid(received_opts[:conn]) -    end - -    test "don't receive conn if receive_conn is false" do -      uri = URI.parse("http://another-domain.com") -      :ok = Conn.open(uri, :gun_connections) - -      opts = [receive_conn: false] -      received_opts = Gun.options(opts, uri) -      assert received_opts[:close_conn] == nil -      assert received_opts[:conn] == nil -    end -  end - -  describe "after_request/1" do -    setup :gun_mock - -    test "body_as not chunks" do -      uri = URI.parse("http://some-domain.com") -      :ok = Conn.open(uri, :gun_connections) -      opts = Gun.options(uri) -      :ok = Gun.after_request(opts) -      conn = opts[:conn] - -      assert %Connections{ -               conns: %{ -                 "http:some-domain.com:80" => %Pleroma.Gun.Conn{ -                   conn: ^conn, -                   conn_state: :idle, -                   used_by: [] -                 } -               } -             } = Connections.get_state(:gun_connections) -    end - -    test "body_as chunks" do -      uri = URI.parse("http://some-domain.com") -      :ok = Conn.open(uri, :gun_connections) -      opts = Gun.options([body_as: :chunks], uri) -      :ok = Gun.after_request(opts) -      conn = opts[:conn] -      self = self() - -      assert %Connections{ -               conns: %{ -                 "http:some-domain.com:80" => %Pleroma.Gun.Conn{ -                   conn: ^conn, -                   conn_state: :active, -                   used_by: [{^self, _}] -                 } -               } -             } = Connections.get_state(:gun_connections) -    end - -    test "with no connection" do -      uri = URI.parse("http://uniq-domain.com") - -      :ok = Conn.open(uri, :gun_connections) - -      opts = Gun.options([body_as: :chunks], uri) -      conn = opts[:conn] -      opts = Keyword.delete(opts, :conn) -      self = self() - -      :ok = Gun.after_request(opts) - -      assert %Connections{ -               conns: %{ -                 "http:uniq-domain.com:80" => %Pleroma.Gun.Conn{ -                   conn: ^conn, -                   conn_state: :active, -                   used_by: [{^self, _}] -                 } -               } -             } = Connections.get_state(:gun_connections) -    end - -    test "with ipv4" do -      uri = URI.parse("http://127.0.0.1") -      :ok = Conn.open(uri, :gun_connections) -      opts = Gun.options(uri) -      :ok = Gun.after_request(opts) -      conn = opts[:conn] - -      assert %Connections{ -               conns: %{ -                 "http:127.0.0.1:80" => %Pleroma.Gun.Conn{ -                   conn: ^conn, -                   conn_state: :idle, -                   used_by: [] -                 } -               } -             } = Connections.get_state(:gun_connections) -    end - -    test "with ipv6" do -      uri = URI.parse("http://[2a03:2880:f10c:83:face:b00c:0:25de]") -      :ok = Conn.open(uri, :gun_connections) -      opts = Gun.options(uri) -      :ok = Gun.after_request(opts) -      conn = opts[:conn] - -      assert %Connections{ -               conns: %{ -                 "http:2a03:2880:f10c:83:face:b00c:0:25de:80" => %Pleroma.Gun.Conn{ -                   conn: ^conn, -                   conn_state: :idle, -                   used_by: [] -                 } -               } -             } = Connections.get_state(:gun_connections) -    end -  end  end diff --git a/test/http/connection_test.exs b/test/http/connection_test.exs deleted file mode 100644 index 7c94a50b2..000000000 --- a/test/http/connection_test.exs +++ /dev/null @@ -1,135 +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.HTTP.ConnectionTest do -  use ExUnit.Case -  use Pleroma.Tests.Helpers - -  import ExUnit.CaptureLog - -  alias Pleroma.Config -  alias Pleroma.HTTP.Connection - -  describe "parse_host/1" do -    test "as atom to charlist" do -      assert Connection.parse_host(:localhost) == 'localhost' -    end - -    test "as string to charlist" do -      assert Connection.parse_host("localhost.com") == 'localhost.com' -    end - -    test "as string ip to tuple" do -      assert Connection.parse_host("127.0.0.1") == {127, 0, 0, 1} -    end -  end - -  describe "parse_proxy/1" do -    test "ip with port" do -      assert Connection.parse_proxy("127.0.0.1:8123") == {:ok, {127, 0, 0, 1}, 8123} -    end - -    test "host with port" do -      assert Connection.parse_proxy("localhost:8123") == {:ok, 'localhost', 8123} -    end - -    test "as tuple" do -      assert Connection.parse_proxy({:socks4, :localhost, 9050}) == -               {:ok, :socks4, 'localhost', 9050} -    end - -    test "as tuple with string host" do -      assert Connection.parse_proxy({:socks5, "localhost", 9050}) == -               {:ok, :socks5, 'localhost', 9050} -    end -  end - -  describe "parse_proxy/1 errors" do -    test "ip without port" do -      capture_log(fn -> -        assert Connection.parse_proxy("127.0.0.1") == {:error, :invalid_proxy} -      end) =~ "parsing proxy fail \"127.0.0.1\"" -    end - -    test "host without port" do -      capture_log(fn -> -        assert Connection.parse_proxy("localhost") == {:error, :invalid_proxy} -      end) =~ "parsing proxy fail \"localhost\"" -    end - -    test "host with bad port" do -      capture_log(fn -> -        assert Connection.parse_proxy("localhost:port") == {:error, :invalid_proxy_port} -      end) =~ "parsing port in proxy fail \"localhost:port\"" -    end - -    test "ip with bad port" do -      capture_log(fn -> -        assert Connection.parse_proxy("127.0.0.1:15.9") == {:error, :invalid_proxy_port} -      end) =~ "parsing port in proxy fail \"127.0.0.1:15.9\"" -    end - -    test "as tuple without port" do -      capture_log(fn -> -        assert Connection.parse_proxy({:socks5, :localhost}) == {:error, :invalid_proxy} -      end) =~ "parsing proxy fail {:socks5, :localhost}" -    end - -    test "with nil" do -      assert Connection.parse_proxy(nil) == nil -    end -  end - -  describe "options/3" do -    setup do: clear_config([:http, :proxy_url]) - -    test "without proxy_url in config" do -      Config.delete([:http, :proxy_url]) - -      opts = Connection.options(%URI{}) -      refute Keyword.has_key?(opts, :proxy) -    end - -    test "parses string proxy host & port" do -      Config.put([:http, :proxy_url], "localhost:8123") - -      opts = Connection.options(%URI{}) -      assert opts[:proxy] == {'localhost', 8123} -    end - -    test "parses tuple proxy scheme host and port" do -      Config.put([:http, :proxy_url], {:socks, 'localhost', 1234}) - -      opts = Connection.options(%URI{}) -      assert opts[:proxy] == {:socks, 'localhost', 1234} -    end - -    test "passed opts have more weight than defaults" do -      Config.put([:http, :proxy_url], {:socks5, 'localhost', 1234}) - -      opts = Connection.options(%URI{}, proxy: {'example.com', 4321}) - -      assert opts[:proxy] == {'example.com', 4321} -    end -  end - -  describe "format_host/1" do -    test "with domain" do -      assert Connection.format_host("example.com") == 'example.com' -    end - -    test "with idna domain" do -      assert Connection.format_host("ですexample.com") == 'xn--example-183fne.com' -    end - -    test "with ipv4" do -      assert Connection.format_host("127.0.0.1") == '127.0.0.1' -    end - -    test "with ipv6" do -      assert Connection.format_host("2a03:2880:f10c:83:face:b00c:0:25de") == -               '2a03:2880:f10c:83:face:b00c:0:25de' -    end -  end -end diff --git a/test/notification_test.exs b/test/notification_test.exs index 6add3f7eb..8243cfd34 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -246,49 +246,18 @@ defmodule Pleroma.NotificationTest do        assert Notification.create_notification(activity, muter)      end -    test "it disables notifications from followers" do -      follower = insert(:user) - -      followed = -        insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false}) - -      User.follow(follower, followed) -      {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"}) -      refute Notification.create_notification(activity, followed) -    end - -    test "it disables notifications from non-followers" do +    test "it disables notifications from strangers" do        follower = insert(:user)        followed =          insert(:user, -          notification_settings: %Pleroma.User.NotificationSetting{non_followers: false} +          notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}          )        {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})        refute Notification.create_notification(activity, followed)      end -    test "it disables notifications from people the user follows" do -      follower = -        insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false}) - -      followed = insert(:user) -      User.follow(follower, followed) -      follower = Repo.get(User, follower.id) -      {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"}) -      refute Notification.create_notification(activity, follower) -    end - -    test "it disables notifications from people the user does not follow" do -      follower = -        insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false}) - -      followed = insert(:user) -      {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"}) -      refute Notification.create_notification(activity, follower) -    end -      test "it doesn't create a notification for user if he is the activity author" do        activity = insert(:note_activity)        author = User.get_cached_by_ap_id(activity.data["actor"]) @@ -324,6 +293,44 @@ defmodule Pleroma.NotificationTest do        {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})        refute Notification.create_notification(status, user)      end + +    test "it doesn't create notifications if content matches with an irreversible filter" do +      user = insert(:user) +      subscriber = insert(:user) + +      User.subscribe(subscriber, user) +      insert(:filter, user: subscriber, phrase: "cofe", hide: true) + +      {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"}) + +      assert {:ok, []} == Notification.create_notifications(status) +    end + +    test "it creates notifications if content matches with a not irreversible filter" do +      user = insert(:user) +      subscriber = insert(:user) + +      User.subscribe(subscriber, user) +      insert(:filter, user: subscriber, phrase: "cofe", hide: false) + +      {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"}) +      {:ok, [notification]} = Notification.create_notifications(status) + +      assert notification +    end + +    test "it creates notifications when someone likes user's status with a filtered word" do +      user = insert(:user) +      other_user = insert(:user) +      insert(:filter, user: user, phrase: "tesla", hide: true) + +      {:ok, activity_one} = CommonAPI.post(user, %{status: "wow tesla"}) +      {:ok, activity_two} = CommonAPI.favorite(other_user, activity_one.id) + +      {:ok, [notification]} = Notification.create_notifications(activity_two) + +      assert notification +    end    end    describe "follow / follow_request notifications" do @@ -990,8 +997,13 @@ defmodule Pleroma.NotificationTest do    end    describe "for_user" do -    test "it returns notifications for muted user without notifications" do +    setup do        user = insert(:user) + +      {:ok, %{user: user}} +    end + +    test "it returns notifications for muted user without notifications", %{user: user} do        muted = insert(:user)        {:ok, _user_relationships} = User.mute(user, muted, false) @@ -1002,8 +1014,7 @@ defmodule Pleroma.NotificationTest do        assert notification.activity.object      end -    test "it doesn't return notifications for muted user with notifications" do -      user = insert(:user) +    test "it doesn't return notifications for muted user with notifications", %{user: user} do        muted = insert(:user)        {:ok, _user_relationships} = User.mute(user, muted) @@ -1012,8 +1023,7 @@ defmodule Pleroma.NotificationTest do        assert Notification.for_user(user) == []      end -    test "it doesn't return notifications for blocked user" do -      user = insert(:user) +    test "it doesn't return notifications for blocked user", %{user: user} do        blocked = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked) @@ -1022,8 +1032,7 @@ defmodule Pleroma.NotificationTest do        assert Notification.for_user(user) == []      end -    test "it doesn't return notifications for domain-blocked non-followed user" do -      user = insert(:user) +    test "it doesn't return notifications for domain-blocked non-followed user", %{user: user} do        blocked = insert(:user, ap_id: "http://some-domain.com")        {:ok, user} = User.block_domain(user, "some-domain.com") @@ -1044,8 +1053,7 @@ defmodule Pleroma.NotificationTest do        assert length(Notification.for_user(user)) == 1      end -    test "it doesn't return notifications for muted thread" do -      user = insert(:user) +    test "it doesn't return notifications for muted thread", %{user: user} do        another_user = insert(:user)        {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"}) @@ -1054,8 +1062,7 @@ defmodule Pleroma.NotificationTest do        assert Notification.for_user(user) == []      end -    test "it returns notifications from a muted user when with_muted is set" do -      user = insert(:user) +    test "it returns notifications from a muted user when with_muted is set", %{user: user} do        muted = insert(:user)        {:ok, _user_relationships} = User.mute(user, muted) @@ -1064,8 +1071,9 @@ defmodule Pleroma.NotificationTest do        assert length(Notification.for_user(user, %{with_muted: true})) == 1      end -    test "it doesn't return notifications from a blocked user when with_muted is set" do -      user = insert(:user) +    test "it doesn't return notifications from a blocked user when with_muted is set", %{ +      user: user +    } do        blocked = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked) @@ -1075,8 +1083,8 @@ defmodule Pleroma.NotificationTest do      end      test "when with_muted is set, " <> -           "it doesn't return notifications from a domain-blocked non-followed user" do -      user = insert(:user) +           "it doesn't return notifications from a domain-blocked non-followed user", +         %{user: user} do        blocked = insert(:user, ap_id: "http://some-domain.com")        {:ok, user} = User.block_domain(user, "some-domain.com") @@ -1085,8 +1093,7 @@ defmodule Pleroma.NotificationTest do        assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))      end -    test "it returns notifications from muted threads when with_muted is set" do -      user = insert(:user) +    test "it returns notifications from muted threads when with_muted is set", %{user: user} do        another_user = insert(:user)        {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"}) @@ -1094,5 +1101,33 @@ defmodule Pleroma.NotificationTest do        {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])        assert length(Notification.for_user(user, %{with_muted: true})) == 1      end + +    test "it doesn't return notifications about mentions with filtered word", %{user: user} do +      insert(:filter, user: user, phrase: "cofe", hide: true) +      another_user = insert(:user) + +      {:ok, _activity} = CommonAPI.post(another_user, %{status: "@#{user.nickname} got cofe?"}) + +      assert Enum.empty?(Notification.for_user(user)) +    end + +    test "it returns notifications about mentions with not hidden filtered word", %{user: user} do +      insert(:filter, user: user, phrase: "test", hide: false) +      another_user = insert(:user) + +      {:ok, _} = CommonAPI.post(another_user, %{status: "@#{user.nickname} test"}) + +      assert length(Notification.for_user(user)) == 1 +    end + +    test "it returns notifications about favorites with filtered word", %{user: user} do +      insert(:filter, user: user, phrase: "cofe", hide: true) +      another_user = insert(:user) + +      {:ok, activity} = CommonAPI.post(user, %{status: "Give me my cofe!"}) +      {:ok, _} = CommonAPI.favorite(another_user, activity.id) + +      assert length(Notification.for_user(user)) == 1 +    end    end  end diff --git a/test/pagination_test.exs b/test/pagination_test.exs index 9165427ae..e526f23e8 100644 --- a/test/pagination_test.exs +++ b/test/pagination_test.exs @@ -54,6 +54,20 @@ defmodule Pleroma.PaginationTest do        assert length(paginated) == 1      end + +    test "handles id gracefully", %{notes: notes} do +      id = Enum.at(notes, 1).id |> Integer.to_string() + +      paginated = +        Pagination.fetch_paginated(Object, %{ +          id: "9s99Hq44Cnv8PKBwWG", +          max_id: id, +          limit: 20, +          offset: 0 +        }) + +      assert length(paginated) == 1 +    end    end    describe "offset" do diff --git a/test/plugs/admin_secret_authentication_plug_test.exs b/test/plugs/admin_secret_authentication_plug_test.exs index 100016c62..89df03c4b 100644 --- a/test/plugs/admin_secret_authentication_plug_test.exs +++ b/test/plugs/admin_secret_authentication_plug_test.exs @@ -4,9 +4,14 @@  defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do    use Pleroma.Web.ConnCase, async: true + +  import Mock    import Pleroma.Factory    alias Pleroma.Plugs.AdminSecretAuthenticationPlug +  alias Pleroma.Plugs.OAuthScopesPlug +  alias Pleroma.Plugs.PlugHelper +  alias Pleroma.Plugs.RateLimiter    test "does nothing if a user is assigned", %{conn: conn} do      user = insert(:user) @@ -25,6 +30,10 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do    describe "when secret set it assigns an admin user" do      setup do: clear_config([:admin_token]) +    setup_with_mocks([{RateLimiter, [:passthrough], []}]) do +      :ok +    end +      test "with `admin_token` query parameter", %{conn: conn} do        Pleroma.Config.put(:admin_token, "password123") @@ -33,12 +42,14 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do          |> AdminSecretAuthenticationPlug.call(%{})        refute conn.assigns[:user] +      assert called(RateLimiter.call(conn, name: :authentication))        conn =          %{conn | params: %{"admin_token" => "password123"}}          |> AdminSecretAuthenticationPlug.call(%{})        assert conn.assigns[:user].is_admin +      assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)      end      test "with `x-admin-token` HTTP header", %{conn: conn} do @@ -50,6 +61,7 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do          |> AdminSecretAuthenticationPlug.call(%{})        refute conn.assigns[:user] +      assert called(RateLimiter.call(conn, name: :authentication))        conn =          conn @@ -57,6 +69,7 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do          |> AdminSecretAuthenticationPlug.call(%{})        assert conn.assigns[:user].is_admin +      assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)      end    end  end diff --git a/test/plugs/http_security_plug_test.exs b/test/plugs/http_security_plug_test.exs index 63b4d3f31..2297e3dac 100644 --- a/test/plugs/http_security_plug_test.exs +++ b/test/plugs/http_security_plug_test.exs @@ -4,17 +4,12 @@  defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do    use Pleroma.Web.ConnCase +    alias Pleroma.Config    alias Plug.Conn -  setup do: clear_config([:http_securiy, :enabled]) -  setup do: clear_config([:http_security, :sts]) -  setup do: clear_config([:http_security, :referrer_policy]) -    describe "http security enabled" do -    setup do -      Config.put([:http_security, :enabled], true) -    end +    setup do: clear_config([:http_security, :enabled], true)      test "it sends CSP headers when enabled", %{conn: conn} do        conn = get(conn, "/api/v1/instance") @@ -29,7 +24,7 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do      end      test "it sends STS headers when enabled", %{conn: conn} do -      Config.put([:http_security, :sts], true) +      clear_config([:http_security, :sts], true)        conn = get(conn, "/api/v1/instance") @@ -38,7 +33,7 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do      end      test "it does not send STS headers when disabled", %{conn: conn} do -      Config.put([:http_security, :sts], false) +      clear_config([:http_security, :sts], false)        conn = get(conn, "/api/v1/instance") @@ -47,23 +42,19 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do      end      test "referrer-policy header reflects configured value", %{conn: conn} do -      conn = get(conn, "/api/v1/instance") +      resp = get(conn, "/api/v1/instance") -      assert Conn.get_resp_header(conn, "referrer-policy") == ["same-origin"] +      assert Conn.get_resp_header(resp, "referrer-policy") == ["same-origin"] -      Config.put([:http_security, :referrer_policy], "no-referrer") +      clear_config([:http_security, :referrer_policy], "no-referrer") -      conn = -        build_conn() -        |> get("/api/v1/instance") +      resp = get(conn, "/api/v1/instance") -      assert Conn.get_resp_header(conn, "referrer-policy") == ["no-referrer"] +      assert Conn.get_resp_header(resp, "referrer-policy") == ["no-referrer"]      end -    test "it sends `report-to` & `report-uri` CSP response headers" do -      conn = -        build_conn() -        |> get("/api/v1/instance") +    test "it sends `report-to` & `report-uri` CSP response headers", %{conn: conn} do +      conn = get(conn, "/api/v1/instance")        [csp] = Conn.get_resp_header(conn, "content-security-policy") @@ -74,10 +65,67 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do        assert reply_to ==                 "{\"endpoints\":[{\"url\":\"https://endpoint.com\"}],\"group\":\"csp-endpoint\",\"max-age\":10886400}"      end + +    test "default values for img-src and media-src with disabled media proxy", %{conn: conn} do +      conn = get(conn, "/api/v1/instance") + +      [csp] = Conn.get_resp_header(conn, "content-security-policy") +      assert csp =~ "media-src 'self' https:;" +      assert csp =~ "img-src 'self' data: blob: https:;" +    end +  end + +  describe "img-src and media-src" do +    setup do +      clear_config([:http_security, :enabled], true) +      clear_config([:media_proxy, :enabled], true) +      clear_config([:media_proxy, :proxy_opts, :redirect_on_failure], false) +    end + +    test "media_proxy with base_url", %{conn: conn} do +      url = "https://example.com" +      clear_config([:media_proxy, :base_url], url) +      assert_media_img_src(conn, url) +    end + +    test "upload with base url", %{conn: conn} do +      url = "https://example2.com" +      clear_config([Pleroma.Upload, :base_url], url) +      assert_media_img_src(conn, url) +    end + +    test "with S3 public endpoint", %{conn: conn} do +      url = "https://example3.com" +      clear_config([Pleroma.Uploaders.S3, :public_endpoint], url) +      assert_media_img_src(conn, url) +    end + +    test "with captcha endpoint", %{conn: conn} do +      clear_config([Pleroma.Captcha.Mock, :endpoint], "https://captcha.com") +      assert_media_img_src(conn, "https://captcha.com") +    end + +    test "with media_proxy whitelist", %{conn: conn} do +      clear_config([:media_proxy, :whitelist], ["https://example6.com", "https://example7.com"]) +      assert_media_img_src(conn, "https://example7.com https://example6.com") +    end + +    # TODO: delete after removing support bare domains for media proxy whitelist +    test "with media_proxy bare domains whitelist (deprecated)", %{conn: conn} do +      clear_config([:media_proxy, :whitelist], ["example4.com", "example5.com"]) +      assert_media_img_src(conn, "example5.com example4.com") +    end +  end + +  defp assert_media_img_src(conn, url) do +    conn = get(conn, "/api/v1/instance") +    [csp] = Conn.get_resp_header(conn, "content-security-policy") +    assert csp =~ "media-src 'self' #{url};" +    assert csp =~ "img-src 'self' data: blob: #{url};"    end    test "it does not send CSP headers when disabled", %{conn: conn} do -    Config.put([:http_security, :enabled], false) +    clear_config([:http_security, :enabled], false)      conn = get(conn, "/api/v1/instance") diff --git a/test/plugs/user_is_admin_plug_test.exs b/test/plugs/user_is_admin_plug_test.exs index fd6a50e53..8bc00e444 100644 --- a/test/plugs/user_is_admin_plug_test.exs +++ b/test/plugs/user_is_admin_plug_test.exs @@ -8,112 +8,30 @@ defmodule Pleroma.Plugs.UserIsAdminPlugTest do    alias Pleroma.Plugs.UserIsAdminPlug    import Pleroma.Factory -  describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do -    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false) +  test "accepts a user that is an admin" do +    user = insert(:user, is_admin: true) -    test "accepts a user that is an admin" do -      user = insert(:user, is_admin: true) +    conn = assign(build_conn(), :user, user) -      conn = assign(build_conn(), :user, user) +    ret_conn = UserIsAdminPlug.call(conn, %{}) -      ret_conn = UserIsAdminPlug.call(conn, %{}) - -      assert conn == ret_conn -    end - -    test "denies a user that isn't an admin" do -      user = insert(:user) - -      conn = -        build_conn() -        |> assign(:user, user) -        |> UserIsAdminPlug.call(%{}) - -      assert conn.status == 403 -    end - -    test "denies when a user isn't set" do -      conn = UserIsAdminPlug.call(build_conn(), %{}) - -      assert conn.status == 403 -    end +    assert conn == ret_conn    end -  describe "with [:auth, :enforce_oauth_admin_scope_usage]," do -    setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true) - -    setup do -      admin_user = insert(:user, is_admin: true) -      non_admin_user = insert(:user, is_admin: false) -      blank_user = nil - -      {:ok, %{users: [admin_user, non_admin_user, blank_user]}} -    end - -    test "if token has any of admin scopes, accepts a user that is an admin", %{conn: conn} do -      user = insert(:user, is_admin: true) -      token = insert(:oauth_token, user: user, scopes: ["admin:something"]) - -      conn = -        conn -        |> assign(:user, user) -        |> assign(:token, token) +  test "denies a user that isn't an admin" do +    user = insert(:user) -      ret_conn = UserIsAdminPlug.call(conn, %{}) +    conn = +      build_conn() +      |> assign(:user, user) +      |> UserIsAdminPlug.call(%{}) -      assert conn == ret_conn -    end - -    test "if token has any of admin scopes, denies a user that isn't an admin", %{conn: conn} do -      user = insert(:user, is_admin: false) -      token = insert(:oauth_token, user: user, scopes: ["admin:something"]) - -      conn = -        conn -        |> assign(:user, user) -        |> assign(:token, token) -        |> UserIsAdminPlug.call(%{}) - -      assert conn.status == 403 -    end - -    test "if token has any of admin scopes, denies when a user isn't set", %{conn: conn} do -      token = insert(:oauth_token, scopes: ["admin:something"]) - -      conn = -        conn -        |> assign(:user, nil) -        |> assign(:token, token) -        |> UserIsAdminPlug.call(%{}) - -      assert conn.status == 403 -    end - -    test "if token lacks admin scopes, denies users regardless of is_admin flag", -         %{users: users} do -      for user <- users do -        token = insert(:oauth_token, user: user) - -        conn = -          build_conn() -          |> assign(:user, user) -          |> assign(:token, token) -          |> UserIsAdminPlug.call(%{}) - -        assert conn.status == 403 -      end -    end +    assert conn.status == 403 +  end -    test "if token is missing, denies users regardless of is_admin flag", %{users: users} do -      for user <- users do -        conn = -          build_conn() -          |> assign(:user, user) -          |> assign(:token, nil) -          |> UserIsAdminPlug.call(%{}) +  test "denies when a user isn't set" do +    conn = UserIsAdminPlug.call(build_conn(), %{}) -        assert conn.status == 403 -      end -    end +    assert conn.status == 403    end  end diff --git a/test/pool/connections_test.exs b/test/pool/connections_test.exs deleted file mode 100644 index aeda54875..000000000 --- a/test/pool/connections_test.exs +++ /dev/null @@ -1,760 +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.Pool.ConnectionsTest do -  use ExUnit.Case, async: true -  use Pleroma.Tests.Helpers - -  import ExUnit.CaptureLog -  import Mox - -  alias Pleroma.Gun.Conn -  alias Pleroma.GunMock -  alias Pleroma.Pool.Connections - -  setup :verify_on_exit! - -  setup_all do -    name = :test_connections -    {:ok, pid} = Connections.start_link({name, [checkin_timeout: 150]}) -    {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.GunMock) - -    on_exit(fn -> -      if Process.alive?(pid), do: GenServer.stop(name) -    end) - -    {:ok, name: name} -  end - -  defp open_mock(num \\ 1) do -    GunMock -    |> expect(:open, num, &start_and_register(&1, &2, &3)) -    |> expect(:await_up, num, fn _, _ -> {:ok, :http} end) -    |> expect(:set_owner, num, fn _, _ -> :ok end) -  end - -  defp connect_mock(mock) do -    mock -    |> expect(:connect, &connect(&1, &2)) -    |> expect(:await, &await(&1, &2)) -  end - -  defp info_mock(mock), do: expect(mock, :info, &info(&1)) - -  defp start_and_register('gun-not-up.com', _, _), do: {:error, :timeout} - -  defp start_and_register(host, port, _) do -    {:ok, pid} = Task.start_link(fn -> Process.sleep(1000) end) - -    scheme = -      case port do -        443 -> "https" -        _ -> "http" -      end - -    Registry.register(GunMock, pid, %{ -      origin_scheme: scheme, -      origin_host: host, -      origin_port: port -    }) - -    {:ok, pid} -  end - -  defp info(pid) do -    [{_, info}] = Registry.lookup(GunMock, pid) -    info -  end - -  defp connect(pid, _) do -    ref = make_ref() -    Registry.register(GunMock, ref, pid) -    ref -  end - -  defp await(pid, ref) do -    [{_, ^pid}] = Registry.lookup(GunMock, ref) -    {:response, :fin, 200, []} -  end - -  defp now, do: :os.system_time(:second) - -  describe "alive?/2" do -    test "is alive", %{name: name} do -      assert Connections.alive?(name) -    end - -    test "returns false if not started" do -      refute Connections.alive?(:some_random_name) -    end -  end - -  test "opens connection and reuse it on next request", %{name: name} do -    open_mock() -    url = "http://some-domain.com" -    key = "http:some-domain.com:80" -    refute Connections.checkin(url, name) -    :ok = Conn.open(url, name) - -    conn = Connections.checkin(url, name) -    assert is_pid(conn) -    assert Process.alive?(conn) - -    self = self() - -    %Connections{ -      conns: %{ -        ^key => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}], -          conn_state: :active -        } -      } -    } = Connections.get_state(name) - -    reused_conn = Connections.checkin(url, name) - -    assert conn == reused_conn - -    %Connections{ -      conns: %{ -        ^key => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}, {^self, _}], -          conn_state: :active -        } -      } -    } = Connections.get_state(name) - -    :ok = Connections.checkout(conn, self, name) - -    %Connections{ -      conns: %{ -        ^key => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}], -          conn_state: :active -        } -      } -    } = Connections.get_state(name) - -    :ok = Connections.checkout(conn, self, name) - -    %Connections{ -      conns: %{ -        ^key => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [], -          conn_state: :idle -        } -      } -    } = Connections.get_state(name) -  end - -  test "reuse connection for idna domains", %{name: name} do -    open_mock() -    url = "http://ですsome-domain.com" -    refute Connections.checkin(url, name) - -    :ok = Conn.open(url, name) - -    conn = Connections.checkin(url, name) -    assert is_pid(conn) -    assert Process.alive?(conn) - -    self = self() - -    %Connections{ -      conns: %{ -        "http:ですsome-domain.com:80" => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}], -          conn_state: :active -        } -      } -    } = Connections.get_state(name) - -    reused_conn = Connections.checkin(url, name) - -    assert conn == reused_conn -  end - -  test "reuse for ipv4", %{name: name} do -    open_mock() -    url = "http://127.0.0.1" - -    refute Connections.checkin(url, name) - -    :ok = Conn.open(url, name) - -    conn = Connections.checkin(url, name) -    assert is_pid(conn) -    assert Process.alive?(conn) - -    self = self() - -    %Connections{ -      conns: %{ -        "http:127.0.0.1:80" => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}], -          conn_state: :active -        } -      } -    } = Connections.get_state(name) - -    reused_conn = Connections.checkin(url, name) - -    assert conn == reused_conn - -    :ok = Connections.checkout(conn, self, name) -    :ok = Connections.checkout(reused_conn, self, name) - -    %Connections{ -      conns: %{ -        "http:127.0.0.1:80" => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [], -          conn_state: :idle -        } -      } -    } = Connections.get_state(name) -  end - -  test "reuse for ipv6", %{name: name} do -    open_mock() -    url = "http://[2a03:2880:f10c:83:face:b00c:0:25de]" - -    refute Connections.checkin(url, name) - -    :ok = Conn.open(url, name) - -    conn = Connections.checkin(url, name) -    assert is_pid(conn) -    assert Process.alive?(conn) - -    self = self() - -    %Connections{ -      conns: %{ -        "http:2a03:2880:f10c:83:face:b00c:0:25de:80" => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}], -          conn_state: :active -        } -      } -    } = Connections.get_state(name) - -    reused_conn = Connections.checkin(url, name) - -    assert conn == reused_conn -  end - -  test "up and down ipv4", %{name: name} do -    open_mock() -    |> info_mock() -    |> allow(self(), name) - -    self = self() -    url = "http://127.0.0.1" -    :ok = Conn.open(url, name) -    conn = Connections.checkin(url, name) -    send(name, {:gun_down, conn, nil, nil, nil}) -    send(name, {:gun_up, conn, nil}) - -    %Connections{ -      conns: %{ -        "http:127.0.0.1:80" => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}], -          conn_state: :active -        } -      } -    } = Connections.get_state(name) -  end - -  test "up and down ipv6", %{name: name} do -    self = self() - -    open_mock() -    |> info_mock() -    |> allow(self, name) - -    url = "http://[2a03:2880:f10c:83:face:b00c:0:25de]" -    :ok = Conn.open(url, name) -    conn = Connections.checkin(url, name) -    send(name, {:gun_down, conn, nil, nil, nil}) -    send(name, {:gun_up, conn, nil}) - -    %Connections{ -      conns: %{ -        "http:2a03:2880:f10c:83:face:b00c:0:25de:80" => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}], -          conn_state: :active -        } -      } -    } = Connections.get_state(name) -  end - -  test "reuses connection based on protocol", %{name: name} do -    open_mock(2) -    http_url = "http://some-domain.com" -    http_key = "http:some-domain.com:80" -    https_url = "https://some-domain.com" -    https_key = "https:some-domain.com:443" - -    refute Connections.checkin(http_url, name) -    :ok = Conn.open(http_url, name) -    conn = Connections.checkin(http_url, name) -    assert is_pid(conn) -    assert Process.alive?(conn) - -    refute Connections.checkin(https_url, name) -    :ok = Conn.open(https_url, name) -    https_conn = Connections.checkin(https_url, name) - -    refute conn == https_conn - -    reused_https = Connections.checkin(https_url, name) - -    refute conn == reused_https - -    assert reused_https == https_conn - -    %Connections{ -      conns: %{ -        ^http_key => %Conn{ -          conn: ^conn, -          gun_state: :up -        }, -        ^https_key => %Conn{ -          conn: ^https_conn, -          gun_state: :up -        } -      } -    } = Connections.get_state(name) -  end - -  test "connection can't get up", %{name: name} do -    expect(GunMock, :open, &start_and_register(&1, &2, &3)) -    url = "http://gun-not-up.com" - -    assert capture_log(fn -> -             refute Conn.open(url, name) -             refute Connections.checkin(url, name) -           end) =~ -             "Opening connection to http://gun-not-up.com failed with error {:error, :timeout}" -  end - -  test "process gun_down message and then gun_up", %{name: name} do -    self = self() - -    open_mock() -    |> info_mock() -    |> allow(self, name) - -    url = "http://gun-down-and-up.com" -    key = "http:gun-down-and-up.com:80" -    :ok = Conn.open(url, name) -    conn = Connections.checkin(url, name) - -    assert is_pid(conn) -    assert Process.alive?(conn) - -    %Connections{ -      conns: %{ -        ^key => %Conn{ -          conn: ^conn, -          gun_state: :up, -          used_by: [{^self, _}] -        } -      } -    } = Connections.get_state(name) - -    send(name, {:gun_down, conn, :http, nil, nil}) - -    %Connections{ -      conns: %{ -        ^key => %Conn{ -          conn: ^conn, -          gun_state: :down, -          used_by: [{^self, _}] -        } -      } -    } = Connections.get_state(name) - -    send(name, {:gun_up, conn, :http}) - -    conn2 = Connections.checkin(url, name) -    assert conn == conn2 - -    assert is_pid(conn2) -    assert Process.alive?(conn2) - -    %Connections{ -      conns: %{ -        ^key => %Conn{ -          conn: _, -          gun_state: :up, -          used_by: [{^self, _}, {^self, _}] -        } -      } -    } = Connections.get_state(name) -  end - -  test "async processes get same conn for same domain", %{name: name} do -    open_mock() -    url = "http://some-domain.com" -    :ok = Conn.open(url, name) - -    tasks = -      for _ <- 1..5 do -        Task.async(fn -> -          Connections.checkin(url, name) -        end) -      end - -    tasks_with_results = Task.yield_many(tasks) - -    results = -      Enum.map(tasks_with_results, fn {task, res} -> -        res || Task.shutdown(task, :brutal_kill) -      end) - -    conns = for {:ok, value} <- results, do: value - -    %Connections{ -      conns: %{ -        "http:some-domain.com:80" => %Conn{ -          conn: conn, -          gun_state: :up -        } -      } -    } = Connections.get_state(name) - -    assert Enum.all?(conns, fn res -> res == conn end) -  end - -  test "remove frequently used and idle", %{name: name} do -    open_mock(3) -    self = self() -    http_url = "http://some-domain.com" -    https_url = "https://some-domain.com" -    :ok = Conn.open(https_url, name) -    :ok = Conn.open(http_url, name) - -    conn1 = Connections.checkin(https_url, name) - -    [conn2 | _conns] = -      for _ <- 1..4 do -        Connections.checkin(http_url, name) -      end - -    http_key = "http:some-domain.com:80" - -    %Connections{ -      conns: %{ -        ^http_key => %Conn{ -          conn: ^conn2, -          gun_state: :up, -          conn_state: :active, -          used_by: [{^self, _}, {^self, _}, {^self, _}, {^self, _}] -        }, -        "https:some-domain.com:443" => %Conn{ -          conn: ^conn1, -          gun_state: :up, -          conn_state: :active, -          used_by: [{^self, _}] -        } -      } -    } = Connections.get_state(name) - -    :ok = Connections.checkout(conn1, self, name) - -    another_url = "http://another-domain.com" -    :ok = Conn.open(another_url, name) -    conn = Connections.checkin(another_url, name) - -    %Connections{ -      conns: %{ -        "http:another-domain.com:80" => %Conn{ -          conn: ^conn, -          gun_state: :up -        }, -        ^http_key => %Conn{ -          conn: _, -          gun_state: :up -        } -      } -    } = Connections.get_state(name) -  end - -  describe "with proxy" do -    test "as ip", %{name: name} do -      open_mock() -      |> connect_mock() - -      url = "http://proxy-string.com" -      key = "http:proxy-string.com:80" -      :ok = Conn.open(url, name, proxy: {{127, 0, 0, 1}, 8123}) - -      conn = Connections.checkin(url, name) - -      %Connections{ -        conns: %{ -          ^key => %Conn{ -            conn: ^conn, -            gun_state: :up -          } -        } -      } = Connections.get_state(name) - -      reused_conn = Connections.checkin(url, name) - -      assert reused_conn == conn -    end - -    test "as host", %{name: name} do -      open_mock() -      |> connect_mock() - -      url = "http://proxy-tuple-atom.com" -      :ok = Conn.open(url, name, proxy: {'localhost', 9050}) -      conn = Connections.checkin(url, name) - -      %Connections{ -        conns: %{ -          "http:proxy-tuple-atom.com:80" => %Conn{ -            conn: ^conn, -            gun_state: :up -          } -        } -      } = Connections.get_state(name) - -      reused_conn = Connections.checkin(url, name) - -      assert reused_conn == conn -    end - -    test "as ip and ssl", %{name: name} do -      open_mock() -      |> connect_mock() - -      url = "https://proxy-string.com" - -      :ok = Conn.open(url, name, proxy: {{127, 0, 0, 1}, 8123}) -      conn = Connections.checkin(url, name) - -      %Connections{ -        conns: %{ -          "https:proxy-string.com:443" => %Conn{ -            conn: ^conn, -            gun_state: :up -          } -        } -      } = Connections.get_state(name) - -      reused_conn = Connections.checkin(url, name) - -      assert reused_conn == conn -    end - -    test "as host and ssl", %{name: name} do -      open_mock() -      |> connect_mock() - -      url = "https://proxy-tuple-atom.com" -      :ok = Conn.open(url, name, proxy: {'localhost', 9050}) -      conn = Connections.checkin(url, name) - -      %Connections{ -        conns: %{ -          "https:proxy-tuple-atom.com:443" => %Conn{ -            conn: ^conn, -            gun_state: :up -          } -        } -      } = Connections.get_state(name) - -      reused_conn = Connections.checkin(url, name) - -      assert reused_conn == conn -    end - -    test "with socks type", %{name: name} do -      open_mock() - -      url = "http://proxy-socks.com" - -      :ok = Conn.open(url, name, proxy: {:socks5, 'localhost', 1234}) - -      conn = Connections.checkin(url, name) - -      %Connections{ -        conns: %{ -          "http:proxy-socks.com:80" => %Conn{ -            conn: ^conn, -            gun_state: :up -          } -        } -      } = Connections.get_state(name) - -      reused_conn = Connections.checkin(url, name) - -      assert reused_conn == conn -    end - -    test "with socks4 type and ssl", %{name: name} do -      open_mock() -      url = "https://proxy-socks.com" - -      :ok = Conn.open(url, name, proxy: {:socks4, 'localhost', 1234}) - -      conn = Connections.checkin(url, name) - -      %Connections{ -        conns: %{ -          "https:proxy-socks.com:443" => %Conn{ -            conn: ^conn, -            gun_state: :up -          } -        } -      } = Connections.get_state(name) - -      reused_conn = Connections.checkin(url, name) - -      assert reused_conn == conn -    end -  end - -  describe "crf/3" do -    setup do -      crf = Connections.crf(1, 10, 1) -      {:ok, crf: crf} -    end - -    test "more used will have crf higher", %{crf: crf} do -      # used 3 times -      crf1 = Connections.crf(1, 10, crf) -      crf1 = Connections.crf(1, 10, crf1) - -      # used 2 times -      crf2 = Connections.crf(1, 10, crf) - -      assert crf1 > crf2 -    end - -    test "recently used will have crf higher on equal references", %{crf: crf} do -      # used 3 sec ago -      crf1 = Connections.crf(3, 10, crf) - -      # used 4 sec ago -      crf2 = Connections.crf(4, 10, crf) - -      assert crf1 > crf2 -    end - -    test "equal crf on equal reference and time", %{crf: crf} do -      # used 2 times -      crf1 = Connections.crf(1, 10, crf) - -      # used 2 times -      crf2 = Connections.crf(1, 10, crf) - -      assert crf1 == crf2 -    end - -    test "recently used will have higher crf", %{crf: crf} do -      crf1 = Connections.crf(2, 10, crf) -      crf1 = Connections.crf(1, 10, crf1) - -      crf2 = Connections.crf(3, 10, crf) -      crf2 = Connections.crf(4, 10, crf2) -      assert crf1 > crf2 -    end -  end - -  describe "get_unused_conns/1" do -    test "crf is equalent, sorting by reference", %{name: name} do -      Connections.add_conn(name, "1", %Conn{ -        conn_state: :idle, -        last_reference: now() - 1 -      }) - -      Connections.add_conn(name, "2", %Conn{ -        conn_state: :idle, -        last_reference: now() -      }) - -      assert [{"1", _unused_conn} | _others] = Connections.get_unused_conns(name) -    end - -    test "reference is equalent, sorting by crf", %{name: name} do -      Connections.add_conn(name, "1", %Conn{ -        conn_state: :idle, -        crf: 1.999 -      }) - -      Connections.add_conn(name, "2", %Conn{ -        conn_state: :idle, -        crf: 2 -      }) - -      assert [{"1", _unused_conn} | _others] = Connections.get_unused_conns(name) -    end - -    test "higher crf and lower reference", %{name: name} do -      Connections.add_conn(name, "1", %Conn{ -        conn_state: :idle, -        crf: 3, -        last_reference: now() - 1 -      }) - -      Connections.add_conn(name, "2", %Conn{ -        conn_state: :idle, -        crf: 2, -        last_reference: now() -      }) - -      assert [{"2", _unused_conn} | _others] = Connections.get_unused_conns(name) -    end - -    test "lower crf and lower reference", %{name: name} do -      Connections.add_conn(name, "1", %Conn{ -        conn_state: :idle, -        crf: 1.99, -        last_reference: now() - 1 -      }) - -      Connections.add_conn(name, "2", %Conn{ -        conn_state: :idle, -        crf: 2, -        last_reference: now() -      }) - -      assert [{"1", _unused_conn} | _others] = Connections.get_unused_conns(name) -    end -  end - -  test "count/1" do -    name = :test_count -    {:ok, _} = Connections.start_link({name, [checkin_timeout: 150]}) -    assert Connections.count(name) == 0 -    Connections.add_conn(name, "1", %Conn{conn: self()}) -    assert Connections.count(name) == 1 -    Connections.remove_conn(name, "1") -    assert Connections.count(name) == 0 -  end -end diff --git a/test/reverse_proxy/reverse_proxy_test.exs b/test/reverse_proxy/reverse_proxy_test.exs index c677066b3..8df63de65 100644 --- a/test/reverse_proxy/reverse_proxy_test.exs +++ b/test/reverse_proxy/reverse_proxy_test.exs @@ -314,7 +314,7 @@ defmodule Pleroma.ReverseProxyTest do      test "not atachment", %{conn: conn} do        disposition_headers_mock([          {"content-type", "image/gif"}, -        {"content-length", 0} +        {"content-length", "0"}        ])        conn = ReverseProxy.call(conn, "/disposition") @@ -325,7 +325,7 @@ defmodule Pleroma.ReverseProxyTest do      test "with content-disposition header", %{conn: conn} do        disposition_headers_mock([          {"content-disposition", "attachment; filename=\"filename.jpg\""}, -        {"content-length", 0} +        {"content-length", "0"}        ])        conn = ReverseProxy.call(conn, "/disposition") diff --git a/test/support/cluster.ex b/test/support/cluster.ex index deb37f361..524194cf4 100644 --- a/test/support/cluster.ex +++ b/test/support/cluster.ex @@ -97,7 +97,7 @@ defmodule Pleroma.Cluster do      silence_logger_warnings(fn ->        node_configs        |> Enum.map(&Task.async(fn -> start_slave(&1) end)) -      |> Enum.map(&Task.await(&1, 60_000)) +      |> Enum.map(&Task.await(&1, 90_000))      end)    end diff --git a/test/support/factory.ex b/test/support/factory.ex index 6e22b66a4..635d83650 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -67,6 +67,7 @@ defmodule Pleroma.Factory do      data = %{        "type" => "Note",        "content" => text, +      "source" => text,        "id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),        "actor" => user.ap_id,        "to" => ["https://www.w3.org/ns/activitystreams#Public"], @@ -427,4 +428,12 @@ defmodule Pleroma.Factory do        user: build(:user)      }    end + +  def filter_factory do +    %Pleroma.Filter{ +      user: build(:user), +      filter_id: sequence(:filter_id, & &1), +      phrase: "cofe" +    } +  end  end diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 3d5128835..19a202654 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -308,6 +308,22 @@ defmodule HttpRequestMock do       }}    end +  def get("https://framatube.org/accounts/framasoft", _, _, _) do +    {:ok, +     %Tesla.Env{ +       status: 200, +       body: File.read!("test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json") +     }} +  end + +  def get("https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206", _, _, _) do +    {:ok, +     %Tesla.Env{ +       status: 200, +       body: File.read!("test/fixtures/tesla_mock/framatube.org-video.json") +     }} +  end +    def get("https://peertube.social/accounts/craigmaloney", _, _, _) do      {:ok,       %Tesla.Env{ @@ -1326,6 +1342,18 @@ defmodule HttpRequestMock do      {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/relay/relay.json")}}    end +  def get("http://localhost:4001/", _, "", Accept: "text/html") do +    {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/7369654.html")}} +  end + +  def get("https://osada.macgirvin.com/", _, "", Accept: "text/html") do +    {:ok, +     %Tesla.Env{ +       status: 200, +       body: File.read!("test/fixtures/tesla_mock/https___osada.macgirvin.com.html") +     }} +  end +    def get(url, query, body, headers) do      {:error,       "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{ diff --git a/test/support/oban_helpers.ex b/test/support/oban_helpers.ex index e96994c57..9f90a821c 100644 --- a/test/support/oban_helpers.ex +++ b/test/support/oban_helpers.ex @@ -20,7 +20,7 @@ defmodule Pleroma.Tests.ObanHelpers do    end    def perform(%Oban.Job{} = job) do -    res = apply(String.to_existing_atom("Elixir." <> job.worker), :perform, [job.args, job]) +    res = apply(String.to_existing_atom("Elixir." <> job.worker), :perform, [job])      Repo.delete(job)      res    end diff --git a/test/tasks/relay_test.exs b/test/tasks/relay_test.exs index a8ba0658d..79ab72002 100644 --- a/test/tasks/relay_test.exs +++ b/test/tasks/relay_test.exs @@ -10,6 +10,8 @@ defmodule Mix.Tasks.Pleroma.RelayTest do    alias Pleroma.Web.ActivityPub.Utils    use Pleroma.DataCase +  import Pleroma.Factory +    setup_all do      Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -46,7 +48,8 @@ defmodule Mix.Tasks.Pleroma.RelayTest do    describe "running unfollow" do      test "relay is unfollowed" do -      target_instance = "http://mastodon.example.org/users/admin" +      user = insert(:user) +      target_instance = user.ap_id        Mix.Tasks.Pleroma.Relay.run(["follow", target_instance]) @@ -71,7 +74,7 @@ defmodule Mix.Tasks.Pleroma.RelayTest do        assert undo_activity.data["type"] == "Undo"        assert undo_activity.data["actor"] == local_user.ap_id -      assert undo_activity.data["object"] == cancelled_activity.data +      assert undo_activity.data["object"]["id"] == cancelled_activity.data["id"]        refute "#{target_instance}/followers" in User.following(local_user)      end    end diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs index 9220d23fc..ce43a9cc7 100644 --- a/test/tasks/user_test.exs +++ b/test/tasks/user_test.exs @@ -110,7 +110,23 @@ defmodule Mix.Tasks.Pleroma.UserTest do      test "a remote user's create activity is deleted when the object has been pruned" do        user = insert(:user) +      user2 = insert(:user) +        {:ok, post} = CommonAPI.post(user, %{status: "uguu"}) +      {:ok, post2} = CommonAPI.post(user2, %{status: "test"}) +      obj = Object.normalize(post2) + +      {:ok, like_object, meta} = Pleroma.Web.ActivityPub.Builder.like(user, obj) + +      {:ok, like_activity, _meta} = +        Pleroma.Web.ActivityPub.Pipeline.common_pipeline( +          like_object, +          Keyword.put(meta, :local, true) +        ) + +      like_activity.data["object"] +      |> Pleroma.Object.get_by_ap_id() +      |> Repo.delete()        clear_config([:instance, :federating], true) @@ -127,6 +143,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do          assert %{deactivated: true} = User.get_by_nickname(user.nickname)          assert called(Pleroma.Web.Federator.publish(:_)) +        refute Pleroma.Repo.get(Pleroma.Activity, like_activity.id)        end        refute Activity.get_by_id(post.id) @@ -464,17 +481,17 @@ defmodule Mix.Tasks.Pleroma.UserTest do        moot = insert(:user, nickname: "moot")        kawen = insert(:user, nickname: "kawen", name: "fediverse expert moon") -      {:ok, user} = User.follow(user, kawen) +      {:ok, user} = User.follow(user, moon)        assert [moon.id, kawen.id] == User.Search.search("moon") |> Enum.map(& &1.id) +        res = User.search("moo") |> Enum.map(& &1.id) -      assert moon.id in res -      assert moot.id in res -      assert kawen.id in res -      assert [moon.id, kawen.id] == User.Search.search("moon fediverse") |> Enum.map(& &1.id) +      assert Enum.sort([moon.id, moot.id, kawen.id]) == Enum.sort(res) + +      assert [kawen.id, moon.id] == User.Search.search("expert fediverse") |> Enum.map(& &1.id) -      assert [kawen.id, moon.id] == -               User.Search.search("moon fediverse", for_user: user) |> Enum.map(& &1.id) +      assert [moon.id, kawen.id] == +               User.Search.search("expert fediverse", for_user: user) |> Enum.map(& &1.id)      end    end diff --git a/test/upload/filter/exiftool_test.exs b/test/upload/filter/exiftool_test.exs new file mode 100644 index 000000000..a1b7e46cd --- /dev/null +++ b/test/upload/filter/exiftool_test.exs @@ -0,0 +1,31 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Upload.Filter.ExiftoolTest do +  use Pleroma.DataCase +  alias Pleroma.Upload.Filter + +  test "apply exiftool filter" do +    File.cp!( +      "test/fixtures/DSCN0010.jpg", +      "test/fixtures/DSCN0010_tmp.jpg" +    ) + +    upload = %Pleroma.Upload{ +      name: "image_with_GPS_data.jpg", +      content_type: "image/jpg", +      path: Path.absname("test/fixtures/DSCN0010.jpg"), +      tempfile: Path.absname("test/fixtures/DSCN0010_tmp.jpg") +    } + +    assert Filter.Exiftool.filter(upload) == :ok + +    {exif_original, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010.jpg"]) +    {exif_filtered, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010_tmp.jpg"]) + +    refute exif_original == exif_filtered +    assert String.match?(exif_original, ~r/GPS/) +    refute String.match?(exif_filtered, ~r/GPS/) +  end +end diff --git a/test/upload_test.exs b/test/upload_test.exs index 2abf0edec..b06b54487 100644 --- a/test/upload_test.exs +++ b/test/upload_test.exs @@ -107,6 +107,19 @@ defmodule Pleroma.UploadTest do    describe "Storing a file with the Local uploader" do      setup [:ensure_local_uploader] +    test "does not allow descriptions longer than the post limit" do +      clear_config([:instance, :description_limit], 2) +      File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg") + +      file = %Plug.Upload{ +        content_type: "image/jpg", +        path: Path.absname("test/fixtures/image_tmp.jpg"), +        filename: "image.jpg" +      } + +      {:error, :description_too_long} = Upload.store(file, description: "123") +    end +      test "returns a media url" do        File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg") diff --git a/test/user/notification_setting_test.exs b/test/user/notification_setting_test.exs index 95bca22c4..308da216a 100644 --- a/test/user/notification_setting_test.exs +++ b/test/user/notification_setting_test.exs @@ -8,11 +8,11 @@ defmodule Pleroma.User.NotificationSettingTest do    alias Pleroma.User.NotificationSetting    describe "changeset/2" do -    test "sets valid privacy option" do +    test "sets option to hide notification contents" do        changeset =          NotificationSetting.changeset(            %NotificationSetting{}, -          %{"privacy_option" => true} +          %{"hide_notification_contents" => true}          )        assert %Ecto.Changeset{valid?: true} = changeset diff --git a/test/user_search_test.exs b/test/user_search_test.exs index 17c63322a..559ba5966 100644 --- a/test/user_search_test.exs +++ b/test/user_search_test.exs @@ -17,7 +17,7 @@ defmodule Pleroma.UserSearchTest do    describe "User.search" do      setup do: clear_config([:instance, :limit_to_local_content]) -    test "excluded invisible users from results" do +    test "excludes invisible users from results" do        user = insert(:user, %{nickname: "john t1000"})        insert(:user, %{invisible: true, nickname: "john t800"}) @@ -25,6 +25,15 @@ defmodule Pleroma.UserSearchTest do        assert found_user.id == user.id      end +    test "excludes service actors from results" do +      insert(:user, actor_type: "Application", nickname: "user1") +      service = insert(:user, actor_type: "Service", nickname: "user2") +      person = insert(:user, actor_type: "Person", nickname: "user3") + +      assert [found_user1, found_user2] = User.search("user") +      assert [found_user1.id, found_user2.id] -- [service.id, person.id] == [] +    end +      test "accepts limit parameter" do        Enum.each(0..4, &insert(:user, %{nickname: "john#{&1}"}))        assert length(User.search("john", limit: 3)) == 3 @@ -37,30 +46,49 @@ defmodule Pleroma.UserSearchTest do        assert length(User.search("john", limit: 3, offset: 3)) == 2      end -    test "finds a user by full or partial nickname" do +    defp clear_virtual_fields(user) do +      Map.merge(user, %{search_rank: nil, search_type: nil}) +    end + +    test "finds a user by full nickname or its leading fragment" do        user = insert(:user, %{nickname: "john"})        Enum.each(["john", "jo", "j"], fn query ->          assert user ==                   User.search(query)                   |> List.first() -                 |> Map.put(:search_rank, nil) -                 |> Map.put(:search_type, nil) +                 |> clear_virtual_fields()        end)      end -    test "finds a user by full or partial name" do +    test "finds a user by full name or leading fragment(s) of its words" do        user = insert(:user, %{name: "John Doe"})        Enum.each(["John Doe", "JOHN", "doe", "j d", "j", "d"], fn query ->          assert user ==                   User.search(query)                   |> List.first() -                 |> Map.put(:search_rank, nil) -                 |> Map.put(:search_type, nil) +                 |> clear_virtual_fields()        end)      end +    test "matches by leading fragment of user domain" do +      user = insert(:user, %{nickname: "arandom@dude.com"}) +      insert(:user, %{nickname: "iamthedude"}) + +      assert [user.id] == User.search("dud") |> Enum.map(& &1.id) +    end + +    test "ranks full nickname match higher than full name match" do +      nicknamed_user = insert(:user, %{nickname: "hj@shigusegubu.club"}) +      named_user = insert(:user, %{nickname: "xyz@sample.com", name: "HJ"}) + +      results = User.search("hj") + +      assert [nicknamed_user.id, named_user.id] == Enum.map(results, & &1.id) +      assert Enum.at(results, 0).search_rank > Enum.at(results, 1).search_rank +    end +      test "finds users, considering density of matched tokens" do        u1 = insert(:user, %{name: "Bar Bar plus Word Word"})        u2 = insert(:user, %{name: "Word Word Bar Bar Bar"}) diff --git a/test/user_test.exs b/test/user_test.exs index 7126bb539..9788e09d9 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -486,6 +486,15 @@ defmodule Pleroma.UserTest do      }      setup do: clear_config([:instance, :account_activation_required], true) +    test "it sets the 'accepts_chat_messages' set to true" do +      changeset = User.register_changeset(%User{}, @full_user_data) +      assert changeset.valid? + +      {:ok, user} = Repo.insert(changeset) + +      assert user.accepts_chat_messages +    end +      test "it creates unconfirmed user" do        changeset = User.register_changeset(%User{}, @full_user_data)        assert changeset.valid? diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index e722f7c04..ed900d8f8 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -1082,6 +1082,45 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do        assert object = Object.get_by_ap_id(note_object.data["id"])        assert object.data["like_count"] == 1      end + +    test "it doesn't spreads faulty attributedTo or actor fields", %{ +      conn: conn, +      activity: activity +    } do +      reimu = insert(:user, nickname: "reimu") +      cirno = insert(:user, nickname: "cirno") + +      assert reimu.ap_id +      assert cirno.ap_id + +      activity = +        activity +        |> put_in(["object", "actor"], reimu.ap_id) +        |> put_in(["object", "attributedTo"], reimu.ap_id) +        |> put_in(["actor"], reimu.ap_id) +        |> put_in(["attributedTo"], reimu.ap_id) + +      _reimu_outbox = +        conn +        |> assign(:user, cirno) +        |> put_req_header("content-type", "application/activity+json") +        |> post("/users/#{reimu.nickname}/outbox", activity) +        |> json_response(403) + +      cirno_outbox = +        conn +        |> assign(:user, cirno) +        |> put_req_header("content-type", "application/activity+json") +        |> post("/users/#{cirno.nickname}/outbox", activity) +        |> json_response(201) + +      assert cirno_outbox["attributedTo"] == nil +      assert cirno_outbox["actor"] == cirno.ap_id + +      assert cirno_object = Object.normalize(cirno_outbox["object"]) +      assert cirno_object.data["actor"] == cirno.ap_id +      assert cirno_object.data["attributedTo"] == cirno.ap_id +    end    end    describe "/relay/followers" do diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 575e0c5db..f3951462f 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -184,36 +184,43 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert User.invisible?(user)      end -    test "it fetches the appropriate tag-restricted posts" do -      user = insert(:user) +    test "it returns a user that accepts chat messages" do +      user_id = "http://mastodon.example.org/users/admin" +      {:ok, user} = ActivityPub.make_user_from_ap_id(user_id) -      {:ok, status_one} = CommonAPI.post(user, %{status: ". #test"}) -      {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"}) -      {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"}) +      assert user.accepts_chat_messages +    end +  end -      fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"}) +  test "it fetches the appropriate tag-restricted posts" do +    user = insert(:user) -      fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]}) +    {:ok, status_one} = CommonAPI.post(user, %{status: ". #test"}) +    {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"}) +    {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"}) -      fetch_three = -        ActivityPub.fetch_activities([], %{ -          type: "Create", -          tag: ["test", "essais"], -          tag_reject: ["reject"] -        }) +    fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"}) -      fetch_four = -        ActivityPub.fetch_activities([], %{ -          type: "Create", -          tag: ["test"], -          tag_all: ["test", "reject"] -        }) +    fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]}) -      assert fetch_one == [status_one, status_three] -      assert fetch_two == [status_one, status_two, status_three] -      assert fetch_three == [status_one, status_two] -      assert fetch_four == [status_three] -    end +    fetch_three = +      ActivityPub.fetch_activities([], %{ +        type: "Create", +        tag: ["test", "essais"], +        tag_reject: ["reject"] +      }) + +    fetch_four = +      ActivityPub.fetch_activities([], %{ +        type: "Create", +        tag: ["test"], +        tag_all: ["test", "reject"] +      }) + +    assert fetch_one == [status_one, status_three] +    assert fetch_two == [status_one, status_two, status_three] +    assert fetch_three == [status_one, status_two] +    assert fetch_four == [status_three]    end    describe "insertion" do @@ -507,6 +514,33 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        activities = ActivityPub.fetch_activities_for_context("2hu", %{blocking_user: user})        assert activities == [activity_two, activity]      end + +    test "doesn't return activities with filtered words" do +      user = insert(:user) +      user_two = insert(:user) +      insert(:filter, user: user, phrase: "test", hide: true) + +      {:ok, %{id: id1, data: %{"context" => context}}} = CommonAPI.post(user, %{status: "1"}) + +      {:ok, %{id: id2}} = CommonAPI.post(user_two, %{status: "2", in_reply_to_status_id: id1}) + +      {:ok, %{id: id3} = user_activity} = +        CommonAPI.post(user, %{status: "3 test?", in_reply_to_status_id: id2}) + +      {:ok, %{id: id4} = filtered_activity} = +        CommonAPI.post(user_two, %{status: "4 test!", in_reply_to_status_id: id3}) + +      {:ok, _} = CommonAPI.post(user, %{status: "5", in_reply_to_status_id: id4}) + +      activities = +        context +        |> ActivityPub.fetch_activities_for_context(%{user: user}) +        |> Enum.map(& &1.id) + +      assert length(activities) == 4 +      assert user_activity.id in activities +      refute filtered_activity.id in activities +    end    end    test "doesn't return blocked activities" do @@ -642,7 +676,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      refute activity in activities      followed_user = insert(:user) -    ActivityPub.follow(user, followed_user) +    CommonAPI.follow(user, followed_user)      {:ok, repeat_activity} = CommonAPI.repeat(activity.id, followed_user)      activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true}) @@ -785,6 +819,75 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      assert activity == expected_activity    end +  describe "irreversible filters" do +    setup do +      user = insert(:user) +      user_two = insert(:user) + +      insert(:filter, user: user_two, phrase: "cofe", hide: true) +      insert(:filter, user: user_two, phrase: "ok boomer", hide: true) +      insert(:filter, user: user_two, phrase: "test", hide: false) + +      params = %{ +        type: ["Create", "Announce"], +        user: user_two +      } + +      {:ok, %{user: user, user_two: user_two, params: params}} +    end + +    test "it returns statuses if they don't contain exact filter words", %{ +      user: user, +      params: params +    } do +      {:ok, _} = CommonAPI.post(user, %{status: "hey"}) +      {:ok, _} = CommonAPI.post(user, %{status: "got cofefe?"}) +      {:ok, _} = CommonAPI.post(user, %{status: "I am not a boomer"}) +      {:ok, _} = CommonAPI.post(user, %{status: "ok boomers"}) +      {:ok, _} = CommonAPI.post(user, %{status: "ccofee is not a word"}) +      {:ok, _} = CommonAPI.post(user, %{status: "this is a test"}) + +      activities = ActivityPub.fetch_activities([], params) + +      assert Enum.count(activities) == 6 +    end + +    test "it does not filter user's own statuses", %{user_two: user_two, params: params} do +      {:ok, _} = CommonAPI.post(user_two, %{status: "Give me some cofe!"}) +      {:ok, _} = CommonAPI.post(user_two, %{status: "ok boomer"}) + +      activities = ActivityPub.fetch_activities([], params) + +      assert Enum.count(activities) == 2 +    end + +    test "it excludes statuses with filter words", %{user: user, params: params} do +      {:ok, _} = CommonAPI.post(user, %{status: "Give me some cofe!"}) +      {:ok, _} = CommonAPI.post(user, %{status: "ok boomer"}) +      {:ok, _} = CommonAPI.post(user, %{status: "is it a cOfE?"}) +      {:ok, _} = CommonAPI.post(user, %{status: "cofe is all I need"}) +      {:ok, _} = CommonAPI.post(user, %{status: "— ok BOOMER\n"}) + +      activities = ActivityPub.fetch_activities([], params) + +      assert Enum.empty?(activities) +    end + +    test "it returns all statuses if user does not have any filters" do +      another_user = insert(:user) +      {:ok, _} = CommonAPI.post(another_user, %{status: "got cofe?"}) +      {:ok, _} = CommonAPI.post(another_user, %{status: "test!"}) + +      activities = +        ActivityPub.fetch_activities([], %{ +          type: ["Create", "Announce"], +          user: another_user +        }) + +      assert Enum.count(activities) == 2 +    end +  end +    describe "public fetch activities" do      test "doesn't retrieve unlisted activities" do        user = insert(:user) @@ -917,24 +1020,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      end    end -  describe "following / unfollowing" do -    test "it reverts follow activity" do -      follower = insert(:user) -      followed = insert(:user) - -      with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do -        assert {:error, :reverted} = ActivityPub.follow(follower, followed) -      end - -      assert Repo.aggregate(Activity, :count, :id) == 0 -      assert Repo.aggregate(Object, :count, :id) == 0 -    end - +  describe "unfollowing" do      test "it reverts unfollow activity" do        follower = insert(:user)        followed = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do          assert {:error, :reverted} = ActivityPub.unfollow(follower, followed) @@ -947,21 +1038,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert activity.data["object"] == followed.ap_id      end -    test "creates a follow activity" do -      follower = insert(:user) -      followed = insert(:user) - -      {:ok, activity} = ActivityPub.follow(follower, followed) -      assert activity.data["type"] == "Follow" -      assert activity.data["actor"] == follower.ap_id -      assert activity.data["object"] == followed.ap_id -    end -      test "creates an undo activity for the last follow" do        follower = insert(:user)        followed = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        {:ok, activity} = ActivityPub.unfollow(follower, followed)        assert activity.data["type"] == "Undo" @@ -978,7 +1059,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        follower = insert(:user)        followed = insert(:user, %{locked: true}) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        {:ok, activity} = ActivityPub.unfollow(follower, followed)        assert activity.data["type"] == "Undo" @@ -1363,7 +1444,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert_enqueued(worker: Pleroma.Workers.BackgroundWorker, args: params) -      Pleroma.Workers.BackgroundWorker.perform(params, nil) +      Pleroma.Workers.BackgroundWorker.perform(%Oban.Job{args: params})        refute User.following?(follower, old_user)        assert User.following?(follower, new_user) @@ -1975,4 +2056,46 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all()      end    end + +  describe "handling of clashing nicknames" do +    test "renames an existing user with a clashing nickname and a different ap id" do +      orig_user = +        insert( +          :user, +          local: false, +          nickname: "admin@mastodon.example.org", +          ap_id: "http://mastodon.example.org/users/harinezumigari" +        ) + +      %{ +        nickname: orig_user.nickname, +        ap_id: orig_user.ap_id <> "part_2" +      } +      |> ActivityPub.maybe_handle_clashing_nickname() + +      user = User.get_by_id(orig_user.id) + +      assert user.nickname == "#{orig_user.id}.admin@mastodon.example.org" +    end + +    test "does nothing with a clashing nickname and the same ap id" do +      orig_user = +        insert( +          :user, +          local: false, +          nickname: "admin@mastodon.example.org", +          ap_id: "http://mastodon.example.org/users/harinezumigari" +        ) + +      %{ +        nickname: orig_user.nickname, +        ap_id: orig_user.ap_id +      } +      |> ActivityPub.maybe_handle_clashing_nickname() + +      user = User.get_by_id(orig_user.id) + +      assert user.nickname == orig_user.nickname +    end +  end  end diff --git a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs index fca0de7c6..3c795f5ac 100644 --- a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs +++ b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs @@ -21,7 +21,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do          "id" => "https://example.com/activities/1234"        } -      {:reject, nil} = AntiFollowbotPolicy.filter(message) +      assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)      end      test "matches followbots by display name" do @@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do          "id" => "https://example.com/activities/1234"        } -      {:reject, nil} = AntiFollowbotPolicy.filter(message) +      assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)      end    end diff --git a/test/web/activity_pub/mrf/hellthread_policy_test.exs b/test/web/activity_pub/mrf/hellthread_policy_test.exs index 6e9daa7f9..26f5bcdaa 100644 --- a/test/web/activity_pub/mrf/hellthread_policy_test.exs +++ b/test/web/activity_pub/mrf/hellthread_policy_test.exs @@ -50,7 +50,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do      } do        Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 2}) -      {:reject, nil} = filter(message) +      assert {:reject, "[HellthreadPolicy] 3 recipients is over the limit of 2"} == +               filter(message)      end      test "does not reject the message if the recipient count is below reject_threshold", %{ diff --git a/test/web/activity_pub/mrf/keyword_policy_test.exs b/test/web/activity_pub/mrf/keyword_policy_test.exs index fd1f7aec8..b3d0f3d90 100644 --- a/test/web/activity_pub/mrf/keyword_policy_test.exs +++ b/test/web/activity_pub/mrf/keyword_policy_test.exs @@ -25,7 +25,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do          }        } -      assert {:reject, nil} == KeywordPolicy.filter(message) +      assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} = +               KeywordPolicy.filter(message)      end      test "rejects if string matches in summary" do @@ -39,7 +40,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do          }        } -      assert {:reject, nil} == KeywordPolicy.filter(message) +      assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} = +               KeywordPolicy.filter(message)      end      test "rejects if regex matches in content" do @@ -55,7 +57,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do                     }                   } -                 {:reject, nil} == KeywordPolicy.filter(message) +                 {:reject, "[KeywordPolicy] Matches with rejected keyword"} == +                   KeywordPolicy.filter(message)                 end)      end @@ -72,7 +75,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do                     }                   } -                 {:reject, nil} == KeywordPolicy.filter(message) +                 {:reject, "[KeywordPolicy] Matches with rejected keyword"} == +                   KeywordPolicy.filter(message)                 end)      end    end diff --git a/test/web/activity_pub/mrf/mention_policy_test.exs b/test/web/activity_pub/mrf/mention_policy_test.exs index aa003bef5..220309cc9 100644 --- a/test/web/activity_pub/mrf/mention_policy_test.exs +++ b/test/web/activity_pub/mrf/mention_policy_test.exs @@ -76,7 +76,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do          "to" => ["https://example.com/blocked"]        } -      assert MentionPolicy.filter(message) == {:reject, nil} +      assert MentionPolicy.filter(message) == +               {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}      end      test "cc" do @@ -88,7 +89,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do          "cc" => ["https://example.com/blocked"]        } -      assert MentionPolicy.filter(message) == {:reject, nil} +      assert MentionPolicy.filter(message) == +               {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}      end    end  end diff --git a/test/web/activity_pub/mrf/reject_non_public_test.exs b/test/web/activity_pub/mrf/reject_non_public_test.exs index f36299b86..58b46b9a2 100644 --- a/test/web/activity_pub/mrf/reject_non_public_test.exs +++ b/test/web/activity_pub/mrf/reject_non_public_test.exs @@ -64,7 +64,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do        }        Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], false) -      assert {:reject, nil} = RejectNonPublic.filter(message) +      assert {:reject, _} = RejectNonPublic.filter(message)      end    end @@ -94,7 +94,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do        }        Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], false) -      assert {:reject, nil} = RejectNonPublic.filter(message) +      assert {:reject, _} = RejectNonPublic.filter(message)      end    end  end diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs index b7b9bc6a2..e842d8d8d 100644 --- a/test/web/activity_pub/mrf/simple_policy_test.exs +++ b/test/web/activity_pub/mrf/simple_policy_test.exs @@ -124,7 +124,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        report_message = build_report_message()        local_message = build_local_message() -      assert SimplePolicy.filter(report_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(report_message)        assert SimplePolicy.filter(local_message) == {:ok, local_message}      end @@ -133,7 +133,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        report_message = build_report_message()        local_message = build_local_message() -      assert SimplePolicy.filter(report_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(report_message)        assert SimplePolicy.filter(local_message) == {:ok, local_message}      end    end @@ -241,7 +241,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        remote_message = build_remote_message() -      assert SimplePolicy.filter(remote_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(remote_message)      end      test "activity matches with wildcard domain" do @@ -249,7 +249,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        remote_message = build_remote_message() -      assert SimplePolicy.filter(remote_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(remote_message)      end      test "actor has a matching host" do @@ -257,7 +257,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        remote_user = build_remote_user() -      assert SimplePolicy.filter(remote_user) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(remote_user)      end    end @@ -279,7 +279,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        remote_message = build_remote_message()        assert SimplePolicy.filter(local_message) == {:ok, local_message} -      assert SimplePolicy.filter(remote_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(remote_message)      end      test "activity has a matching host" do @@ -429,7 +429,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do      test "it rejects the deletion" do        deletion_message = build_remote_deletion_message() -      assert SimplePolicy.filter(deletion_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(deletion_message)      end    end @@ -439,7 +439,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do      test "it rejects the deletion" do        deletion_message = build_remote_deletion_message() -      assert SimplePolicy.filter(deletion_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(deletion_message)      end    end diff --git a/test/web/activity_pub/mrf/tag_policy_test.exs b/test/web/activity_pub/mrf/tag_policy_test.exs index e7793641a..6ff71d640 100644 --- a/test/web/activity_pub/mrf/tag_policy_test.exs +++ b/test/web/activity_pub/mrf/tag_policy_test.exs @@ -12,8 +12,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do    describe "mrf_tag:disable-any-subscription" do      test "rejects message" do        actor = insert(:user, tags: ["mrf_tag:disable-any-subscription"]) -      message = %{"object" => actor.ap_id, "type" => "Follow"} -      assert {:reject, nil} = TagPolicy.filter(message) +      message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => actor.ap_id} +      assert {:reject, _} = TagPolicy.filter(message)      end    end @@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do        actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])        follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: false)        message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id} -      assert {:reject, nil} = TagPolicy.filter(message) +      assert {:reject, _} = TagPolicy.filter(message)      end      test "allows non-local follow requests" do diff --git a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs index ba1b69658..8e1ad5bc8 100644 --- a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs +++ b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs @@ -26,6 +26,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do      actor = insert(:user)      Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => ["test-ap-id"]})      message = %{"actor" => actor.ap_id} -    assert UserAllowListPolicy.filter(message) == {:reject, nil} +    assert {:reject, _} = UserAllowListPolicy.filter(message)    end  end diff --git a/test/web/activity_pub/mrf/vocabulary_policy_test.exs b/test/web/activity_pub/mrf/vocabulary_policy_test.exs index 69f22bb77..2bceb67ee 100644 --- a/test/web/activity_pub/mrf/vocabulary_policy_test.exs +++ b/test/web/activity_pub/mrf/vocabulary_policy_test.exs @@ -46,7 +46,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do          }        } -      {:reject, nil} = VocabularyPolicy.filter(message) +      {:reject, _} = VocabularyPolicy.filter(message)      end      test "it does not accept disallowed parent types" do @@ -60,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do          }        } -      {:reject, nil} = VocabularyPolicy.filter(message) +      {:reject, _} = VocabularyPolicy.filter(message)      end    end @@ -75,7 +75,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do          "object" => "whatever"        } -      {:reject, nil} = VocabularyPolicy.filter(message) +      {:reject, _} = VocabularyPolicy.filter(message)      end      test "it rejects based on child object type" do @@ -89,7 +89,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do          }        } -      {:reject, nil} = VocabularyPolicy.filter(message) +      {:reject, _} = VocabularyPolicy.filter(message)      end      test "it passes through objects that aren't disallowed" do diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs deleted file mode 100644 index f38bf7e08..000000000 --- a/test/web/activity_pub/object_validator_test.exs +++ /dev/null @@ -1,684 +0,0 @@ -defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do -  use Pleroma.DataCase - -  alias Pleroma.Object -  alias Pleroma.Web.ActivityPub.ActivityPub -  alias Pleroma.Web.ActivityPub.Builder -  alias Pleroma.Web.ActivityPub.ObjectValidator -  alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator -  alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator -  alias Pleroma.Web.ActivityPub.Utils -  alias Pleroma.Web.CommonAPI - -  import Pleroma.Factory - -  describe "attachments" do -    test "works with honkerific attachments" do -      attachment = %{ -        "mediaType" => "", -        "name" => "", -        "summary" => "298p3RG7j27tfsZ9RQ.jpg", -        "type" => "Document", -        "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg" -      } - -      assert {:ok, attachment} = -               AttachmentValidator.cast_and_validate(attachment) -               |> Ecto.Changeset.apply_action(:insert) - -      assert attachment.mediaType == "application/octet-stream" -    end - -    test "it turns mastodon attachments into our attachments" do -      attachment = %{ -        "url" => -          "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg", -        "type" => "Document", -        "name" => nil, -        "mediaType" => "image/jpeg" -      } - -      {:ok, attachment} = -        AttachmentValidator.cast_and_validate(attachment) -        |> Ecto.Changeset.apply_action(:insert) - -      assert [ -               %{ -                 href: -                   "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg", -                 type: "Link", -                 mediaType: "image/jpeg" -               } -             ] = attachment.url - -      assert attachment.mediaType == "image/jpeg" -    end - -    test "it handles our own uploads" do -      user = insert(:user) - -      file = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) - -      {:ok, attachment} = -        attachment.data -        |> AttachmentValidator.cast_and_validate() -        |> Ecto.Changeset.apply_action(:insert) - -      assert attachment.mediaType == "image/jpeg" -    end -  end - -  describe "chat message create activities" do -    test "it is invalid if the object already exists" do -      user = insert(:user) -      recipient = insert(:user) -      {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "hey") -      object = Object.normalize(activity, false) - -      {:ok, create_data, _} = Builder.create(user, object.data, [recipient.ap_id]) - -      {:error, cng} = ObjectValidator.validate(create_data, []) - -      assert {:object, {"The object to create already exists", []}} in cng.errors -    end - -    test "it is invalid if the object data has a different `to` or `actor` field" do -      user = insert(:user) -      recipient = insert(:user) -      {:ok, object_data, _} = Builder.chat_message(recipient, user.ap_id, "Hey") - -      {:ok, create_data, _} = Builder.create(user, object_data, [recipient.ap_id]) - -      {:error, cng} = ObjectValidator.validate(create_data, []) - -      assert {:to, {"Recipients don't match with object recipients", []}} in cng.errors -      assert {:actor, {"Actor doesn't match with object actor", []}} in cng.errors -    end -  end - -  describe "chat messages" do -    setup do -      clear_config([:instance, :remote_limit]) -      user = insert(:user) -      recipient = insert(:user, local: false) - -      {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey :firefox:") - -      %{user: user, recipient: recipient, valid_chat_message: valid_chat_message} -    end - -    test "let's through some basic html", %{user: user, recipient: recipient} do -      {:ok, valid_chat_message, _} = -        Builder.chat_message( -          user, -          recipient.ap_id, -          "hey <a href='https://example.org'>example</a> <script>alert('uguu')</script>" -        ) - -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert object["content"] == -               "hey <a href=\"https://example.org\">example</a> alert('uguu')" -    end - -    test "validates for a basic object we build", %{valid_chat_message: valid_chat_message} do -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert Map.put(valid_chat_message, "attachment", nil) == object -    end - -    test "validates for a basic object with an attachment", %{ -      valid_chat_message: valid_chat_message, -      user: user -    } do -      file = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) - -      valid_chat_message = -        valid_chat_message -        |> Map.put("attachment", attachment.data) - -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert object["attachment"] -    end - -    test "validates for a basic object with an attachment in an array", %{ -      valid_chat_message: valid_chat_message, -      user: user -    } do -      file = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) - -      valid_chat_message = -        valid_chat_message -        |> Map.put("attachment", [attachment.data]) - -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert object["attachment"] -    end - -    test "validates for a basic object with an attachment but without content", %{ -      valid_chat_message: valid_chat_message, -      user: user -    } do -      file = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) - -      valid_chat_message = -        valid_chat_message -        |> Map.put("attachment", attachment.data) -        |> Map.delete("content") - -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert object["attachment"] -    end - -    test "does not validate if the message has no content", %{ -      valid_chat_message: valid_chat_message -    } do -      contentless = -        valid_chat_message -        |> Map.delete("content") - -      refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, [])) -    end - -    test "does not validate if the message is longer than the remote_limit", %{ -      valid_chat_message: valid_chat_message -    } do -      Pleroma.Config.put([:instance, :remote_limit], 2) -      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) -    end - -    test "does not validate if the recipient is blocking the actor", %{ -      valid_chat_message: valid_chat_message, -      user: user, -      recipient: recipient -    } do -      Pleroma.User.block(recipient, user) -      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) -    end - -    test "does not validate if the actor or the recipient is not in our system", %{ -      valid_chat_message: valid_chat_message -    } do -      chat_message = -        valid_chat_message -        |> Map.put("actor", "https://raymoo.com/raymoo") - -      {:error, _} = ObjectValidator.validate(chat_message, []) - -      chat_message = -        valid_chat_message -        |> Map.put("to", ["https://raymoo.com/raymoo"]) - -      {:error, _} = ObjectValidator.validate(chat_message, []) -    end - -    test "does not validate for a message with multiple recipients", %{ -      valid_chat_message: valid_chat_message, -      user: user, -      recipient: recipient -    } do -      chat_message = -        valid_chat_message -        |> Map.put("to", [user.ap_id, recipient.ap_id]) - -      assert {:error, _} = ObjectValidator.validate(chat_message, []) -    end - -    test "does not validate if it doesn't concern local users" do -      user = insert(:user, local: false) -      recipient = insert(:user, local: false) - -      {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey") -      assert {:error, _} = ObjectValidator.validate(valid_chat_message, []) -    end -  end - -  describe "EmojiReacts" do -    setup do -      user = insert(:user) -      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) - -      object = Pleroma.Object.get_by_ap_id(post_activity.data["object"]) - -      {:ok, valid_emoji_react, []} = Builder.emoji_react(user, object, "👌") - -      %{user: user, post_activity: post_activity, valid_emoji_react: valid_emoji_react} -    end - -    test "it validates a valid EmojiReact", %{valid_emoji_react: valid_emoji_react} do -      assert {:ok, _, _} = ObjectValidator.validate(valid_emoji_react, []) -    end - -    test "it is not valid without a 'content' field", %{valid_emoji_react: valid_emoji_react} do -      without_content = -        valid_emoji_react -        |> Map.delete("content") - -      {:error, cng} = ObjectValidator.validate(without_content, []) - -      refute cng.valid? -      assert {:content, {"can't be blank", [validation: :required]}} in cng.errors -    end - -    test "it is not valid with a non-emoji content field", %{valid_emoji_react: valid_emoji_react} do -      without_emoji_content = -        valid_emoji_react -        |> Map.put("content", "x") - -      {:error, cng} = ObjectValidator.validate(without_emoji_content, []) - -      refute cng.valid? - -      assert {:content, {"must be a single character emoji", []}} in cng.errors -    end -  end - -  describe "Undos" do -    setup do -      user = insert(:user) -      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) -      {:ok, like} = CommonAPI.favorite(user, post_activity.id) -      {:ok, valid_like_undo, []} = Builder.undo(user, like) - -      %{user: user, like: like, valid_like_undo: valid_like_undo} -    end - -    test "it validates a basic like undo", %{valid_like_undo: valid_like_undo} do -      assert {:ok, _, _} = ObjectValidator.validate(valid_like_undo, []) -    end - -    test "it does not validate if the actor of the undo is not the actor of the object", %{ -      valid_like_undo: valid_like_undo -    } do -      other_user = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo") - -      bad_actor = -        valid_like_undo -        |> Map.put("actor", other_user.ap_id) - -      {:error, cng} = ObjectValidator.validate(bad_actor, []) - -      assert {:actor, {"not the same as object actor", []}} in cng.errors -    end - -    test "it does not validate if the object is missing", %{valid_like_undo: valid_like_undo} do -      missing_object = -        valid_like_undo -        |> Map.put("object", "https://gensokyo.2hu/objects/1") - -      {:error, cng} = ObjectValidator.validate(missing_object, []) - -      assert {:object, {"can't find object", []}} in cng.errors -      assert length(cng.errors) == 1 -    end -  end - -  describe "deletes" do -    setup do -      user = insert(:user) -      {:ok, post_activity} = CommonAPI.post(user, %{status: "cancel me daddy"}) - -      {:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"]) -      {:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id) - -      %{user: user, valid_post_delete: valid_post_delete, valid_user_delete: valid_user_delete} -    end - -    test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do -      {:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, []) - -      assert valid_post_delete["deleted_activity_id"] -    end - -    test "it is invalid if the object isn't in a list of certain types", %{ -      valid_post_delete: valid_post_delete -    } do -      object = Object.get_by_ap_id(valid_post_delete["object"]) - -      data = -        object.data -        |> Map.put("type", "Like") - -      {:ok, _object} = -        object -        |> Ecto.Changeset.change(%{data: data}) -        |> Object.update_and_set_cache() - -      {:error, cng} = ObjectValidator.validate(valid_post_delete, []) -      assert {:object, {"object not in allowed types", []}} in cng.errors -    end - -    test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do -      assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, [])) -    end - -    test "it's invalid if the id is missing", %{valid_post_delete: valid_post_delete} do -      no_id = -        valid_post_delete -        |> Map.delete("id") - -      {:error, cng} = ObjectValidator.validate(no_id, []) - -      assert {:id, {"can't be blank", [validation: :required]}} in cng.errors -    end - -    test "it's invalid if the object doesn't exist", %{valid_post_delete: valid_post_delete} do -      missing_object = -        valid_post_delete -        |> Map.put("object", "http://does.not/exist") - -      {:error, cng} = ObjectValidator.validate(missing_object, []) - -      assert {:object, {"can't find object", []}} in cng.errors -    end - -    test "it's invalid if the actor of the object and the actor of delete are from different domains", -         %{valid_post_delete: valid_post_delete} do -      valid_user = insert(:user) - -      valid_other_actor = -        valid_post_delete -        |> Map.put("actor", valid_user.ap_id) - -      assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, [])) - -      invalid_other_actor = -        valid_post_delete -        |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") - -      {:error, cng} = ObjectValidator.validate(invalid_other_actor, []) - -      assert {:actor, {"is not allowed to delete object", []}} in cng.errors -    end - -    test "it's valid if the actor of the object is a local superuser", -         %{valid_post_delete: valid_post_delete} do -      user = -        insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo") - -      valid_other_actor = -        valid_post_delete -        |> Map.put("actor", user.ap_id) - -      {:ok, _, meta} = ObjectValidator.validate(valid_other_actor, []) -      assert meta[:do_not_federate] -    end -  end - -  describe "likes" do -    setup do -      user = insert(:user) -      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) - -      valid_like = %{ -        "to" => [user.ap_id], -        "cc" => [], -        "type" => "Like", -        "id" => Utils.generate_activity_id(), -        "object" => post_activity.data["object"], -        "actor" => user.ap_id, -        "context" => "a context" -      } - -      %{valid_like: valid_like, user: user, post_activity: post_activity} -    end - -    test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do -      {:ok, object, _meta} = ObjectValidator.validate(valid_like, []) - -      assert "id" in Map.keys(object) -    end - -    test "is valid for a valid object", %{valid_like: valid_like} do -      assert LikeValidator.cast_and_validate(valid_like).valid? -    end - -    test "sets the 'to' field to the object actor if no recipients are given", %{ -      valid_like: valid_like, -      user: user -    } do -      without_recipients = -        valid_like -        |> Map.delete("to") - -      {:ok, object, _meta} = ObjectValidator.validate(without_recipients, []) - -      assert object["to"] == [user.ap_id] -    end - -    test "sets the context field to the context of the object if no context is given", %{ -      valid_like: valid_like, -      post_activity: post_activity -    } do -      without_context = -        valid_like -        |> Map.delete("context") - -      {:ok, object, _meta} = ObjectValidator.validate(without_context, []) - -      assert object["context"] == post_activity.data["context"] -    end - -    test "it errors when the actor is missing or not known", %{valid_like: valid_like} do -      without_actor = Map.delete(valid_like, "actor") - -      refute LikeValidator.cast_and_validate(without_actor).valid? - -      with_invalid_actor = Map.put(valid_like, "actor", "invalidactor") - -      refute LikeValidator.cast_and_validate(with_invalid_actor).valid? -    end - -    test "it errors when the object is missing or not known", %{valid_like: valid_like} do -      without_object = Map.delete(valid_like, "object") - -      refute LikeValidator.cast_and_validate(without_object).valid? - -      with_invalid_object = Map.put(valid_like, "object", "invalidobject") - -      refute LikeValidator.cast_and_validate(with_invalid_object).valid? -    end - -    test "it errors when the actor has already like the object", %{ -      valid_like: valid_like, -      user: user, -      post_activity: post_activity -    } do -      _like = CommonAPI.favorite(user, post_activity.id) - -      refute LikeValidator.cast_and_validate(valid_like).valid? -    end - -    test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do -      wrapped_like = -        valid_like -        |> Map.put("actor", %{"id" => valid_like["actor"]}) -        |> Map.put("object", %{"id" => valid_like["object"]}) - -      validated = LikeValidator.cast_and_validate(wrapped_like) - -      assert validated.valid? - -      assert {:actor, valid_like["actor"]} in validated.changes -      assert {:object, valid_like["object"]} in validated.changes -    end -  end - -  describe "announces" do -    setup do -      user = insert(:user) -      announcer = insert(:user) -      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) - -      object = Object.normalize(post_activity, false) -      {:ok, valid_announce, []} = Builder.announce(announcer, object) - -      %{ -        valid_announce: valid_announce, -        user: user, -        post_activity: post_activity, -        announcer: announcer -      } -    end - -    test "returns ok for a valid announce", %{valid_announce: valid_announce} do -      assert {:ok, _object, _meta} = ObjectValidator.validate(valid_announce, []) -    end - -    test "returns an error if the object can't be found", %{valid_announce: valid_announce} do -      without_object = -        valid_announce -        |> Map.delete("object") - -      {:error, cng} = ObjectValidator.validate(without_object, []) - -      assert {:object, {"can't be blank", [validation: :required]}} in cng.errors - -      nonexisting_object = -        valid_announce -        |> Map.put("object", "https://gensokyo.2hu/objects/99999999") - -      {:error, cng} = ObjectValidator.validate(nonexisting_object, []) - -      assert {:object, {"can't find object", []}} in cng.errors -    end - -    test "returns an error if we don't have the actor", %{valid_announce: valid_announce} do -      nonexisting_actor = -        valid_announce -        |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") - -      {:error, cng} = ObjectValidator.validate(nonexisting_actor, []) - -      assert {:actor, {"can't find user", []}} in cng.errors -    end - -    test "returns an error if the actor already announced the object", %{ -      valid_announce: valid_announce, -      announcer: announcer, -      post_activity: post_activity -    } do -      _announce = CommonAPI.repeat(post_activity.id, announcer) - -      {:error, cng} = ObjectValidator.validate(valid_announce, []) - -      assert {:actor, {"already announced this object", []}} in cng.errors -      assert {:object, {"already announced by this actor", []}} in cng.errors -    end - -    test "returns an error if the actor can't announce the object", %{ -      announcer: announcer, -      user: user -    } do -      {:ok, post_activity} = -        CommonAPI.post(user, %{status: "a secret post", visibility: "private"}) - -      object = Object.normalize(post_activity, false) - -      # Another user can't announce it -      {:ok, announce, []} = Builder.announce(announcer, object, public: false) - -      {:error, cng} = ObjectValidator.validate(announce, []) - -      assert {:actor, {"can not announce this object", []}} in cng.errors - -      # The actor of the object can announce it -      {:ok, announce, []} = Builder.announce(user, object, public: false) - -      assert {:ok, _, _} = ObjectValidator.validate(announce, []) - -      # The actor of the object can not announce it publicly -      {:ok, announce, []} = Builder.announce(user, object, public: true) - -      {:error, cng} = ObjectValidator.validate(announce, []) - -      assert {:actor, {"can not announce this object publicly", []}} in cng.errors -    end -  end - -  describe "updates" do -    setup do -      user = insert(:user) - -      object = %{ -        "id" => user.ap_id, -        "name" => "A new name", -        "summary" => "A new bio" -      } - -      {:ok, valid_update, []} = Builder.update(user, object) - -      %{user: user, valid_update: valid_update} -    end - -    test "validates a basic object", %{valid_update: valid_update} do -      assert {:ok, _update, []} = ObjectValidator.validate(valid_update, []) -    end - -    test "returns an error if the object can't be updated by the actor", %{ -      valid_update: valid_update -    } do -      other_user = insert(:user) - -      update = -        valid_update -        |> Map.put("actor", other_user.ap_id) - -      assert {:error, _cng} = ObjectValidator.validate(update, []) -    end -  end - -  describe "blocks" do -    setup do -      user = insert(:user, local: false) -      blocked = insert(:user) - -      {:ok, valid_block, []} = Builder.block(user, blocked) - -      %{user: user, valid_block: valid_block} -    end - -    test "validates a basic object", %{ -      valid_block: valid_block -    } do -      assert {:ok, _block, []} = ObjectValidator.validate(valid_block, []) -    end - -    test "returns an error if we don't know the blocked user", %{ -      valid_block: valid_block -    } do -      block = -        valid_block -        |> Map.put("object", "https://gensokyo.2hu/users/raymoo") - -      assert {:error, _cng} = ObjectValidator.validate(block, []) -    end -  end -end diff --git a/test/web/activity_pub/object_validators/announce_validation_test.exs b/test/web/activity_pub/object_validators/announce_validation_test.exs new file mode 100644 index 000000000..623342f76 --- /dev/null +++ b/test/web/activity_pub/object_validators/announce_validation_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.ActivityPub.ObjectValidators.AnnouncValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "announces" do +    setup do +      user = insert(:user) +      announcer = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) + +      object = Object.normalize(post_activity, false) +      {:ok, valid_announce, []} = Builder.announce(announcer, object) + +      %{ +        valid_announce: valid_announce, +        user: user, +        post_activity: post_activity, +        announcer: announcer +      } +    end + +    test "returns ok for a valid announce", %{valid_announce: valid_announce} do +      assert {:ok, _object, _meta} = ObjectValidator.validate(valid_announce, []) +    end + +    test "returns an error if the object can't be found", %{valid_announce: valid_announce} do +      without_object = +        valid_announce +        |> Map.delete("object") + +      {:error, cng} = ObjectValidator.validate(without_object, []) + +      assert {:object, {"can't be blank", [validation: :required]}} in cng.errors + +      nonexisting_object = +        valid_announce +        |> Map.put("object", "https://gensokyo.2hu/objects/99999999") + +      {:error, cng} = ObjectValidator.validate(nonexisting_object, []) + +      assert {:object, {"can't find object", []}} in cng.errors +    end + +    test "returns an error if we don't have the actor", %{valid_announce: valid_announce} do +      nonexisting_actor = +        valid_announce +        |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") + +      {:error, cng} = ObjectValidator.validate(nonexisting_actor, []) + +      assert {:actor, {"can't find user", []}} in cng.errors +    end + +    test "returns an error if the actor already announced the object", %{ +      valid_announce: valid_announce, +      announcer: announcer, +      post_activity: post_activity +    } do +      _announce = CommonAPI.repeat(post_activity.id, announcer) + +      {:error, cng} = ObjectValidator.validate(valid_announce, []) + +      assert {:actor, {"already announced this object", []}} in cng.errors +      assert {:object, {"already announced by this actor", []}} in cng.errors +    end + +    test "returns an error if the actor can't announce the object", %{ +      announcer: announcer, +      user: user +    } do +      {:ok, post_activity} = +        CommonAPI.post(user, %{status: "a secret post", visibility: "private"}) + +      object = Object.normalize(post_activity, false) + +      # Another user can't announce it +      {:ok, announce, []} = Builder.announce(announcer, object, public: false) + +      {:error, cng} = ObjectValidator.validate(announce, []) + +      assert {:actor, {"can not announce this object", []}} in cng.errors + +      # The actor of the object can announce it +      {:ok, announce, []} = Builder.announce(user, object, public: false) + +      assert {:ok, _, _} = ObjectValidator.validate(announce, []) + +      # The actor of the object can not announce it publicly +      {:ok, announce, []} = Builder.announce(user, object, public: true) + +      {:error, cng} = ObjectValidator.validate(announce, []) + +      assert {:actor, {"can not announce this object publicly", []}} in cng.errors +    end +  end +end diff --git a/test/web/activity_pub/object_validators/attachment_validator_test.exs b/test/web/activity_pub/object_validators/attachment_validator_test.exs new file mode 100644 index 000000000..558bb3131 --- /dev/null +++ b/test/web/activity_pub/object_validators/attachment_validator_test.exs @@ -0,0 +1,74 @@ +# 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.ObjectValidators.AttachmentValidatorTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + +  import Pleroma.Factory + +  describe "attachments" do +    test "works with honkerific attachments" do +      attachment = %{ +        "mediaType" => "", +        "name" => "", +        "summary" => "298p3RG7j27tfsZ9RQ.jpg", +        "type" => "Document", +        "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg" +      } + +      assert {:ok, attachment} = +               AttachmentValidator.cast_and_validate(attachment) +               |> Ecto.Changeset.apply_action(:insert) + +      assert attachment.mediaType == "application/octet-stream" +    end + +    test "it turns mastodon attachments into our attachments" do +      attachment = %{ +        "url" => +          "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg", +        "type" => "Document", +        "name" => nil, +        "mediaType" => "image/jpeg" +      } + +      {:ok, attachment} = +        AttachmentValidator.cast_and_validate(attachment) +        |> Ecto.Changeset.apply_action(:insert) + +      assert [ +               %{ +                 href: +                   "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg", +                 type: "Link", +                 mediaType: "image/jpeg" +               } +             ] = attachment.url + +      assert attachment.mediaType == "image/jpeg" +    end + +    test "it handles our own uploads" do +      user = insert(:user) + +      file = %Plug.Upload{ +        content_type: "image/jpg", +        path: Path.absname("test/fixtures/image.jpg"), +        filename: "an_image.jpg" +      } + +      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) + +      {:ok, attachment} = +        attachment.data +        |> AttachmentValidator.cast_and_validate() +        |> Ecto.Changeset.apply_action(:insert) + +      assert attachment.mediaType == "image/jpeg" +    end +  end +end diff --git a/test/web/activity_pub/object_validators/block_validation_test.exs b/test/web/activity_pub/object_validators/block_validation_test.exs new file mode 100644 index 000000000..c08d4b2e8 --- /dev/null +++ b/test/web/activity_pub/object_validators/block_validation_test.exs @@ -0,0 +1,39 @@ +# 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.ObjectValidators.BlockValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator + +  import Pleroma.Factory + +  describe "blocks" do +    setup do +      user = insert(:user, local: false) +      blocked = insert(:user) + +      {:ok, valid_block, []} = Builder.block(user, blocked) + +      %{user: user, valid_block: valid_block} +    end + +    test "validates a basic object", %{ +      valid_block: valid_block +    } do +      assert {:ok, _block, []} = ObjectValidator.validate(valid_block, []) +    end + +    test "returns an error if we don't know the blocked user", %{ +      valid_block: valid_block +    } do +      block = +        valid_block +        |> Map.put("object", "https://gensokyo.2hu/users/raymoo") + +      assert {:error, _cng} = ObjectValidator.validate(block, []) +    end +  end +end diff --git a/test/web/activity_pub/object_validators/chat_validation_test.exs b/test/web/activity_pub/object_validators/chat_validation_test.exs new file mode 100644 index 000000000..50bf03515 --- /dev/null +++ b/test/web/activity_pub/object_validators/chat_validation_test.exs @@ -0,0 +1,211 @@ +# 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.ObjectValidators.ChatValidationTest do +  use Pleroma.DataCase +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "chat message create activities" do +    test "it is invalid if the object already exists" do +      user = insert(:user) +      recipient = insert(:user) +      {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "hey") +      object = Object.normalize(activity, false) + +      {:ok, create_data, _} = Builder.create(user, object.data, [recipient.ap_id]) + +      {:error, cng} = ObjectValidator.validate(create_data, []) + +      assert {:object, {"The object to create already exists", []}} in cng.errors +    end + +    test "it is invalid if the object data has a different `to` or `actor` field" do +      user = insert(:user) +      recipient = insert(:user) +      {:ok, object_data, _} = Builder.chat_message(recipient, user.ap_id, "Hey") + +      {:ok, create_data, _} = Builder.create(user, object_data, [recipient.ap_id]) + +      {:error, cng} = ObjectValidator.validate(create_data, []) + +      assert {:to, {"Recipients don't match with object recipients", []}} in cng.errors +      assert {:actor, {"Actor doesn't match with object actor", []}} in cng.errors +    end +  end + +  describe "chat messages" do +    setup do +      clear_config([:instance, :remote_limit]) +      user = insert(:user) +      recipient = insert(:user, local: false) + +      {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey :firefox:") + +      %{user: user, recipient: recipient, valid_chat_message: valid_chat_message} +    end + +    test "let's through some basic html", %{user: user, recipient: recipient} do +      {:ok, valid_chat_message, _} = +        Builder.chat_message( +          user, +          recipient.ap_id, +          "hey <a href='https://example.org'>example</a> <script>alert('uguu')</script>" +        ) + +      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + +      assert object["content"] == +               "hey <a href=\"https://example.org\">example</a> alert('uguu')" +    end + +    test "validates for a basic object we build", %{valid_chat_message: valid_chat_message} do +      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + +      assert Map.put(valid_chat_message, "attachment", nil) == object +    end + +    test "validates for a basic object with an attachment", %{ +      valid_chat_message: valid_chat_message, +      user: user +    } do +      file = %Plug.Upload{ +        content_type: "image/jpg", +        path: Path.absname("test/fixtures/image.jpg"), +        filename: "an_image.jpg" +      } + +      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) + +      valid_chat_message = +        valid_chat_message +        |> Map.put("attachment", attachment.data) + +      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + +      assert object["attachment"] +    end + +    test "validates for a basic object with an attachment in an array", %{ +      valid_chat_message: valid_chat_message, +      user: user +    } do +      file = %Plug.Upload{ +        content_type: "image/jpg", +        path: Path.absname("test/fixtures/image.jpg"), +        filename: "an_image.jpg" +      } + +      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) + +      valid_chat_message = +        valid_chat_message +        |> Map.put("attachment", [attachment.data]) + +      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + +      assert object["attachment"] +    end + +    test "validates for a basic object with an attachment but without content", %{ +      valid_chat_message: valid_chat_message, +      user: user +    } do +      file = %Plug.Upload{ +        content_type: "image/jpg", +        path: Path.absname("test/fixtures/image.jpg"), +        filename: "an_image.jpg" +      } + +      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) + +      valid_chat_message = +        valid_chat_message +        |> Map.put("attachment", attachment.data) +        |> Map.delete("content") + +      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + +      assert object["attachment"] +    end + +    test "does not validate if the message has no content", %{ +      valid_chat_message: valid_chat_message +    } do +      contentless = +        valid_chat_message +        |> Map.delete("content") + +      refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, [])) +    end + +    test "does not validate if the message is longer than the remote_limit", %{ +      valid_chat_message: valid_chat_message +    } do +      Pleroma.Config.put([:instance, :remote_limit], 2) +      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) +    end + +    test "does not validate if the recipient is blocking the actor", %{ +      valid_chat_message: valid_chat_message, +      user: user, +      recipient: recipient +    } do +      Pleroma.User.block(recipient, user) +      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) +    end + +    test "does not validate if the recipient is not accepting chat messages", %{ +      valid_chat_message: valid_chat_message, +      recipient: recipient +    } do +      recipient +      |> Ecto.Changeset.change(%{accepts_chat_messages: false}) +      |> Pleroma.Repo.update!() + +      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) +    end + +    test "does not validate if the actor or the recipient is not in our system", %{ +      valid_chat_message: valid_chat_message +    } do +      chat_message = +        valid_chat_message +        |> Map.put("actor", "https://raymoo.com/raymoo") + +      {:error, _} = ObjectValidator.validate(chat_message, []) + +      chat_message = +        valid_chat_message +        |> Map.put("to", ["https://raymoo.com/raymoo"]) + +      {:error, _} = ObjectValidator.validate(chat_message, []) +    end + +    test "does not validate for a message with multiple recipients", %{ +      valid_chat_message: valid_chat_message, +      user: user, +      recipient: recipient +    } do +      chat_message = +        valid_chat_message +        |> Map.put("to", [user.ap_id, recipient.ap_id]) + +      assert {:error, _} = ObjectValidator.validate(chat_message, []) +    end + +    test "does not validate if it doesn't concern local users" do +      user = insert(:user, local: false) +      recipient = insert(:user, local: false) + +      {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey") +      assert {:error, _} = ObjectValidator.validate(valid_chat_message, []) +    end +  end +end diff --git a/test/web/activity_pub/object_validators/delete_validation_test.exs b/test/web/activity_pub/object_validators/delete_validation_test.exs new file mode 100644 index 000000000..42cd18298 --- /dev/null +++ b/test/web/activity_pub/object_validators/delete_validation_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.ActivityPub.ObjectValidators.DeleteValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "deletes" do +    setup do +      user = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{status: "cancel me daddy"}) + +      {:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"]) +      {:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id) + +      %{user: user, valid_post_delete: valid_post_delete, valid_user_delete: valid_user_delete} +    end + +    test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do +      {:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, []) + +      assert valid_post_delete["deleted_activity_id"] +    end + +    test "it is invalid if the object isn't in a list of certain types", %{ +      valid_post_delete: valid_post_delete +    } do +      object = Object.get_by_ap_id(valid_post_delete["object"]) + +      data = +        object.data +        |> Map.put("type", "Like") + +      {:ok, _object} = +        object +        |> Ecto.Changeset.change(%{data: data}) +        |> Object.update_and_set_cache() + +      {:error, cng} = ObjectValidator.validate(valid_post_delete, []) +      assert {:object, {"object not in allowed types", []}} in cng.errors +    end + +    test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do +      assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, [])) +    end + +    test "it's invalid if the id is missing", %{valid_post_delete: valid_post_delete} do +      no_id = +        valid_post_delete +        |> Map.delete("id") + +      {:error, cng} = ObjectValidator.validate(no_id, []) + +      assert {:id, {"can't be blank", [validation: :required]}} in cng.errors +    end + +    test "it's invalid if the object doesn't exist", %{valid_post_delete: valid_post_delete} do +      missing_object = +        valid_post_delete +        |> Map.put("object", "http://does.not/exist") + +      {:error, cng} = ObjectValidator.validate(missing_object, []) + +      assert {:object, {"can't find object", []}} in cng.errors +    end + +    test "it's invalid if the actor of the object and the actor of delete are from different domains", +         %{valid_post_delete: valid_post_delete} do +      valid_user = insert(:user) + +      valid_other_actor = +        valid_post_delete +        |> Map.put("actor", valid_user.ap_id) + +      assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, [])) + +      invalid_other_actor = +        valid_post_delete +        |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") + +      {:error, cng} = ObjectValidator.validate(invalid_other_actor, []) + +      assert {:actor, {"is not allowed to delete object", []}} in cng.errors +    end + +    test "it's valid if the actor of the object is a local superuser", +         %{valid_post_delete: valid_post_delete} do +      user = +        insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo") + +      valid_other_actor = +        valid_post_delete +        |> Map.put("actor", user.ap_id) + +      {:ok, _, meta} = ObjectValidator.validate(valid_other_actor, []) +      assert meta[:do_not_federate] +    end +  end +end diff --git a/test/web/activity_pub/object_validators/emoji_react_validation_test.exs b/test/web/activity_pub/object_validators/emoji_react_validation_test.exs new file mode 100644 index 000000000..582e6d785 --- /dev/null +++ b/test/web/activity_pub/object_validators/emoji_react_validation_test.exs @@ -0,0 +1,53 @@ +# 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.ObjectValidators.EmojiReactHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "EmojiReacts" do +    setup do +      user = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) + +      object = Pleroma.Object.get_by_ap_id(post_activity.data["object"]) + +      {:ok, valid_emoji_react, []} = Builder.emoji_react(user, object, "👌") + +      %{user: user, post_activity: post_activity, valid_emoji_react: valid_emoji_react} +    end + +    test "it validates a valid EmojiReact", %{valid_emoji_react: valid_emoji_react} do +      assert {:ok, _, _} = ObjectValidator.validate(valid_emoji_react, []) +    end + +    test "it is not valid without a 'content' field", %{valid_emoji_react: valid_emoji_react} do +      without_content = +        valid_emoji_react +        |> Map.delete("content") + +      {:error, cng} = ObjectValidator.validate(without_content, []) + +      refute cng.valid? +      assert {:content, {"can't be blank", [validation: :required]}} in cng.errors +    end + +    test "it is not valid with a non-emoji content field", %{valid_emoji_react: valid_emoji_react} do +      without_emoji_content = +        valid_emoji_react +        |> Map.put("content", "x") + +      {:error, cng} = ObjectValidator.validate(without_emoji_content, []) + +      refute cng.valid? + +      assert {:content, {"must be a single character emoji", []}} in cng.errors +    end +  end +end diff --git a/test/web/activity_pub/object_validators/follow_validation_test.exs b/test/web/activity_pub/object_validators/follow_validation_test.exs new file mode 100644 index 000000000..6e1378be2 --- /dev/null +++ b/test/web/activity_pub/object_validators/follow_validation_test.exs @@ -0,0 +1,26 @@ +# 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.ObjectValidators.FollowValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator + +  import Pleroma.Factory + +  describe "Follows" do +    setup do +      follower = insert(:user) +      followed = insert(:user) + +      {:ok, valid_follow, []} = Builder.follow(follower, followed) +      %{follower: follower, followed: followed, valid_follow: valid_follow} +    end + +    test "validates a basic follow object", %{valid_follow: valid_follow} do +      assert {:ok, _follow, []} = ObjectValidator.validate(valid_follow, []) +    end +  end +end diff --git a/test/web/activity_pub/object_validators/like_validation_test.exs b/test/web/activity_pub/object_validators/like_validation_test.exs new file mode 100644 index 000000000..2c033b7e2 --- /dev/null +++ b/test/web/activity_pub/object_validators/like_validation_test.exs @@ -0,0 +1,113 @@ +# 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.ObjectValidators.LikeValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator +  alias Pleroma.Web.ActivityPub.Utils +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "likes" do +    setup do +      user = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) + +      valid_like = %{ +        "to" => [user.ap_id], +        "cc" => [], +        "type" => "Like", +        "id" => Utils.generate_activity_id(), +        "object" => post_activity.data["object"], +        "actor" => user.ap_id, +        "context" => "a context" +      } + +      %{valid_like: valid_like, user: user, post_activity: post_activity} +    end + +    test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do +      {:ok, object, _meta} = ObjectValidator.validate(valid_like, []) + +      assert "id" in Map.keys(object) +    end + +    test "is valid for a valid object", %{valid_like: valid_like} do +      assert LikeValidator.cast_and_validate(valid_like).valid? +    end + +    test "sets the 'to' field to the object actor if no recipients are given", %{ +      valid_like: valid_like, +      user: user +    } do +      without_recipients = +        valid_like +        |> Map.delete("to") + +      {:ok, object, _meta} = ObjectValidator.validate(without_recipients, []) + +      assert object["to"] == [user.ap_id] +    end + +    test "sets the context field to the context of the object if no context is given", %{ +      valid_like: valid_like, +      post_activity: post_activity +    } do +      without_context = +        valid_like +        |> Map.delete("context") + +      {:ok, object, _meta} = ObjectValidator.validate(without_context, []) + +      assert object["context"] == post_activity.data["context"] +    end + +    test "it errors when the actor is missing or not known", %{valid_like: valid_like} do +      without_actor = Map.delete(valid_like, "actor") + +      refute LikeValidator.cast_and_validate(without_actor).valid? + +      with_invalid_actor = Map.put(valid_like, "actor", "invalidactor") + +      refute LikeValidator.cast_and_validate(with_invalid_actor).valid? +    end + +    test "it errors when the object is missing or not known", %{valid_like: valid_like} do +      without_object = Map.delete(valid_like, "object") + +      refute LikeValidator.cast_and_validate(without_object).valid? + +      with_invalid_object = Map.put(valid_like, "object", "invalidobject") + +      refute LikeValidator.cast_and_validate(with_invalid_object).valid? +    end + +    test "it errors when the actor has already like the object", %{ +      valid_like: valid_like, +      user: user, +      post_activity: post_activity +    } do +      _like = CommonAPI.favorite(user, post_activity.id) + +      refute LikeValidator.cast_and_validate(valid_like).valid? +    end + +    test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do +      wrapped_like = +        valid_like +        |> Map.put("actor", %{"id" => valid_like["actor"]}) +        |> Map.put("object", %{"id" => valid_like["object"]}) + +      validated = LikeValidator.cast_and_validate(wrapped_like) + +      assert validated.valid? + +      assert {:actor, valid_like["actor"]} in validated.changes +      assert {:object, valid_like["object"]} in validated.changes +    end +  end +end diff --git a/test/web/activity_pub/object_validators/undo_validation_test.exs b/test/web/activity_pub/object_validators/undo_validation_test.exs new file mode 100644 index 000000000..75bbcc4b6 --- /dev/null +++ b/test/web/activity_pub/object_validators/undo_validation_test.exs @@ -0,0 +1,53 @@ +# 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.ObjectValidators.UndoHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "Undos" do +    setup do +      user = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) +      {:ok, like} = CommonAPI.favorite(user, post_activity.id) +      {:ok, valid_like_undo, []} = Builder.undo(user, like) + +      %{user: user, like: like, valid_like_undo: valid_like_undo} +    end + +    test "it validates a basic like undo", %{valid_like_undo: valid_like_undo} do +      assert {:ok, _, _} = ObjectValidator.validate(valid_like_undo, []) +    end + +    test "it does not validate if the actor of the undo is not the actor of the object", %{ +      valid_like_undo: valid_like_undo +    } do +      other_user = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo") + +      bad_actor = +        valid_like_undo +        |> Map.put("actor", other_user.ap_id) + +      {:error, cng} = ObjectValidator.validate(bad_actor, []) + +      assert {:actor, {"not the same as object actor", []}} in cng.errors +    end + +    test "it does not validate if the object is missing", %{valid_like_undo: valid_like_undo} do +      missing_object = +        valid_like_undo +        |> Map.put("object", "https://gensokyo.2hu/objects/1") + +      {:error, cng} = ObjectValidator.validate(missing_object, []) + +      assert {:object, {"can't find object", []}} in cng.errors +      assert length(cng.errors) == 1 +    end +  end +end diff --git a/test/web/activity_pub/object_validators/update_validation_test.exs b/test/web/activity_pub/object_validators/update_validation_test.exs new file mode 100644 index 000000000..5e80cf731 --- /dev/null +++ b/test/web/activity_pub/object_validators/update_validation_test.exs @@ -0,0 +1,44 @@ +# 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.ObjectValidators.UpdateHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator + +  import Pleroma.Factory + +  describe "updates" do +    setup do +      user = insert(:user) + +      object = %{ +        "id" => user.ap_id, +        "name" => "A new name", +        "summary" => "A new bio" +      } + +      {:ok, valid_update, []} = Builder.update(user, object) + +      %{user: user, valid_update: valid_update} +    end + +    test "validates a basic object", %{valid_update: valid_update} do +      assert {:ok, _update, []} = ObjectValidator.validate(valid_update, []) +    end + +    test "returns an error if the object can't be updated by the actor", %{ +      valid_update: valid_update +    } do +      other_user = insert(:user) + +      update = +        valid_update +        |> Map.put("actor", other_user.ap_id) + +      assert {:error, _cng} = ObjectValidator.validate(update, []) +    end +  end +end diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs index c2bc38d52..b9388b966 100644 --- a/test/web/activity_pub/publisher_test.exs +++ b/test/web/activity_pub/publisher_test.exs @@ -123,6 +123,39 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do    end    describe "publish_one/1" do +    test "publish to url with with different ports" do +      inbox80 = "http://42.site/users/nick1/inbox" +      inbox42 = "http://42.site:42/users/nick1/inbox" + +      mock(fn +        %{method: :post, url: "http://42.site:42/users/nick1/inbox"} -> +          {:ok, %Tesla.Env{status: 200, body: "port 42"}} + +        %{method: :post, url: "http://42.site/users/nick1/inbox"} -> +          {:ok, %Tesla.Env{status: 200, body: "port 80"}} +      end) + +      actor = insert(:user) + +      assert {:ok, %{body: "port 42"}} = +               Publisher.publish_one(%{ +                 inbox: inbox42, +                 json: "{}", +                 actor: actor, +                 id: 1, +                 unreachable_since: true +               }) + +      assert {:ok, %{body: "port 80"}} = +               Publisher.publish_one(%{ +                 inbox: inbox80, +                 json: "{}", +                 actor: actor, +                 id: 1, +                 unreachable_since: true +               }) +    end +      test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",                     Instances,                     [:passthrough], @@ -131,7 +164,6 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do        inbox = "http://200.site/users/nick1/inbox"        assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1}) -        assert called(Instances.set_reachable(inbox))      end diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs index b3b573c9b..9d657ac4f 100644 --- a/test/web/activity_pub/relay_test.exs +++ b/test/web/activity_pub/relay_test.exs @@ -7,8 +7,8 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do    alias Pleroma.Activity    alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.ActivityPub.Relay +  alias Pleroma.Web.CommonAPI    import ExUnit.CaptureLog    import Pleroma.Factory @@ -53,8 +53,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do      test "returns activity" do        user = insert(:user)        service_actor = Relay.get_actor() -      ActivityPub.follow(service_actor, user) -      Pleroma.User.follow(service_actor, user) +      CommonAPI.follow(service_actor, user)        assert "#{user.ap_id}/followers" in User.following(service_actor)        assert {:ok, %Activity{} = activity} = Relay.unfollow(user.ap_id)        assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay" @@ -74,6 +73,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do        assert Relay.publish(activity) == {:error, "Not implemented"}      end +    @tag capture_log: true      test "returns error when activity not public" do        activity = insert(:direct_note_activity)        assert Relay.publish(activity) == {:error, false} diff --git a/test/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs index 06c39eed6..17e764ca1 100644 --- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -160,7 +160,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do          |> Poison.decode!()          |> Map.put("object", user.ap_id) -      with_mock Pleroma.User, [:passthrough], follow: fn _, _ -> {:error, :testing} end do +      with_mock Pleroma.User, [:passthrough], follow: fn _, _, _ -> {:error, :testing} end do          {:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)          %Activity{} = activity = Activity.get_by_ap_id(id) diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 6a53fd3f0..248b410c6 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -11,7 +11,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do    alias Pleroma.Object.Fetcher    alias Pleroma.Tests.ObanHelpers    alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.ActivityPub.Transmogrifier    alias Pleroma.Web.AdminAPI.AccountView    alias Pleroma.Web.CommonAPI @@ -452,7 +451,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        {:ok, follower} = User.follow(follower, followed)        assert User.following?(follower, followed) == true -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        accept_data =          File.read!("test/fixtures/mastodon-accept-activity.json") @@ -482,7 +481,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        follower = insert(:user)        followed = insert(:user, locked: true) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        accept_data =          File.read!("test/fixtures/mastodon-accept-activity.json") @@ -504,7 +503,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        follower = insert(:user)        followed = insert(:user, locked: true) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        accept_data =          File.read!("test/fixtures/mastodon-accept-activity.json") @@ -569,7 +568,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        followed = insert(:user, locked: true)        {:ok, follower} = User.follow(follower, followed) -      {:ok, _follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, followed)        assert User.following?(follower, followed) == true @@ -595,7 +594,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        followed = insert(:user, locked: true)        {:ok, follower} = User.follow(follower, followed) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        assert User.following?(follower, followed) == true @@ -659,22 +658,44 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do            "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"          ) -      attachment = %{ -        "type" => "Link", -        "mediaType" => "video/mp4", -        "url" => [ -          %{ -            "href" => -              "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", -            "mediaType" => "video/mp4" -          } -        ] -      } -        assert object.data["url"] ==                 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" -      assert object.data["attachment"] == [attachment] +      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" +                   } +                 ] +               } +             ] + +      {: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" +                   } +                 ] +               } +             ] + +      assert object.data["url"] == +               "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"      end      test "it accepts Flag activities" do @@ -753,6 +774,29 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert [user.follower_address] == activity.data["to"]      end +    test "it correctly processes messages with weirdness in address fields" do +      user = insert(:user) + +      message = %{ +        "@context" => "https://www.w3.org/ns/activitystreams", +        "to" => [nil, user.follower_address], +        "cc" => ["https://www.w3.org/ns/activitystreams#Public", ["¿"]], +        "type" => "Create", +        "object" => %{ +          "content" => "…", +          "type" => "Note", +          "attributedTo" => user.ap_id, +          "inReplyTo" => nil +        }, +        "actor" => user.ap_id +      } + +      assert {:ok, activity} = Transmogrifier.handle_incoming(message) + +      assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"] +      assert [user.follower_address] == activity.data["to"] +    end +      test "it accepts Move activities" do        old_user = insert(:user)        new_user = insert(:user) diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index 2f9ecb5a3..361dc5a41 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do    alias Pleroma.Object    alias Pleroma.Repo    alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.ActivityPub.Utils    alias Pleroma.Web.AdminAPI.AccountView    alias Pleroma.Web.CommonAPI @@ -197,8 +196,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        user = insert(:user, locked: true)        follower = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, user) -      {:ok, follow_activity_two} = ActivityPub.follow(follower, user) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user) +      {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)        data =          follow_activity_two.data @@ -221,8 +220,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        user = insert(:user, locked: true)        follower = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, user) -      {:ok, follow_activity_two} = ActivityPub.follow(follower, user) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user) +      {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)        data =          follow_activity_two.data diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index bec15a996..98c7c9d09 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -158,4 +158,23 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do        assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})      end    end + +  describe "acceptsChatMessages" do +    test "it returns this value if it is set" do +      true_user = insert(:user, accepts_chat_messages: true) +      false_user = insert(:user, accepts_chat_messages: false) +      nil_user = insert(:user, accepts_chat_messages: nil) + +      assert %{"capabilities" => %{"acceptsChatMessages" => true}} = +               UserView.render("user.json", user: true_user) + +      assert %{"capabilities" => %{"acceptsChatMessages" => false}} = +               UserView.render("user.json", user: false_user) + +      refute Map.has_key?( +               UserView.render("user.json", user: nil_user)["capabilities"], +               "acceptsChatMessages" +             ) +    end +  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 48fb108ec..da91cd552 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -41,6 +41,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      {:ok, %{admin: admin, token: token, conn: conn}}    end +  test "with valid `admin_token` query parameter, skips OAuth scopes check" do +    clear_config([:admin_token], "password123") + +    user = insert(:user) + +    conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123") + +    assert json_response(conn, 200) +  end +    describe "with [:auth, :enforce_oauth_admin_scope_usage]," do      setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true) @@ -1514,6 +1524,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end +  test "gets a remote users when [:instance, :limit_to_local_content] is set to :unauthenticated", +       %{conn: conn} do +    clear_config(Pleroma.Config.get([:instance, :limit_to_local_content]), :unauthenticated) +    user = insert(:user, %{local: false, nickname: "u@peer1.com"}) +    conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials") + +    assert json_response(conn, 200) +  end +    describe "GET /users/:nickname/credentials" do      test "gets the user credentials", %{conn: conn} do        user = insert(:user) diff --git a/test/web/admin_api/controllers/config_controller_test.exs b/test/web/admin_api/controllers/config_controller_test.exs index 064ef9bc7..61bc9fd39 100644 --- a/test/web/admin_api/controllers/config_controller_test.exs +++ b/test/web/admin_api/controllers/config_controller_test.exs @@ -152,6 +152,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do        assert emoji_val[:groups] == [a: 1, b: 2]        assert assets_val[:mascots] == [a: 1, b: 2]      end + +    test "with valid `admin_token` query parameter, skips OAuth scopes check" do +      clear_config([:admin_token], "password123") + +      build_conn() +      |> get("/api/pleroma/admin/config?admin_token=password123") +      |> json_response_and_validate_schema(200) +    end    end    test "POST /api/pleroma/admin/config error", %{conn: conn} do diff --git a/test/web/admin_api/controllers/report_controller_test.exs b/test/web/admin_api/controllers/report_controller_test.exs index 940bce340..f30dc8956 100644 --- a/test/web/admin_api/controllers/report_controller_test.exs +++ b/test/web/admin_api/controllers/report_controller_test.exs @@ -297,7 +297,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do          |> get("/api/pleroma/admin/reports")        assert json_response(conn, :forbidden) == -               %{"error" => "User is not an admin or OAuth admin scope is not granted."} +               %{"error" => "User is not an admin."}      end      test "returns 403 when requested by anonymous" do diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index fc3bb845d..7e11fede3 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -491,6 +491,7 @@ defmodule Pleroma.Web.CommonAPITest do        object = Object.normalize(activity)        assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')" +      assert object.data["source"] == post      end      test "it filters out obviously bad tags when accepting a post as Markdown" do @@ -507,6 +508,7 @@ defmodule Pleroma.Web.CommonAPITest do        object = Object.normalize(activity)        assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')" +      assert object.data["source"] == post      end      test "it does not allow replies to direct messages that are not direct messages themselves" do @@ -932,6 +934,15 @@ defmodule Pleroma.Web.CommonAPITest do      end    end +  describe "follow/2" do +    test "directly follows a non-locked local user" do +      [follower, followed] = insert_pair(:user) +      {:ok, follower, followed, _} = CommonAPI.follow(follower, followed) + +      assert User.following?(follower, followed) +    end +  end +    describe "unfollow/2" do      test "also unsubscribes a user" do        [follower, followed] = insert_pair(:user) @@ -996,9 +1007,9 @@ defmodule Pleroma.Web.CommonAPITest do        follower = insert(:user)        follower_two = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, user) -      {:ok, follow_activity_two} = ActivityPub.follow(follower, user) -      {:ok, follow_activity_three} = ActivityPub.follow(follower_two, user) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user) +      {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user) +      {:ok, _, _, follow_activity_three} = CommonAPI.follow(follower_two, user)        assert follow_activity.data["state"] == "pending"        assert follow_activity_two.data["state"] == "pending" @@ -1016,9 +1027,9 @@ defmodule Pleroma.Web.CommonAPITest do        follower = insert(:user)        follower_two = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, user) -      {:ok, follow_activity_two} = ActivityPub.follow(follower, user) -      {:ok, follow_activity_three} = ActivityPub.follow(follower_two, user) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user) +      {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user) +      {:ok, _, _, follow_activity_three} = CommonAPI.follow(follower_two, user)        assert follow_activity.data["state"] == "pending"        assert follow_activity_two.data["state"] == "pending" diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs index f67d294ba..b888e4c71 100644 --- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs +++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs @@ -108,6 +108,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert user_data["locked"] == true      end +    test "updates the user's chat acceptance status", %{conn: conn} do +      conn = patch(conn, "/api/v1/accounts/update_credentials", %{accepts_chat_messages: "false"}) + +      assert user_data = json_response_and_validate_schema(conn, 200) +      assert user_data["pleroma"]["accepts_chat_messages"] == false +    end +      test "updates the user's allow_following_move", %{user: user, conn: conn} do        assert user.allow_following_move == true @@ -216,10 +223,21 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do          filename: "an_image.jpg"        } -      conn = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar}) +      assert user.avatar == %{} -      assert user_response = json_response_and_validate_schema(conn, 200) +      res = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar}) + +      assert user_response = json_response_and_validate_schema(res, 200)        assert user_response["avatar"] != User.avatar_url(user) + +      user = User.get_by_id(user.id) +      refute user.avatar == %{} + +      # Also resets it +      _res = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => ""}) + +      user = User.get_by_id(user.id) +      assert user.avatar == nil      end      test "updates the user's banner", %{user: user, conn: conn} do @@ -229,26 +247,39 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do          filename: "an_image.jpg"        } -      conn = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header}) +      res = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header}) -      assert user_response = json_response_and_validate_schema(conn, 200) +      assert user_response = json_response_and_validate_schema(res, 200)        assert user_response["header"] != User.banner_url(user) + +      # Also resets it +      _res = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => ""}) + +      user = User.get_by_id(user.id) +      assert user.banner == nil      end -    test "updates the user's background", %{conn: conn} do +    test "updates the user's background", %{conn: conn, user: user} do        new_header = %Plug.Upload{          content_type: "image/jpg",          path: Path.absname("test/fixtures/image.jpg"),          filename: "an_image.jpg"        } -      conn = +      res =          patch(conn, "/api/v1/accounts/update_credentials", %{            "pleroma_background_image" => new_header          }) -      assert user_response = json_response_and_validate_schema(conn, 200) +      assert user_response = json_response_and_validate_schema(res, 200)        assert user_response["pleroma"]["background_image"] +      # +      # Also resets it +      _res = +        patch(conn, "/api/v1/accounts/update_credentials", %{"pleroma_background_image" => ""}) + +      user = User.get_by_id(user.id) +      assert user.background == nil      end      test "requires 'write:accounts' permission" do @@ -320,6 +351,30 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do               ]      end +    test "emojis in fields labels", %{conn: conn} do +      fields = [ +        %{"name" => ":firefox:", "value" => "is best 2hu"}, +        %{"name" => "they wins", "value" => ":blank:"} +      ] + +      account_data = +        conn +        |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) +        |> json_response_and_validate_schema(200) + +      assert account_data["fields"] == [ +               %{"name" => ":firefox:", "value" => "is best 2hu"}, +               %{"name" => "they wins", "value" => ":blank:"} +             ] + +      assert account_data["source"]["fields"] == [ +               %{"name" => ":firefox:", "value" => "is best 2hu"}, +               %{"name" => "they wins", "value" => ":blank:"} +             ] + +      assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = account_data["emojis"] +    end +      test "update fields via x-www-form-urlencoded", %{conn: conn} do        fields =          [ diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index 260ad2306..c304487ea 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -583,6 +583,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do                 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3_id}")                 |> json_response_and_validate_schema(200) +      assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] = +               conn +               |> get( +                 "/api/v1/accounts/#{user.id}/followers?id=#{user.id}&limit=20&max_id=#{ +                   follower3_id +                 }" +               ) +               |> json_response_and_validate_schema(200) +        res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3_id}")        assert [%{"id" => ^follower2_id}] = json_response_and_validate_schema(res_conn, 200) @@ -655,6 +664,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        assert id1 == following1.id        res_conn = +        get( +          conn, +          "/api/v1/accounts/#{user.id}/following?id=#{user.id}&limit=20&max_id=#{following3.id}" +        ) + +      assert [%{"id" => id2}, %{"id" => id1}] = json_response_and_validate_schema(res_conn, 200) +      assert id2 == following2.id +      assert id1 == following1.id + +      res_conn =          get(conn, "/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")        assert [%{"id" => id2}] = json_response_and_validate_schema(res_conn, 200) @@ -708,7 +727,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        followed = insert(:user)        other_user = insert(:user) -      ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow?reblogs=false") +      ret_conn = +        conn +        |> put_req_header("content-type", "application/json") +        |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})        assert %{"showing_reblogs" => false} = json_response_and_validate_schema(ret_conn, 200) @@ -722,7 +744,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        assert %{"showing_reblogs" => true} =                 conn -               |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true") +               |> put_req_header("content-type", "application/json") +               |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: true})                 |> json_response_and_validate_schema(200)        assert [%{"id" => ^reblog_id}] = @@ -731,6 +754,35 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do                 |> json_response(200)      end +    test "following with reblogs" do +      %{conn: conn} = oauth_access(["follow", "read:statuses"]) +      followed = insert(:user) +      other_user = insert(:user) + +      ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow") + +      assert %{"showing_reblogs" => true} = json_response_and_validate_schema(ret_conn, 200) + +      {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) +      {:ok, %{id: reblog_id}} = CommonAPI.repeat(activity.id, followed) + +      assert [%{"id" => ^reblog_id}] = +               conn +               |> get("/api/v1/timelines/home") +               |> json_response(200) + +      assert %{"showing_reblogs" => false} = +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false}) +               |> json_response_and_validate_schema(200) + +      assert [] == +               conn +               |> get("/api/v1/timelines/home") +               |> json_response(200) +    end +      test "following / unfollowing errors", %{user: user, conn: conn} do        # self follow        conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow") @@ -904,7 +956,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        %{          "access_token" => token,          "created_at" => _created_at, -        "scope" => _scope, +        "scope" => ^scope,          "token_type" => "Bearer"        } = json_response_and_validate_schema(conn, 200) @@ -1066,7 +1118,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        assert %{                 "access_token" => access_token,                 "created_at" => _, -               "scope" => ["read", "write", "follow", "push"], +               "scope" => "read write follow push",                 "token_type" => "Bearer"               } = response @@ -1184,7 +1236,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        assert %{                 "access_token" => access_token,                 "created_at" => _, -               "scope" => ["read"], +               "scope" => "read",                 "token_type" => "Bearer"               } =                 conn diff --git a/test/web/mastodon_api/controllers/follow_request_controller_test.exs b/test/web/mastodon_api/controllers/follow_request_controller_test.exs index 44e12d15a..6749e0e83 100644 --- a/test/web/mastodon_api/controllers/follow_request_controller_test.exs +++ b/test/web/mastodon_api/controllers/follow_request_controller_test.exs @@ -6,7 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do    use Pleroma.Web.ConnCase    alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.CommonAPI    import Pleroma.Factory @@ -20,7 +20,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do      test "/api/v1/follow_requests works", %{user: user, conn: conn} do        other_user = insert(:user) -      {:ok, _activity} = ActivityPub.follow(other_user, user) +      {:ok, _, _, _activity} = CommonAPI.follow(other_user, user)        {:ok, other_user} = User.follow(other_user, user, :follow_pending)        assert User.following?(other_user, user) == false @@ -34,7 +34,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do      test "/api/v1/follow_requests/:id/authorize works", %{user: user, conn: conn} do        other_user = insert(:user) -      {:ok, _activity} = ActivityPub.follow(other_user, user) +      {:ok, _, _, _activity} = CommonAPI.follow(other_user, user)        {:ok, other_user} = User.follow(other_user, user, :follow_pending)        user = User.get_cached_by_id(user.id) @@ -56,7 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do      test "/api/v1/follow_requests/:id/reject works", %{user: user, conn: conn} do        other_user = insert(:user) -      {:ok, _activity} = ActivityPub.follow(other_user, user) +      {:ok, _, _, _activity} = CommonAPI.follow(other_user, user)        user = User.get_cached_by_id(user.id) diff --git a/test/web/mastodon_api/controllers/instance_controller_test.exs b/test/web/mastodon_api/controllers/instance_controller_test.exs index 8bdfdddd1..cc880d82c 100644 --- a/test/web/mastodon_api/controllers/instance_controller_test.exs +++ b/test/web/mastodon_api/controllers/instance_controller_test.exs @@ -32,11 +32,15 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do               "avatar_upload_limit" => _,               "background_upload_limit" => _,               "banner_upload_limit" => _, -             "background_image" => _ +             "background_image" => _, +             "chat_limit" => _, +             "description_limit" => _             } = result +    assert result["pleroma"]["metadata"]["account_activation_required"] != nil      assert result["pleroma"]["metadata"]["features"]      assert result["pleroma"]["metadata"]["federation"] +    assert result["pleroma"]["metadata"]["fields_limits"]      assert result["pleroma"]["vapid_public_key"]      assert email == from_config_email diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs index 826f37fbc..24d1959f8 100644 --- a/test/web/mastodon_api/controllers/search_controller_test.exs +++ b/test/web/mastodon_api/controllers/search_controller_test.exs @@ -79,6 +79,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do        assert status["id"] == to_string(activity.id)      end +    @tag capture_log: true      test "constructs hashtags from search query", %{conn: conn} do        results =          conn @@ -318,11 +319,13 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do      test "search fetches remote accounts", %{conn: conn} do        user = insert(:user) +      query = URI.encode_query(%{q: "       mike@osada.macgirvin.com          ", resolve: true}) +        results =          conn          |> assign(:user, user)          |> assign(:token, insert(:oauth_token, user: user, scopes: ["read"])) -        |> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=true") +        |> get("/api/v1/search?#{query}")          |> json_response_and_validate_schema(200)        [account] = results["accounts"] diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index a98e939e8..d34f300da 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -22,6 +22,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do    setup do: clear_config([:instance, :federating])    setup do: clear_config([:instance, :allow_relay])    setup do: clear_config([:rich_media, :enabled]) +  setup do: clear_config([:mrf, :policies]) +  setup do: clear_config([:mrf_keyword, :reject])    describe "posting statuses" do      setup do: oauth_access(["write:statuses"]) @@ -157,6 +159,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do                 |> json_response_and_validate_schema(422)      end +    test "Get MRF reason when posting a status is rejected by one", %{conn: conn} do +      Pleroma.Config.put([:mrf_keyword, :reject], ["GNO"]) +      Pleroma.Config.put([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) + +      assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} = +               conn +               |> put_req_header("content-type", "application/json") +               |> post("api/v1/statuses", %{"status" => "GNO/Linux"}) +               |> json_response_and_validate_schema(422) +    end +      test "posting an undefined status with an attachment", %{user: user, conn: conn} do        file = %Plug.Upload{          content_type: "image/jpg", @@ -760,13 +773,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      test "when you created it" do        %{user: author, conn: conn} = oauth_access(["write:statuses"])        activity = insert(:note_activity, user: author) +      object = Object.normalize(activity) -      conn = +      content = object.data["content"] +      source = object.data["source"] + +      result =          conn          |> assign(:user, author)          |> delete("/api/v1/statuses/#{activity.id}") +        |> json_response_and_validate_schema(200) -      assert %{} = json_response_and_validate_schema(conn, 200) +      assert match?(%{"content" => ^content, "text" => ^source}, result)        refute Activity.get_by_id(activity.id)      end @@ -789,7 +807,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        conn = delete(conn, "/api/v1/statuses/#{activity.id}") -      assert %{"error" => _} = json_response_and_validate_schema(conn, 403) +      assert %{"error" => "Record not found"} == json_response_and_validate_schema(conn, 404)        assert Activity.get_by_id(activity.id) == activity      end diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs index f069390c1..50e0d783d 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -418,4 +418,78 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do        assert [status_none] == json_response_and_validate_schema(all_test, :ok)      end    end + +  describe "hashtag timeline handling of :restrict_unauthenticated setting" do +    setup do +      user = insert(:user) +      {:ok, activity1} = CommonAPI.post(user, %{status: "test #tag1"}) +      {:ok, _activity2} = CommonAPI.post(user, %{status: "test #tag1"}) + +      activity1 +      |> Ecto.Changeset.change(%{local: false}) +      |> Pleroma.Repo.update() + +      base_uri = "/api/v1/timelines/tag/tag1" +      error_response = %{"error" => "authorization required for timeline view"} + +      %{base_uri: base_uri, error_response: error_response} +    end + +    defp ensure_authenticated_access(base_uri) do +      %{conn: auth_conn} = oauth_access(["read:statuses"]) + +      res_conn = get(auth_conn, "#{base_uri}?local=true") +      assert length(json_response(res_conn, 200)) == 1 + +      res_conn = get(auth_conn, "#{base_uri}?local=false") +      assert length(json_response(res_conn, 200)) == 2 +    end + +    test "with `%{local: true, federated: true}`, returns 403 for unauthenticated users", %{ +      conn: conn, +      base_uri: base_uri, +      error_response: error_response +    } do +      clear_config([:restrict_unauthenticated, :timelines, :local], true) +      clear_config([:restrict_unauthenticated, :timelines, :federated], true) + +      for local <- [true, false] do +        res_conn = get(conn, "#{base_uri}?local=#{local}") + +        assert json_response(res_conn, :unauthorized) == error_response +      end + +      ensure_authenticated_access(base_uri) +    end + +    test "with `%{local: false, federated: true}`, forbids unauthenticated access to federated timeline", +         %{conn: conn, base_uri: base_uri, error_response: error_response} do +      clear_config([:restrict_unauthenticated, :timelines, :local], false) +      clear_config([:restrict_unauthenticated, :timelines, :federated], true) + +      res_conn = get(conn, "#{base_uri}?local=true") +      assert length(json_response(res_conn, 200)) == 1 + +      res_conn = get(conn, "#{base_uri}?local=false") +      assert json_response(res_conn, :unauthorized) == error_response + +      ensure_authenticated_access(base_uri) +    end + +    test "with `%{local: true, federated: false}`, forbids unauthenticated access to public timeline" <> +           "(but not to local public activities which are delivered as part of federated timeline)", +         %{conn: conn, base_uri: base_uri, error_response: error_response} do +      clear_config([:restrict_unauthenticated, :timelines, :local], true) +      clear_config([:restrict_unauthenticated, :timelines, :federated], false) + +      res_conn = get(conn, "#{base_uri}?local=true") +      assert json_response(res_conn, :unauthorized) == error_response + +      # Note: local activities get delivered as part of federated timeline +      res_conn = get(conn, "#{base_uri}?local=false") +      assert length(json_response(res_conn, 200)) == 2 + +      ensure_authenticated_access(base_uri) +    end +  end  end diff --git a/test/web/mastodon_api/mastodon_api_test.exs b/test/web/mastodon_api/mastodon_api_test.exs index a7f9c5205..c08be37d4 100644 --- a/test/web/mastodon_api/mastodon_api_test.exs +++ b/test/web/mastodon_api/mastodon_api_test.exs @@ -18,7 +18,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do        follower = insert(:user)        user = insert(:user, local: true, deactivated: true)        {:error, error} = MastodonAPI.follow(follower, user) -      assert error == "Could not follow user: #{user.nickname} is deactivated." +      assert error == :rejected      end      test "following for user" do diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 80b1f734c..a83bf90a3 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 @@ -18,6 +19,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do      :ok    end +  setup do: clear_config([:instances_favicons, :enabled]) +    test "Represent a user account" do      background_image = %{        "url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}] @@ -75,6 +78,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        pleroma: %{          ap_id: user.ap_id,          background_image: "https://example.com/images/asuka_hospital.png", +        favicon: +          "https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png",          confirmation_pending: false,          tags: [],          is_admin: false, @@ -85,22 +90,37 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do          hide_followers_count: false,          hide_follows_count: false,          relationship: %{}, -        skip_thread_containment: false +        skip_thread_containment: false, +        accepts_chat_messages: nil        }      }      assert expected == AccountView.render("show.json", %{user: user})    end +  test "Favicon is nil when :instances_favicons is disabled" do +    user = insert(:user) + +    Config.put([:instances_favicons, :enabled], true) + +    assert %{ +             pleroma: %{ +               favicon: +                 "https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png" +             } +           } = AccountView.render("show.json", %{user: user}) + +    Config.put([:instances_favicons, :enabled], false) + +    assert %{pleroma: %{favicon: nil}} = AccountView.render("show.json", %{user: user}) +  end +    test "Represent the user account for the account owner" do      user = insert(:user)      notification_settings = %{ -      followers: true, -      follows: true, -      non_followers: true, -      non_follows: true, -      privacy_option: false +      block_from_strangers: false, +      hide_notification_contents: false      }      privacy = user.default_scope @@ -152,6 +172,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        pleroma: %{          ap_id: user.ap_id,          background_image: nil, +        favicon: +          "https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png",          confirmation_pending: false,          tags: [],          is_admin: false, @@ -162,7 +184,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do          hide_followers_count: false,          hide_follows_count: false,          relationship: %{}, -        skip_thread_containment: false +        skip_thread_containment: false, +        accepts_chat_messages: nil        }      } @@ -372,6 +395,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        user = insert(:user, hide_followers: true, hide_follows: true)        other_user = insert(:user)        {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user) + +      assert User.following?(user, other_user) +      assert Pleroma.FollowingRelationship.follower_count(other_user) == 1        {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)        assert %{ diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs index f90a0c273..fa26b3129 100644 --- a/test/web/mastodon_api/views/status_view_test.exs +++ b/test/web/mastodon_api/views/status_view_test.exs @@ -183,6 +183,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do        card: nil,        reblog: nil,        content: HTML.filter_tags(object_data["content"]), +      text: nil,        created_at: created_at,        reblogs_count: 0,        replies_count: 0, diff --git a/test/web/media_proxy/media_proxy_controller_test.exs b/test/web/media_proxy/media_proxy_controller_test.exs index d61cef83b..d4db44c63 100644 --- a/test/web/media_proxy/media_proxy_controller_test.exs +++ b/test/web/media_proxy/media_proxy_controller_test.exs @@ -4,82 +4,118 @@  defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do    use Pleroma.Web.ConnCase +    import Mock -  alias Pleroma.Config -  setup do: clear_config(:media_proxy) -  setup do: clear_config([Pleroma.Web.Endpoint, :secret_key_base]) +  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 -    Config.put([:media_proxy, :enabled], false) +    clear_config([:media_proxy, :enabled], false) -    assert %Plug.Conn{ +    assert %Conn{               status: 404,               resp_body: "Not Found"             } = get(conn, "/proxy/hhgfh/eeeee") -    assert %Plug.Conn{ +    assert %Conn{               status: 404,               resp_body: "Not Found"             } = get(conn, "/proxy/hhgfh/eeee/fff")    end -  test "it returns 403 when signature invalidated", %{conn: conn} do -    Config.put([:media_proxy, :enabled], true) -    Config.put([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") -    path = URI.parse(Pleroma.Web.MediaProxy.encode_url("https://google.fn")).path -    Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000") - -    assert %Plug.Conn{ -             status: 403, -             resp_body: "Forbidden" -           } = get(conn, path) - -    assert %Plug.Conn{ -             status: 403, -             resp_body: "Forbidden" -           } = get(conn, "/proxy/hhgfh/eeee") - -    assert %Plug.Conn{ -             status: 403, -             resp_body: "Forbidden" -           } = get(conn, "/proxy/hhgfh/eeee/fff") -  end +  describe "" 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 "redirects on valid url when filename invalidated", %{conn: conn} do -    Config.put([:media_proxy, :enabled], true) -    Config.put([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") -    url = Pleroma.Web.MediaProxy.encode_url("https://google.fn/test.png") -    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 "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/hhgfh/eeee") + +      assert %Conn{ +               status: 403, +               resp_body: "Forbidden" +             } = get(conn, "/proxy/hhgfh/eeee/fff") +    end -  test "it performs ReverseProxy.call when signature valid", %{conn: conn} do -    Config.put([:media_proxy, :enabled], true) -    Config.put([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") -    url = Pleroma.Web.MediaProxy.encode_url("https://google.fn/test.png") +    test "redirects on 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 -    with_mock Pleroma.ReverseProxy, -      call: fn _conn, _url, _opts -> %Plug.Conn{status: :success} end do -      assert %Plug.Conn{status: :success} = get(conn, url) +    test "it performs ReverseProxy.call with valid signature", %{conn: conn, url: url} do +      with_mock Pleroma.ReverseProxy, +        call: fn _conn, _url, _opts -> %Conn{status: :success} end do +        assert %Conn{status: :success} = get(conn, url) +      end +    end + +    test "it returns 404 when url is in banned_urls cache", %{conn: conn, url: url} do +      MediaProxy.put_in_banned_urls("https://google.fn/test.png") + +      with_mock Pleroma.ReverseProxy, +        call: fn _conn, _url, _opts -> %Conn{status: :success} end do +        assert %Conn{status: 404, resp_body: "Not Found"} = get(conn, url) +      end      end    end -  test "it returns 404 when url contains in banned_urls cache", %{conn: conn} do -    Config.put([:media_proxy, :enabled], true) -    Config.put([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") -    url = Pleroma.Web.MediaProxy.encode_url("https://google.fn/test.png") -    Pleroma.Web.MediaProxy.put_in_banned_urls("https://google.fn/test.png") +  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" -    with_mock Pleroma.ReverseProxy, -      call: fn _conn, _url, _opts -> %Plug.Conn{status: :success} end do -      assert %Plug.Conn{status: 404, resp_body: "Not Found"} = get(conn, url) +      assert MediaProxyController.filename_matches( +               true, +               request_path, +               "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg" +             ) == :ok      end    end  end diff --git a/test/web/media_proxy/media_proxy_test.exs b/test/web/media_proxy/media_proxy_test.exs index ac5d8fd32..06990464f 100644 --- a/test/web/media_proxy/media_proxy_test.exs +++ b/test/web/media_proxy/media_proxy_test.exs @@ -71,12 +71,9 @@ defmodule Pleroma.Web.MediaProxyTest do      end      test "validates signature" do -      secret_key_base = Config.get([Endpoint, :secret_key_base]) -      clear_config([Endpoint, :secret_key_base], secret_key_base) -        encoded = MediaProxy.url("https://pleroma.social") -      Config.put( +      clear_config(          [Endpoint, :secret_key_base],          "00000000000000000000000000000000000000000000000"        ) @@ -144,15 +141,17 @@ defmodule Pleroma.Web.MediaProxyTest do                 request_path,                 "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg"               ) == :ok +      assert MediaProxy.decode_url(sig, base64) == {:error, :invalid_signature}      end      test "uses the configured base_url" do -      clear_config([:media_proxy, :base_url], "https://cache.pleroma.social") +      base_url = "https://cache.pleroma.social" +      clear_config([:media_proxy, :base_url], base_url)        url = "https://pleroma.soykaf.com/static/logo.png"        encoded = MediaProxy.url(url) -      assert String.starts_with?(encoded, Config.get([:media_proxy, :base_url])) +      assert String.starts_with?(encoded, base_url)      end      # Some sites expect ASCII encoded characters in the URL to be preserved even if @@ -194,10 +193,25 @@ 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)      test "mediaproxy whitelist" do +      clear_config([:media_proxy, :whitelist], ["https://google.com", "https://feld.me"]) +      url = "https://feld.me/foo.png" + +      unencoded = MediaProxy.url(url) +      assert unencoded == url +    end + +    # TODO: delete after removing support bare domains for media proxy whitelist +    test "mediaproxy whitelist bare domains whitelist (deprecated)" do        clear_config([:media_proxy, :whitelist], ["google.com", "feld.me"])        url = "https://feld.me/foo.png" diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs index 103997c31..07909d48b 100644 --- a/test/web/pleroma_api/controllers/account_controller_test.exs +++ b/test/web/pleroma_api/controllers/account_controller_test.exs @@ -13,8 +13,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do    import Pleroma.Factory    import Swoosh.TestAssertions -  @image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" -    describe "POST /api/v1/pleroma/accounts/confirmation_resend" do      setup do        {:ok, user} = @@ -68,103 +66,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      end    end -  describe "PATCH /api/v1/pleroma/accounts/update_avatar" do -    setup do: oauth_access(["write:accounts"]) - -    test "user avatar can be set", %{user: user, conn: conn} do -      avatar_image = File.read!("test/fixtures/avatar_data_uri") - -      conn = -        conn -        |> put_req_header("content-type", "multipart/form-data") -        |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image}) - -      user = refresh_record(user) - -      assert %{ -               "name" => _, -               "type" => _, -               "url" => [ -                 %{ -                   "href" => _, -                   "mediaType" => _, -                   "type" => _ -                 } -               ] -             } = user.avatar - -      assert %{"url" => _} = json_response_and_validate_schema(conn, 200) -    end - -    test "user avatar can be reset", %{user: user, conn: conn} do -      conn = -        conn -        |> put_req_header("content-type", "multipart/form-data") -        |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""}) - -      user = User.get_cached_by_id(user.id) - -      assert user.avatar == nil - -      assert %{"url" => nil} = json_response_and_validate_schema(conn, 200) -    end -  end - -  describe "PATCH /api/v1/pleroma/accounts/update_banner" do -    setup do: oauth_access(["write:accounts"]) - -    test "can set profile banner", %{user: user, conn: conn} do -      conn = -        conn -        |> put_req_header("content-type", "multipart/form-data") -        |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image}) - -      user = refresh_record(user) -      assert user.banner["type"] == "Image" - -      assert %{"url" => _} = json_response_and_validate_schema(conn, 200) -    end - -    test "can reset profile banner", %{user: user, conn: conn} do -      conn = -        conn -        |> put_req_header("content-type", "multipart/form-data") -        |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""}) - -      user = refresh_record(user) -      assert user.banner == %{} - -      assert %{"url" => nil} = json_response_and_validate_schema(conn, 200) -    end -  end - -  describe "PATCH /api/v1/pleroma/accounts/update_background" do -    setup do: oauth_access(["write:accounts"]) - -    test "background image can be set", %{user: user, conn: conn} do -      conn = -        conn -        |> put_req_header("content-type", "multipart/form-data") -        |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image}) - -      user = refresh_record(user) -      assert user.background["type"] == "Image" -      # assert %{"url" => _} = json_response(conn, 200) -      assert %{"url" => _} = json_response_and_validate_schema(conn, 200) -    end - -    test "background image can be reset", %{user: user, conn: conn} do -      conn = -        conn -        |> put_req_header("content-type", "multipart/form-data") -        |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""}) - -      user = refresh_record(user) -      assert user.background == %{} -      assert %{"url" => nil} = json_response_and_validate_schema(conn, 200) -    end -  end -    describe "getting favorites timeline of specified user" do      setup do        [current_user, user] = insert_pair(:user, hide_favorites: false) diff --git a/test/web/preload/status_net_test.exs b/test/web/preload/status_net_test.exs deleted file mode 100644 index df7acdb11..000000000 --- a/test/web/preload/status_net_test.exs +++ /dev/null @@ -1,15 +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.Preload.Providers.StatusNetTest do -  use Pleroma.DataCase -  alias Pleroma.Web.Preload.Providers.StatusNet - -  setup do: {:ok, StatusNet.generate_terms(nil)} - -  test "it renders the info", %{"/api/statusnet/config.json" => info} do -    assert {:ok, res} = Jason.decode(info) -    assert res["site"] -  end -end diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index b48952b29..aeb5c1fbd 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -238,9 +238,11 @@ defmodule Pleroma.Web.Push.ImplTest do               }      end -    test "hides details for notifications when privacy option enabled" do +    test "hides contents of notifications when option enabled" do        user = insert(:user, nickname: "Bob") -      user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: true}) + +      user2 = +        insert(:user, nickname: "Rob", notification_settings: %{hide_notification_contents: true})        {:ok, activity} =          CommonAPI.post(user, %{ @@ -284,9 +286,11 @@ defmodule Pleroma.Web.Push.ImplTest do               }      end -    test "returns regular content for notifications with privacy option disabled" do +    test "returns regular content when hiding contents option disabled" do        user = insert(:user, nickname: "Bob") -      user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: false}) + +      user2 = +        insert(:user, nickname: "Rob", notification_settings: %{hide_notification_contents: false})        {:ok, activity} =          CommonAPI.post(user, %{ diff --git a/test/web/static_fe/static_fe_controller_test.exs b/test/web/static_fe/static_fe_controller_test.exs index a49ab002f..1598bf675 100644 --- a/test/web/static_fe/static_fe_controller_test.exs +++ b/test/web/static_fe/static_fe_controller_test.exs @@ -87,6 +87,20 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do        assert html =~ "testing a thing!"      end +    test "redirects to json if requested", %{conn: conn, user: user} do +      {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"}) + +      conn = +        conn +        |> put_req_header( +          "accept", +          "Accept: application/activity+json, application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", text/html" +        ) +        |> get("/notice/#{activity.id}") + +      assert redirected_to(conn, 302) =~ activity.data["object"] +    end +      test "filters HTML tags", %{conn: conn} do        user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{status: "<script>alert('xss')</script>"}) diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index dfe341b34..d56d74464 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -128,6 +128,23 @@ defmodule Pleroma.Web.StreamerTest do        assert Streamer.filtered_by_user?(user, announce)      end +    test "it does stream notifications announces of the user's own posts in the 'user' stream", %{ +      user: user +    } do +      Streamer.get_topic_and_add_socket("user", user) + +      other_user = insert(:user) +      {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) +      {:ok, announce} = CommonAPI.repeat(activity.id, other_user) + +      notification = +        Pleroma.Notification +        |> Repo.get_by(%{user_id: user.id, activity_id: announce.id}) +        |> Repo.preload(:activity) + +      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) diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs index ad919d341..109c1e637 100644 --- a/test/web/twitter_api/util_controller_test.exs +++ b/test/web/twitter_api/util_controller_test.exs @@ -191,7 +191,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do      test "it updates notification settings", %{user: user, conn: conn} do        conn        |> put("/api/pleroma/notification_settings", %{ -        "followers" => false, +        "block_from_strangers" => true,          "bar" => 1        })        |> json_response(:ok) @@ -199,130 +199,25 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do        user = refresh_record(user)        assert %Pleroma.User.NotificationSetting{ -               followers: false, -               follows: true, -               non_follows: true, -               non_followers: true, -               privacy_option: false +               block_from_strangers: true, +               hide_notification_contents: false               } == user.notification_settings      end -    test "it updates notification privacy option", %{user: user, conn: conn} do +    test "it updates notification settings to enable hiding contents", %{user: user, conn: conn} do        conn -      |> put("/api/pleroma/notification_settings", %{"privacy_option" => "1"}) +      |> put("/api/pleroma/notification_settings", %{"hide_notification_contents" => "1"})        |> json_response(:ok)        user = refresh_record(user)        assert %Pleroma.User.NotificationSetting{ -               followers: true, -               follows: true, -               non_follows: true, -               non_followers: true, -               privacy_option: true +               block_from_strangers: false, +               hide_notification_contents: true               } == user.notification_settings      end    end -  describe "GET /api/statusnet/config" do -    test "it returns config in xml format", %{conn: conn} do -      instance = Config.get(:instance) - -      response = -        conn -        |> put_req_header("accept", "application/xml") -        |> get("/api/statusnet/config") -        |> response(:ok) - -      assert response == -               "<config>\n<site>\n<name>#{Keyword.get(instance, :name)}</name>\n<site>#{ -                 Pleroma.Web.base_url() -               }</site>\n<textlimit>#{Keyword.get(instance, :limit)}</textlimit>\n<closed>#{ -                 !Keyword.get(instance, :registrations_open) -               }</closed>\n</site>\n</config>\n" -    end - -    test "it returns config in json format", %{conn: conn} do -      instance = Config.get(:instance) -      Config.put([:instance, :managed_config], true) -      Config.put([:instance, :registrations_open], false) -      Config.put([:instance, :invites_enabled], true) -      Config.put([:instance, :public], false) -      Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"}) - -      response = -        conn -        |> put_req_header("accept", "application/json") -        |> get("/api/statusnet/config") -        |> json_response(:ok) - -      expected_data = %{ -        "site" => %{ -          "accountActivationRequired" => "0", -          "closed" => "1", -          "description" => Keyword.get(instance, :description), -          "invitesEnabled" => "1", -          "name" => Keyword.get(instance, :name), -          "pleromafe" => %{"theme" => "asuka-hospital"}, -          "private" => "1", -          "safeDMMentionsEnabled" => "0", -          "server" => Pleroma.Web.base_url(), -          "textlimit" => to_string(Keyword.get(instance, :limit)), -          "uploadlimit" => %{ -            "avatarlimit" => to_string(Keyword.get(instance, :avatar_upload_limit)), -            "backgroundlimit" => to_string(Keyword.get(instance, :background_upload_limit)), -            "bannerlimit" => to_string(Keyword.get(instance, :banner_upload_limit)), -            "uploadlimit" => to_string(Keyword.get(instance, :upload_limit)) -          }, -          "vapidPublicKey" => Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key) -        } -      } - -      assert response == expected_data -    end - -    test "returns the state of safe_dm_mentions flag", %{conn: conn} do -      Config.put([:instance, :safe_dm_mentions], true) - -      response = -        conn -        |> get("/api/statusnet/config.json") -        |> json_response(:ok) - -      assert response["site"]["safeDMMentionsEnabled"] == "1" - -      Config.put([:instance, :safe_dm_mentions], false) - -      response = -        conn -        |> get("/api/statusnet/config.json") -        |> json_response(:ok) - -      assert response["site"]["safeDMMentionsEnabled"] == "0" -    end - -    test "it returns the managed config", %{conn: conn} do -      Config.put([:instance, :managed_config], false) -      Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"}) - -      response = -        conn -        |> get("/api/statusnet/config.json") -        |> json_response(:ok) - -      refute response["site"]["pleromafe"] - -      Config.put([:instance, :managed_config], true) - -      response = -        conn -        |> get("/api/statusnet/config.json") -        |> json_response(:ok) - -      assert response["site"]["pleromafe"] == %{"theme" => "asuka-hospital"} -    end -  end -    describe "GET /api/pleroma/frontend_configurations" do      test "returns everything in :pleroma, :frontend_configurations", %{conn: conn} do        config = [ @@ -451,28 +346,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do      end    end -  describe "GET /api/statusnet/version" do -    test "it returns version in xml format", %{conn: conn} do -      response = -        conn -        |> put_req_header("accept", "application/xml") -        |> get("/api/statusnet/version") -        |> response(:ok) - -      assert response == "<version>#{Pleroma.Application.named_version()}</version>" -    end - -    test "it returns version in json format", %{conn: conn} do -      response = -        conn -        |> put_req_header("accept", "application/json") -        |> get("/api/statusnet/version") -        |> json_response(:ok) - -      assert response == "#{Pleroma.Application.named_version()}" -    end -  end -    describe "POST /main/ostatus - remote_subscribe/2" do      setup do: clear_config([:instance, :federating], true) diff --git a/test/workers/cron/clear_oauth_token_worker_test.exs b/test/workers/cron/clear_oauth_token_worker_test.exs index df82dc75d..67836f34f 100644 --- a/test/workers/cron/clear_oauth_token_worker_test.exs +++ b/test/workers/cron/clear_oauth_token_worker_test.exs @@ -16,7 +16,7 @@ defmodule Pleroma.Workers.Cron.ClearOauthTokenWorkerTest do      )      Pleroma.Config.put([:oauth2, :clean_expired_tokens], true) -    ClearOauthTokenWorker.perform(:opts, :job) +    ClearOauthTokenWorker.perform(%Oban.Job{})      assert Pleroma.Repo.all(Pleroma.Web.OAuth.Token) == []    end  end diff --git a/test/workers/cron/digest_emails_worker_test.exs b/test/workers/cron/digest_emails_worker_test.exs index f9bc50db5..65887192e 100644 --- a/test/workers/cron/digest_emails_worker_test.exs +++ b/test/workers/cron/digest_emails_worker_test.exs @@ -35,7 +35,7 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorkerTest do    end    test "it sends digest emails", %{user2: user2} do -    Pleroma.Workers.Cron.DigestEmailsWorker.perform(:opts, :pid) +    Pleroma.Workers.Cron.DigestEmailsWorker.perform(%Oban.Job{})      # Performing job(s) enqueued at previous step      ObanHelpers.perform_all() @@ -47,7 +47,7 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorkerTest do    test "it doesn't fail when a user has no email", %{user2: user2} do      {:ok, _} = user2 |> Ecto.Changeset.change(%{email: nil}) |> Pleroma.Repo.update() -    Pleroma.Workers.Cron.DigestEmailsWorker.perform(:opts, :pid) +    Pleroma.Workers.Cron.DigestEmailsWorker.perform(%Oban.Job{})      # Performing job(s) enqueued at previous step      ObanHelpers.perform_all()    end diff --git a/test/workers/cron/new_users_digest_worker_test.exs b/test/workers/cron/new_users_digest_worker_test.exs index ee589bb55..129534cb1 100644 --- a/test/workers/cron/new_users_digest_worker_test.exs +++ b/test/workers/cron/new_users_digest_worker_test.exs @@ -17,7 +17,7 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorkerTest do      user2 = insert(:user, %{inserted_at: yesterday})      CommonAPI.post(user, %{status: "cofe"}) -    NewUsersDigestWorker.perform(nil, nil) +    NewUsersDigestWorker.perform(%Oban.Job{})      ObanHelpers.perform_all()      assert_received {:email, email} @@ -39,7 +39,7 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorkerTest do      CommonAPI.post(user, %{status: "cofe"}) -    NewUsersDigestWorker.perform(nil, nil) +    NewUsersDigestWorker.perform(%Oban.Job{})      ObanHelpers.perform_all()    end  end diff --git a/test/workers/cron/purge_expired_activities_worker_test.exs b/test/workers/cron/purge_expired_activities_worker_test.exs index b1db59fdf..d1acd9ae6 100644 --- a/test/workers/cron/purge_expired_activities_worker_test.exs +++ b/test/workers/cron/purge_expired_activities_worker_test.exs @@ -32,7 +32,7 @@ defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do          %{activity_id: activity.id, scheduled_at: naive_datetime}        ) -    Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(:ops, :pid) +    Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{})      refute Pleroma.Repo.get(Pleroma.Activity, activity.id)      refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id) @@ -58,7 +58,7 @@ defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do      |> Ecto.Changeset.change(%{scheduled_at: past_date})      |> Repo.update!() -    Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(:ops, :pid) +    Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{})      assert [%{data: %{"type" => "Delete", "deleted_activity_id" => ^id}}] =               Pleroma.Repo.all(Pleroma.Activity) diff --git a/test/workers/scheduled_activity_worker_test.exs b/test/workers/scheduled_activity_worker_test.exs index b312d975b..f3eddf7b1 100644 --- a/test/workers/scheduled_activity_worker_test.exs +++ b/test/workers/scheduled_activity_worker_test.exs @@ -32,10 +32,7 @@ defmodule Pleroma.Workers.ScheduledActivityWorkerTest do          params: %{status: "hi"}        ) -    ScheduledActivityWorker.perform( -      %{"activity_id" => scheduled_activity.id}, -      :pid -    ) +    ScheduledActivityWorker.perform(%Oban.Job{args: %{"activity_id" => scheduled_activity.id}})      refute Repo.get(ScheduledActivity, scheduled_activity.id)      activity = Repo.all(Pleroma.Activity) |> Enum.find(&(&1.actor == user.ap_id)) @@ -46,7 +43,7 @@ defmodule Pleroma.Workers.ScheduledActivityWorkerTest do      Pleroma.Config.put([ScheduledActivity, :enabled], true)      assert capture_log([level: :error], fn -> -             ScheduledActivityWorker.perform(%{"activity_id" => 42}, :pid) +             ScheduledActivityWorker.perform(%Oban.Job{args: %{"activity_id" => 42}})             end) =~ "Couldn't find scheduled activity"    end  end | 
