summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/activity_test.exs15
-rw-r--r--test/bbs/handler_test.exs6
-rw-r--r--test/bookmark_test.exs6
-rw-r--r--test/captcha_test.exs7
-rw-r--r--test/chat/message_reference_test.exs29
-rw-r--r--test/chat_test.exs61
-rw-r--r--test/config/config_db_test.exs591
-rw-r--r--test/config/transfer_task_test.exs91
-rw-r--r--test/conversation/participation_test.exs72
-rw-r--r--test/conversation_test.exs22
-rw-r--r--test/filter_test.exs10
-rw-r--r--test/fixtures/config/temp.secret.exs2
-rw-r--r--test/fixtures/create-chat-message.json31
-rw-r--r--test/fixtures/kroeg-announce-with-inline-actor.json89
-rw-r--r--test/fixtures/mastodon-note-object.json50
-rw-r--r--test/fixtures/tesla_mock/craigmaloney.json112
-rw-r--r--test/fixtures/tesla_mock/peertube-social.json234
-rw-r--r--test/html_test.exs14
-rw-r--r--test/http/adapter_helper/hackney_test.exs12
-rw-r--r--test/http/connection_test.exs2
-rw-r--r--test/http/request_builder_test.exs14
-rw-r--r--test/instance_static/add/shortcode.pngbin0 -> 95 bytes
-rw-r--r--test/instance_static/emoji/pack_bad_sha/blank.pngbin0 -> 95 bytes
-rw-r--r--test/instance_static/emoji/pack_bad_sha/pack.json13
-rw-r--r--test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zipbin0 -> 256 bytes
-rw-r--r--test/instance_static/emoji/test_pack/pack.json14
-rw-r--r--test/instance_static/emoji/test_pack_nonshared/pack.json5
-rw-r--r--test/instance_static/local_pack/files.json3
-rw-r--r--test/instance_static/local_pack/manifest.json10
-rw-r--r--test/integration/mastodon_websocket_test.exs21
-rw-r--r--test/marker_test.exs29
-rw-r--r--test/mfa/backup_codes_test.exs11
-rw-r--r--test/mfa/totp_test.exs17
-rw-r--r--test/mfa_test.exs52
-rw-r--r--test/migration_helper/notification_backfill_test.exs56
-rw-r--r--test/notification_test.exs330
-rw-r--r--test/pagination_test.exs12
-rw-r--r--test/plugs/authentication_plug_test.exs51
-rw-r--r--test/plugs/ensure_authenticated_plug_test.exs45
-rw-r--r--test/plugs/ensure_public_or_authenticated_plug_test.exs4
-rw-r--r--test/plugs/http_security_plug_test.exs2
-rw-r--r--test/plugs/legacy_authentication_plug_test.exs6
-rw-r--r--test/plugs/oauth_scopes_plug_test.exs39
-rw-r--r--test/signature_test.exs18
-rw-r--r--test/stats_test.exs (renamed from test/stat_test.exs)34
-rw-r--r--test/support/api_spec_helpers.ex57
-rw-r--r--test/support/builders/activity_builder.ex10
-rw-r--r--test/support/builders/user_builder.ex3
-rw-r--r--test/support/captcha_mock.ex6
-rw-r--r--test/support/conn_case.ex60
-rw-r--r--test/support/data_case.ex6
-rw-r--r--test/support/factory.ex38
-rw-r--r--test/support/helpers.ex8
-rw-r--r--test/support/http_request_mock.ex34
-rw-r--r--test/tasks/app_test.exs65
-rw-r--r--test/tasks/config_test.exs44
-rw-r--r--test/tasks/count_statuses_test.exs6
-rw-r--r--test/tasks/database_test.exs6
-rw-r--r--test/tasks/digest_test.exs2
-rw-r--r--test/tasks/emoji_test.exs13
-rw-r--r--test/tasks/instance_test.exs3
-rw-r--r--test/tasks/refresh_counter_cache_test.exs14
-rw-r--r--test/tasks/relay_test.exs9
-rw-r--r--test/tasks/user_test.exs92
-rw-r--r--test/upload/filter/mogrify_test.exs8
-rw-r--r--test/upload_test.exs1
-rw-r--r--test/uploaders/s3_test.exs2
-rw-r--r--test/user_search_test.exs1
-rw-r--r--test/user_test.exs131
-rw-r--r--test/web/activity_pub/activity_pub_controller_test.exs244
-rw-r--r--test/web/activity_pub/activity_pub_test.exs1434
-rw-r--r--test/web/activity_pub/mrf/activity_expiration_policy_test.exs77
-rw-r--r--test/web/activity_pub/mrf/object_age_policy_test.exs52
-rw-r--r--test/web/activity_pub/mrf/simple_policy_test.exs70
-rw-r--r--test/web/activity_pub/mrf/steal_emoji_policy_test.exs68
-rw-r--r--test/web/activity_pub/mrf/user_allowlist_policy_test.exs6
-rw-r--r--test/web/activity_pub/object_validator_test.exs544
-rw-r--r--test/web/activity_pub/object_validators/types/date_time_test.exs2
-rw-r--r--test/web/activity_pub/object_validators/types/object_id_test.exs6
-rw-r--r--test/web/activity_pub/object_validators/types/recipients_test.exs27
-rw-r--r--test/web/activity_pub/object_validators/types/safe_text_test.exs30
-rw-r--r--test/web/activity_pub/pipeline_test.exs51
-rw-r--r--test/web/activity_pub/relay_test.exs16
-rw-r--r--test/web/activity_pub/side_effects_test.exs504
-rw-r--r--test/web/activity_pub/transmogrifier/announce_handling_test.exs172
-rw-r--r--test/web/activity_pub/transmogrifier/chat_message_test.exs153
-rw-r--r--test/web/activity_pub/transmogrifier/delete_handling_test.exs114
-rw-r--r--test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs61
-rw-r--r--test/web/activity_pub/transmogrifier/follow_handling_test.exs27
-rw-r--r--test/web/activity_pub/transmogrifier/like_handling_test.exs78
-rw-r--r--test/web/activity_pub/transmogrifier/undo_handling_test.exs185
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs657
-rw-r--r--test/web/activity_pub/utils_test.exs61
-rw-r--r--test/web/activity_pub/views/object_view_test.exs4
-rw-r--r--test/web/activity_pub/views/user_view_test.exs31
-rw-r--r--test/web/activity_pub/visibilty_test.exs12
-rw-r--r--test/web/admin_api/admin_api_controller_test.exs3527
-rw-r--r--test/web/admin_api/controllers/admin_api_controller_test.exs1743
-rw-r--r--test/web/admin_api/controllers/config_controller_test.exs1388
-rw-r--r--test/web/admin_api/controllers/invite_controller_test.exs281
-rw-r--r--test/web/admin_api/controllers/media_proxy_cache_controller_test.exs145
-rw-r--r--test/web/admin_api/controllers/oauth_app_controller_test.exs220
-rw-r--r--test/web/admin_api/controllers/relay_controller_test.exs92
-rw-r--r--test/web/admin_api/controllers/report_controller_test.exs374
-rw-r--r--test/web/admin_api/controllers/status_controller_test.exs202
-rw-r--r--test/web/admin_api/views/report_view_test.exs20
-rw-r--r--test/web/api_spec/app_operation_test.exs45
-rw-r--r--test/web/api_spec/schema_examples_test.exs43
-rw-r--r--test/web/auth/auth_test_controller_test.exs242
-rw-r--r--test/web/auth/basic_auth_test.exs46
-rw-r--r--test/web/auth/oauth_test_controller_test.exs49
-rw-r--r--test/web/auth/pleroma_authenticator_test.exs48
-rw-r--r--test/web/auth/totp_authenticator_test.exs51
-rw-r--r--test/web/common_api/common_api_test.exs523
-rw-r--r--test/web/common_api/common_api_utils_test.exs85
-rw-r--r--test/web/federator_test.exs11
-rw-r--r--test/web/feed/tag_controller_test.exs16
-rw-r--r--test/web/feed/user_controller_test.exs26
-rw-r--r--test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs189
-rw-r--r--test/web/mastodon_api/controllers/account_controller_test.exs797
-rw-r--r--test/web/mastodon_api/controllers/app_controller_test.exs4
-rw-r--r--test/web/mastodon_api/controllers/conversation_controller_test.exs221
-rw-r--r--test/web/mastodon_api/controllers/custom_emoji_controller_test.exs9
-rw-r--r--test/web/mastodon_api/controllers/domain_block_controller_test.exs28
-rw-r--r--test/web/mastodon_api/controllers/filter_controller_test.exs26
-rw-r--r--test/web/mastodon_api/controllers/follow_request_controller_test.exs6
-rw-r--r--test/web/mastodon_api/controllers/instance_controller_test.exs15
-rw-r--r--test/web/mastodon_api/controllers/list_controller_test.exs60
-rw-r--r--test/web/mastodon_api/controllers/marker_controller_test.exs25
-rw-r--r--test/web/mastodon_api/controllers/media_controller_test.exs86
-rw-r--r--test/web/mastodon_api/controllers/notification_controller_test.exs318
-rw-r--r--test/web/mastodon_api/controllers/poll_controller_test.exs76
-rw-r--r--test/web/mastodon_api/controllers/report_controller_test.exs26
-rw-r--r--test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs34
-rw-r--r--test/web/mastodon_api/controllers/search_controller_test.exs212
-rw-r--r--test/web/mastodon_api/controllers/status_controller_test.exs585
-rw-r--r--test/web/mastodon_api/controllers/subscription_controller_test.exs39
-rw-r--r--test/web/mastodon_api/controllers/suggestion_controller_test.exs4
-rw-r--r--test/web/mastodon_api/controllers/timeline_controller_test.exs288
-rw-r--r--test/web/mastodon_api/mastodon_api_controller_test.exs33
-rw-r--r--test/web/mastodon_api/mastodon_api_test.exs4
-rw-r--r--test/web/mastodon_api/views/account_view_test.exs153
-rw-r--r--test/web/mastodon_api/views/conversation_view_test.exs11
-rw-r--r--test/web/mastodon_api/views/marker_view_test.exs8
-rw-r--r--test/web/mastodon_api/views/notification_view_test.exs50
-rw-r--r--test/web/mastodon_api/views/poll_view_test.exs52
-rw-r--r--test/web/mastodon_api/views/scheduled_activity_view_test.exs4
-rw-r--r--test/web/mastodon_api/views/status_view_test.exs87
-rw-r--r--test/web/mastodon_api/views/subscription_view_test.exs (renamed from test/web/mastodon_api/views/push_subscription_view_test.exs)6
-rw-r--r--test/web/media_proxy/invalidation_test.exs64
-rw-r--r--test/web/media_proxy/invalidations/http_test.exs39
-rw-r--r--test/web/media_proxy/invalidations/script_test.exs26
-rw-r--r--test/web/media_proxy/media_proxy_controller_test.exs16
-rw-r--r--test/web/media_proxy/media_proxy_test.exs14
-rw-r--r--test/web/metadata/twitter_card_test.exs6
-rw-r--r--test/web/mongooseim/mongoose_im_controller_test.exs24
-rw-r--r--test/web/node_info_test.exs3
-rw-r--r--test/web/oauth/ldap_authorization_test.exs6
-rw-r--r--test/web/oauth/mfa_controller_test.exs306
-rw-r--r--test/web/oauth/oauth_controller_test.exs91
-rw-r--r--test/web/ostatus/ostatus_controller_test.exs45
-rw-r--r--test/web/pleroma_api/controllers/account_controller_test.exs131
-rw-r--r--test/web/pleroma_api/controllers/chat_controller_test.exs336
-rw-r--r--test/web/pleroma_api/controllers/conversation_controller_test.exs136
-rw-r--r--test/web/pleroma_api/controllers/emoji_api_controller_test.exs463
-rw-r--r--test/web/pleroma_api/controllers/emoji_pack_controller_test.exs780
-rw-r--r--test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs132
-rw-r--r--test/web/pleroma_api/controllers/mascot_controller_test.exs25
-rw-r--r--test/web/pleroma_api/controllers/notification_controller_test.exs68
-rw-r--r--test/web/pleroma_api/controllers/pleroma_api_controller_test.exs296
-rw-r--r--test/web/pleroma_api/controllers/scrobble_controller_test.exs26
-rw-r--r--test/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs260
-rw-r--r--test/web/pleroma_api/views/chat/message_reference_view_test.exs61
-rw-r--r--test/web/pleroma_api/views/chat_view_test.exs48
-rw-r--r--test/web/pleroma_api/views/scrobble_view_test.exs20
-rw-r--r--test/web/plugs/plug_test.exs91
-rw-r--r--test/web/push/impl_test.exs152
-rw-r--r--test/web/rel_me_test.exs2
-rw-r--r--test/web/rich_media/helpers_test.exs28
-rw-r--r--test/web/rich_media/parser_test.exs75
-rw-r--r--test/web/rich_media/parsers/twitter_card_test.exs130
-rw-r--r--test/web/static_fe/static_fe_controller_test.exs27
-rw-r--r--test/web/streamer/ping_test.exs36
-rw-r--r--test/web/streamer/state_test.exs54
-rw-r--r--test/web/streamer/streamer_test.exs754
-rw-r--r--test/web/twitter_api/password_controller_test.exs2
-rw-r--r--test/web/twitter_api/remote_follow_controller_test.exs116
-rw-r--r--test/web/twitter_api/twitter_api_controller_test.exs8
-rw-r--r--test/web/twitter_api/twitter_api_test.exs225
-rw-r--r--test/web/twitter_api/util_controller_test.exs49
-rw-r--r--test/web/web_finger/web_finger_test.exs2
-rw-r--r--test/workers/cron/digest_emails_worker_test.exs2
-rw-r--r--test/workers/cron/new_users_digest_worker_test.exs5
-rw-r--r--test/workers/cron/purge_expired_activities_worker_test.exs34
194 files changed, 16483 insertions, 8911 deletions
diff --git a/test/activity_test.exs b/test/activity_test.exs
index 0c19f481b..2a92327d1 100644
--- a/test/activity_test.exs
+++ b/test/activity_test.exs
@@ -11,6 +11,11 @@ defmodule Pleroma.ActivityTest do
alias Pleroma.ThreadMute
import Pleroma.Factory
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
test "returns an activity by it's AP id" do
activity = insert(:note_activity)
found_activity = Activity.get_by_ap_id(activity.data["id"])
@@ -107,8 +112,6 @@ defmodule Pleroma.ActivityTest do
describe "search" do
setup do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
-
user = insert(:user)
params = %{
@@ -125,8 +128,8 @@ defmodule Pleroma.ActivityTest do
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
}
- {:ok, local_activity} = Pleroma.Web.CommonAPI.post(user, %{"status" => "find me!"})
- {:ok, japanese_activity} = Pleroma.Web.CommonAPI.post(user, %{"status" => "更新情報"})
+ {:ok, local_activity} = Pleroma.Web.CommonAPI.post(user, %{status: "find me!"})
+ {:ok, japanese_activity} = Pleroma.Web.CommonAPI.post(user, %{status: "更新情報"})
{:ok, job} = Pleroma.Web.Federator.incoming_ap_doc(params)
{:ok, remote_activity} = ObanHelpers.perform(job)
@@ -225,8 +228,8 @@ defmodule Pleroma.ActivityTest do
test "all_by_actor_and_id/2" do
user = insert(:user)
- {:ok, %{id: id1}} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofe"})
- {:ok, %{id: id2}} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofefe"})
+ {:ok, %{id: id1}} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"})
+ {:ok, %{id: id2}} = Pleroma.Web.CommonAPI.post(user, %{status: "cofefe"})
assert [] == Activity.all_by_actor_and_id(user, [])
diff --git a/test/bbs/handler_test.exs b/test/bbs/handler_test.exs
index 74982547b..eb716486e 100644
--- a/test/bbs/handler_test.exs
+++ b/test/bbs/handler_test.exs
@@ -21,8 +21,8 @@ defmodule Pleroma.BBS.HandlerTest do
{:ok, user} = User.follow(user, followed)
- {:ok, _first} = CommonAPI.post(user, %{"status" => "hey"})
- {:ok, _second} = CommonAPI.post(followed, %{"status" => "hello"})
+ {:ok, _first} = CommonAPI.post(user, %{status: "hey"})
+ {:ok, _second} = CommonAPI.post(followed, %{status: "hello"})
output =
capture_io(fn ->
@@ -62,7 +62,7 @@ defmodule Pleroma.BBS.HandlerTest do
user = insert(:user)
another_user = insert(:user)
- {:ok, activity} = CommonAPI.post(another_user, %{"status" => "this is a test post"})
+ {:ok, activity} = CommonAPI.post(another_user, %{status: "this is a test post"})
activity_object = Object.normalize(activity)
output =
diff --git a/test/bookmark_test.exs b/test/bookmark_test.exs
index 021f79322..2726fe7cd 100644
--- a/test/bookmark_test.exs
+++ b/test/bookmark_test.exs
@@ -11,7 +11,7 @@ defmodule Pleroma.BookmarkTest do
describe "create/2" do
test "with valid params" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Some cool information"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Some cool information"})
{:ok, bookmark} = Bookmark.create(user.id, activity.id)
assert bookmark.user_id == user.id
assert bookmark.activity_id == activity.id
@@ -32,7 +32,7 @@ defmodule Pleroma.BookmarkTest do
test "with valid params" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Some cool information"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Some cool information"})
{:ok, _bookmark} = Bookmark.create(user.id, activity.id)
{:ok, _deleted_bookmark} = Bookmark.destroy(user.id, activity.id)
@@ -45,7 +45,7 @@ defmodule Pleroma.BookmarkTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"Scientists Discover The Secret Behind Tenshi Eating A Corndog Being So Cute – Science Daily"
})
diff --git a/test/captcha_test.exs b/test/captcha_test.exs
index ac1d846e8..1ab9019ab 100644
--- a/test/captcha_test.exs
+++ b/test/captcha_test.exs
@@ -61,7 +61,7 @@ defmodule Pleroma.CaptchaTest do
assert is_binary(answer)
assert :ok = Native.validate(token, answer, answer)
- assert {:error, "Invalid CAPTCHA"} == Native.validate(token, answer, answer <> "foobar")
+ assert {:error, :invalid} == Native.validate(token, answer, answer <> "foobar")
end
end
@@ -78,6 +78,7 @@ defmodule Pleroma.CaptchaTest do
assert is_binary(answer)
assert :ok = Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer)
+ Cachex.del(:used_captcha_cache, token)
end
test "doesn't validate invalid answer" do
@@ -92,7 +93,7 @@ defmodule Pleroma.CaptchaTest do
assert is_binary(answer)
- assert {:error, "Invalid answer data"} =
+ assert {:error, :invalid_answer_data} =
Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer <> "foobar")
end
@@ -108,7 +109,7 @@ defmodule Pleroma.CaptchaTest do
assert is_binary(answer)
- assert {:error, "Invalid answer data"} =
+ assert {:error, :invalid_answer_data} =
Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", nil)
end
end
diff --git a/test/chat/message_reference_test.exs b/test/chat/message_reference_test.exs
new file mode 100644
index 000000000..aaa7c1ad4
--- /dev/null
+++ b/test/chat/message_reference_test.exs
@@ -0,0 +1,29 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Chat.MessageReferenceTest do
+ use Pleroma.DataCase, async: true
+
+ alias Pleroma.Chat
+ alias Pleroma.Chat.MessageReference
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "messages" do
+ test "it returns the last message in a chat" do
+ user = insert(:user)
+ recipient = insert(:user)
+
+ {:ok, _message_1} = CommonAPI.post_chat_message(user, recipient, "hey")
+ {:ok, _message_2} = CommonAPI.post_chat_message(recipient, user, "ho")
+
+ {:ok, chat} = Chat.get_or_create(user.id, recipient.ap_id)
+
+ message = MessageReference.last_message_for_chat(chat)
+
+ assert message.object.data["content"] == "ho"
+ end
+ end
+end
diff --git a/test/chat_test.exs b/test/chat_test.exs
new file mode 100644
index 000000000..332f2180a
--- /dev/null
+++ b/test/chat_test.exs
@@ -0,0 +1,61 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.ChatTest do
+ use Pleroma.DataCase, async: true
+
+ alias Pleroma.Chat
+
+ import Pleroma.Factory
+
+ describe "creation and getting" do
+ test "it only works if the recipient is a valid user (for now)" do
+ user = insert(:user)
+
+ assert {:error, _chat} = Chat.bump_or_create(user.id, "http://some/nonexisting/account")
+ assert {:error, _chat} = Chat.get_or_create(user.id, "http://some/nonexisting/account")
+ end
+
+ test "it creates a chat for a user and recipient" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
+
+ assert chat.id
+ end
+
+ test "it returns and bumps a chat for a user and recipient if it already exists" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
+ {:ok, chat_two} = Chat.bump_or_create(user.id, other_user.ap_id)
+
+ assert chat.id == chat_two.id
+ end
+
+ test "it returns a chat for a user and recipient if it already exists" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
+ {:ok, chat_two} = Chat.get_or_create(user.id, other_user.ap_id)
+
+ assert chat.id == chat_two.id
+ end
+
+ test "a returning chat will have an updated `update_at` field" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
+ :timer.sleep(1500)
+ {:ok, chat_two} = Chat.bump_or_create(user.id, other_user.ap_id)
+
+ assert chat.id == chat_two.id
+ assert chat.updated_at != chat_two.updated_at
+ end
+ end
+end
diff --git a/test/config/config_db_test.exs b/test/config/config_db_test.exs
index 6b0e7b4b6..3895e2cda 100644
--- a/test/config/config_db_test.exs
+++ b/test/config/config_db_test.exs
@@ -7,57 +7,43 @@ defmodule Pleroma.ConfigDBTest do
import Pleroma.Factory
alias Pleroma.ConfigDB
- test "get_by_key/1" do
+ test "get_by_params/1" do
config = insert(:config)
insert(:config)
assert config == ConfigDB.get_by_params(%{group: config.group, key: config.key})
end
- test "create/1" do
- {:ok, config} = ConfigDB.create(%{group: ":pleroma", key: ":some_key", value: "some_value"})
- assert config == ConfigDB.get_by_params(%{group: ":pleroma", key: ":some_key"})
- end
-
- test "update/1" do
- config = insert(:config)
- {:ok, updated} = ConfigDB.update(config, %{value: "some_value"})
- loaded = ConfigDB.get_by_params(%{group: config.group, key: config.key})
- assert loaded == updated
- end
-
test "get_all_as_keyword/0" do
saved = insert(:config)
- insert(:config, group: ":quack", key: ":level", value: ConfigDB.to_binary(:info))
- insert(:config, group: ":quack", key: ":meta", value: ConfigDB.to_binary([:none]))
+ insert(:config, group: ":quack", key: ":level", value: :info)
+ insert(:config, group: ":quack", key: ":meta", value: [:none])
insert(:config,
group: ":quack",
key: ":webhook_url",
- value: ConfigDB.to_binary("https://hooks.slack.com/services/KEY/some_val")
+ value: "https://hooks.slack.com/services/KEY/some_val"
)
config = ConfigDB.get_all_as_keyword()
assert config[:pleroma] == [
- {ConfigDB.from_string(saved.key), ConfigDB.from_binary(saved.value)}
+ {saved.key, saved.value}
]
- assert config[:quack] == [
- level: :info,
- meta: [:none],
- webhook_url: "https://hooks.slack.com/services/KEY/some_val"
- ]
+ assert config[:quack][:level] == :info
+ assert config[:quack][:meta] == [:none]
+ assert config[:quack][:webhook_url] == "https://hooks.slack.com/services/KEY/some_val"
end
describe "update_or_create/1" do
test "common" do
config = insert(:config)
- key2 = "another_key"
+ key2 = :another_key
params = [
- %{group: "pleroma", key: key2, value: "another_value"},
- %{group: config.group, key: config.key, value: "new_value"}
+ %{group: :pleroma, key: key2, value: "another_value"},
+ %{group: :pleroma, key: config.key, value: [a: 1, b: 2, c: "new_value"]}
]
assert Repo.all(ConfigDB) |> length() == 1
@@ -67,16 +53,16 @@ defmodule Pleroma.ConfigDBTest do
assert Repo.all(ConfigDB) |> length() == 2
config1 = ConfigDB.get_by_params(%{group: config.group, key: config.key})
- config2 = ConfigDB.get_by_params(%{group: "pleroma", key: key2})
+ config2 = ConfigDB.get_by_params(%{group: :pleroma, key: key2})
- assert config1.value == ConfigDB.transform("new_value")
- assert config2.value == ConfigDB.transform("another_value")
+ assert config1.value == [a: 1, b: 2, c: "new_value"]
+ assert config2.value == "another_value"
end
test "partial update" do
- config = insert(:config, value: ConfigDB.to_binary(key1: "val1", key2: :val2))
+ config = insert(:config, value: [key1: "val1", key2: :val2])
- {:ok, _config} =
+ {:ok, config} =
ConfigDB.update_or_create(%{
group: config.group,
key: config.key,
@@ -85,15 +71,14 @@ defmodule Pleroma.ConfigDBTest do
updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
- value = ConfigDB.from_binary(updated.value)
- assert length(value) == 3
- assert value[:key1] == :val1
- assert value[:key2] == :val2
- assert value[:key3] == :val3
+ assert config.value == updated.value
+ assert updated.value[:key1] == :val1
+ assert updated.value[:key2] == :val2
+ assert updated.value[:key3] == :val3
end
test "deep merge" do
- config = insert(:config, value: ConfigDB.to_binary(key1: "val1", key2: [k1: :v1, k2: "v2"]))
+ config = insert(:config, value: [key1: "val1", key2: [k1: :v1, k2: "v2"]])
{:ok, config} =
ConfigDB.update_or_create(%{
@@ -105,18 +90,15 @@ defmodule Pleroma.ConfigDBTest do
updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
assert config.value == updated.value
-
- value = ConfigDB.from_binary(updated.value)
- assert value[:key1] == :val1
- assert value[:key2] == [k1: :v1, k2: :v2, k3: :v3]
- assert value[:key3] == :val3
+ assert updated.value[:key1] == :val1
+ assert updated.value[:key2] == [k1: :v1, k2: :v2, k3: :v3]
+ assert updated.value[:key3] == :val3
end
test "only full update for some keys" do
- config1 = insert(:config, key: ":ecto_repos", value: ConfigDB.to_binary(repo: Pleroma.Repo))
+ config1 = insert(:config, key: :ecto_repos, value: [repo: Pleroma.Repo])
- config2 =
- insert(:config, group: ":cors_plug", key: ":max_age", value: ConfigDB.to_binary(18))
+ config2 = insert(:config, group: :cors_plug, key: :max_age, value: 18)
{:ok, _config} =
ConfigDB.update_or_create(%{
@@ -135,8 +117,8 @@ defmodule Pleroma.ConfigDBTest do
updated1 = ConfigDB.get_by_params(%{group: config1.group, key: config1.key})
updated2 = ConfigDB.get_by_params(%{group: config2.group, key: config2.key})
- assert ConfigDB.from_binary(updated1.value) == [another_repo: [Pleroma.Repo]]
- assert ConfigDB.from_binary(updated2.value) == 777
+ assert updated1.value == [another_repo: [Pleroma.Repo]]
+ assert updated2.value == 777
end
test "full update if value is not keyword" do
@@ -144,7 +126,7 @@ defmodule Pleroma.ConfigDBTest do
insert(:config,
group: ":tesla",
key: ":adapter",
- value: ConfigDB.to_binary(Tesla.Adapter.Hackney)
+ value: Tesla.Adapter.Hackney
)
{:ok, _config} =
@@ -156,20 +138,20 @@ defmodule Pleroma.ConfigDBTest do
updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
- assert ConfigDB.from_binary(updated.value) == Tesla.Adapter.Httpc
+ assert updated.value == Tesla.Adapter.Httpc
end
test "only full update for some subkeys" do
config1 =
insert(:config,
key: ":emoji",
- value: ConfigDB.to_binary(groups: [a: 1, b: 2], key: [a: 1])
+ value: [groups: [a: 1, b: 2], key: [a: 1]]
)
config2 =
insert(:config,
key: ":assets",
- value: ConfigDB.to_binary(mascots: [a: 1, b: 2], key: [a: 1])
+ value: [mascots: [a: 1, b: 2], key: [a: 1]]
)
{:ok, _config} =
@@ -189,8 +171,8 @@ defmodule Pleroma.ConfigDBTest do
updated1 = ConfigDB.get_by_params(%{group: config1.group, key: config1.key})
updated2 = ConfigDB.get_by_params(%{group: config2.group, key: config2.key})
- assert ConfigDB.from_binary(updated1.value) == [groups: [c: 3, d: 4], key: [a: 1, b: 2]]
- assert ConfigDB.from_binary(updated2.value) == [mascots: [c: 3, d: 4], key: [a: 1, b: 2]]
+ assert updated1.value == [groups: [c: 3, d: 4], key: [a: 1, b: 2]]
+ assert updated2.value == [mascots: [c: 3, d: 4], key: [a: 1, b: 2]]
end
end
@@ -208,14 +190,14 @@ defmodule Pleroma.ConfigDBTest do
end
test "partial subkeys delete" do
- config = insert(:config, value: ConfigDB.to_binary(groups: [a: 1, b: 2], key: [a: 1]))
+ config = insert(:config, value: [groups: [a: 1, b: 2], key: [a: 1]])
{:ok, deleted} =
ConfigDB.delete(%{group: config.group, key: config.key, subkeys: [":groups"]})
assert Ecto.get_meta(deleted, :state) == :loaded
- assert deleted.value == ConfigDB.to_binary(key: [a: 1])
+ assert deleted.value == [key: [a: 1]]
updated = ConfigDB.get_by_params(%{group: config.group, key: config.key})
@@ -223,7 +205,7 @@ defmodule Pleroma.ConfigDBTest do
end
test "full delete if remaining value after subkeys deletion is empty list" do
- config = insert(:config, value: ConfigDB.to_binary(groups: [a: 1, b: 2]))
+ config = insert(:config, value: [groups: [a: 1, b: 2]])
{:ok, deleted} =
ConfigDB.delete(%{group: config.group, key: config.key, subkeys: [":groups"]})
@@ -234,234 +216,159 @@ defmodule Pleroma.ConfigDBTest do
end
end
- describe "transform/1" do
+ describe "to_elixir_types/1" do
test "string" do
- binary = ConfigDB.transform("value as string")
- assert binary == :erlang.term_to_binary("value as string")
- assert ConfigDB.from_binary(binary) == "value as string"
+ assert ConfigDB.to_elixir_types("value as string") == "value as string"
end
test "boolean" do
- binary = ConfigDB.transform(false)
- assert binary == :erlang.term_to_binary(false)
- assert ConfigDB.from_binary(binary) == false
+ assert ConfigDB.to_elixir_types(false) == false
end
test "nil" do
- binary = ConfigDB.transform(nil)
- assert binary == :erlang.term_to_binary(nil)
- assert ConfigDB.from_binary(binary) == nil
+ assert ConfigDB.to_elixir_types(nil) == nil
end
test "integer" do
- binary = ConfigDB.transform(150)
- assert binary == :erlang.term_to_binary(150)
- assert ConfigDB.from_binary(binary) == 150
+ assert ConfigDB.to_elixir_types(150) == 150
end
test "atom" do
- binary = ConfigDB.transform(":atom")
- assert binary == :erlang.term_to_binary(:atom)
- assert ConfigDB.from_binary(binary) == :atom
+ assert ConfigDB.to_elixir_types(":atom") == :atom
end
test "ssl options" do
- binary = ConfigDB.transform([":tlsv1", ":tlsv1.1", ":tlsv1.2"])
- assert binary == :erlang.term_to_binary([:tlsv1, :"tlsv1.1", :"tlsv1.2"])
- assert ConfigDB.from_binary(binary) == [:tlsv1, :"tlsv1.1", :"tlsv1.2"]
+ assert ConfigDB.to_elixir_types([":tlsv1", ":tlsv1.1", ":tlsv1.2"]) == [
+ :tlsv1,
+ :"tlsv1.1",
+ :"tlsv1.2"
+ ]
end
test "pleroma module" do
- binary = ConfigDB.transform("Pleroma.Bookmark")
- assert binary == :erlang.term_to_binary(Pleroma.Bookmark)
- assert ConfigDB.from_binary(binary) == Pleroma.Bookmark
+ assert ConfigDB.to_elixir_types("Pleroma.Bookmark") == Pleroma.Bookmark
end
test "pleroma string" do
- binary = ConfigDB.transform("Pleroma")
- assert binary == :erlang.term_to_binary("Pleroma")
- assert ConfigDB.from_binary(binary) == "Pleroma"
+ assert ConfigDB.to_elixir_types("Pleroma") == "Pleroma"
end
test "phoenix module" do
- binary = ConfigDB.transform("Phoenix.Socket.V1.JSONSerializer")
- assert binary == :erlang.term_to_binary(Phoenix.Socket.V1.JSONSerializer)
- assert ConfigDB.from_binary(binary) == Phoenix.Socket.V1.JSONSerializer
+ assert ConfigDB.to_elixir_types("Phoenix.Socket.V1.JSONSerializer") ==
+ Phoenix.Socket.V1.JSONSerializer
end
test "tesla module" do
- binary = ConfigDB.transform("Tesla.Adapter.Hackney")
- assert binary == :erlang.term_to_binary(Tesla.Adapter.Hackney)
- assert ConfigDB.from_binary(binary) == Tesla.Adapter.Hackney
+ assert ConfigDB.to_elixir_types("Tesla.Adapter.Hackney") == Tesla.Adapter.Hackney
end
test "ExSyslogger module" do
- binary = ConfigDB.transform("ExSyslogger")
- assert binary == :erlang.term_to_binary(ExSyslogger)
- assert ConfigDB.from_binary(binary) == ExSyslogger
+ assert ConfigDB.to_elixir_types("ExSyslogger") == ExSyslogger
end
test "Quack.Logger module" do
- binary = ConfigDB.transform("Quack.Logger")
- assert binary == :erlang.term_to_binary(Quack.Logger)
- assert ConfigDB.from_binary(binary) == Quack.Logger
+ assert ConfigDB.to_elixir_types("Quack.Logger") == Quack.Logger
end
test "Swoosh.Adapters modules" do
- binary = ConfigDB.transform("Swoosh.Adapters.SMTP")
- assert binary == :erlang.term_to_binary(Swoosh.Adapters.SMTP)
- assert ConfigDB.from_binary(binary) == Swoosh.Adapters.SMTP
- binary = ConfigDB.transform("Swoosh.Adapters.AmazonSES")
- assert binary == :erlang.term_to_binary(Swoosh.Adapters.AmazonSES)
- assert ConfigDB.from_binary(binary) == Swoosh.Adapters.AmazonSES
+ assert ConfigDB.to_elixir_types("Swoosh.Adapters.SMTP") == Swoosh.Adapters.SMTP
+ assert ConfigDB.to_elixir_types("Swoosh.Adapters.AmazonSES") == Swoosh.Adapters.AmazonSES
end
test "sigil" do
- binary = ConfigDB.transform("~r[comp[lL][aA][iI][nN]er]")
- assert binary == :erlang.term_to_binary(~r/comp[lL][aA][iI][nN]er/)
- assert ConfigDB.from_binary(binary) == ~r/comp[lL][aA][iI][nN]er/
+ assert ConfigDB.to_elixir_types("~r[comp[lL][aA][iI][nN]er]") == ~r/comp[lL][aA][iI][nN]er/
end
test "link sigil" do
- binary = ConfigDB.transform("~r/https:\/\/example.com/")
- assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/)
- assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/
+ assert ConfigDB.to_elixir_types("~r/https:\/\/example.com/") == ~r/https:\/\/example.com/
end
test "link sigil with um modifiers" do
- binary = ConfigDB.transform("~r/https:\/\/example.com/um")
- assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/um)
- assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/um
+ assert ConfigDB.to_elixir_types("~r/https:\/\/example.com/um") ==
+ ~r/https:\/\/example.com/um
end
test "link sigil with i modifier" do
- binary = ConfigDB.transform("~r/https:\/\/example.com/i")
- assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/i)
- assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/i
+ assert ConfigDB.to_elixir_types("~r/https:\/\/example.com/i") == ~r/https:\/\/example.com/i
end
test "link sigil with s modifier" do
- binary = ConfigDB.transform("~r/https:\/\/example.com/s")
- assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/s)
- assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/s
+ assert ConfigDB.to_elixir_types("~r/https:\/\/example.com/s") == ~r/https:\/\/example.com/s
end
test "raise if valid delimiter not found" do
assert_raise ArgumentError, "valid delimiter for Regex expression not found", fn ->
- ConfigDB.transform("~r/https://[]{}<>\"'()|example.com/s")
+ ConfigDB.to_elixir_types("~r/https://[]{}<>\"'()|example.com/s")
end
end
test "2 child tuple" do
- binary = ConfigDB.transform(%{"tuple" => ["v1", ":v2"]})
- assert binary == :erlang.term_to_binary({"v1", :v2})
- assert ConfigDB.from_binary(binary) == {"v1", :v2}
+ assert ConfigDB.to_elixir_types(%{"tuple" => ["v1", ":v2"]}) == {"v1", :v2}
end
test "proxy tuple with localhost" do
- binary =
- ConfigDB.transform(%{
- "tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]
- })
-
- assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, :localhost, 1234}})
- assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, :localhost, 1234}}
+ assert ConfigDB.to_elixir_types(%{
+ "tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]
+ }) == {:proxy_url, {:socks5, :localhost, 1234}}
end
test "proxy tuple with domain" do
- binary =
- ConfigDB.transform(%{
- "tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]
- })
-
- assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, 'domain.com', 1234}})
- assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, 'domain.com', 1234}}
+ assert ConfigDB.to_elixir_types(%{
+ "tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]
+ }) == {:proxy_url, {:socks5, 'domain.com', 1234}}
end
test "proxy tuple with ip" do
- binary =
- ConfigDB.transform(%{
- "tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]
- })
-
- assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}})
- assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}}
+ assert ConfigDB.to_elixir_types(%{
+ "tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]
+ }) == {:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}}
end
test "tuple with n childs" do
- binary =
- ConfigDB.transform(%{
- "tuple" => [
- "v1",
- ":v2",
- "Pleroma.Bookmark",
- 150,
- false,
- "Phoenix.Socket.V1.JSONSerializer"
- ]
- })
-
- assert binary ==
- :erlang.term_to_binary(
- {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
- )
-
- assert ConfigDB.from_binary(binary) ==
- {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
+ assert ConfigDB.to_elixir_types(%{
+ "tuple" => [
+ "v1",
+ ":v2",
+ "Pleroma.Bookmark",
+ 150,
+ false,
+ "Phoenix.Socket.V1.JSONSerializer"
+ ]
+ }) == {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer}
end
test "map with string key" do
- binary = ConfigDB.transform(%{"key" => "value"})
- assert binary == :erlang.term_to_binary(%{"key" => "value"})
- assert ConfigDB.from_binary(binary) == %{"key" => "value"}
+ assert ConfigDB.to_elixir_types(%{"key" => "value"}) == %{"key" => "value"}
end
test "map with atom key" do
- binary = ConfigDB.transform(%{":key" => "value"})
- assert binary == :erlang.term_to_binary(%{key: "value"})
- assert ConfigDB.from_binary(binary) == %{key: "value"}
+ assert ConfigDB.to_elixir_types(%{":key" => "value"}) == %{key: "value"}
end
test "list of strings" do
- binary = ConfigDB.transform(["v1", "v2", "v3"])
- assert binary == :erlang.term_to_binary(["v1", "v2", "v3"])
- assert ConfigDB.from_binary(binary) == ["v1", "v2", "v3"]
+ assert ConfigDB.to_elixir_types(["v1", "v2", "v3"]) == ["v1", "v2", "v3"]
end
test "list of modules" do
- binary = ConfigDB.transform(["Pleroma.Repo", "Pleroma.Activity"])
- assert binary == :erlang.term_to_binary([Pleroma.Repo, Pleroma.Activity])
- assert ConfigDB.from_binary(binary) == [Pleroma.Repo, Pleroma.Activity]
+ assert ConfigDB.to_elixir_types(["Pleroma.Repo", "Pleroma.Activity"]) == [
+ Pleroma.Repo,
+ Pleroma.Activity
+ ]
end
test "list of atoms" do
- binary = ConfigDB.transform([":v1", ":v2", ":v3"])
- assert binary == :erlang.term_to_binary([:v1, :v2, :v3])
- assert ConfigDB.from_binary(binary) == [:v1, :v2, :v3]
+ assert ConfigDB.to_elixir_types([":v1", ":v2", ":v3"]) == [:v1, :v2, :v3]
end
test "list of mixed values" do
- binary =
- ConfigDB.transform([
- "v1",
- ":v2",
- "Pleroma.Repo",
- "Phoenix.Socket.V1.JSONSerializer",
- 15,
- false
- ])
-
- assert binary ==
- :erlang.term_to_binary([
- "v1",
- :v2,
- Pleroma.Repo,
- Phoenix.Socket.V1.JSONSerializer,
- 15,
- false
- ])
-
- assert ConfigDB.from_binary(binary) == [
+ assert ConfigDB.to_elixir_types([
+ "v1",
+ ":v2",
+ "Pleroma.Repo",
+ "Phoenix.Socket.V1.JSONSerializer",
+ 15,
+ false
+ ]) == [
"v1",
:v2,
Pleroma.Repo,
@@ -472,32 +379,17 @@ defmodule Pleroma.ConfigDBTest do
end
test "simple keyword" do
- binary = ConfigDB.transform([%{"tuple" => [":key", "value"]}])
- assert binary == :erlang.term_to_binary([{:key, "value"}])
- assert ConfigDB.from_binary(binary) == [{:key, "value"}]
- assert ConfigDB.from_binary(binary) == [key: "value"]
+ assert ConfigDB.to_elixir_types([%{"tuple" => [":key", "value"]}]) == [key: "value"]
end
test "keyword" do
- binary =
- ConfigDB.transform([
- %{"tuple" => [":types", "Pleroma.PostgresTypes"]},
- %{"tuple" => [":telemetry_event", ["Pleroma.Repo.Instrumenter"]]},
- %{"tuple" => [":migration_lock", nil]},
- %{"tuple" => [":key1", 150]},
- %{"tuple" => [":key2", "string"]}
- ])
-
- assert binary ==
- :erlang.term_to_binary(
- types: Pleroma.PostgresTypes,
- telemetry_event: [Pleroma.Repo.Instrumenter],
- migration_lock: nil,
- key1: 150,
- key2: "string"
- )
-
- assert ConfigDB.from_binary(binary) == [
+ assert ConfigDB.to_elixir_types([
+ %{"tuple" => [":types", "Pleroma.PostgresTypes"]},
+ %{"tuple" => [":telemetry_event", ["Pleroma.Repo.Instrumenter"]]},
+ %{"tuple" => [":migration_lock", nil]},
+ %{"tuple" => [":key1", 150]},
+ %{"tuple" => [":key2", "string"]}
+ ]) == [
types: Pleroma.PostgresTypes,
telemetry_event: [Pleroma.Repo.Instrumenter],
migration_lock: nil,
@@ -506,86 +398,60 @@ defmodule Pleroma.ConfigDBTest do
]
end
+ test "trandformed keyword" do
+ assert ConfigDB.to_elixir_types(a: 1, b: 2, c: "string") == [a: 1, b: 2, c: "string"]
+ end
+
test "complex keyword with nested mixed childs" do
- binary =
- ConfigDB.transform([
- %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]},
- %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]},
- %{"tuple" => [":link_name", true]},
- %{"tuple" => [":proxy_remote", false]},
- %{"tuple" => [":common_map", %{":key" => "value"}]},
- %{
- "tuple" => [
- ":proxy_opts",
- [
- %{"tuple" => [":redirect_on_failure", false]},
- %{"tuple" => [":max_body_length", 1_048_576]},
- %{
- "tuple" => [
- ":http",
- [%{"tuple" => [":follow_redirect", true]}, %{"tuple" => [":pool", ":upload"]}]
- ]
- }
- ]
- ]
- }
- ])
-
- assert binary ==
- :erlang.term_to_binary(
- uploader: Pleroma.Uploaders.Local,
- filters: [Pleroma.Upload.Filter.Dedupe],
- link_name: true,
- proxy_remote: false,
- common_map: %{key: "value"},
- proxy_opts: [
- redirect_on_failure: false,
- max_body_length: 1_048_576,
- http: [
- follow_redirect: true,
- pool: :upload
+ assert ConfigDB.to_elixir_types([
+ %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]},
+ %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]},
+ %{"tuple" => [":link_name", true]},
+ %{"tuple" => [":proxy_remote", false]},
+ %{"tuple" => [":common_map", %{":key" => "value"}]},
+ %{
+ "tuple" => [
+ ":proxy_opts",
+ [
+ %{"tuple" => [":redirect_on_failure", false]},
+ %{"tuple" => [":max_body_length", 1_048_576]},
+ %{
+ "tuple" => [
+ ":http",
+ [
+ %{"tuple" => [":follow_redirect", true]},
+ %{"tuple" => [":pool", ":upload"]}
+ ]
+ ]
+ }
]
]
- )
-
- assert ConfigDB.from_binary(binary) ==
- [
- uploader: Pleroma.Uploaders.Local,
- filters: [Pleroma.Upload.Filter.Dedupe],
- link_name: true,
- proxy_remote: false,
- common_map: %{key: "value"},
- proxy_opts: [
- redirect_on_failure: false,
- max_body_length: 1_048_576,
- http: [
- follow_redirect: true,
- pool: :upload
- ]
+ }
+ ]) == [
+ uploader: Pleroma.Uploaders.Local,
+ filters: [Pleroma.Upload.Filter.Dedupe],
+ link_name: true,
+ proxy_remote: false,
+ common_map: %{key: "value"},
+ proxy_opts: [
+ redirect_on_failure: false,
+ max_body_length: 1_048_576,
+ http: [
+ follow_redirect: true,
+ pool: :upload
]
]
+ ]
end
test "common keyword" do
- binary =
- ConfigDB.transform([
- %{"tuple" => [":level", ":warn"]},
- %{"tuple" => [":meta", [":all"]]},
- %{"tuple" => [":path", ""]},
- %{"tuple" => [":val", nil]},
- %{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]}
- ])
-
- assert binary ==
- :erlang.term_to_binary(
- level: :warn,
- meta: [:all],
- path: "",
- val: nil,
- webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
- )
-
- assert ConfigDB.from_binary(binary) == [
+ assert ConfigDB.to_elixir_types([
+ %{"tuple" => [":level", ":warn"]},
+ %{"tuple" => [":meta", [":all"]]},
+ %{"tuple" => [":path", ""]},
+ %{"tuple" => [":val", nil]},
+ %{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]}
+ ]) == [
level: :warn,
meta: [:all],
path: "",
@@ -595,98 +461,73 @@ defmodule Pleroma.ConfigDBTest do
end
test "complex keyword with sigil" do
- binary =
- ConfigDB.transform([
- %{"tuple" => [":federated_timeline_removal", []]},
- %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]},
- %{"tuple" => [":replace", []]}
- ])
-
- assert binary ==
- :erlang.term_to_binary(
- federated_timeline_removal: [],
- reject: [~r/comp[lL][aA][iI][nN]er/],
- replace: []
- )
-
- assert ConfigDB.from_binary(binary) ==
- [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []]
+ assert ConfigDB.to_elixir_types([
+ %{"tuple" => [":federated_timeline_removal", []]},
+ %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]},
+ %{"tuple" => [":replace", []]}
+ ]) == [
+ federated_timeline_removal: [],
+ reject: [~r/comp[lL][aA][iI][nN]er/],
+ replace: []
+ ]
end
test "complex keyword with tuples with more than 2 values" do
- binary =
- ConfigDB.transform([
- %{
- "tuple" => [
- ":http",
- [
- %{
- "tuple" => [
- ":key1",
- [
- %{
- "tuple" => [
- ":_",
- [
- %{
- "tuple" => [
- "/api/v1/streaming",
- "Pleroma.Web.MastodonAPI.WebsocketHandler",
- []
- ]
- },
- %{
- "tuple" => [
- "/websocket",
- "Phoenix.Endpoint.CowboyWebSocket",
- %{
- "tuple" => [
- "Phoenix.Transports.WebSocket",
- %{
- "tuple" => [
- "Pleroma.Web.Endpoint",
- "Pleroma.Web.UserSocket",
- []
- ]
- }
- ]
- }
- ]
- },
- %{
- "tuple" => [
- ":_",
- "Phoenix.Endpoint.Cowboy2Handler",
- %{"tuple" => ["Pleroma.Web.Endpoint", []]}
- ]
- }
- ]
- ]
- }
- ]
- ]
- }
- ]
- ]
- }
- ])
-
- assert binary ==
- :erlang.term_to_binary(
- http: [
- key1: [
- _: [
- {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
- {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
- {Phoenix.Transports.WebSocket,
- {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}},
- {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
- ]
+ assert ConfigDB.to_elixir_types([
+ %{
+ "tuple" => [
+ ":http",
+ [
+ %{
+ "tuple" => [
+ ":key1",
+ [
+ %{
+ "tuple" => [
+ ":_",
+ [
+ %{
+ "tuple" => [
+ "/api/v1/streaming",
+ "Pleroma.Web.MastodonAPI.WebsocketHandler",
+ []
+ ]
+ },
+ %{
+ "tuple" => [
+ "/websocket",
+ "Phoenix.Endpoint.CowboyWebSocket",
+ %{
+ "tuple" => [
+ "Phoenix.Transports.WebSocket",
+ %{
+ "tuple" => [
+ "Pleroma.Web.Endpoint",
+ "Pleroma.Web.UserSocket",
+ []
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ %{
+ "tuple" => [
+ ":_",
+ "Phoenix.Endpoint.Cowboy2Handler",
+ %{"tuple" => ["Pleroma.Web.Endpoint", []]}
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
]
]
- )
-
- assert ConfigDB.from_binary(binary) == [
+ }
+ ]) == [
http: [
key1: [
{:_,
diff --git a/test/config/transfer_task_test.exs b/test/config/transfer_task_test.exs
index 00db0b686..f53829e09 100644
--- a/test/config/transfer_task_test.exs
+++ b/test/config/transfer_task_test.exs
@@ -6,9 +6,9 @@ defmodule Pleroma.Config.TransferTaskTest do
use Pleroma.DataCase
import ExUnit.CaptureLog
+ import Pleroma.Factory
alias Pleroma.Config.TransferTask
- alias Pleroma.ConfigDB
setup do: clear_config(:configurable_from_database, true)
@@ -16,27 +16,14 @@ defmodule Pleroma.Config.TransferTaskTest do
refute Application.get_env(:pleroma, :test_key)
refute Application.get_env(:idna, :test_key)
refute Application.get_env(:quack, :test_key)
+ refute Application.get_env(:postgrex, :test_key)
initial = Application.get_env(:logger, :level)
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":test_key",
- value: [live: 2, com: 3]
- })
-
- ConfigDB.create(%{
- group: ":idna",
- key: ":test_key",
- value: [live: 15, com: 35]
- })
-
- ConfigDB.create(%{
- group: ":quack",
- key: ":test_key",
- value: [:test_value1, :test_value2]
- })
-
- ConfigDB.create(%{group: ":logger", key: ":level", value: :debug})
+ insert(:config, key: :test_key, value: [live: 2, com: 3])
+ insert(:config, group: :idna, key: :test_key, value: [live: 15, com: 35])
+ insert(:config, group: :quack, key: :test_key, value: [:test_value1, :test_value2])
+ insert(:config, group: :postgrex, key: :test_key, value: :value)
+ insert(:config, group: :logger, key: :level, value: :debug)
TransferTask.start_link([])
@@ -44,11 +31,13 @@ defmodule Pleroma.Config.TransferTaskTest do
assert Application.get_env(:idna, :test_key) == [live: 15, com: 35]
assert Application.get_env(:quack, :test_key) == [:test_value1, :test_value2]
assert Application.get_env(:logger, :level) == :debug
+ assert Application.get_env(:postgrex, :test_key) == :value
on_exit(fn ->
Application.delete_env(:pleroma, :test_key)
Application.delete_env(:idna, :test_key)
Application.delete_env(:quack, :test_key)
+ Application.delete_env(:postgrex, :test_key)
Application.put_env(:logger, :level, initial)
end)
end
@@ -57,17 +46,8 @@ defmodule Pleroma.Config.TransferTaskTest do
level = Application.get_env(:quack, :level)
meta = Application.get_env(:quack, :meta)
- ConfigDB.create(%{
- group: ":quack",
- key: ":level",
- value: :info
- })
-
- ConfigDB.create(%{
- group: ":quack",
- key: ":meta",
- value: [:none]
- })
+ insert(:config, group: :quack, key: :level, value: :info)
+ insert(:config, group: :quack, key: :meta, value: [:none])
TransferTask.start_link([])
@@ -86,17 +66,8 @@ defmodule Pleroma.Config.TransferTaskTest do
clear_config(:emoji)
clear_config(:assets)
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":emoji",
- value: [groups: [a: 1, b: 2]]
- })
-
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":assets",
- value: [mascots: [a: 1, b: 2]]
- })
+ insert(:config, key: :emoji, value: [groups: [a: 1, b: 2]])
+ insert(:config, key: :assets, value: [mascots: [a: 1, b: 2]])
TransferTask.start_link([])
@@ -113,12 +84,7 @@ defmodule Pleroma.Config.TransferTaskTest do
test "don't restart if no reboot time settings were changed" do
clear_config(:emoji)
-
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":emoji",
- value: [groups: [a: 1, b: 2]]
- })
+ insert(:config, key: :emoji, value: [groups: [a: 1, b: 2]])
refute String.contains?(
capture_log(fn -> TransferTask.start_link([]) end),
@@ -128,25 +94,13 @@ defmodule Pleroma.Config.TransferTaskTest do
test "on reboot time key" do
clear_config(:chat)
-
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":chat",
- value: [enabled: false]
- })
-
+ insert(:config, key: :chat, value: [enabled: false])
assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
end
test "on reboot time subkey" do
clear_config(Pleroma.Captcha)
-
- ConfigDB.create(%{
- group: ":pleroma",
- key: "Pleroma.Captcha",
- value: [seconds_valid: 60]
- })
-
+ insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60])
assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
end
@@ -154,17 +108,8 @@ defmodule Pleroma.Config.TransferTaskTest do
clear_config(:chat)
clear_config(Pleroma.Captcha)
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":chat",
- value: [enabled: false]
- })
-
- ConfigDB.create(%{
- group: ":pleroma",
- key: "Pleroma.Captcha",
- value: [seconds_valid: 60]
- })
+ insert(:config, key: :chat, value: [enabled: false])
+ insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60])
refute String.contains?(
capture_log(fn -> TransferTask.load_and_update_env([], false) end),
diff --git a/test/conversation/participation_test.exs b/test/conversation/participation_test.exs
index 3536842e8..59a1b6492 100644
--- a/test/conversation/participation_test.exs
+++ b/test/conversation/participation_test.exs
@@ -16,7 +16,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
other_user = insert(:user)
{:ok, _activity} =
- CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
+ CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
[participation] = Participation.for_user(user)
@@ -30,7 +30,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
other_user = insert(:user)
{:ok, _} =
- CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
+ CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
user = User.get_cached_by_id(user.id)
other_user = User.get_cached_by_id(other_user.id)
@@ -43,9 +43,9 @@ defmodule Pleroma.Conversation.ParticipationTest do
{:ok, _} =
CommonAPI.post(other_user, %{
- "status" => "Hey @#{user.nickname}.",
- "visibility" => "direct",
- "in_reply_to_conversation_id" => participation.id
+ status: "Hey @#{user.nickname}.",
+ visibility: "direct",
+ in_reply_to_conversation_id: participation.id
})
user = User.get_cached_by_id(user.id)
@@ -64,7 +64,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
third_user = insert(:user)
{:ok, activity} =
- CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
+ CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
user = User.get_cached_by_id(user.id)
other_user = User.get_cached_by_id(other_user.id)
@@ -79,9 +79,9 @@ defmodule Pleroma.Conversation.ParticipationTest do
{:ok, _activity} =
CommonAPI.post(user, %{
- "in_reply_to_status_id" => activity.id,
- "status" => "Hey @#{third_user.nickname}.",
- "visibility" => "direct"
+ in_reply_to_status_id: activity.id,
+ status: "Hey @#{third_user.nickname}.",
+ visibility: "direct"
})
[participation] = Participation.for_user(user)
@@ -154,14 +154,14 @@ defmodule Pleroma.Conversation.ParticipationTest do
test "gets all the participations for a user, ordered by updated at descending" do
user = insert(:user)
- {:ok, activity_one} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
- {:ok, activity_two} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
+ {:ok, activity_one} = CommonAPI.post(user, %{status: "x", visibility: "direct"})
+ {:ok, activity_two} = CommonAPI.post(user, %{status: "x", visibility: "direct"})
{:ok, activity_three} =
CommonAPI.post(user, %{
- "status" => "x",
- "visibility" => "direct",
- "in_reply_to_status_id" => activity_one.id
+ status: "x",
+ visibility: "direct",
+ in_reply_to_status_id: activity_one.id
})
# Offset participations because the accuracy of updated_at is down to a second
@@ -201,7 +201,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
test "Doesn't die when the conversation gets empty" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+ {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
[participation] = Participation.for_user_with_last_activity_id(user)
assert participation.last_activity_id == activity.id
@@ -215,7 +215,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, _activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+ {:ok, _activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
[participation] = Participation.for_user_with_last_activity_id(user)
participation = Repo.preload(participation, :recipients)
@@ -239,26 +239,26 @@ defmodule Pleroma.Conversation.ParticipationTest do
{:ok, _direct1} =
CommonAPI.post(third_user, %{
- "status" => "Hi @#{blocker.nickname}",
- "visibility" => "direct"
+ status: "Hi @#{blocker.nickname}",
+ visibility: "direct"
})
{:ok, _direct2} =
CommonAPI.post(third_user, %{
- "status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
- "visibility" => "direct"
+ status: "Hi @#{blocker.nickname}, @#{blocked.nickname}",
+ visibility: "direct"
})
{:ok, _direct3} =
CommonAPI.post(blocked, %{
- "status" => "Hi @#{blocker.nickname}",
- "visibility" => "direct"
+ status: "Hi @#{blocker.nickname}",
+ visibility: "direct"
})
{:ok, _direct4} =
CommonAPI.post(blocked, %{
- "status" => "Hi @#{blocker.nickname}, @#{third_user.nickname}",
- "visibility" => "direct"
+ status: "Hi @#{blocker.nickname}, @#{third_user.nickname}",
+ visibility: "direct"
})
assert [%{read: false}, %{read: false}, %{read: false}, %{read: false}] =
@@ -293,8 +293,8 @@ defmodule Pleroma.Conversation.ParticipationTest do
# When the blocked user is the author
{:ok, _direct1} =
CommonAPI.post(blocked, %{
- "status" => "Hi @#{blocker.nickname}",
- "visibility" => "direct"
+ status: "Hi @#{blocker.nickname}",
+ visibility: "direct"
})
assert [%{read: true}] = Participation.for_user(blocker)
@@ -303,8 +303,8 @@ defmodule Pleroma.Conversation.ParticipationTest do
# When the blocked user is a recipient
{:ok, _direct2} =
CommonAPI.post(third_user, %{
- "status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
- "visibility" => "direct"
+ status: "Hi @#{blocker.nickname}, @#{blocked.nickname}",
+ visibility: "direct"
})
assert [%{read: true}, %{read: true}] = Participation.for_user(blocker)
@@ -321,8 +321,8 @@ defmodule Pleroma.Conversation.ParticipationTest do
{:ok, _direct1} =
CommonAPI.post(blocker, %{
- "status" => "Hi @#{third_user.nickname}, @#{blocked.nickname}",
- "visibility" => "direct"
+ status: "Hi @#{third_user.nickname}, @#{blocked.nickname}",
+ visibility: "direct"
})
{:ok, _user_relationship} = User.block(blocker, blocked)
@@ -334,9 +334,9 @@ defmodule Pleroma.Conversation.ParticipationTest do
# When it's a reply from the blocked user
{:ok, _direct2} =
CommonAPI.post(blocked, %{
- "status" => "reply",
- "visibility" => "direct",
- "in_reply_to_conversation_id" => blocked_participation.id
+ status: "reply",
+ visibility: "direct",
+ in_reply_to_conversation_id: blocked_participation.id
})
assert [%{read: true}] = Participation.for_user(blocker)
@@ -347,9 +347,9 @@ defmodule Pleroma.Conversation.ParticipationTest do
# When it's a reply from the third user
{:ok, _direct3} =
CommonAPI.post(third_user, %{
- "status" => "reply",
- "visibility" => "direct",
- "in_reply_to_conversation_id" => third_user_participation.id
+ status: "reply",
+ visibility: "direct",
+ in_reply_to_conversation_id: third_user_participation.id
})
assert [%{read: true}] = Participation.for_user(blocker)
diff --git a/test/conversation_test.exs b/test/conversation_test.exs
index 056a0e920..359aa6840 100644
--- a/test/conversation_test.exs
+++ b/test/conversation_test.exs
@@ -18,7 +18,7 @@ defmodule Pleroma.ConversationTest do
other_user = insert(:user)
{:ok, _activity} =
- CommonAPI.post(user, %{"visibility" => "direct", "status" => "hey @#{other_user.nickname}"})
+ CommonAPI.post(user, %{visibility: "direct", status: "hey @#{other_user.nickname}"})
Pleroma.Tests.ObanHelpers.perform_all()
@@ -46,7 +46,7 @@ defmodule Pleroma.ConversationTest do
test "public posts don't create conversations" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Hey"})
object = Pleroma.Object.normalize(activity)
context = object.data["context"]
@@ -62,7 +62,7 @@ defmodule Pleroma.ConversationTest do
tridi = insert(:user)
{:ok, activity} =
- CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "direct"})
+ CommonAPI.post(har, %{status: "Hey @#{jafnhar.nickname}", visibility: "direct"})
object = Pleroma.Object.normalize(activity)
context = object.data["context"]
@@ -81,9 +81,9 @@ defmodule Pleroma.ConversationTest do
{:ok, activity} =
CommonAPI.post(jafnhar, %{
- "status" => "Hey @#{har.nickname}",
- "visibility" => "direct",
- "in_reply_to_status_id" => activity.id
+ status: "Hey @#{har.nickname}",
+ visibility: "direct",
+ in_reply_to_status_id: activity.id
})
object = Pleroma.Object.normalize(activity)
@@ -105,9 +105,9 @@ defmodule Pleroma.ConversationTest do
{:ok, activity} =
CommonAPI.post(tridi, %{
- "status" => "Hey @#{har.nickname}",
- "visibility" => "direct",
- "in_reply_to_status_id" => activity.id
+ status: "Hey @#{har.nickname}",
+ visibility: "direct",
+ in_reply_to_status_id: activity.id
})
object = Pleroma.Object.normalize(activity)
@@ -149,14 +149,14 @@ defmodule Pleroma.ConversationTest do
jafnhar = insert(:user, local: false)
{:ok, activity} =
- CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "direct"})
+ CommonAPI.post(har, %{status: "Hey @#{jafnhar.nickname}", visibility: "direct"})
{:ok, conversation} = Conversation.create_or_bump_for(activity)
assert length(conversation.participations) == 2
{:ok, activity} =
- CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "public"})
+ CommonAPI.post(har, %{status: "Hey @#{jafnhar.nickname}", visibility: "public"})
assert {:error, _} = Conversation.create_or_bump_for(activity)
end
diff --git a/test/filter_test.exs b/test/filter_test.exs
index b2a8330ee..63a30c736 100644
--- a/test/filter_test.exs
+++ b/test/filter_test.exs
@@ -141,17 +141,15 @@ defmodule Pleroma.FilterTest do
context: ["home"]
}
- query_two = %Pleroma.Filter{
- user_id: user.id,
- filter_id: 1,
+ changes = %{
phrase: "who",
context: ["home", "timeline"]
}
{:ok, filter_one} = Pleroma.Filter.create(query_one)
- {:ok, filter_two} = Pleroma.Filter.update(query_two)
+ {:ok, filter_two} = Pleroma.Filter.update(filter_one, changes)
assert filter_one != filter_two
- assert filter_two.phrase == query_two.phrase
- assert filter_two.context == query_two.context
+ assert filter_two.phrase == changes.phrase
+ assert filter_two.context == changes.context
end
end
diff --git a/test/fixtures/config/temp.secret.exs b/test/fixtures/config/temp.secret.exs
index f4686c101..dc950ca30 100644
--- a/test/fixtures/config/temp.secret.exs
+++ b/test/fixtures/config/temp.secret.exs
@@ -7,3 +7,5 @@ config :pleroma, :second_setting, key: "value2", key2: ["Activity"]
config :quack, level: :info
config :pleroma, Pleroma.Repo, pool: Ecto.Adapters.SQL.Sandbox
+
+config :postgrex, :json_library, Poison
diff --git a/test/fixtures/create-chat-message.json b/test/fixtures/create-chat-message.json
new file mode 100644
index 000000000..9c23a1c9b
--- /dev/null
+++ b/test/fixtures/create-chat-message.json
@@ -0,0 +1,31 @@
+{
+ "actor": "http://2hu.gensokyo/users/raymoo",
+ "id": "http://2hu.gensokyo/objects/1",
+ "object": {
+ "attributedTo": "http://2hu.gensokyo/users/raymoo",
+ "content": "You expected a cute girl? Too bad. <script>alert('XSS')</script>",
+ "id": "http://2hu.gensokyo/objects/2",
+ "published": "2020-02-12T14:08:20Z",
+ "to": [
+ "http://2hu.gensokyo/users/marisa"
+ ],
+ "tag": [
+ {
+ "icon": {
+ "type": "Image",
+ "url": "http://2hu.gensokyo/emoji/Firefox.gif"
+ },
+ "id": "http://2hu.gensokyo/emoji/Firefox.gif",
+ "name": ":firefox:",
+ "type": "Emoji",
+ "updated": "1970-01-01T00:00:00Z"
+ }
+ ],
+ "type": "ChatMessage"
+ },
+ "published": "2018-02-12T14:08:20Z",
+ "to": [
+ "http://2hu.gensokyo/users/marisa"
+ ],
+ "type": "Create"
+}
diff --git a/test/fixtures/kroeg-announce-with-inline-actor.json b/test/fixtures/kroeg-announce-with-inline-actor.json
index 7bd6e8199..f73f93410 100644
--- a/test/fixtures/kroeg-announce-with-inline-actor.json
+++ b/test/fixtures/kroeg-announce-with-inline-actor.json
@@ -1 +1,88 @@
-{"@context":["https://www.w3.org/ns/activitystreams","https://puckipedia.com/-/context"],"actor":{"endpoints":"https://puckipedia.com/#endpoints","followers":"https://puckipedia.com/followers","following":"https://puckipedia.com/following","icon":{"mediaType":"image/png","type":"Image","url":"https://puckipedia.com/images/avatar.png"},"id":"https://puckipedia.com/","inbox":"https://puckipedia.com/inbox","kroeg:blocks":{"id":"https://puckipedia.com/blocks"},"liked":"https://puckipedia.com/liked","manuallyApprovesFollowers":false,"name":"HACKER TEEN PUCKIPEDIA 👩‍💻","outbox":"https://puckipedia.com/outbox","preferredUsername":"puckipedia","publicKey":{"id":"https://puckipedia.com/#key","owner":"https://puckipedia.com/","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvN05xIcFE0Qgany7Rht4\n0ZI5wu++IT7K5iSqRimBYkpoeHbVcT9RFlW+aWH/QJJW/YgZ7+LMr8AMCrKrwSpS\nCndyrpx4O4lZ3FNRLu7tbklh01rGZfE6R1SFfYBpvMvImc9nYT6iezYDbv6NkHku\no3aVhjql216XlA0OhIrqQme9sAdrLbjbMrTUS8douCTkDOX+JFj1ghHCqdYEMZJI\nOY9kovtgnqyxFLm0RsPGsO1+g/OVojqG+VqHz6O2lceaTVQLlnZ4gOhLVG1tVsA2\nRfXQK+R/VgXncYE+BlQVd/tcdGAz7CDL7PP3rP65gmARnafhGR96cCOi/KzlAXSO\nMwIDAQAB\n-----END PUBLIC KEY-----","type":[]},"summary":"<p>federated hacker teen<br/>\n[<a href=\"https://pronoun.is/she\">she</a>/<a href=\"https://pronoun.is/they\">they</a>]</p>","type":"Person","updated":"2017-12-19T16:56:29.7576707+00:00"},"cc":"http://mastodon.example.org/users/admin","id":"https://puckipedia.com/cc56a9658e","object":{"as:sensitive":false,"attributedTo":{"endpoints":{"sharedInbox":"https://mastodon.social/inbox","type":[]},"followers":"http://mastodon.example.org/users/admin/followers","following":"http://mastodon.example.org/users/admin/following","icon":{"mediaType":"image/png","type":"Image","url":"https://files.mastodon.social/accounts/avatars/000/015/163/original/70ca6c52b01ca913.png"},"id":"http://mastodon.example.org/users/admin","inbox":"http://mastodon.example.org/users/admin/inbox","manuallyApprovesFollowers":{"@value":"False","type":"xsd:boolean"},"name":"","outbox":"http://mastodon.example.org/users/admin/outbox","preferredUsername":"revenant","publicKey":{"id":"http://mastodon.example.org/users/admin#main-key","owner":"http://mastodon.example.org/users/admin","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0gEN3wPW7gkE2gQqnmfB\n1ychjmFIf2LIwY0oCJLiGE/xpZrUKoq+eWH30AP7mATw4LD0gOYABL/ijqPUrPqR\nDXLL+0CqMP8HsZKvRlj9KArMK3YtNiSGGj2U7iReiRrD7nJzjJlsjjJXflLZhZ7/\nenSv1CcaeK8tB0PoAgShy/MyfhPF7WI5/Zm9DmmDQFvUEnDYKXAf/vG/IWw1EyMC\nkbaEYJeIowQU3GsbPxzRGI22bQtfotm431Ch2MbNo+kyzmYVFLAVoSGNMzvJwOPg\nTxLIIBeQXG7MinRyK887yPKhxhcALea4yCcALaa+3jPE7yqwIKYwTHtSlblsHDAo\nmQIDAQAB\n-----END PUBLIC KEY-----\n","type":[]},"summary":"<p>neatly partitioned meats and cheeses appeal to me on an aesthetic level | any pronouns | revenant1.net</p>","type":"Person","url":"https://mastodon.social/@revenant"},"cc":"http://mastodon.example.org/users/admin/followers","content":"<p>the name&apos;s jond (jeans bond)</p>","contentMap":{"en":"<p>the name&apos;s jond (jeans bond)</p>"},"conversation":"tag:mastodon.social,2018-09-25:objectId=55659382:objectType=Conversation","id":"http://mastodon.example.org/users/admin/statuses/100787282858396771","ostatus:atomUri":"http://mastodon.example.org/users/admin/statuses/100787282858396771","published":"2018-09-25T16:11:29Z","to":"https://www.w3.org/ns/activitystreams#Public","type":"Note","url":"https://mastodon.social/@revenant/100787282858396771"},"to":["https://www.w3.org/ns/activitystreams#Public","https://puckipedia.com/followers"],"type":"Announce"}
+{
+ "@context" : [
+ "https://www.w3.org/ns/activitystreams",
+ "https://puckipedia.com/-/context"
+ ],
+ "actor" : {
+ "endpoints" : "https://puckipedia.com/#endpoints",
+ "followers" : "https://puckipedia.com/followers",
+ "following" : "https://puckipedia.com/following",
+ "icon" : {
+ "mediaType" : "image/png",
+ "type" : "Image",
+ "url" : "https://puckipedia.com/images/avatar.png"
+ },
+ "id" : "https://puckipedia.com/",
+ "inbox" : "https://puckipedia.com/inbox",
+ "kroeg:blocks" : {
+ "id" : "https://puckipedia.com/blocks"
+ },
+ "liked" : "https://puckipedia.com/liked",
+ "manuallyApprovesFollowers" : false,
+ "name" : "HACKER TEEN PUCKIPEDIA 👩‍💻",
+ "outbox" : "https://puckipedia.com/outbox",
+ "preferredUsername" : "puckipedia",
+ "publicKey" : {
+ "id" : "https://puckipedia.com/#key",
+ "owner" : "https://puckipedia.com/",
+ "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvN05xIcFE0Qgany7Rht4\n0ZI5wu++IT7K5iSqRimBYkpoeHbVcT9RFlW+aWH/QJJW/YgZ7+LMr8AMCrKrwSpS\nCndyrpx4O4lZ3FNRLu7tbklh01rGZfE6R1SFfYBpvMvImc9nYT6iezYDbv6NkHku\no3aVhjql216XlA0OhIrqQme9sAdrLbjbMrTUS8douCTkDOX+JFj1ghHCqdYEMZJI\nOY9kovtgnqyxFLm0RsPGsO1+g/OVojqG+VqHz6O2lceaTVQLlnZ4gOhLVG1tVsA2\nRfXQK+R/VgXncYE+BlQVd/tcdGAz7CDL7PP3rP65gmARnafhGR96cCOi/KzlAXSO\nMwIDAQAB\n-----END PUBLIC KEY-----",
+ "type" : []
+ },
+ "summary" : "<p>federated hacker teen<br/>\n[<a href=\"https://pronoun.is/she\">she</a>/<a href=\"https://pronoun.is/they\">they</a>]</p>",
+ "type" : "Person",
+ "updated" : "2017-12-19T16:56:29.7576707+00:00"
+ },
+ "cc" : "http://mastodon.example.org/users/admin",
+ "id" : "https://puckipedia.com/cc56a9658e",
+ "object" : {
+ "as:sensitive" : false,
+ "attributedTo" : {
+ "endpoints" : {
+ "sharedInbox" : "https://mastodon.social/inbox",
+ "type" : []
+ },
+ "followers" : "http://mastodon.example.org/users/admin/followers",
+ "following" : "http://mastodon.example.org/users/admin/following",
+ "icon" : {
+ "mediaType" : "image/png",
+ "type" : "Image",
+ "url" : "https://files.mastodon.social/accounts/avatars/000/015/163/original/70ca6c52b01ca913.png"
+ },
+ "id" : "http://mastodon.example.org/users/admin",
+ "inbox" : "http://mastodon.example.org/users/admin/inbox",
+ "manuallyApprovesFollowers" : {
+ "@value" : "False",
+ "type" : "xsd:boolean"
+ },
+ "name" : "",
+ "outbox" : "http://mastodon.example.org/users/admin/outbox",
+ "preferredUsername" : "revenant",
+ "publicKey" : {
+ "id" : "http://mastodon.example.org/users/admin#main-key",
+ "owner" : "http://mastodon.example.org/users/admin",
+ "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0gEN3wPW7gkE2gQqnmfB\n1ychjmFIf2LIwY0oCJLiGE/xpZrUKoq+eWH30AP7mATw4LD0gOYABL/ijqPUrPqR\nDXLL+0CqMP8HsZKvRlj9KArMK3YtNiSGGj2U7iReiRrD7nJzjJlsjjJXflLZhZ7/\nenSv1CcaeK8tB0PoAgShy/MyfhPF7WI5/Zm9DmmDQFvUEnDYKXAf/vG/IWw1EyMC\nkbaEYJeIowQU3GsbPxzRGI22bQtfotm431Ch2MbNo+kyzmYVFLAVoSGNMzvJwOPg\nTxLIIBeQXG7MinRyK887yPKhxhcALea4yCcALaa+3jPE7yqwIKYwTHtSlblsHDAo\nmQIDAQAB\n-----END PUBLIC KEY-----\n",
+ "type" : []
+ },
+ "summary" : "<p>neatly partitioned meats and cheeses appeal to me on an aesthetic level | any pronouns | revenant1.net</p>",
+ "type" : "Person",
+ "url" : "https://mastodon.social/@revenant"
+ },
+ "cc" : "http://mastodon.example.org/users/admin/followers",
+ "content" : "<p>the name&apos;s jond (jeans bond)</p>",
+ "contentMap" : {
+ "en" : "<p>the name&apos;s jond (jeans bond)</p>"
+ },
+ "conversation" : "tag:mastodon.social,2018-09-25:objectId=55659382:objectType=Conversation",
+ "id" : "http://mastodon.example.org/users/admin/statuses/100787282858396771",
+ "ostatus:atomUri" : "http://mastodon.example.org/users/admin/statuses/100787282858396771",
+ "published" : "2018-09-25T16:11:29Z",
+ "to" : "https://www.w3.org/ns/activitystreams#Public",
+ "type" : "Note",
+ "url" : "https://mastodon.social/@revenant/100787282858396771"
+ },
+ "to" : [
+ "https://www.w3.org/ns/activitystreams#Public",
+ "https://puckipedia.com/followers"
+ ],
+ "type" : "Announce"
+}
diff --git a/test/fixtures/mastodon-note-object.json b/test/fixtures/mastodon-note-object.json
index 75bed9625..d28c7fbe9 100644
--- a/test/fixtures/mastodon-note-object.json
+++ b/test/fixtures/mastodon-note-object.json
@@ -1,9 +1,45 @@
-{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","movedTo":"as:movedTo","Hashtag":"as:Hashtag","ostatus":"http://ostatus.org#","atomUri":"ostatus:atomUri","inReplyToAtomUri":"ostatus:inReplyToAtomUri","conversation":"ostatus:conversation","toot":"http://joinmastodon.org/ns#","Emoji":"toot:Emoji"}],"id":"http://mastodon.example.org/users/admin/statuses/99541947525187367","type":"Note","summary":null,"content":"\u003cp\u003eyeah.\u003c/p\u003e","inReplyTo":null,"published":"2018-02-17T17:46:20Z","url":"http://mastodon.example.org/@admin/99541947525187367","attributedTo":"http://mastodon.example.org/users/admin","to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["http://mastodon.example.org/users/admin/followers"],"sensitive":false,"atomUri":"http://mastodon.example.org/users/admin/statuses/99541947525187367","inReplyToAtomUri":null,"conversation":"tag:mastodon.example.org,2018-02-17:objectId=59:objectType=Conversation","tag":[],
- "attachment": [
+{
+ "@context" : [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
{
- "url": "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
- "type": "Document",
- "name": null,
- "mediaType": "image/jpeg"
+ "Emoji" : "toot:Emoji",
+ "Hashtag" : "as:Hashtag",
+ "atomUri" : "ostatus:atomUri",
+ "conversation" : "ostatus:conversation",
+ "inReplyToAtomUri" : "ostatus:inReplyToAtomUri",
+ "manuallyApprovesFollowers" : "as:manuallyApprovesFollowers",
+ "movedTo" : "as:movedTo",
+ "ostatus" : "http://ostatus.org#",
+ "sensitive" : "as:sensitive",
+ "toot" : "http://joinmastodon.org/ns#"
}
- ]}
+ ],
+ "atomUri" : "http://mastodon.example.org/users/admin/statuses/99541947525187367",
+ "attachment" : [
+ {
+ "mediaType" : "image/jpeg",
+ "name" : null,
+ "type" : "Document",
+ "url" : "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg"
+ }
+ ],
+ "attributedTo" : "http://mastodon.example.org/users/admin",
+ "cc" : [
+ "http://mastodon.example.org/users/admin/followers"
+ ],
+ "content" : "<p>yeah.</p>",
+ "conversation" : "tag:mastodon.example.org,2018-02-17:objectId=59:objectType=Conversation",
+ "id" : "http://mastodon.example.org/users/admin/statuses/99541947525187367",
+ "inReplyTo" : null,
+ "inReplyToAtomUri" : null,
+ "published" : "2018-02-17T17:46:20Z",
+ "sensitive" : false,
+ "summary" : null,
+ "tag" : [],
+ "to" : [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "type" : "Note",
+ "url" : "http://mastodon.example.org/@admin/99541947525187367"
+}
diff --git a/test/fixtures/tesla_mock/craigmaloney.json b/test/fixtures/tesla_mock/craigmaloney.json
new file mode 100644
index 000000000..56ea9c7c3
--- /dev/null
+++ b/test/fixtures/tesla_mock/craigmaloney.json
@@ -0,0 +1,112 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "CacheFile": "pt:CacheFile",
+ "Hashtag": "as:Hashtag",
+ "Infohash": "pt:Infohash",
+ "RsaSignature2017": "https://w3id.org/security#RsaSignature2017",
+ "category": "sc:category",
+ "commentsEnabled": {
+ "@id": "pt:commentsEnabled",
+ "@type": "sc:Boolean"
+ },
+ "downloadEnabled": {
+ "@id": "pt:downloadEnabled",
+ "@type": "sc:Boolean"
+ },
+ "expires": "sc:expires",
+ "fps": {
+ "@id": "pt:fps",
+ "@type": "sc:Number"
+ },
+ "language": "sc:inLanguage",
+ "licence": "sc:license",
+ "originallyPublishedAt": "sc:datePublished",
+ "position": {
+ "@id": "pt:position",
+ "@type": "sc:Number"
+ },
+ "pt": "https://joinpeertube.org/ns#",
+ "sc": "http://schema.org#",
+ "sensitive": "as:sensitive",
+ "size": {
+ "@id": "pt:size",
+ "@type": "sc:Number"
+ },
+ "startTimestamp": {
+ "@id": "pt:startTimestamp",
+ "@type": "sc:Number"
+ },
+ "state": {
+ "@id": "pt:state",
+ "@type": "sc:Number"
+ },
+ "stopTimestamp": {
+ "@id": "pt:stopTimestamp",
+ "@type": "sc:Number"
+ },
+ "subtitleLanguage": "sc:subtitleLanguage",
+ "support": {
+ "@id": "pt:support",
+ "@type": "sc:Text"
+ },
+ "uuid": "sc:identifier",
+ "views": {
+ "@id": "pt:views",
+ "@type": "sc:Number"
+ },
+ "waitTranscoding": {
+ "@id": "pt:waitTranscoding",
+ "@type": "sc:Boolean"
+ }
+ },
+ {
+ "comments": {
+ "@id": "as:comments",
+ "@type": "@id"
+ },
+ "dislikes": {
+ "@id": "as:dislikes",
+ "@type": "@id"
+ },
+ "likes": {
+ "@id": "as:likes",
+ "@type": "@id"
+ },
+ "playlists": {
+ "@id": "pt:playlists",
+ "@type": "@id"
+ },
+ "shares": {
+ "@id": "as:shares",
+ "@type": "@id"
+ }
+ }
+ ],
+ "endpoints": {
+ "sharedInbox": "https://peertube.social/inbox"
+ },
+ "followers": "https://peertube.social/accounts/craigmaloney/followers",
+ "following": "https://peertube.social/accounts/craigmaloney/following",
+ "icon": {
+ "mediaType": "image/png",
+ "type": "Image",
+ "url": "https://peertube.social/lazy-static/avatars/87bd694b-95bc-4066-83f4-bddfcd2b9caa.png"
+ },
+ "id": "https://peertube.social/accounts/craigmaloney",
+ "inbox": "https://peertube.social/accounts/craigmaloney/inbox",
+ "name": "Craig Maloney",
+ "outbox": "https://peertube.social/accounts/craigmaloney/outbox",
+ "playlists": "https://peertube.social/accounts/craigmaloney/playlists",
+ "preferredUsername": "craigmaloney",
+ "publicKey": {
+ "id": "https://peertube.social/accounts/craigmaloney#main-key",
+ "owner": "https://peertube.social/accounts/craigmaloney",
+ "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9qvGIYUW01yc8CCsrwxK\n5OXlV5s7EbNWY8tJr/p1oGuELZwAnG2XKxtdbvgcCT+YxL5uRXIdCFIIIKrzRFr/\nHfS0mOgNT9u3gu+SstCNgtatciT0RVP77yiC3b2NHq1NRRvvVhzQb4cpIWObIxqh\nb2ypDClTc7XaKtgmQCbwZlGyZMT+EKz/vustD6BlpGsglRkm7iES6s1PPGb1BU+n\nS94KhbS2DOFiLcXCVWt0QarokIIuKznp4+xP1axKyP+SkT5AHx08Nd5TYFb2C1Jl\nz0WD/1q0mAN62m7QrA3SQPUgB+wWD+S3Nzf7FwNPiP4srbBgxVEUnji/r9mQ6BXC\nrQIDAQAB\n-----END PUBLIC KEY-----"
+ },
+ "summary": null,
+ "type": "Person",
+ "url": "https://peertube.social/accounts/craigmaloney"
+}
diff --git a/test/fixtures/tesla_mock/peertube-social.json b/test/fixtures/tesla_mock/peertube-social.json
new file mode 100644
index 000000000..0e996ba35
--- /dev/null
+++ b/test/fixtures/tesla_mock/peertube-social.json
@@ -0,0 +1,234 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "CacheFile": "pt:CacheFile",
+ "Hashtag": "as:Hashtag",
+ "Infohash": "pt:Infohash",
+ "RsaSignature2017": "https://w3id.org/security#RsaSignature2017",
+ "category": "sc:category",
+ "commentsEnabled": {
+ "@id": "pt:commentsEnabled",
+ "@type": "sc:Boolean"
+ },
+ "downloadEnabled": {
+ "@id": "pt:downloadEnabled",
+ "@type": "sc:Boolean"
+ },
+ "expires": "sc:expires",
+ "fps": {
+ "@id": "pt:fps",
+ "@type": "sc:Number"
+ },
+ "language": "sc:inLanguage",
+ "licence": "sc:license",
+ "originallyPublishedAt": "sc:datePublished",
+ "position": {
+ "@id": "pt:position",
+ "@type": "sc:Number"
+ },
+ "pt": "https://joinpeertube.org/ns#",
+ "sc": "http://schema.org#",
+ "sensitive": "as:sensitive",
+ "size": {
+ "@id": "pt:size",
+ "@type": "sc:Number"
+ },
+ "startTimestamp": {
+ "@id": "pt:startTimestamp",
+ "@type": "sc:Number"
+ },
+ "state": {
+ "@id": "pt:state",
+ "@type": "sc:Number"
+ },
+ "stopTimestamp": {
+ "@id": "pt:stopTimestamp",
+ "@type": "sc:Number"
+ },
+ "subtitleLanguage": "sc:subtitleLanguage",
+ "support": {
+ "@id": "pt:support",
+ "@type": "sc:Text"
+ },
+ "uuid": "sc:identifier",
+ "views": {
+ "@id": "pt:views",
+ "@type": "sc:Number"
+ },
+ "waitTranscoding": {
+ "@id": "pt:waitTranscoding",
+ "@type": "sc:Boolean"
+ }
+ },
+ {
+ "comments": {
+ "@id": "as:comments",
+ "@type": "@id"
+ },
+ "dislikes": {
+ "@id": "as:dislikes",
+ "@type": "@id"
+ },
+ "likes": {
+ "@id": "as:likes",
+ "@type": "@id"
+ },
+ "playlists": {
+ "@id": "pt:playlists",
+ "@type": "@id"
+ },
+ "shares": {
+ "@id": "as:shares",
+ "@type": "@id"
+ }
+ }
+ ],
+ "attributedTo": [
+ {
+ "id": "https://peertube.social/accounts/craigmaloney",
+ "type": "Person"
+ },
+ {
+ "id": "https://peertube.social/video-channels/9909c7d9-6b5b-4aae-9164-c1af7229c91c",
+ "type": "Group"
+ }
+ ],
+ "category": {
+ "identifier": "15",
+ "name": "Science & Technology"
+ },
+ "cc": [
+ "https://peertube.social/accounts/craigmaloney/followers"
+ ],
+ "comments": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe/comments",
+ "commentsEnabled": true,
+ "content": "Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership\n\nTwenty Years in Jail: FreeBSD's Jails, Then and Now\n\nJails started as a limited virtualization system, but over the last two years they've...",
+ "dislikes": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe/dislikes",
+ "downloadEnabled": true,
+ "duration": "PT5151S",
+ "icon": {
+ "height": 122,
+ "mediaType": "image/jpeg",
+ "type": "Image",
+ "url": "https://peertube.social/static/thumbnails/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe.jpg",
+ "width": 223
+ },
+ "id": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe",
+ "language": {
+ "identifier": "en",
+ "name": "English"
+ },
+ "licence": {
+ "identifier": "1",
+ "name": "Attribution"
+ },
+ "likes": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe/likes",
+ "mediaType": "text/markdown",
+ "name": "Twenty Years in Jail: FreeBSD's Jails, Then and Now",
+ "originallyPublishedAt": "2019-08-13T00:00:00.000Z",
+ "published": "2020-02-12T01:06:08.054Z",
+ "sensitive": false,
+ "shares": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe/announces",
+ "state": 1,
+ "subtitleLanguage": [],
+ "support": "Learn more at http://mug.org",
+ "tag": [
+ {
+ "name": "linux",
+ "type": "Hashtag"
+ },
+ {
+ "name": "mug.org",
+ "type": "Hashtag"
+ },
+ {
+ "name": "open",
+ "type": "Hashtag"
+ },
+ {
+ "name": "oss",
+ "type": "Hashtag"
+ },
+ {
+ "name": "source",
+ "type": "Hashtag"
+ }
+ ],
+ "to": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "type": "Video",
+ "updated": "2020-02-15T15:01:09.474Z",
+ "url": [
+ {
+ "href": "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe",
+ "mediaType": "text/html",
+ "type": "Link"
+ },
+ {
+ "fps": 30,
+ "height": 240,
+ "href": "https://peertube.social/static/webseed/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-240.mp4",
+ "mediaType": "video/mp4",
+ "size": 119465800,
+ "type": "Link"
+ },
+ {
+ "height": 240,
+ "href": "https://peertube.social/static/torrents/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-240.torrent",
+ "mediaType": "application/x-bittorrent",
+ "type": "Link"
+ },
+ {
+ "height": 240,
+ "href": "magnet:?xs=https%3A%2F%2Fpeertube.social%2Fstatic%2Ftorrents%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-240.torrent&xt=urn:btih:b3365331a8543bf48d09add56d7fe4b1cbbb5659&dn=Twenty+Years+in+Jail%3A+FreeBSD's+Jails%2C+Then+and+Now&tr=wss%3A%2F%2Fpeertube.social%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube.social%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fwebseed%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-240.mp4",
+ "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
+ "type": "Link"
+ },
+ {
+ "fps": 30,
+ "height": 360,
+ "href": "https://peertube.social/static/webseed/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-360.mp4",
+ "mediaType": "video/mp4",
+ "size": 143930318,
+ "type": "Link"
+ },
+ {
+ "height": 360,
+ "href": "https://peertube.social/static/torrents/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-360.torrent",
+ "mediaType": "application/x-bittorrent",
+ "type": "Link"
+ },
+ {
+ "height": 360,
+ "href": "magnet:?xs=https%3A%2F%2Fpeertube.social%2Fstatic%2Ftorrents%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-360.torrent&xt=urn:btih:0d37b23c98cb0d89e28b5dc8f49b3c97a041e569&dn=Twenty+Years+in+Jail%3A+FreeBSD's+Jails%2C+Then+and+Now&tr=wss%3A%2F%2Fpeertube.social%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube.social%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fwebseed%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-360.mp4",
+ "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
+ "type": "Link"
+ },
+ {
+ "fps": 30,
+ "height": 480,
+ "href": "https://peertube.social/static/webseed/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-480.mp4",
+ "mediaType": "video/mp4",
+ "size": 130530754,
+ "type": "Link"
+ },
+ {
+ "height": 480,
+ "href": "https://peertube.social/static/torrents/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-480.torrent",
+ "mediaType": "application/x-bittorrent",
+ "type": "Link"
+ },
+ {
+ "height": 480,
+ "href": "magnet:?xs=https%3A%2F%2Fpeertube.social%2Fstatic%2Ftorrents%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-480.torrent&xt=urn:btih:3a13ff822ad9494165eff6167183ddaaabc1372a&dn=Twenty+Years+in+Jail%3A+FreeBSD's+Jails%2C+Then+and+Now&tr=wss%3A%2F%2Fpeertube.social%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube.social%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fwebseed%2F278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe-480.mp4",
+ "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
+ "type": "Link"
+ }
+ ],
+ "uuid": "278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe",
+ "views": 2,
+ "waitTranscoding": false
+}
diff --git a/test/html_test.exs b/test/html_test.exs
index a006fd492..0a4b4ebbc 100644
--- a/test/html_test.exs
+++ b/test/html_test.exs
@@ -171,7 +171,7 @@ defmodule Pleroma.HTMLTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"I think I just found the best github repo https://github.com/komeiji-satori/Dress"
})
@@ -186,7 +186,7 @@ defmodule Pleroma.HTMLTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"@#{other_user.nickname} install misskey! https://github.com/syuilo/misskey/blob/develop/docs/setup.en.md"
})
@@ -203,8 +203,7 @@ defmodule Pleroma.HTMLTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
- "#cofe https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
+ status: "#cofe https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
})
object = Object.normalize(activity)
@@ -218,9 +217,9 @@ defmodule Pleroma.HTMLTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"<a href=\"https://pleroma.gov/tags/cofe\" rel=\"tag\">#cofe</a> https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140",
- "content_type" => "text/html"
+ content_type: "text/html"
})
object = Object.normalize(activity)
@@ -232,8 +231,7 @@ defmodule Pleroma.HTMLTest do
test "does not crash when there is an HTML entity in a link" do
user = insert(:user)
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "\"http://cofe.com/?boomer=ok&foo=bar\""})
+ {:ok, activity} = CommonAPI.post(user, %{status: "\"http://cofe.com/?boomer=ok&foo=bar\""})
object = Object.normalize(activity)
diff --git a/test/http/adapter_helper/hackney_test.exs b/test/http/adapter_helper/hackney_test.exs
index 3f7e708e0..f2361ff0b 100644
--- a/test/http/adapter_helper/hackney_test.exs
+++ b/test/http/adapter_helper/hackney_test.exs
@@ -31,17 +31,5 @@ defmodule Pleroma.HTTP.AdapterHelper.HackneyTest do
assert opts[:b] == 1
refute Keyword.has_key?(opts, :proxy)
end
-
- test "add opts for https" do
- uri = URI.parse("https://domain.com")
-
- opts = Hackney.options(uri)
-
- assert opts[:ssl_options] == [
- partial_chain: &:hackney_connect.partial_chain/1,
- versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"],
- server_name_indication: 'domain.com'
- ]
- end
end
end
diff --git a/test/http/connection_test.exs b/test/http/connection_test.exs
index 5cc78ad5b..7c94a50b2 100644
--- a/test/http/connection_test.exs
+++ b/test/http/connection_test.exs
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.HTTP.ConnectionTest do
- use ExUnit.Case, async: true
+ use ExUnit.Case
use Pleroma.Tests.Helpers
import ExUnit.CaptureLog
diff --git a/test/http/request_builder_test.exs b/test/http/request_builder_test.exs
index f11528c3f..fab909905 100644
--- a/test/http/request_builder_test.exs
+++ b/test/http/request_builder_test.exs
@@ -3,23 +3,19 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.HTTP.RequestBuilderTest do
- use ExUnit.Case, async: true
+ use ExUnit.Case
use Pleroma.Tests.Helpers
- alias Pleroma.Config
alias Pleroma.HTTP.Request
alias Pleroma.HTTP.RequestBuilder
describe "headers/2" do
- setup do: clear_config([:http, :send_user_agent])
- setup do: clear_config([:http, :user_agent])
-
test "don't send pleroma user agent" do
assert RequestBuilder.headers(%Request{}, []) == %Request{headers: []}
end
test "send pleroma user agent" do
- Config.put([:http, :send_user_agent], true)
- Config.put([:http, :user_agent], :default)
+ clear_config([:http, :send_user_agent], true)
+ clear_config([:http, :user_agent], :default)
assert RequestBuilder.headers(%Request{}, []) == %Request{
headers: [{"user-agent", Pleroma.Application.user_agent()}]
@@ -27,8 +23,8 @@ defmodule Pleroma.HTTP.RequestBuilderTest do
end
test "send custom user agent" do
- Config.put([:http, :send_user_agent], true)
- Config.put([:http, :user_agent], "totally-not-pleroma")
+ clear_config([:http, :send_user_agent], true)
+ clear_config([:http, :user_agent], "totally-not-pleroma")
assert RequestBuilder.headers(%Request{}, []) == %Request{
headers: [{"user-agent", "totally-not-pleroma"}]
diff --git a/test/instance_static/add/shortcode.png b/test/instance_static/add/shortcode.png
new file mode 100644
index 000000000..8f50fa023
--- /dev/null
+++ b/test/instance_static/add/shortcode.png
Binary files differ
diff --git a/test/instance_static/emoji/pack_bad_sha/blank.png b/test/instance_static/emoji/pack_bad_sha/blank.png
new file mode 100644
index 000000000..8f50fa023
--- /dev/null
+++ b/test/instance_static/emoji/pack_bad_sha/blank.png
Binary files differ
diff --git a/test/instance_static/emoji/pack_bad_sha/pack.json b/test/instance_static/emoji/pack_bad_sha/pack.json
new file mode 100644
index 000000000..35caf4298
--- /dev/null
+++ b/test/instance_static/emoji/pack_bad_sha/pack.json
@@ -0,0 +1,13 @@
+{
+ "pack": {
+ "license": "Test license",
+ "homepage": "https://pleroma.social",
+ "description": "Test description",
+ "can-download": true,
+ "share-files": true,
+ "download-sha256": "57482F30674FD3DE821FF48C81C00DA4D4AF1F300209253684ABA7075E5FC238"
+ },
+ "files": {
+ "blank": "blank.png"
+ }
+} \ No newline at end of file
diff --git a/test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip b/test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip
new file mode 100644
index 000000000..148446c64
--- /dev/null
+++ b/test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip
Binary files differ
diff --git a/test/instance_static/emoji/test_pack/pack.json b/test/instance_static/emoji/test_pack/pack.json
index 5a8ee75f9..481891b08 100644
--- a/test/instance_static/emoji/test_pack/pack.json
+++ b/test/instance_static/emoji/test_pack/pack.json
@@ -1,13 +1,11 @@
{
+ "files": {
+ "blank": "blank.png"
+ },
"pack": {
- "license": "Test license",
- "homepage": "https://pleroma.social",
"description": "Test description",
-
+ "homepage": "https://pleroma.social",
+ "license": "Test license",
"share-files": true
- },
-
- "files": {
- "blank": "blank.png"
}
-}
+} \ No newline at end of file
diff --git a/test/instance_static/emoji/test_pack_nonshared/pack.json b/test/instance_static/emoji/test_pack_nonshared/pack.json
index b96781f81..93d643a5f 100644
--- a/test/instance_static/emoji/test_pack_nonshared/pack.json
+++ b/test/instance_static/emoji/test_pack_nonshared/pack.json
@@ -3,14 +3,11 @@
"license": "Test license",
"homepage": "https://pleroma.social",
"description": "Test description",
-
"fallback-src": "https://nonshared-pack",
"fallback-src-sha256": "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF",
-
"share-files": false
},
-
"files": {
"blank": "blank.png"
}
-}
+} \ No newline at end of file
diff --git a/test/instance_static/local_pack/files.json b/test/instance_static/local_pack/files.json
new file mode 100644
index 000000000..279770998
--- /dev/null
+++ b/test/instance_static/local_pack/files.json
@@ -0,0 +1,3 @@
+{
+ "blank": "blank.png"
+} \ No newline at end of file
diff --git a/test/instance_static/local_pack/manifest.json b/test/instance_static/local_pack/manifest.json
new file mode 100644
index 000000000..01067042f
--- /dev/null
+++ b/test/instance_static/local_pack/manifest.json
@@ -0,0 +1,10 @@
+{
+ "local": {
+ "src_sha256": "384025A1AC6314473863A11AC7AB38A12C01B851A3F82359B89B4D4211D3291D",
+ "src": "test/fixtures/emoji/packs/blank.png.zip",
+ "license": "Apache 2.0",
+ "homepage": "https://example.com",
+ "files": "files.json",
+ "description": "Some local pack"
+ }
+} \ No newline at end of file
diff --git a/test/integration/mastodon_websocket_test.exs b/test/integration/mastodon_websocket_test.exs
index bd229c55f..ea17e9feb 100644
--- a/test/integration/mastodon_websocket_test.exs
+++ b/test/integration/mastodon_websocket_test.exs
@@ -12,17 +12,14 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.OAuth
+ @moduletag needs_streamer: true, capture_log: true
+
@path Pleroma.Web.Endpoint.url()
|> URI.parse()
|> Map.put(:scheme, "ws")
|> Map.put(:path, "/api/v1/streaming")
|> URI.to_string()
- setup_all do
- start_supervised(Pleroma.Web.Streamer.supervisor())
- :ok
- end
-
def start_socket(qs \\ nil, headers \\ []) do
path =
case qs do
@@ -35,7 +32,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
test "refuses invalid requests" do
capture_log(fn ->
- assert {:error, {400, _}} = start_socket()
+ assert {:error, {404, _}} = start_socket()
assert {:error, {404, _}} = start_socket("?stream=ncjdk")
Process.sleep(30)
end)
@@ -43,8 +40,8 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
test "requires authentication and a valid token for protected streams" do
capture_log(fn ->
- assert {:error, {403, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
- assert {:error, {403, _}} = start_socket("?stream=user")
+ assert {:error, {401, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
+ assert {:error, {401, _}} = start_socket("?stream=user")
Process.sleep(30)
end)
end
@@ -58,7 +55,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
test "receives well formatted events" do
user = insert(:user)
{:ok, _} = start_socket("?stream=public")
- {:ok, activity} = CommonAPI.post(user, %{"status" => "nice echo chamber"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "nice echo chamber"})
assert_receive {:text, raw_json}, 1_000
assert {:ok, json} = Jason.decode(raw_json)
@@ -103,7 +100,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
assert capture_log(fn ->
- assert {:error, {403, "Forbidden"}} = start_socket("?stream=user")
+ assert {:error, {401, _}} = start_socket("?stream=user")
Process.sleep(30)
end) =~ ":badarg"
end
@@ -112,7 +109,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
assert capture_log(fn ->
- assert {:error, {403, "Forbidden"}} = start_socket("?stream=user:notification")
+ assert {:error, {401, _}} = start_socket("?stream=user:notification")
Process.sleep(30)
end) =~ ":badarg"
end
@@ -121,7 +118,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
assert capture_log(fn ->
- assert {:error, {403, "Forbidden"}} =
+ assert {:error, {401, _}} =
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
Process.sleep(30)
diff --git a/test/marker_test.exs b/test/marker_test.exs
index c80ae16b6..5b6d0b4a4 100644
--- a/test/marker_test.exs
+++ b/test/marker_test.exs
@@ -8,12 +8,39 @@ defmodule Pleroma.MarkerTest do
import Pleroma.Factory
+ describe "multi_set_unread_count/3" do
+ test "returns multi" do
+ user = insert(:user)
+
+ assert %Ecto.Multi{
+ operations: [marker: {:run, _}, counters: {:run, _}]
+ } =
+ Marker.multi_set_last_read_id(
+ Ecto.Multi.new(),
+ user,
+ "notifications"
+ )
+ end
+
+ test "return empty multi" do
+ user = insert(:user)
+ multi = Ecto.Multi.new()
+ assert Marker.multi_set_last_read_id(multi, user, "home") == multi
+ end
+ end
+
describe "get_markers/2" do
test "returns user markers" do
user = insert(:user)
marker = insert(:marker, user: user)
+ insert(:notification, user: user)
+ insert(:notification, user: user)
insert(:marker, timeline: "home", user: user)
- assert Marker.get_markers(user, ["notifications"]) == [refresh_record(marker)]
+
+ assert Marker.get_markers(
+ user,
+ ["notifications"]
+ ) == [%Marker{refresh_record(marker) | unread_count: 2}]
end
end
diff --git a/test/mfa/backup_codes_test.exs b/test/mfa/backup_codes_test.exs
new file mode 100644
index 000000000..7bc01b36b
--- /dev/null
+++ b/test/mfa/backup_codes_test.exs
@@ -0,0 +1,11 @@
+defmodule Pleroma.MFA.BackupCodesTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.MFA.BackupCodes
+
+ test "generate backup codes" do
+ codes = BackupCodes.generate(number_of_codes: 2, length: 4)
+
+ assert [<<_::bytes-size(4)>>, <<_::bytes-size(4)>>] = codes
+ end
+end
diff --git a/test/mfa/totp_test.exs b/test/mfa/totp_test.exs
new file mode 100644
index 000000000..50153d208
--- /dev/null
+++ b/test/mfa/totp_test.exs
@@ -0,0 +1,17 @@
+defmodule Pleroma.MFA.TOTPTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.MFA.TOTP
+
+ test "create provisioning_uri to generate qrcode" do
+ uri =
+ TOTP.provisioning_uri("test-secrcet", "test@example.com",
+ issuer: "Plerome-42",
+ digits: 8,
+ period: 60
+ )
+
+ assert uri ==
+ "otpauth://totp/test@example.com?digits=8&issuer=Plerome-42&period=60&secret=test-secrcet"
+ end
+end
diff --git a/test/mfa_test.exs b/test/mfa_test.exs
new file mode 100644
index 000000000..8875cefd9
--- /dev/null
+++ b/test/mfa_test.exs
@@ -0,0 +1,52 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.MFATest do
+ use Pleroma.DataCase
+
+ import Pleroma.Factory
+ alias Pleroma.MFA
+
+ describe "mfa_settings" do
+ test "returns settings user's" do
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: "xx", confirmed: true}
+ }
+ )
+
+ settings = MFA.mfa_settings(user)
+ assert match?(^settings, %{enabled: true, totp: true})
+ end
+ end
+
+ describe "generate backup codes" do
+ test "returns backup codes" do
+ user = insert(:user)
+
+ {:ok, [code1, code2]} = MFA.generate_backup_codes(user)
+ updated_user = refresh_record(user)
+ [hash1, hash2] = updated_user.multi_factor_authentication_settings.backup_codes
+ assert Pbkdf2.verify_pass(code1, hash1)
+ assert Pbkdf2.verify_pass(code2, hash2)
+ end
+ end
+
+ describe "invalidate_backup_code" do
+ test "invalid used code" do
+ user = insert(:user)
+
+ {:ok, _} = MFA.generate_backup_codes(user)
+ user = refresh_record(user)
+ assert length(user.multi_factor_authentication_settings.backup_codes) == 2
+ [hash_code | _] = user.multi_factor_authentication_settings.backup_codes
+
+ {:ok, user} = MFA.invalidate_backup_code(user, hash_code)
+
+ assert length(user.multi_factor_authentication_settings.backup_codes) == 1
+ end
+ end
+end
diff --git a/test/migration_helper/notification_backfill_test.exs b/test/migration_helper/notification_backfill_test.exs
new file mode 100644
index 000000000..2a62a2b00
--- /dev/null
+++ b/test/migration_helper/notification_backfill_test.exs
@@ -0,0 +1,56 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.MigrationHelper.NotificationBackfillTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.MigrationHelper.NotificationBackfill
+ alias Pleroma.Notification
+ alias Pleroma.Repo
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "fill_in_notification_types" do
+ test "it fills in missing notification types" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "yeah, @#{other_user.nickname}"})
+ {:ok, chat} = CommonAPI.post_chat_message(user, other_user, "yo")
+ {:ok, react} = CommonAPI.react_with_emoji(post.id, other_user, "☕")
+ {:ok, like} = CommonAPI.favorite(other_user, post.id)
+ {:ok, react_2} = CommonAPI.react_with_emoji(post.id, other_user, "☕")
+
+ data =
+ react_2.data
+ |> Map.put("type", "EmojiReaction")
+
+ {:ok, react_2} =
+ react_2
+ |> Activity.change(%{data: data})
+ |> Repo.update()
+
+ assert {5, nil} = Repo.update_all(Notification, set: [type: nil])
+
+ NotificationBackfill.fill_in_notification_types()
+
+ assert %{type: "mention"} =
+ Repo.get_by(Notification, user_id: other_user.id, activity_id: post.id)
+
+ assert %{type: "favourite"} =
+ Repo.get_by(Notification, user_id: user.id, activity_id: like.id)
+
+ assert %{type: "pleroma:emoji_reaction"} =
+ Repo.get_by(Notification, user_id: user.id, activity_id: react.id)
+
+ assert %{type: "pleroma:emoji_reaction"} =
+ Repo.get_by(Notification, user_id: user.id, activity_id: react_2.id)
+
+ assert %{type: "pleroma:chat_mention"} =
+ Repo.get_by(Notification, user_id: other_user.id, activity_id: chat.id)
+ end
+ end
+end
diff --git a/test/notification_test.exs b/test/notification_test.exs
index 837a9dacd..526f43fab 100644
--- a/test/notification_test.exs
+++ b/test/notification_test.exs
@@ -8,11 +8,16 @@ defmodule Pleroma.NotificationTest do
import Pleroma.Factory
import Mock
+ alias Pleroma.FollowingRelationship
alias Pleroma.Notification
+ alias Pleroma.Repo
alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.MastodonAPI.NotificationView
alias Pleroma.Web.Push
alias Pleroma.Web.Streamer
@@ -21,12 +26,13 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "yeah"})
- {:ok, activity, _object} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
+ {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
+ {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
{:ok, [notification]} = Notification.create_notifications(activity)
assert notification.user_id == user.id
+ assert notification.type == "pleroma:emoji_reaction"
end
test "notifies someone when they are directly addressed" do
@@ -36,7 +42,7 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "hey @#{other_user.nickname} and @#{third_user.nickname}"
+ status: "hey @#{other_user.nickname} and @#{third_user.nickname}"
})
{:ok, [notification, other_notification]} = Notification.create_notifications(activity)
@@ -44,7 +50,11 @@ defmodule Pleroma.NotificationTest do
notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
assert notified_ids == [other_user.id, third_user.id]
assert notification.activity_id == activity.id
+ assert notification.type == "mention"
assert other_notification.activity_id == activity.id
+
+ assert [%Pleroma.Marker{unread_count: 2}] =
+ Pleroma.Marker.get_markers(other_user, ["notifications"])
end
test "it creates a notification for subscribed users" do
@@ -53,7 +63,7 @@ defmodule Pleroma.NotificationTest do
User.subscribe(subscriber, user)
- {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
+ {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
{:ok, [notification]} = Notification.create_notifications(status)
assert notification.user_id == subscriber.id
@@ -66,12 +76,12 @@ defmodule Pleroma.NotificationTest do
User.subscribe(subscriber, other_user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
{:ok, _reply_activity} =
CommonAPI.post(other_user, %{
- "status" => "test reply",
- "in_reply_to_status_id" => activity.id
+ status: "test reply",
+ in_reply_to_status_id: activity.id
})
user_notifications = Notification.for_user(user)
@@ -91,7 +101,7 @@ defmodule Pleroma.NotificationTest do
blocker = insert(:user)
{:ok, _user_relationship} = User.block(blocker, user)
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{blocker.nickname}!"})
+ {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{blocker.nickname}!"})
blocker_id = blocker.id
assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
@@ -106,7 +116,7 @@ defmodule Pleroma.NotificationTest do
muter = insert(:user)
{:ok, _user_relationships} = User.mute(muter, user)
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{muter.nickname}!"})
+ {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{muter.nickname}!"})
muter_id = muter.id
assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
@@ -120,14 +130,14 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
thread_muter = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{thread_muter.nickname}!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{thread_muter.nickname}!"})
{:ok, _} = CommonAPI.add_mute(thread_muter, activity)
{:ok, _same_context_activity} =
CommonAPI.post(user, %{
- "status" => "hey-hey-hey @#{thread_muter.nickname}!",
- "in_reply_to_status_id" => activity.id
+ status: "hey-hey-hey @#{thread_muter.nickname}!",
+ in_reply_to_status_id: activity.id
})
[pre_mute_notification, post_mute_notification] =
@@ -160,14 +170,18 @@ defmodule Pleroma.NotificationTest do
@tag needs_streamer: true
test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
user = insert(:user)
- task = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
- task_user_notification = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
- Streamer.add_socket("user", %{transport_pid: task.pid, assigns: %{user: user}})
- Streamer.add_socket(
- "user:notification",
- %{transport_pid: task_user_notification.pid, assigns: %{user: user}}
- )
+ task =
+ Task.async(fn ->
+ Streamer.get_topic_and_add_socket("user", user)
+ assert_receive {:render_with_user, _, _, _}, 4_000
+ end)
+
+ task_user_notification =
+ Task.async(fn ->
+ Streamer.get_topic_and_add_socket("user:notification", user)
+ assert_receive {:render_with_user, _, _, _}, 4_000
+ end)
activity = insert(:note_activity)
@@ -191,7 +205,7 @@ defmodule Pleroma.NotificationTest do
muted = insert(:user)
{:ok, _} = User.mute(muter, muted)
muter = Repo.get(User, muter.id)
- {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
+ {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
assert Notification.create_notification(activity, muter)
end
@@ -202,7 +216,7 @@ defmodule Pleroma.NotificationTest do
{:ok, _user_relationships} = User.mute(muter, muted, false)
- {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
+ {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
assert Notification.create_notification(activity, muter)
end
@@ -210,13 +224,13 @@ defmodule Pleroma.NotificationTest do
test "it creates a notification for an activity from a muted thread" do
muter = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(muter, %{"status" => "hey"})
+ {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
CommonAPI.add_mute(muter, activity)
{:ok, activity} =
CommonAPI.post(other_user, %{
- "status" => "Hi @#{muter.nickname}",
- "in_reply_to_status_id" => activity.id
+ status: "Hi @#{muter.nickname}",
+ in_reply_to_status_id: activity.id
})
assert Notification.create_notification(activity, muter)
@@ -229,7 +243,7 @@ defmodule Pleroma.NotificationTest do
insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
User.follow(follower, followed)
- {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
+ {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
refute Notification.create_notification(activity, followed)
end
@@ -241,7 +255,7 @@ defmodule Pleroma.NotificationTest do
notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
)
- {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
+ {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
refute Notification.create_notification(activity, followed)
end
@@ -252,7 +266,7 @@ defmodule Pleroma.NotificationTest do
followed = insert(:user)
User.follow(follower, followed)
follower = Repo.get(User, follower.id)
- {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
+ {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
refute Notification.create_notification(activity, follower)
end
@@ -261,7 +275,7 @@ defmodule Pleroma.NotificationTest do
insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
followed = insert(:user)
- {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
+ {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
refute Notification.create_notification(activity, follower)
end
@@ -272,23 +286,13 @@ defmodule Pleroma.NotificationTest do
refute Notification.create_notification(activity, author)
end
- test "it doesn't create a notification for follow-unfollow-follow chains" do
- user = insert(:user)
- followed_user = insert(:user)
- {:ok, _, _, activity} = CommonAPI.follow(user, followed_user)
- Notification.create_notification(activity, followed_user)
- CommonAPI.unfollow(user, followed_user)
- {:ok, _, _, activity_dupe} = CommonAPI.follow(user, followed_user)
- refute Notification.create_notification(activity_dupe, followed_user)
- end
-
test "it doesn't create duplicate notifications for follow+subscribed users" do
user = insert(:user)
subscriber = insert(:user)
{:ok, _, _, _} = CommonAPI.follow(subscriber, user)
User.subscribe(subscriber, user)
- {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
+ {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
{:ok, [_notif]} = Notification.create_notifications(status)
end
@@ -298,10 +302,81 @@ defmodule Pleroma.NotificationTest do
User.subscribe(subscriber, user)
- {:ok, status} = CommonAPI.post(user, %{"status" => "inwisible", "visibility" => "direct"})
+ {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
assert {:ok, []} == Notification.create_notifications(status)
end
+
+ test "it disables notifications from people who are invisible" do
+ author = insert(:user, invisible: true)
+ user = insert(:user)
+
+ {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
+ refute Notification.create_notification(status, user)
+ end
+ end
+
+ describe "follow / follow_request notifications" do
+ test "it creates `follow` notification for approved Follow activity" do
+ user = insert(:user)
+ followed_user = insert(:user, locked: false)
+
+ {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
+ assert FollowingRelationship.following?(user, followed_user)
+ assert [notification] = Notification.for_user(followed_user)
+
+ assert %{type: "follow"} =
+ NotificationView.render("show.json", %{
+ notification: notification,
+ for: followed_user
+ })
+ end
+
+ test "it creates `follow_request` notification for pending Follow activity" do
+ user = insert(:user)
+ followed_user = insert(:user, locked: true)
+
+ {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
+ refute FollowingRelationship.following?(user, followed_user)
+ assert [notification] = Notification.for_user(followed_user)
+
+ render_opts = %{notification: notification, for: followed_user}
+ assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
+
+ # After request is accepted, the same notification is rendered with type "follow":
+ assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
+
+ notification =
+ Repo.get(Notification, notification.id)
+ |> Repo.preload(:activity)
+
+ assert %{type: "follow"} =
+ NotificationView.render("show.json", notification: notification, for: followed_user)
+ end
+
+ test "it doesn't create a notification for follow-unfollow-follow chains" do
+ user = insert(:user)
+ followed_user = insert(:user, locked: false)
+
+ {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
+ assert FollowingRelationship.following?(user, followed_user)
+ assert [notification] = Notification.for_user(followed_user)
+
+ CommonAPI.unfollow(user, followed_user)
+ {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
+
+ notification_id = notification.id
+ assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
+ end
+
+ test "dismisses the notification on follow request rejection" do
+ user = insert(:user, locked: true)
+ follower = insert(:user)
+ {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
+ assert [notification] = Notification.for_user(user)
+ {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
+ assert [] = Notification.for_user(user)
+ end
end
describe "get notification" do
@@ -309,7 +384,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
{:ok, [notification]} = Notification.create_notifications(activity)
{:ok, notification} = Notification.get(other_user, notification.id)
@@ -321,7 +396,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
{:ok, [notification]} = Notification.create_notifications(activity)
{:error, _notification} = Notification.get(user, notification.id)
@@ -333,7 +408,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
{:ok, [notification]} = Notification.create_notifications(activity)
{:ok, notification} = Notification.dismiss(other_user, notification.id)
@@ -345,7 +420,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
{:ok, [notification]} = Notification.create_notifications(activity)
{:error, _notification} = Notification.dismiss(user, notification.id)
@@ -360,14 +435,14 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "hey @#{other_user.nickname} and @#{third_user.nickname} !"
+ status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
})
{:ok, _notifs} = Notification.create_notifications(activity)
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
+ status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
})
{:ok, _notifs} = Notification.create_notifications(activity)
@@ -385,31 +460,42 @@ defmodule Pleroma.NotificationTest do
{:ok, _activity} =
CommonAPI.post(user, %{
- "status" => "hey @#{other_user.nickname}!"
+ status: "hey @#{other_user.nickname}!"
})
{:ok, _activity} =
CommonAPI.post(user, %{
- "status" => "hey again @#{other_user.nickname}!"
+ status: "hey again @#{other_user.nickname}!"
})
- [n2, n1] = notifs = Notification.for_user(other_user)
- assert length(notifs) == 2
+ [n2, n1] = Notification.for_user(other_user)
assert n2.id > n1.id
{:ok, _activity} =
CommonAPI.post(user, %{
- "status" => "hey yet again @#{other_user.nickname}!"
+ status: "hey yet again @#{other_user.nickname}!"
})
- Notification.set_read_up_to(other_user, n2.id)
+ [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
+
+ assert read_notification.activity.object
[n3, n2, n1] = Notification.for_user(other_user)
assert n1.seen == true
assert n2.seen == true
assert n3.seen == false
+
+ assert %Pleroma.Marker{} =
+ m =
+ Pleroma.Repo.get_by(
+ Pleroma.Marker,
+ user_id: other_user.id,
+ timeline: "notifications"
+ )
+
+ assert m.last_read_id == to_string(n2.id)
end
end
@@ -429,7 +515,7 @@ defmodule Pleroma.NotificationTest do
Enum.each(0..10, fn i ->
{:ok, _activity} =
CommonAPI.post(user1, %{
- "status" => "hey ##{i} @#{user2.nickname}!"
+ status: "hey ##{i} @#{user2.nickname}!"
})
end)
@@ -465,7 +551,7 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "hey @#{other_user.nickname}!"
+ status: "hey @#{other_user.nickname}!"
})
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
@@ -534,7 +620,7 @@ defmodule Pleroma.NotificationTest do
{:ok, activity_one} =
CommonAPI.post(user, %{
- "status" => "hey @#{other_user.nickname}!"
+ status: "hey @#{other_user.nickname}!"
})
{:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
@@ -545,6 +631,28 @@ defmodule Pleroma.NotificationTest do
assert other_user not in enabled_receivers
end
+ test "it only notifies the post's author in likes" do
+ user = insert(:user)
+ other_user = insert(:user)
+ third_user = insert(:user)
+
+ {:ok, activity_one} =
+ CommonAPI.post(user, %{
+ status: "hey @#{other_user.nickname}!"
+ })
+
+ {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
+
+ {:ok, like, _} =
+ like_data
+ |> Map.put("to", [other_user.ap_id | like_data["to"]])
+ |> ActivityPub.persist(local: true)
+
+ {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
+
+ assert other_user not in enabled_receivers
+ end
+
test "it does not send notification to mentioned users in announces" do
user = insert(:user)
other_user = insert(:user)
@@ -552,10 +660,10 @@ defmodule Pleroma.NotificationTest do
{:ok, activity_one} =
CommonAPI.post(user, %{
- "status" => "hey @#{other_user.nickname}!"
+ status: "hey @#{other_user.nickname}!"
})
- {:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
+ {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
{enabled_receivers, _disabled_receivers} =
Notification.get_notified_from_activity(activity_two)
@@ -568,7 +676,7 @@ defmodule Pleroma.NotificationTest do
other_user = insert(:user)
{:ok, _user_relationship} = User.block(other_user, user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
@@ -581,7 +689,7 @@ defmodule Pleroma.NotificationTest do
other_user = insert(:user)
{:ok, _user_relationships} = User.mute(other_user, user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
@@ -593,14 +701,14 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
{:ok, _} = CommonAPI.add_mute(other_user, activity)
{:ok, same_context_activity} =
CommonAPI.post(user, %{
- "status" => "hey-hey-hey @#{other_user.nickname}!",
- "in_reply_to_status_id" => activity.id
+ status: "hey-hey-hey @#{other_user.nickname}!",
+ in_reply_to_status_id: activity.id
})
{enabled_receivers, disabled_receivers} =
@@ -609,6 +717,37 @@ defmodule Pleroma.NotificationTest do
assert [other_user] == disabled_receivers
refute other_user in enabled_receivers
end
+
+ test "it returns non-following domain-blocking recipient in disabled recipients list" do
+ blocked_domain = "blocked.domain"
+ user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
+ other_user = insert(:user)
+
+ {:ok, other_user} = User.block_domain(other_user, blocked_domain)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
+
+ {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
+
+ assert [] == enabled_receivers
+ assert [other_user] == disabled_receivers
+ end
+
+ test "it returns following domain-blocking recipient in enabled recipients list" do
+ blocked_domain = "blocked.domain"
+ user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
+ other_user = insert(:user)
+
+ {:ok, other_user} = User.block_domain(other_user, blocked_domain)
+ {:ok, other_user} = User.follow(other_user, user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
+
+ {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
+
+ assert [other_user] == enabled_receivers
+ assert [] == disabled_receivers
+ end
end
describe "notification lifecycle" do
@@ -616,7 +755,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
assert Enum.empty?(Notification.for_user(user))
@@ -633,7 +772,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
assert Enum.empty?(Notification.for_user(user))
@@ -641,7 +780,7 @@ defmodule Pleroma.NotificationTest do
assert length(Notification.for_user(user)) == 1
- {:ok, _, _, _} = CommonAPI.unfavorite(activity.id, other_user)
+ {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
assert Enum.empty?(Notification.for_user(user))
end
@@ -650,11 +789,11 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
assert Enum.empty?(Notification.for_user(user))
- {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
+ {:ok, _} = CommonAPI.repeat(activity.id, other_user)
assert length(Notification.for_user(user)) == 1
@@ -667,15 +806,15 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
assert Enum.empty?(Notification.for_user(user))
- {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
+ {:ok, _} = CommonAPI.repeat(activity.id, other_user)
assert length(Notification.for_user(user)) == 1
- {:ok, _, _} = CommonAPI.unrepeat(activity.id, other_user)
+ {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
assert Enum.empty?(Notification.for_user(user))
end
@@ -684,7 +823,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
assert Enum.empty?(Notification.for_user(user))
@@ -701,7 +840,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
assert Enum.empty?(Notification.for_user(user))
@@ -718,13 +857,13 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
{:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
{:ok, _reply_activity} =
CommonAPI.post(other_user, %{
- "status" => "test reply",
- "in_reply_to_status_id" => activity.id
+ status: "test reply",
+ in_reply_to_status_id: activity.id
})
assert Enum.empty?(Notification.for_user(user))
@@ -735,7 +874,7 @@ defmodule Pleroma.NotificationTest do
other_user = insert(:user)
{:ok, _activity} =
- CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}", "visibility" => "direct"})
+ CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
refute Enum.empty?(Notification.for_user(other_user))
@@ -846,9 +985,11 @@ defmodule Pleroma.NotificationTest do
muted = insert(:user)
{:ok, _user_relationships} = User.mute(user, muted, false)
- {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
- assert length(Notification.for_user(user)) == 1
+ [notification] = Notification.for_user(user)
+
+ assert notification.activity.object
end
test "it doesn't return notifications for muted user with notifications" do
@@ -856,7 +997,7 @@ defmodule Pleroma.NotificationTest do
muted = insert(:user)
{:ok, _user_relationships} = User.mute(user, muted)
- {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
assert Notification.for_user(user) == []
end
@@ -866,26 +1007,38 @@ defmodule Pleroma.NotificationTest do
blocked = insert(:user)
{:ok, _user_relationship} = User.block(user, blocked)
- {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
assert Notification.for_user(user) == []
end
- test "it doesn't return notifications for blocked domain" do
+ test "it doesn't return notifications for domain-blocked non-followed user" do
user = insert(:user)
blocked = insert(:user, ap_id: "http://some-domain.com")
{:ok, user} = User.block_domain(user, "some-domain.com")
- {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
assert Notification.for_user(user) == []
end
+ test "it returns notifications for domain-blocked but followed user" do
+ user = insert(:user)
+ blocked = insert(:user, ap_id: "http://some-domain.com")
+
+ {:ok, user} = User.block_domain(user, "some-domain.com")
+ {:ok, _} = User.follow(user, blocked)
+
+ {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
+
+ assert length(Notification.for_user(user)) == 1
+ end
+
test "it doesn't return notifications for muted thread" do
user = insert(:user)
another_user = insert(:user)
- {:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
+ {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
{:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
assert Notification.for_user(user) == []
@@ -896,7 +1049,7 @@ defmodule Pleroma.NotificationTest do
muted = insert(:user)
{:ok, _user_relationships} = User.mute(user, muted)
- {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
assert length(Notification.for_user(user, %{with_muted: true})) == 1
end
@@ -906,17 +1059,18 @@ defmodule Pleroma.NotificationTest do
blocked = insert(:user)
{:ok, _user_relationship} = User.block(user, blocked)
- {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
end
- test "it doesn't return notifications from a domain-blocked user when with_muted is set" do
+ test "when with_muted is set, " <>
+ "it doesn't return notifications from a domain-blocked non-followed user" do
user = insert(:user)
blocked = insert(:user, ap_id: "http://some-domain.com")
{:ok, user} = User.block_domain(user, "some-domain.com")
- {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
end
@@ -925,7 +1079,7 @@ defmodule Pleroma.NotificationTest do
user = insert(:user)
another_user = insert(:user)
- {:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
+ {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
{:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
assert length(Notification.for_user(user, %{with_muted: true})) == 1
diff --git a/test/pagination_test.exs b/test/pagination_test.exs
index d5b1b782d..9165427ae 100644
--- a/test/pagination_test.exs
+++ b/test/pagination_test.exs
@@ -21,7 +21,7 @@ defmodule Pleroma.PaginationTest do
id = Enum.at(notes, 2).id |> Integer.to_string()
%{total: total, items: paginated} =
- Pagination.fetch_paginated(Object, %{"min_id" => id, "total" => true})
+ Pagination.fetch_paginated(Object, %{min_id: id, total: true})
assert length(paginated) == 2
assert total == 5
@@ -31,7 +31,7 @@ defmodule Pleroma.PaginationTest do
id = Enum.at(notes, 2).id |> Integer.to_string()
%{total: total, items: paginated} =
- Pagination.fetch_paginated(Object, %{"since_id" => id, "total" => true})
+ Pagination.fetch_paginated(Object, %{since_id: id, total: true})
assert length(paginated) == 2
assert total == 5
@@ -41,7 +41,7 @@ defmodule Pleroma.PaginationTest do
id = Enum.at(notes, 1).id |> Integer.to_string()
%{total: total, items: paginated} =
- Pagination.fetch_paginated(Object, %{"max_id" => id, "total" => true})
+ Pagination.fetch_paginated(Object, %{max_id: id, total: true})
assert length(paginated) == 1
assert total == 5
@@ -50,7 +50,7 @@ defmodule Pleroma.PaginationTest do
test "paginates by min_id & limit", %{notes: notes} do
id = Enum.at(notes, 2).id |> Integer.to_string()
- paginated = Pagination.fetch_paginated(Object, %{"min_id" => id, "limit" => 1})
+ paginated = Pagination.fetch_paginated(Object, %{min_id: id, limit: 1})
assert length(paginated) == 1
end
@@ -64,13 +64,13 @@ defmodule Pleroma.PaginationTest do
end
test "paginates by limit" do
- paginated = Pagination.fetch_paginated(Object, %{"limit" => 2}, :offset)
+ paginated = Pagination.fetch_paginated(Object, %{limit: 2}, :offset)
assert length(paginated) == 2
end
test "paginates by limit & offset" do
- paginated = Pagination.fetch_paginated(Object, %{"limit" => 2, "offset" => 4}, :offset)
+ paginated = Pagination.fetch_paginated(Object, %{limit: 2, offset: 4}, :offset)
assert length(paginated) == 1
end
diff --git a/test/plugs/authentication_plug_test.exs b/test/plugs/authentication_plug_test.exs
index ae2f3f8ec..777ae15ae 100644
--- a/test/plugs/authentication_plug_test.exs
+++ b/test/plugs/authentication_plug_test.exs
@@ -6,15 +6,18 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
use Pleroma.Web.ConnCase, async: true
alias Pleroma.Plugs.AuthenticationPlug
+ alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.Plugs.PlugHelper
alias Pleroma.User
import ExUnit.CaptureLog
+ import Pleroma.Factory
setup %{conn: conn} do
user = %User{
id: 1,
name: "dude",
- password_hash: Comeonin.Pbkdf2.hashpwsalt("guy")
+ password_hash: Pbkdf2.hash_pwd_salt("guy")
}
conn =
@@ -36,25 +39,54 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
assert ret_conn == conn
end
- test "with a correct password in the credentials, it assigns the auth_user", %{conn: conn} do
+ test "with a correct password in the credentials, " <>
+ "it assigns the auth_user and marks OAuthScopesPlug as skipped",
+ %{conn: conn} do
conn =
conn
|> assign(:auth_credentials, %{password: "guy"})
|> AuthenticationPlug.call(%{})
assert conn.assigns.user == conn.assigns.auth_user
+ assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
end
- test "with a wrong password in the credentials, it does nothing", %{conn: conn} do
+ test "with a bcrypt hash, it updates to a pkbdf2 hash", %{conn: conn} do
+ user = insert(:user, password_hash: Bcrypt.hash_pwd_salt("123"))
+ assert "$2" <> _ = user.password_hash
+
conn =
conn
- |> assign(:auth_credentials, %{password: "wrong"})
+ |> assign(:auth_user, user)
+ |> assign(:auth_credentials, %{password: "123"})
+ |> AuthenticationPlug.call(%{})
- ret_conn =
+ assert conn.assigns.user.id == conn.assigns.auth_user.id
+ assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
+
+ user = User.get_by_id(user.id)
+ assert "$pbkdf2" <> _ = user.password_hash
+ end
+
+ @tag :skip_on_mac
+ test "with a crypt hash, it updates to a pkbdf2 hash", %{conn: conn} do
+ user =
+ insert(:user,
+ password_hash:
+ "$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
+ )
+
+ conn =
conn
+ |> assign(:auth_user, user)
+ |> assign(:auth_credentials, %{password: "password"})
|> AuthenticationPlug.call(%{})
- assert conn == ret_conn
+ assert conn.assigns.user.id == conn.assigns.auth_user.id
+ assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
+
+ user = User.get_by_id(user.id)
+ assert "$pbkdf2" <> _ = user.password_hash
end
describe "checkpw/2" do
@@ -74,6 +106,13 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
assert AuthenticationPlug.checkpw("password", hash)
end
+ test "check bcrypt hash" do
+ hash = "$2a$10$uyhC/R/zoE1ndwwCtMusK.TLVzkQ/Ugsbqp3uXI.CTTz0gBw.24jS"
+
+ assert AuthenticationPlug.checkpw("password", hash)
+ refute AuthenticationPlug.checkpw("password1", hash)
+ end
+
test "it returns false when hash invalid" do
hash =
"psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
diff --git a/test/plugs/ensure_authenticated_plug_test.exs b/test/plugs/ensure_authenticated_plug_test.exs
index 7f3559b83..a0667c5e0 100644
--- a/test/plugs/ensure_authenticated_plug_test.exs
+++ b/test/plugs/ensure_authenticated_plug_test.exs
@@ -20,34 +20,61 @@ defmodule Pleroma.Plugs.EnsureAuthenticatedPlugTest do
conn = assign(conn, :user, %User{})
ret_conn = EnsureAuthenticatedPlug.call(conn, %{})
- assert ret_conn == conn
+ refute ret_conn.halted
end
end
+ test "it halts if user is assigned and MFA enabled", %{conn: conn} do
+ conn =
+ conn
+ |> assign(:user, %User{multi_factor_authentication_settings: %{enabled: true}})
+ |> assign(:auth_credentials, %{password: "xd-42"})
+ |> EnsureAuthenticatedPlug.call(%{})
+
+ assert conn.status == 403
+ assert conn.halted == true
+
+ assert conn.resp_body ==
+ "{\"error\":\"Two-factor authentication enabled, you must use a access token.\"}"
+ end
+
+ test "it continues if user is assigned and MFA disabled", %{conn: conn} do
+ conn =
+ conn
+ |> assign(:user, %User{multi_factor_authentication_settings: %{enabled: false}})
+ |> assign(:auth_credentials, %{password: "xd-42"})
+ |> EnsureAuthenticatedPlug.call(%{})
+
+ refute conn.status == 403
+ refute conn.halted
+ end
+
describe "with :if_func / :unless_func options" do
setup do
%{
- true_fn: fn -> true end,
- false_fn: fn -> false end
+ true_fn: fn _conn -> true end,
+ false_fn: fn _conn -> false end
}
end
test "it continues if a user is assigned", %{conn: conn, true_fn: true_fn, false_fn: false_fn} do
conn = assign(conn, :user, %User{})
- assert EnsureAuthenticatedPlug.call(conn, if_func: true_fn) == conn
- assert EnsureAuthenticatedPlug.call(conn, if_func: false_fn) == conn
- assert EnsureAuthenticatedPlug.call(conn, unless_func: true_fn) == conn
- assert EnsureAuthenticatedPlug.call(conn, unless_func: false_fn) == conn
+ refute EnsureAuthenticatedPlug.call(conn, if_func: true_fn).halted
+ refute EnsureAuthenticatedPlug.call(conn, if_func: false_fn).halted
+ refute EnsureAuthenticatedPlug.call(conn, unless_func: true_fn).halted
+ refute EnsureAuthenticatedPlug.call(conn, unless_func: false_fn).halted
end
test "it continues if a user is NOT assigned but :if_func evaluates to `false`",
%{conn: conn, false_fn: false_fn} do
- assert EnsureAuthenticatedPlug.call(conn, if_func: false_fn) == conn
+ ret_conn = EnsureAuthenticatedPlug.call(conn, if_func: false_fn)
+ refute ret_conn.halted
end
test "it continues if a user is NOT assigned but :unless_func evaluates to `true`",
%{conn: conn, true_fn: true_fn} do
- assert EnsureAuthenticatedPlug.call(conn, unless_func: true_fn) == conn
+ ret_conn = EnsureAuthenticatedPlug.call(conn, unless_func: true_fn)
+ refute ret_conn.halted
end
test "it halts if a user is NOT assigned and :if_func evaluates to `true`",
diff --git a/test/plugs/ensure_public_or_authenticated_plug_test.exs b/test/plugs/ensure_public_or_authenticated_plug_test.exs
index 411252274..fc2934369 100644
--- a/test/plugs/ensure_public_or_authenticated_plug_test.exs
+++ b/test/plugs/ensure_public_or_authenticated_plug_test.exs
@@ -29,7 +29,7 @@ defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do
conn
|> EnsurePublicOrAuthenticatedPlug.call(%{})
- assert ret_conn == conn
+ refute ret_conn.halted
end
test "it continues if a user is assigned, even if not public", %{conn: conn} do
@@ -43,6 +43,6 @@ defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do
conn
|> EnsurePublicOrAuthenticatedPlug.call(%{})
- assert ret_conn == conn
+ refute ret_conn.halted
end
end
diff --git a/test/plugs/http_security_plug_test.exs b/test/plugs/http_security_plug_test.exs
index 84e4c274f..63b4d3f31 100644
--- a/test/plugs/http_security_plug_test.exs
+++ b/test/plugs/http_security_plug_test.exs
@@ -67,7 +67,7 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do
[csp] = Conn.get_resp_header(conn, "content-security-policy")
- assert csp =~ ~r|report-uri https://endpoint.com; report-to csp-endpoint;|
+ assert csp =~ ~r|report-uri https://endpoint.com;report-to csp-endpoint;|
[reply_to] = Conn.get_resp_header(conn, "reply-to")
diff --git a/test/plugs/legacy_authentication_plug_test.exs b/test/plugs/legacy_authentication_plug_test.exs
index 7559de7d3..3b8c07627 100644
--- a/test/plugs/legacy_authentication_plug_test.exs
+++ b/test/plugs/legacy_authentication_plug_test.exs
@@ -8,6 +8,8 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do
import Pleroma.Factory
alias Pleroma.Plugs.LegacyAuthenticationPlug
+ alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.Plugs.PlugHelper
alias Pleroma.User
setup do
@@ -36,7 +38,8 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do
end
@tag :skip_on_mac
- test "it authenticates the auth_user if present and password is correct and resets the password",
+ test "if `auth_user` is present and password is correct, " <>
+ "it authenticates the user, resets the password, marks OAuthScopesPlug as skipped",
%{
conn: conn,
user: user
@@ -49,6 +52,7 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do
conn = LegacyAuthenticationPlug.call(conn, %{})
assert conn.assigns.user.id == user.id
+ assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
end
@tag :skip_on_mac
diff --git a/test/plugs/oauth_scopes_plug_test.exs b/test/plugs/oauth_scopes_plug_test.exs
index abab7abb0..884de7b4d 100644
--- a/test/plugs/oauth_scopes_plug_test.exs
+++ b/test/plugs/oauth_scopes_plug_test.exs
@@ -5,23 +5,17 @@
defmodule Pleroma.Plugs.OAuthScopesPlugTest do
use Pleroma.Web.ConnCase, async: true
- alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
- alias Pleroma.Plugs.PlugHelper
alias Pleroma.Repo
import Mock
import Pleroma.Factory
- setup_with_mocks([{EnsurePublicOrAuthenticatedPlug, [], [call: fn conn, _ -> conn end]}]) do
- :ok
- end
-
test "is not performed if marked as skipped", %{conn: conn} do
with_mock OAuthScopesPlug, [:passthrough], perform: &passthrough([&1, &2]) do
conn =
conn
- |> PlugHelper.append_to_skipped_plugs(OAuthScopesPlug)
+ |> OAuthScopesPlug.skip_plug()
|> OAuthScopesPlug.call(%{scopes: ["random_scope"]})
refute called(OAuthScopesPlug.perform(:_, :_))
@@ -61,7 +55,7 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do
describe "with `fallback: :proceed_unauthenticated` option, " do
test "if `token.scopes` doesn't fulfill specified conditions, " <>
- "clears :user and :token assigns and calls EnsurePublicOrAuthenticatedPlug",
+ "clears :user and :token assigns",
%{conn: conn} do
user = insert(:user)
token1 = insert(:oauth_token, scopes: ["read", "write"], user: user)
@@ -80,35 +74,6 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do
refute ret_conn.halted
refute ret_conn.assigns[:user]
refute ret_conn.assigns[:token]
-
- assert called(EnsurePublicOrAuthenticatedPlug.call(ret_conn, :_))
- end
- end
-
- test "with :skip_instance_privacy_check option, " <>
- "if `token.scopes` doesn't fulfill specified conditions, " <>
- "clears :user and :token assigns and does NOT call EnsurePublicOrAuthenticatedPlug",
- %{conn: conn} do
- user = insert(:user)
- token1 = insert(:oauth_token, scopes: ["read:statuses", "write"], user: user)
-
- for token <- [token1, nil], op <- [:|, :&] do
- ret_conn =
- conn
- |> assign(:user, user)
- |> assign(:token, token)
- |> OAuthScopesPlug.call(%{
- scopes: ["read"],
- op: op,
- fallback: :proceed_unauthenticated,
- skip_instance_privacy_check: true
- })
-
- refute ret_conn.halted
- refute ret_conn.assigns[:user]
- refute ret_conn.assigns[:token]
-
- refute called(EnsurePublicOrAuthenticatedPlug.call(ret_conn, :_))
end
end
end
diff --git a/test/signature_test.exs b/test/signature_test.exs
index d5a2a62c4..a7a75aa4d 100644
--- a/test/signature_test.exs
+++ b/test/signature_test.exs
@@ -44,7 +44,8 @@ defmodule Pleroma.SignatureTest do
test "it returns error when not found user" do
assert capture_log(fn ->
- assert Signature.fetch_public_key(make_fake_conn("test-ap_id")) == {:error, :error}
+ assert Signature.fetch_public_key(make_fake_conn("https://test-ap-id")) ==
+ {:error, :error}
end) =~ "[error] Could not decode user"
end
@@ -64,7 +65,7 @@ defmodule Pleroma.SignatureTest do
test "it returns error when not found user" do
assert capture_log(fn ->
- {:error, _} = Signature.refetch_public_key(make_fake_conn("test-ap_id"))
+ {:error, _} = Signature.refetch_public_key(make_fake_conn("https://test-ap_id"))
end) =~ "[error] Could not decode user"
end
end
@@ -100,12 +101,21 @@ defmodule Pleroma.SignatureTest do
describe "key_id_to_actor_id/1" do
test "it properly deduces the actor id for misskey" do
assert Signature.key_id_to_actor_id("https://example.com/users/1234/publickey") ==
- "https://example.com/users/1234"
+ {:ok, "https://example.com/users/1234"}
end
test "it properly deduces the actor id for mastodon and pleroma" do
assert Signature.key_id_to_actor_id("https://example.com/users/1234#main-key") ==
- "https://example.com/users/1234"
+ {:ok, "https://example.com/users/1234"}
+ end
+
+ test "it calls webfinger for 'acct:' accounts" do
+ with_mock(Pleroma.Web.WebFinger,
+ finger: fn _ -> %{"ap_id" => "https://gensokyo.2hu/users/raymoo"} end
+ ) do
+ assert Signature.key_id_to_actor_id("acct:raymoo@gensokyo.2hu") ==
+ {:ok, "https://gensokyo.2hu/users/raymoo"}
+ end
end
end
diff --git a/test/stat_test.exs b/test/stats_test.exs
index bccc1c8d0..4b76e2e78 100644
--- a/test/stat_test.exs
+++ b/test/stats_test.exs
@@ -2,36 +2,46 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.StateTest do
+defmodule Pleroma.StatsTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Web.CommonAPI
+ describe "user count" do
+ test "it ignores internal users" do
+ _user = insert(:user, local: true)
+ _internal = insert(:user, local: true, nickname: nil)
+ _internal = Pleroma.Web.ActivityPub.Relay.get_actor()
+
+ assert match?(%{stats: %{user_count: 1}}, Pleroma.Stats.calculate_stat_data())
+ end
+ end
+
describe "status visibility count" do
test "on new status" do
user = insert(:user)
other_user = insert(:user)
- CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
+ CommonAPI.post(user, %{visibility: "public", status: "hey"})
Enum.each(0..1, fn _ ->
CommonAPI.post(user, %{
- "visibility" => "unlisted",
- "status" => "hey"
+ visibility: "unlisted",
+ status: "hey"
})
end)
Enum.each(0..2, fn _ ->
CommonAPI.post(user, %{
- "visibility" => "direct",
- "status" => "hey @#{other_user.nickname}"
+ visibility: "direct",
+ status: "hey @#{other_user.nickname}"
})
end)
Enum.each(0..3, fn _ ->
CommonAPI.post(user, %{
- "visibility" => "private",
- "status" => "hey"
+ visibility: "private",
+ status: "hey"
})
end)
@@ -41,7 +51,7 @@ defmodule Pleroma.StateTest do
test "on status delete" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
+ {:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
assert %{public: 1} = Pleroma.Stats.get_status_visibility_count()
CommonAPI.delete(activity.id, user)
assert %{public: 0} = Pleroma.Stats.get_status_visibility_count()
@@ -49,16 +59,16 @@ defmodule Pleroma.StateTest do
test "on status visibility update" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
+ {:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
assert %{public: 1, private: 0} = Pleroma.Stats.get_status_visibility_count()
- {:ok, _} = CommonAPI.update_activity_scope(activity.id, %{"visibility" => "private"})
+ {:ok, _} = CommonAPI.update_activity_scope(activity.id, %{visibility: "private"})
assert %{public: 0, private: 1} = Pleroma.Stats.get_status_visibility_count()
end
test "doesn't count unrelated activities" do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
+ {:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
_ = CommonAPI.follow(user, other_user)
CommonAPI.favorite(other_user, activity.id)
CommonAPI.repeat(activity.id, other_user)
diff --git a/test/support/api_spec_helpers.ex b/test/support/api_spec_helpers.ex
new file mode 100644
index 000000000..46388f92c
--- /dev/null
+++ b/test/support/api_spec_helpers.ex
@@ -0,0 +1,57 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Tests.ApiSpecHelpers do
+ @moduledoc """
+ OpenAPI spec test helpers
+ """
+
+ import ExUnit.Assertions
+
+ alias OpenApiSpex.Cast.Error
+ alias OpenApiSpex.Reference
+ alias OpenApiSpex.Schema
+
+ def assert_schema(value, schema) do
+ api_spec = Pleroma.Web.ApiSpec.spec()
+
+ case OpenApiSpex.cast_value(value, schema, api_spec) do
+ {:ok, data} ->
+ data
+
+ {:error, errors} ->
+ errors =
+ Enum.map(errors, fn error ->
+ message = Error.message(error)
+ path = Error.path_to_string(error)
+ "#{message} at #{path}"
+ end)
+
+ flunk(
+ "Value does not conform to schema #{schema.title}: #{Enum.join(errors, "\n")}\n#{
+ inspect(value)
+ }"
+ )
+ end
+ end
+
+ def resolve_schema(%Schema{} = schema), do: schema
+
+ def resolve_schema(%Reference{} = ref) do
+ schemas = Pleroma.Web.ApiSpec.spec().components.schemas
+ Reference.resolve_schema(ref, schemas)
+ end
+
+ def api_operations do
+ paths = Pleroma.Web.ApiSpec.spec().paths
+
+ Enum.flat_map(paths, fn {_, path_item} ->
+ path_item
+ |> Map.take([:delete, :get, :head, :options, :patch, :post, :put, :trace])
+ |> Map.values()
+ |> Enum.reject(&is_nil/1)
+ end)
+ |> Enum.uniq()
+ end
+end
diff --git a/test/support/builders/activity_builder.ex b/test/support/builders/activity_builder.ex
index 6e5a8e059..7c4950bfa 100644
--- a/test/support/builders/activity_builder.ex
+++ b/test/support/builders/activity_builder.ex
@@ -21,7 +21,15 @@ defmodule Pleroma.Builders.ActivityBuilder do
def insert(data \\ %{}, opts \\ %{}) do
activity = build(data, opts)
- ActivityPub.insert(activity)
+
+ case ActivityPub.insert(activity) do
+ ok = {:ok, activity} ->
+ ActivityPub.notify_and_stream(activity)
+ ok
+
+ error ->
+ error
+ end
end
def insert_list(times, data \\ %{}, opts \\ %{}) do
diff --git a/test/support/builders/user_builder.ex b/test/support/builders/user_builder.ex
index fcfea666f..0c687c029 100644
--- a/test/support/builders/user_builder.ex
+++ b/test/support/builders/user_builder.ex
@@ -7,10 +7,11 @@ defmodule Pleroma.Builders.UserBuilder do
email: "test@example.org",
name: "Test Name",
nickname: "testname",
- password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
+ password_hash: Pbkdf2.hash_pwd_salt("test"),
bio: "A tester.",
ap_id: "some id",
last_digest_emailed_at: NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
+ multi_factor_authentication_settings: %Pleroma.MFA.Settings{},
notification_settings: %Pleroma.User.NotificationSetting{}
}
diff --git a/test/support/captcha_mock.ex b/test/support/captcha_mock.ex
index 6dae94edf..7b0c1d5af 100644
--- a/test/support/captcha_mock.ex
+++ b/test/support/captcha_mock.ex
@@ -6,12 +6,16 @@ defmodule Pleroma.Captcha.Mock do
alias Pleroma.Captcha.Service
@behaviour Service
+ @solution "63615261b77f5354fb8c4e4986477555"
+
+ def solution, do: @solution
+
@impl Service
def new,
do: %{
type: :mock,
token: "afa1815e14e29355e6c8f6b143a39fa2",
- answer_data: "63615261b77f5354fb8c4e4986477555",
+ answer_data: @solution,
url: "https://example.org/captcha.png"
}
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
index 064874201..b23918dd1 100644
--- a/test/support/conn_case.ex
+++ b/test/support/conn_case.ex
@@ -51,6 +51,60 @@ defmodule Pleroma.Web.ConnCase do
%{user: user, token: token, conn: conn}
end
+ defp request_content_type(%{conn: conn}) do
+ conn = put_req_header(conn, "content-type", "multipart/form-data")
+ [conn: conn]
+ end
+
+ defp json_response_and_validate_schema(
+ %{
+ private: %{
+ open_api_spex: %{operation_id: op_id, operation_lookup: lookup, spec: spec}
+ }
+ } = conn,
+ status
+ ) do
+ content_type =
+ conn
+ |> Plug.Conn.get_resp_header("content-type")
+ |> List.first()
+ |> String.split(";")
+ |> List.first()
+
+ status = Plug.Conn.Status.code(status)
+
+ unless lookup[op_id].responses[status] do
+ err = "Response schema not found for #{status} #{conn.method} #{conn.request_path}"
+ flunk(err)
+ end
+
+ schema = lookup[op_id].responses[status].content[content_type].schema
+ json = json_response(conn, status)
+
+ case OpenApiSpex.cast_value(json, schema, spec) do
+ {:ok, _data} ->
+ json
+
+ {:error, errors} ->
+ errors =
+ Enum.map(errors, fn error ->
+ message = OpenApiSpex.Cast.Error.message(error)
+ path = OpenApiSpex.Cast.Error.path_to_string(error)
+ "#{message} at #{path}"
+ end)
+
+ flunk(
+ "Response does not conform to schema of #{op_id} operation: #{
+ Enum.join(errors, "\n")
+ }\n#{inspect(json)}"
+ )
+ end
+ end
+
+ defp json_response_and_validate_schema(conn, _status) do
+ flunk("Response schema not found for #{conn.method} #{conn.request_path} #{conn.status}")
+ end
+
defp ensure_federating_or_authenticated(conn, url, user) do
initial_setting = Config.get([:instance, :federating])
on_exit(fn -> Config.put([:instance, :federating], initial_setting) end)
@@ -85,7 +139,11 @@ defmodule Pleroma.Web.ConnCase do
end
if tags[:needs_streamer] do
- start_supervised(Pleroma.Web.Streamer.supervisor())
+ start_supervised(%{
+ id: Pleroma.Web.Streamer.registry(),
+ start:
+ {Registry, :start_link, [[keys: :duplicate, name: Pleroma.Web.Streamer.registry()]]}
+ })
end
{:ok, conn: Phoenix.ConnTest.build_conn()}
diff --git a/test/support/data_case.ex b/test/support/data_case.ex
index 1669f2520..ba8848952 100644
--- a/test/support/data_case.ex
+++ b/test/support/data_case.ex
@@ -40,7 +40,11 @@ defmodule Pleroma.DataCase do
end
if tags[:needs_streamer] do
- start_supervised(Pleroma.Web.Streamer.supervisor())
+ start_supervised(%{
+ id: Pleroma.Web.Streamer.registry(),
+ start:
+ {Registry, :start_link, [[keys: :duplicate, name: Pleroma.Web.Streamer.registry()]]}
+ })
end
:ok
diff --git a/test/support/factory.ex b/test/support/factory.ex
index af639b6cd..6e22b66a4 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -29,17 +29,21 @@ defmodule Pleroma.Factory do
name: sequence(:name, &"Test テスト User #{&1}"),
email: sequence(:email, &"user#{&1}@example.com"),
nickname: sequence(:nickname, &"nick#{&1}"),
- password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
+ password_hash: Pbkdf2.hash_pwd_salt("test"),
bio: sequence(:bio, &"Tester Number #{&1}"),
last_digest_emailed_at: NaiveDateTime.utc_now(),
- notification_settings: %Pleroma.User.NotificationSetting{}
+ last_refreshed_at: NaiveDateTime.utc_now(),
+ notification_settings: %Pleroma.User.NotificationSetting{},
+ multi_factor_authentication_settings: %Pleroma.MFA.Settings{},
+ ap_enabled: true
}
%{
user
| ap_id: User.ap_id(user),
follower_address: User.ap_followers(user),
- following_address: User.ap_following(user)
+ following_address: User.ap_following(user),
+ raw_bio: user.bio
}
end
@@ -294,7 +298,7 @@ defmodule Pleroma.Factory do
def oauth_app_factory do
%Pleroma.Web.OAuth.App{
- client_name: "Some client",
+ client_name: sequence(:client_name, &"Some client #{&1}"),
redirect_uris: "https://example.com/callback",
scopes: ["read", "write", "follow", "push", "admin"],
website: "https://example.com",
@@ -393,24 +397,17 @@ defmodule Pleroma.Factory do
}
end
- def config_factory do
+ def config_factory(attrs \\ %{}) do
%Pleroma.ConfigDB{
- key:
- sequence(:key, fn key ->
- # Atom dynamic registration hack in tests
- "some_key_#{key}"
- |> String.to_atom()
- |> inspect()
- end),
- group: ":pleroma",
+ key: sequence(:key, &String.to_atom("some_key_#{&1}")),
+ group: :pleroma,
value:
sequence(
:value,
- fn key ->
- :erlang.term_to_binary(%{another_key: "#{key}somevalue", another: "#{key}somevalue"})
- end
+ &%{another_key: "#{&1}somevalue", another: "#{&1}somevalue"}
)
}
+ |> merge_attributes(attrs)
end
def marker_factory do
@@ -421,4 +418,13 @@ defmodule Pleroma.Factory do
last_read_id: "1"
}
end
+
+ def mfa_token_factory do
+ %Pleroma.MFA.Token{
+ token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false),
+ authorization: build(:oauth_authorization),
+ valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10),
+ user: build(:user)
+ }
+ end
end
diff --git a/test/support/helpers.ex b/test/support/helpers.ex
index e68e9bfd2..26281b45e 100644
--- a/test/support/helpers.ex
+++ b/test/support/helpers.ex
@@ -40,12 +40,18 @@ defmodule Pleroma.Tests.Helpers do
clear_config: 2
]
- def to_datetime(naive_datetime) do
+ def to_datetime(%NaiveDateTime{} = naive_datetime) do
naive_datetime
|> DateTime.from_naive!("Etc/UTC")
|> DateTime.truncate(:second)
end
+ def to_datetime(datetime) when is_binary(datetime) do
+ datetime
+ |> NaiveDateTime.from_iso8601!()
+ |> to_datetime()
+ end
+
def collect_ids(collection) do
collection
|> Enum.map(& &1.id)
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
index 20cb2b3d1..3d5128835 100644
--- a/test/support/http_request_mock.ex
+++ b/test/support/http_request_mock.ex
@@ -211,7 +211,7 @@ defmodule HttpRequestMock do
end
def get(
- "https://squeet.me/xrd/?uri=lain@squeet.me",
+ "https://squeet.me/xrd/?uri=acct:lain@squeet.me",
_,
_,
[{"accept", "application/xrd+xml,application/jrd+json"}]
@@ -308,6 +308,22 @@ defmodule HttpRequestMock do
}}
end
+ def get("https://peertube.social/accounts/craigmaloney", _, _, _) do
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/craigmaloney.json")
+ }}
+ end
+
+ def get("https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe", _, _, _) do
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/peertube-social.json")
+ }}
+ end
+
def get("https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39", _, _, [
{"accept", "application/activity+json"}
]) do
@@ -854,7 +870,7 @@ defmodule HttpRequestMock do
end
def get(
- "https://social.heldscal.la/.well-known/webfinger?resource=shp@social.heldscal.la",
+ "https://social.heldscal.la/.well-known/webfinger?resource=acct:shp@social.heldscal.la",
_,
_,
[{"accept", "application/xrd+xml,application/jrd+json"}]
@@ -867,7 +883,7 @@ defmodule HttpRequestMock do
end
def get(
- "https://social.heldscal.la/.well-known/webfinger?resource=invalid_content@social.heldscal.la",
+ "https://social.heldscal.la/.well-known/webfinger?resource=acct:invalid_content@social.heldscal.la",
_,
_,
[{"accept", "application/xrd+xml,application/jrd+json"}]
@@ -884,7 +900,7 @@ defmodule HttpRequestMock do
end
def get(
- "http://framatube.org/main/xrd?uri=framasoft@framatube.org",
+ "http://framatube.org/main/xrd?uri=acct:framasoft@framatube.org",
_,
_,
[{"accept", "application/xrd+xml,application/jrd+json"}]
@@ -943,7 +959,7 @@ defmodule HttpRequestMock do
end
def get(
- "https://gerzilla.de/xrd/?uri=kaniini@gerzilla.de",
+ "https://gerzilla.de/xrd/?uri=acct:kaniini@gerzilla.de",
_,
_,
[{"accept", "application/xrd+xml,application/jrd+json"}]
@@ -1139,7 +1155,7 @@ defmodule HttpRequestMock do
end
def get(
- "https://zetsubou.xn--q9jyb4c/.well-known/webfinger?resource=lain@zetsubou.xn--q9jyb4c",
+ "https://zetsubou.xn--q9jyb4c/.well-known/webfinger?resource=acct:lain@zetsubou.xn--q9jyb4c",
_,
_,
[{"accept", "application/xrd+xml,application/jrd+json"}]
@@ -1152,7 +1168,7 @@ defmodule HttpRequestMock do
end
def get(
- "https://zetsubou.xn--q9jyb4c/.well-known/webfinger?resource=https://zetsubou.xn--q9jyb4c/users/lain",
+ "https://zetsubou.xn--q9jyb4c/.well-known/webfinger?resource=acct:https://zetsubou.xn--q9jyb4c/users/lain",
_,
_,
[{"accept", "application/xrd+xml,application/jrd+json"}]
@@ -1275,6 +1291,10 @@ defmodule HttpRequestMock do
}}
end
+ def get("https://example.org/emoji/firedfox.png", _, _, _) do
+ {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")}}
+ end
+
def get("https://skippers-bin.com/users/7v1w1r8ce6", _, _, _) do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/sjw.json")}}
end
diff --git a/test/tasks/app_test.exs b/test/tasks/app_test.exs
new file mode 100644
index 000000000..b8f03566d
--- /dev/null
+++ b/test/tasks/app_test.exs
@@ -0,0 +1,65 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Mix.Tasks.Pleroma.AppTest do
+ use Pleroma.DataCase, async: true
+
+ setup_all do
+ Mix.shell(Mix.Shell.Process)
+
+ on_exit(fn ->
+ Mix.shell(Mix.Shell.IO)
+ end)
+ end
+
+ describe "creates new app" do
+ test "with default scopes" do
+ name = "Some name"
+ redirect = "https://example.com"
+ Mix.Tasks.Pleroma.App.run(["create", "-n", name, "-r", redirect])
+
+ assert_app(name, redirect, ["read", "write", "follow", "push"])
+ end
+
+ test "with custom scopes" do
+ name = "Another name"
+ redirect = "https://example.com"
+
+ Mix.Tasks.Pleroma.App.run([
+ "create",
+ "-n",
+ name,
+ "-r",
+ redirect,
+ "-s",
+ "read,write,follow,push,admin"
+ ])
+
+ assert_app(name, redirect, ["read", "write", "follow", "push", "admin"])
+ end
+ end
+
+ test "with errors" do
+ Mix.Tasks.Pleroma.App.run(["create"])
+ {:mix_shell, :error, ["Creating failed:"]}
+ {:mix_shell, :error, ["name: can't be blank"]}
+ {:mix_shell, :error, ["redirect_uris: can't be blank"]}
+ end
+
+ defp assert_app(name, redirect, scopes) do
+ app = Repo.get_by(Pleroma.Web.OAuth.App, client_name: name)
+
+ assert_received {:mix_shell, :info, [message]}
+ assert message == "#{name} successfully created:"
+
+ assert_received {:mix_shell, :info, [message]}
+ assert message == "App client_id: #{app.client_id}"
+
+ assert_received {:mix_shell, :info, [message]}
+ assert message == "App client_secret: #{app.client_secret}"
+
+ assert app.scopes == scopes
+ assert app.redirect_uris == redirect
+ end
+end
diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs
index 3dee4f082..e1bddfebf 100644
--- a/test/tasks/config_test.exs
+++ b/test/tasks/config_test.exs
@@ -5,6 +5,8 @@
defmodule Mix.Tasks.Pleroma.ConfigTest do
use Pleroma.DataCase
+ import Pleroma.Factory
+
alias Pleroma.ConfigDB
alias Pleroma.Repo
@@ -38,7 +40,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
on_exit(fn -> Application.put_env(:quack, :level, initial) end)
end
- test "settings are migrated to db" do
+ test "filtered settings are migrated to db" do
assert Repo.all(ConfigDB) == []
Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs")
@@ -47,25 +49,21 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
config2 = ConfigDB.get_by_params(%{group: ":pleroma", key: ":second_setting"})
config3 = ConfigDB.get_by_params(%{group: ":quack", key: ":level"})
refute ConfigDB.get_by_params(%{group: ":pleroma", key: "Pleroma.Repo"})
+ refute ConfigDB.get_by_params(%{group: ":postgrex", key: ":json_library"})
- assert ConfigDB.from_binary(config1.value) == [key: "value", key2: [Repo]]
- assert ConfigDB.from_binary(config2.value) == [key: "value2", key2: ["Activity"]]
- assert ConfigDB.from_binary(config3.value) == :info
+ assert config1.value == [key: "value", key2: [Repo]]
+ assert config2.value == [key: "value2", key2: ["Activity"]]
+ assert config3.value == :info
end
test "config table is truncated before migration" do
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":first_setting",
- value: [key: "value", key2: ["Activity"]]
- })
-
+ insert(:config, key: :first_setting, value: [key: "value", key2: ["Activity"]])
assert Repo.aggregate(ConfigDB, :count, :id) == 1
Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs")
config = ConfigDB.get_by_params(%{group: ":pleroma", key: ":first_setting"})
- assert ConfigDB.from_binary(config.value) == [key: "value", key2: [Repo]]
+ assert config.value == [key: "value", key2: [Repo]]
end
end
@@ -81,19 +79,9 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
end
test "settings are migrated to file and deleted from db", %{temp_file: temp_file} do
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":setting_first",
- value: [key: "value", key2: ["Activity"]]
- })
-
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":setting_second",
- value: [key: "value2", key2: [Repo]]
- })
-
- ConfigDB.create(%{group: ":quack", key: ":level", value: :info})
+ insert(:config, key: :setting_first, value: [key: "value", key2: ["Activity"]])
+ insert(:config, key: :setting_second, value: [key: "value2", key2: [Repo]])
+ insert(:config, group: :quack, key: :level, value: :info)
Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "--env", "temp", "-d"])
@@ -106,9 +94,8 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
end
test "load a settings with large values and pass to file", %{temp_file: temp_file} do
- ConfigDB.create(%{
- group: ":pleroma",
- key: ":instance",
+ insert(:config,
+ key: :instance,
value: [
name: "Pleroma",
email: "example@example.com",
@@ -162,7 +149,6 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
extended_nickname_format: true,
multi_factor_authentication: [
totp: [
- # digits 6 or 8
digits: 6,
period: 30
],
@@ -172,7 +158,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
]
]
]
- })
+ )
Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "--env", "temp", "-d"])
diff --git a/test/tasks/count_statuses_test.exs b/test/tasks/count_statuses_test.exs
index 73c2ea690..c5cd16960 100644
--- a/test/tasks/count_statuses_test.exs
+++ b/test/tasks/count_statuses_test.exs
@@ -13,11 +13,11 @@ defmodule Mix.Tasks.Pleroma.CountStatusesTest do
test "counts statuses" do
user = insert(:user)
- {:ok, _} = CommonAPI.post(user, %{"status" => "test"})
- {:ok, _} = CommonAPI.post(user, %{"status" => "test2"})
+ {:ok, _} = CommonAPI.post(user, %{status: "test"})
+ {:ok, _} = CommonAPI.post(user, %{status: "test2"})
user2 = insert(:user)
- {:ok, _} = CommonAPI.post(user2, %{"status" => "test3"})
+ {:ok, _} = CommonAPI.post(user2, %{status: "test3"})
user = refresh_record(user)
user2 = refresh_record(user2)
diff --git a/test/tasks/database_test.exs b/test/tasks/database_test.exs
index 7b05993d3..883828d77 100644
--- a/test/tasks/database_test.exs
+++ b/test/tasks/database_test.exs
@@ -26,7 +26,7 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
describe "running remove_embedded_objects" do
test "it replaces objects with references" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test"})
new_data = Map.put(activity.data, "object", activity.object.data)
{:ok, activity} =
@@ -99,8 +99,8 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
test "it turns OrderedCollection likes into empty arrays" do
[user, user2] = insert_pair(:user)
- {:ok, %{id: id, object: object}} = CommonAPI.post(user, %{"status" => "test"})
- {:ok, %{object: object2}} = CommonAPI.post(user, %{"status" => "test test"})
+ {:ok, %{id: id, object: object}} = CommonAPI.post(user, %{status: "test"})
+ {:ok, %{object: object2}} = CommonAPI.post(user, %{status: "test test"})
CommonAPI.favorite(user2, id)
diff --git a/test/tasks/digest_test.exs b/test/tasks/digest_test.exs
index 96d762685..eefbc8936 100644
--- a/test/tasks/digest_test.exs
+++ b/test/tasks/digest_test.exs
@@ -25,7 +25,7 @@ defmodule Mix.Tasks.Pleroma.DigestTest do
Enum.each(0..10, fn i ->
{:ok, _activity} =
CommonAPI.post(user1, %{
- "status" => "hey ##{i} @#{user2.nickname}!"
+ status: "hey ##{i} @#{user2.nickname}!"
})
end)
diff --git a/test/tasks/emoji_test.exs b/test/tasks/emoji_test.exs
index f5de3ef0e..499f098c2 100644
--- a/test/tasks/emoji_test.exs
+++ b/test/tasks/emoji_test.exs
@@ -73,6 +73,19 @@ defmodule Mix.Tasks.Pleroma.EmojiTest do
on_exit(fn -> File.rm_rf!("test/instance_static/emoji/finmoji") end)
end
+ test "install local emoji pack" do
+ assert capture_io(fn ->
+ Emoji.run([
+ "get-packs",
+ "local",
+ "--manifest",
+ "test/instance_static/local_pack/manifest.json"
+ ])
+ end) =~ "Writing pack.json for"
+
+ on_exit(fn -> File.rm_rf!("test/instance_static/emoji/local") end)
+ end
+
test "pack not found" do
mock(fn
%{
diff --git a/test/tasks/instance_test.exs b/test/tasks/instance_test.exs
index f6a4ba508..3b4c041d9 100644
--- a/test/tasks/instance_test.exs
+++ b/test/tasks/instance_test.exs
@@ -63,7 +63,7 @@ defmodule Pleroma.InstanceTest do
"--uploads-dir",
"test/uploads",
"--static-dir",
- "instance/static/"
+ "./test/../test/instance/static/"
])
end
@@ -83,6 +83,7 @@ defmodule Pleroma.InstanceTest do
assert generated_config =~ "configurable_from_database: true"
assert generated_config =~ "http: [ip: {127, 0, 0, 1}, port: 4000]"
assert File.read!(tmp_path() <> "setup.psql") == generated_setup_psql()
+ assert File.exists?(Path.expand("./test/instance/static/robots.txt"))
end
defp generated_setup_psql do
diff --git a/test/tasks/refresh_counter_cache_test.exs b/test/tasks/refresh_counter_cache_test.exs
index b63f44c08..851971a77 100644
--- a/test/tasks/refresh_counter_cache_test.exs
+++ b/test/tasks/refresh_counter_cache_test.exs
@@ -12,26 +12,26 @@ defmodule Mix.Tasks.Pleroma.RefreshCounterCacheTest do
user = insert(:user)
other_user = insert(:user)
- CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
+ CommonAPI.post(user, %{visibility: "public", status: "hey"})
Enum.each(0..1, fn _ ->
CommonAPI.post(user, %{
- "visibility" => "unlisted",
- "status" => "hey"
+ visibility: "unlisted",
+ status: "hey"
})
end)
Enum.each(0..2, fn _ ->
CommonAPI.post(user, %{
- "visibility" => "direct",
- "status" => "hey @#{other_user.nickname}"
+ visibility: "direct",
+ status: "hey @#{other_user.nickname}"
})
end)
Enum.each(0..3, fn _ ->
CommonAPI.post(user, %{
- "visibility" => "private",
- "status" => "hey"
+ visibility: "private",
+ status: "hey"
})
end)
diff --git a/test/tasks/relay_test.exs b/test/tasks/relay_test.exs
index d3d88467d..a8ba0658d 100644
--- a/test/tasks/relay_test.exs
+++ b/test/tasks/relay_test.exs
@@ -62,10 +62,11 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
[undo_activity] =
ActivityPub.fetch_activities([], %{
- "type" => "Undo",
- "actor_id" => follower_id,
- "limit" => 1,
- "skip_preload" => true
+ type: "Undo",
+ actor_id: follower_id,
+ limit: 1,
+ skip_preload: true,
+ invisible_actors: true
})
assert undo_activity.data["type"] == "Undo"
diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs
index 8df835b56..9220d23fc 100644
--- a/test/tasks/user_test.exs
+++ b/test/tasks/user_test.exs
@@ -3,15 +3,22 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.UserTest do
+ alias Pleroma.Activity
+ alias Pleroma.MFA
+ alias Pleroma.Object
alias Pleroma.Repo
+ alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
alias Pleroma.Web.OAuth.Authorization
alias Pleroma.Web.OAuth.Token
use Pleroma.DataCase
+ use Oban.Testing, repo: Pleroma.Repo
- import Pleroma.Factory
import ExUnit.CaptureIO
+ import Mock
+ import Pleroma.Factory
setup_all do
Mix.shell(Mix.Shell.Process)
@@ -85,14 +92,44 @@ defmodule Mix.Tasks.Pleroma.UserTest do
describe "running rm" do
test "user is deleted" do
+ clear_config([:instance, :federating], true)
user = insert(:user)
- Mix.Tasks.Pleroma.User.run(["rm", user.nickname])
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ Mix.Tasks.Pleroma.User.run(["rm", user.nickname])
+ ObanHelpers.perform_all()
- assert_received {:mix_shell, :info, [message]}
- assert message =~ " deleted"
+ assert_received {:mix_shell, :info, [message]}
+ assert message =~ " deleted"
+ assert %{deactivated: true} = User.get_by_nickname(user.nickname)
+
+ assert called(Pleroma.Web.Federator.publish(:_))
+ end
+ end
+
+ test "a remote user's create activity is deleted when the object has been pruned" do
+ user = insert(:user)
+ {:ok, post} = CommonAPI.post(user, %{status: "uguu"})
- refute User.get_by_nickname(user.nickname)
+ clear_config([:instance, :federating], true)
+
+ object = Object.normalize(post)
+ Object.prune(object)
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ Mix.Tasks.Pleroma.User.run(["rm", user.nickname])
+ ObanHelpers.perform_all()
+
+ assert_received {:mix_shell, :info, [message]}
+ assert message =~ " deleted"
+ assert %{deactivated: true} = User.get_by_nickname(user.nickname)
+
+ assert called(Pleroma.Web.Federator.publish(:_))
+ end
+
+ refute Activity.get_by_id(post.id)
end
test "no user to delete" do
@@ -136,31 +173,31 @@ defmodule Mix.Tasks.Pleroma.UserTest do
end
end
- describe "running unsubscribe" do
+ describe "running deactivate" do
test "user is unsubscribed" do
followed = insert(:user)
+ remote_followed = insert(:user, local: false)
user = insert(:user)
+
User.follow(user, followed, :follow_accept)
+ User.follow(user, remote_followed, :follow_accept)
- Mix.Tasks.Pleroma.User.run(["unsubscribe", user.nickname])
+ Mix.Tasks.Pleroma.User.run(["deactivate", user.nickname])
assert_received {:mix_shell, :info, [message]}
assert message =~ "Deactivating"
- assert_received {:mix_shell, :info, [message]}
- assert message =~ "Unsubscribing"
-
# Note that the task has delay :timer.sleep(500)
assert_received {:mix_shell, :info, [message]}
assert message =~ "Successfully unsubscribed"
user = User.get_cached_by_nickname(user.nickname)
- assert Enum.empty?(User.get_friends(user))
+ assert Enum.empty?(Enum.filter(User.get_friends(user), & &1.local))
assert user.deactivated
end
- test "no user to unsubscribe" do
- Mix.Tasks.Pleroma.User.run(["unsubscribe", "nonexistent"])
+ test "no user to deactivate" do
+ Mix.Tasks.Pleroma.User.run(["deactivate", "nonexistent"])
assert_received {:mix_shell, :error, [message]}
assert message =~ "No user"
@@ -242,6 +279,35 @@ defmodule Mix.Tasks.Pleroma.UserTest do
end
end
+ describe "running reset_mfa" do
+ test "disables MFA" do
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: "xx", confirmed: true}
+ }
+ )
+
+ Mix.Tasks.Pleroma.User.run(["reset_mfa", user.nickname])
+
+ assert_received {:mix_shell, :info, [message]}
+ assert message == "Multi-Factor Authentication disabled for #{user.nickname}"
+
+ assert %{enabled: false, totp: false} ==
+ user.nickname
+ |> User.get_cached_by_nickname()
+ |> MFA.mfa_settings()
+ end
+
+ test "no user to reset MFA" do
+ Mix.Tasks.Pleroma.User.run(["reset_password", "nonexistent"])
+
+ assert_received {:mix_shell, :error, [message]}
+ assert message =~ "No local user"
+ end
+ end
+
describe "running invite" do
test "invite token is generated" do
assert capture_io(fn ->
diff --git a/test/upload/filter/mogrify_test.exs b/test/upload/filter/mogrify_test.exs
index b6a463e8c..62ca30487 100644
--- a/test/upload/filter/mogrify_test.exs
+++ b/test/upload/filter/mogrify_test.exs
@@ -6,21 +6,17 @@ defmodule Pleroma.Upload.Filter.MogrifyTest do
use Pleroma.DataCase
import Mock
- alias Pleroma.Config
- alias Pleroma.Upload
alias Pleroma.Upload.Filter
- setup do: clear_config([Filter.Mogrify, :args])
-
test "apply mogrify filter" do
- Config.put([Filter.Mogrify, :args], [{"tint", "40"}])
+ clear_config(Filter.Mogrify, args: [{"tint", "40"}])
File.cp!(
"test/fixtures/image.jpg",
"test/fixtures/image_tmp.jpg"
)
- upload = %Upload{
+ upload = %Pleroma.Upload{
name: "an… image.jpg",
content_type: "image/jpg",
path: Path.absname("test/fixtures/image_tmp.jpg"),
diff --git a/test/upload_test.exs b/test/upload_test.exs
index 060a940bb..2abf0edec 100644
--- a/test/upload_test.exs
+++ b/test/upload_test.exs
@@ -54,6 +54,7 @@ defmodule Pleroma.UploadTest do
%{
"name" => "image.jpg",
"type" => "Document",
+ "mediaType" => "image/jpeg",
"url" => [
%{
"href" => "http://localhost:4001/media/post-process-file.jpg",
diff --git a/test/uploaders/s3_test.exs b/test/uploaders/s3_test.exs
index 6950ccb25..d949c90a5 100644
--- a/test/uploaders/s3_test.exs
+++ b/test/uploaders/s3_test.exs
@@ -58,7 +58,7 @@ defmodule Pleroma.Uploaders.S3Test do
name: "image-tet.jpg",
content_type: "image/jpg",
path: "test_folder/image-tet.jpg",
- tempfile: Path.absname("test/fixtures/image_tmp.jpg")
+ tempfile: Path.absname("test/instance_static/add/shortcode.png")
}
[file_upload: file_upload]
diff --git a/test/user_search_test.exs b/test/user_search_test.exs
index cb847b516..17c63322a 100644
--- a/test/user_search_test.exs
+++ b/test/user_search_test.exs
@@ -172,6 +172,7 @@ defmodule Pleroma.UserSearchTest do
|> Map.put(:search_rank, nil)
|> Map.put(:search_type, nil)
|> Map.put(:last_digest_emailed_at, nil)
+ |> Map.put(:multi_factor_authentication_settings, nil)
|> Map.put(:notification_settings, nil)
assert user == expected
diff --git a/test/user_test.exs b/test/user_test.exs
index 65e118d6d..98c79da4f 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -15,7 +15,6 @@ defmodule Pleroma.UserTest do
use Pleroma.DataCase
use Oban.Testing, repo: Pleroma.Repo
- import Mock
import Pleroma.Factory
import ExUnit.CaptureLog
@@ -556,6 +555,7 @@ defmodule Pleroma.UserTest do
assert user == fetched_user
end
+ @tag capture_log: true
test "returns nil if no user could be fetched" do
{:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
assert fetched_user == "not found nonexistant@social.heldscal.la"
@@ -586,6 +586,26 @@ defmodule Pleroma.UserTest do
refute user.last_refreshed_at == orig_user.last_refreshed_at
end
+
+ @tag capture_log: true
+ test "it returns the old user if stale, but unfetchable" do
+ a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
+
+ orig_user =
+ insert(
+ :user,
+ local: false,
+ nickname: "admin@mastodon.example.org",
+ ap_id: "http://mastodon.example.org/users/raymoo",
+ last_refreshed_at: a_week_ago
+ )
+
+ assert orig_user.last_refreshed_at == a_week_ago
+
+ {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
+
+ assert user.last_refreshed_at == orig_user.last_refreshed_at
+ end
end
test "returns an ap_id for a user" do
@@ -756,8 +776,8 @@ defmodule Pleroma.UserTest do
]
{:ok, job} = User.follow_import(user1, identifiers)
- result = ObanHelpers.perform(job)
+ assert {:ok, result} = ObanHelpers.perform(job)
assert is_list(result)
assert result == [user2, user3]
end
@@ -979,14 +999,26 @@ defmodule Pleroma.UserTest do
]
{:ok, job} = User.blocks_import(user1, identifiers)
- result = ObanHelpers.perform(job)
+ assert {:ok, result} = ObanHelpers.perform(job)
assert is_list(result)
assert result == [user2, user3]
end
end
describe "get_recipients_from_activity" do
+ test "works for announces" do
+ actor = insert(:user)
+ user = insert(:user, local: true)
+
+ {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
+ {:ok, announce} = CommonAPI.repeat(activity.id, user)
+
+ recipients = User.get_recipients_from_activity(announce)
+
+ assert user in recipients
+ end
+
test "get recipients" do
actor = insert(:user)
user = insert(:user, local: true)
@@ -996,7 +1028,7 @@ defmodule Pleroma.UserTest do
{:ok, activity} =
CommonAPI.post(actor, %{
- "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
+ status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
})
assert Enum.map([actor, addressed], & &1.ap_id) --
@@ -1018,7 +1050,7 @@ defmodule Pleroma.UserTest do
{:ok, activity} =
CommonAPI.post(actor, %{
- "status" => "hey @#{addressed.nickname}"
+ status: "hey @#{addressed.nickname}"
})
assert Enum.map([actor, addressed], & &1.ap_id) --
@@ -1079,7 +1111,7 @@ defmodule Pleroma.UserTest do
{:ok, user2} = User.follow(user2, user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
activity = Repo.preload(activity, :bookmark)
@@ -1090,7 +1122,7 @@ defmodule Pleroma.UserTest do
assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
- "user" => user2
+ user: user2
})
{:ok, _user} = User.deactivate(user)
@@ -1100,7 +1132,7 @@ defmodule Pleroma.UserTest do
assert [] ==
ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
- "user" => user2
+ user: user2
})
end
end
@@ -1115,27 +1147,21 @@ defmodule Pleroma.UserTest do
setup do: clear_config([:instance, :federating])
test ".delete_user_activities deletes all create activities", %{user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
User.delete_user_activities(user)
- # TODO: Remove favorites, repeats, delete activities.
+ # TODO: Test removal favorites, repeats, delete activities.
refute Activity.get_by_id(activity.id)
end
- test "it deletes deactivated user" do
- {:ok, user} = insert(:user, deactivated: true) |> User.set_cache()
-
- {:ok, job} = User.delete(user)
- {:ok, _user} = ObanHelpers.perform(job)
-
- refute User.get_by_id(user.id)
- end
-
- test "it deletes a user, all follow relationships and all activities", %{user: user} do
+ test "it deactivates a user, all follow relationships and all activities", %{user: user} do
follower = insert(:user)
{:ok, follower} = User.follow(follower, user)
+ locked_user = insert(:user, name: "locked", locked: true)
+ {:ok, _} = User.follow(user, locked_user, :follow_pending)
+
object = insert(:note, user: user)
activity = insert(:note_activity, user: user, note: object)
@@ -1144,7 +1170,7 @@ defmodule Pleroma.UserTest do
{:ok, like} = CommonAPI.favorite(user, activity_two.id)
{:ok, like_two} = CommonAPI.favorite(follower, activity.id)
- {:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)
+ {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
{:ok, job} = User.delete(user)
{:ok, _user} = ObanHelpers.perform(job)
@@ -1152,8 +1178,9 @@ defmodule Pleroma.UserTest do
follower = User.get_cached_by_id(follower.id)
refute User.following?(follower, user)
- refute User.get_by_id(user.id)
- assert {:ok, nil} == Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
+ assert %{deactivated: true} = User.get_by_id(user.id)
+
+ assert [] == User.get_follow_requests(locked_user)
user_activities =
user.ap_id
@@ -1168,30 +1195,32 @@ defmodule Pleroma.UserTest do
refute Activity.get_by_id(like_two.id)
refute Activity.get_by_id(repeat.id)
end
+ end
- test_with_mock "it sends out User Delete activity",
- %{user: user},
- Pleroma.Web.ActivityPub.Publisher,
- [:passthrough],
- [] do
- Pleroma.Config.put([:instance, :federating], true)
+ describe "delete/1 when confirmation is pending" do
+ setup do
+ user = insert(:user, confirmation_pending: true)
+ {:ok, user: user}
+ end
- {:ok, follower} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
- {:ok, _} = User.follow(follower, user)
+ test "deletes user from database when activation required", %{user: user} do
+ clear_config([:instance, :account_activation_required], true)
{:ok, job} = User.delete(user)
- {:ok, _user} = ObanHelpers.perform(job)
+ {:ok, _} = ObanHelpers.perform(job)
- assert ObanHelpers.member?(
- %{
- "op" => "publish_one",
- "params" => %{
- "inbox" => "http://mastodon.example.org/inbox",
- "id" => "pleroma:fakeid"
- }
- },
- all_enqueued(worker: Pleroma.Workers.PublisherWorker)
- )
+ refute User.get_cached_by_id(user.id)
+ refute User.get_by_id(user.id)
+ end
+
+ test "deactivates user when activation is not required", %{user: user} do
+ clear_config([:instance, :account_activation_required], false)
+
+ {:ok, job} = User.delete(user)
+ {:ok, _} = ObanHelpers.perform(job)
+
+ assert %{deactivated: true} = User.get_cached_by_id(user.id)
+ assert %{deactivated: true} = User.get_by_id(user.id)
end
end
@@ -1435,7 +1464,7 @@ defmodule Pleroma.UserTest do
{:ok, _} =
CommonAPI.post(user, %{
- "status" => "hey @#{to.nickname}"
+ status: "hey @#{to.nickname}"
})
end)
@@ -1467,12 +1496,12 @@ defmodule Pleroma.UserTest do
Enum.each(recipients, fn to ->
{:ok, _} =
CommonAPI.post(sender, %{
- "status" => "hey @#{to.nickname}"
+ status: "hey @#{to.nickname}"
})
{:ok, _} =
CommonAPI.post(sender, %{
- "status" => "hey again @#{to.nickname}"
+ status: "hey again @#{to.nickname}"
})
end)
@@ -1773,4 +1802,16 @@ defmodule Pleroma.UserTest do
assert result.email_notifications["digest"] == false
end
end
+
+ test "avatar fallback" do
+ user = insert(:user)
+ assert User.avatar_url(user) =~ "/images/avi.png"
+
+ clear_config([:assets, :default_user_avatar], "avatar.png")
+
+ user = User.get_cached_by_nickname_or_id(user.nickname)
+ assert User.avatar_url(user) =~ "avatar.png"
+
+ assert User.avatar_url(user, no_default: true) == nil
+ end
end
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index fbacb3993..e490a5744 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -6,7 +6,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
use Pleroma.Web.ConnCase
use Oban.Testing, repo: Pleroma.Repo
- import Pleroma.Factory
alias Pleroma.Activity
alias Pleroma.Config
alias Pleroma.Delivery
@@ -14,13 +13,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
alias Pleroma.Object
alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.UserView
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.Endpoint
alias Pleroma.Workers.ReceiverWorker
+ import Pleroma.Factory
+
+ require Pleroma.Constants
+
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
@@ -168,6 +173,60 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
end
end
+ describe "mastodon compatibility routes" do
+ test "it returns a json representation of the object with accept application/json", %{
+ conn: conn
+ } do
+ {:ok, object} =
+ %{
+ "type" => "Note",
+ "content" => "hey",
+ "id" => Endpoint.url() <> "/users/raymoo/statuses/999999999",
+ "actor" => Endpoint.url() <> "/users/raymoo",
+ "to" => [Pleroma.Constants.as_public()]
+ }
+ |> Object.create()
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/users/raymoo/statuses/999999999")
+
+ assert json_response(conn, 200) == ObjectView.render("object.json", %{object: object})
+ end
+
+ test "it returns a json representation of the activity with accept application/json", %{
+ conn: conn
+ } do
+ {:ok, object} =
+ %{
+ "type" => "Note",
+ "content" => "hey",
+ "id" => Endpoint.url() <> "/users/raymoo/statuses/999999999",
+ "actor" => Endpoint.url() <> "/users/raymoo",
+ "to" => [Pleroma.Constants.as_public()]
+ }
+ |> Object.create()
+
+ {:ok, activity, _} =
+ %{
+ "id" => object.data["id"] <> "/activity",
+ "type" => "Create",
+ "object" => object.data["id"],
+ "actor" => object.data["actor"],
+ "to" => object.data["to"]
+ }
+ |> ActivityPub.persist(local: true)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/users/raymoo/statuses/999999999/activity")
+
+ assert json_response(conn, 200) == ObjectView.render("object.json", %{object: activity})
+ end
+ end
+
describe "/objects/:uuid" do
test "it returns a json representation of the object with accept application/json", %{
conn: conn
@@ -341,7 +400,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "cached purged after activity deletion", %{conn: conn} do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "cofe"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "cofe"})
uuid = String.split(activity.data["id"], "/") |> List.last()
@@ -392,6 +451,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert Activity.get_by_ap_id(data["id"])
end
+ @tag capture_log: true
+ test "it inserts an incoming activity into the database" <>
+ "even if we can't fetch the user but have it in our db",
+ %{conn: conn} do
+ user =
+ insert(:user,
+ ap_id: "https://mastodon.example.org/users/raymoo",
+ ap_enabled: true,
+ local: false,
+ last_refreshed_at: nil
+ )
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ |> Map.put("actor", user.ap_id)
+ |> put_in(["object", "attridbutedTo"], user.ap_id)
+
+ conn =
+ conn
+ |> assign(:valid_signature, true)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/inbox", data)
+
+ assert "ok" == json_response(conn, 200)
+
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
+ assert Activity.get_by_ap_id(data["id"])
+ end
+
test "it clears `unreachable` federation status of the sender", %{conn: conn} do
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
@@ -715,17 +804,63 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
end
describe "GET /users/:nickname/outbox" do
+ test "it paginates correctly", %{conn: conn} do
+ user = insert(:user)
+ conn = assign(conn, :user, user)
+ outbox_endpoint = user.ap_id <> "/outbox"
+
+ _posts =
+ for i <- 0..25 do
+ {:ok, activity} = CommonAPI.post(user, %{status: "post #{i}"})
+ activity
+ end
+
+ result =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get(outbox_endpoint <> "?page=true")
+ |> json_response(200)
+
+ result_ids = Enum.map(result["orderedItems"], fn x -> x["id"] end)
+ assert length(result["orderedItems"]) == 20
+ assert length(result_ids) == 20
+ assert result["next"]
+ assert String.starts_with?(result["next"], outbox_endpoint)
+
+ result_next =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get(result["next"])
+ |> json_response(200)
+
+ result_next_ids = Enum.map(result_next["orderedItems"], fn x -> x["id"] end)
+ assert length(result_next["orderedItems"]) == 6
+ assert length(result_next_ids) == 6
+ refute Enum.find(result_next_ids, fn x -> x in result_ids end)
+ refute Enum.find(result_ids, fn x -> x in result_next_ids end)
+ assert String.starts_with?(result["id"], outbox_endpoint)
+
+ result_next_again =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get(result_next["id"])
+ |> json_response(200)
+
+ assert result_next == result_next_again
+ end
+
test "it returns 200 even if there're no activities", %{conn: conn} do
user = insert(:user)
+ outbox_endpoint = user.ap_id <> "/outbox"
conn =
conn
|> assign(:user, user)
|> put_req_header("accept", "application/activity+json")
- |> get("/users/#{user.nickname}/outbox")
+ |> get(outbox_endpoint)
result = json_response(conn, 200)
- assert user.ap_id <> "/outbox" == result["id"]
+ assert outbox_endpoint == result["id"]
end
test "it returns a note activity in a collection", %{conn: conn} do
@@ -765,51 +900,110 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
end
end
- describe "POST /users/:nickname/outbox" do
- test "it rejects posts from other users / unauuthenticated users", %{conn: conn} do
- data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
+ describe "POST /users/:nickname/outbox (C2S)" do
+ setup do
+ [
+ activity: %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "type" => "Create",
+ "object" => %{"type" => "Note", "content" => "AP C2S test"},
+ "to" => "https://www.w3.org/ns/activitystreams#Public",
+ "cc" => []
+ }
+ ]
+ end
+
+ test "it rejects posts from other users / unauthenticated users", %{
+ conn: conn,
+ activity: activity
+ } do
user = insert(:user)
other_user = insert(:user)
conn = put_req_header(conn, "content-type", "application/activity+json")
conn
- |> post("/users/#{user.nickname}/outbox", data)
+ |> post("/users/#{user.nickname}/outbox", activity)
|> json_response(403)
conn
|> assign(:user, other_user)
- |> post("/users/#{user.nickname}/outbox", data)
+ |> post("/users/#{user.nickname}/outbox", activity)
|> json_response(403)
end
- test "it inserts an incoming create activity into the database", %{conn: conn} do
- data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
+ test "it inserts an incoming create activity into the database", %{
+ conn: conn,
+ activity: activity
+ } do
user = insert(:user)
- conn =
+ result =
conn
|> assign(:user, user)
|> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", data)
-
- result = json_response(conn, 201)
+ |> post("/users/#{user.nickname}/outbox", activity)
+ |> json_response(201)
assert Activity.get_by_ap_id(result["id"])
+ assert result["object"]
+ assert %Object{data: object} = Object.normalize(result["object"])
+ assert object["content"] == activity["object"]["content"]
end
- test "it rejects an incoming activity with bogus type", %{conn: conn} do
- data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
+ test "it rejects anything beyond 'Note' creations", %{conn: conn, activity: activity} do
user = insert(:user)
- data =
- data
- |> Map.put("type", "BadType")
+ activity =
+ activity
+ |> put_in(["object", "type"], "Benis")
+
+ _result =
+ conn
+ |> assign(:user, user)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/outbox", activity)
+ |> json_response(400)
+ end
+
+ test "it inserts an incoming sensitive activity into the database", %{
+ conn: conn,
+ activity: activity
+ } do
+ user = insert(:user)
+ conn = assign(conn, :user, user)
+ object = Map.put(activity["object"], "sensitive", true)
+ activity = Map.put(activity, "object", object)
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/outbox", activity)
+ |> json_response(201)
+
+ assert Activity.get_by_ap_id(response["id"])
+ assert response["object"]
+ assert %Object{data: response_object} = Object.normalize(response["object"])
+ assert response_object["sensitive"] == true
+ assert response_object["content"] == activity["object"]["content"]
+
+ representation =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get(response["id"])
+ |> json_response(200)
+
+ assert representation["object"]["sensitive"] == true
+ end
+
+ test "it rejects an incoming activity with bogus type", %{conn: conn, activity: activity} do
+ user = insert(:user)
+ activity = Map.put(activity, "type", "BadType")
conn =
conn
|> assign(:user, user)
|> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", data)
+ |> post("/users/#{user.nickname}/outbox", activity)
assert json_response(conn, 400)
end
@@ -1019,12 +1213,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert result["totalItems"] == 15
end
- test "returns 403 if requester is not logged in", %{conn: conn} do
+ test "does not require authentication", %{conn: conn} do
user = insert(:user)
conn
|> get("/users/#{user.nickname}/followers")
- |> json_response(403)
+ |> json_response(200)
end
end
@@ -1116,12 +1310,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert result["totalItems"] == 15
end
- test "returns 403 if requester is not logged in", %{conn: conn} do
+ test "does not require authentication", %{conn: conn} do
user = insert(:user)
conn
|> get("/users/#{user.nickname}/following")
- |> json_response(403)
+ |> json_response(200)
end
end
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index 6410df49b..7693f6400 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -16,11 +16,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
- alias Pleroma.Web.Federator
+ import ExUnit.CaptureLog
+ import Mock
import Pleroma.Factory
import Tesla.Mock
- import Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
@@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
describe "streaming out participations" do
test "it streams them out" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+ {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
{:ok, conversation} = Pleroma.Conversation.create_or_bump_for(activity)
@@ -56,8 +56,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
stream: fn _, _ -> nil end do
{:ok, activity} =
CommonAPI.post(user_one, %{
- "status" => "@#{user_two.nickname}",
- "visibility" => "direct"
+ status: "@#{user_two.nickname}",
+ visibility: "direct"
})
conversation =
@@ -74,40 +74,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
test "it restricts by the appropriate visibility" do
user = insert(:user)
- {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+ {:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
- {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+ {:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
- {:ok, unlisted_activity} =
- CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
+ {:ok, unlisted_activity} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
- {:ok, private_activity} =
- CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ {:ok, private_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
- activities =
- ActivityPub.fetch_activities([], %{:visibility => "direct", "actor_id" => user.ap_id})
+ activities = ActivityPub.fetch_activities([], %{visibility: "direct", actor_id: user.ap_id})
assert activities == [direct_activity]
activities =
- ActivityPub.fetch_activities([], %{:visibility => "unlisted", "actor_id" => user.ap_id})
+ ActivityPub.fetch_activities([], %{visibility: "unlisted", actor_id: user.ap_id})
assert activities == [unlisted_activity]
activities =
- ActivityPub.fetch_activities([], %{:visibility => "private", "actor_id" => user.ap_id})
+ ActivityPub.fetch_activities([], %{visibility: "private", actor_id: user.ap_id})
assert activities == [private_activity]
- activities =
- ActivityPub.fetch_activities([], %{:visibility => "public", "actor_id" => user.ap_id})
+ activities = ActivityPub.fetch_activities([], %{visibility: "public", actor_id: user.ap_id})
assert activities == [public_activity]
activities =
ActivityPub.fetch_activities([], %{
- :visibility => ~w[private public],
- "actor_id" => user.ap_id
+ visibility: ~w[private public],
+ actor_id: user.ap_id
})
assert activities == [public_activity, private_activity]
@@ -118,20 +114,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
test "it excludes by the appropriate visibility" do
user = insert(:user)
- {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+ {:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
- {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+ {:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
- {:ok, unlisted_activity} =
- CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
+ {:ok, unlisted_activity} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
- {:ok, private_activity} =
- CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ {:ok, private_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
activities =
ActivityPub.fetch_activities([], %{
- "exclude_visibilities" => "direct",
- "actor_id" => user.ap_id
+ exclude_visibilities: "direct",
+ actor_id: user.ap_id
})
assert public_activity in activities
@@ -141,8 +135,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activities =
ActivityPub.fetch_activities([], %{
- "exclude_visibilities" => "unlisted",
- "actor_id" => user.ap_id
+ exclude_visibilities: "unlisted",
+ actor_id: user.ap_id
})
assert public_activity in activities
@@ -152,8 +146,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activities =
ActivityPub.fetch_activities([], %{
- "exclude_visibilities" => "private",
- "actor_id" => user.ap_id
+ exclude_visibilities: "private",
+ actor_id: user.ap_id
})
assert public_activity in activities
@@ -163,8 +157,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activities =
ActivityPub.fetch_activities([], %{
- "exclude_visibilities" => "public",
- "actor_id" => user.ap_id
+ exclude_visibilities: "public",
+ actor_id: user.ap_id
})
refute public_activity in activities
@@ -193,27 +187,26 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
test "it fetches the appropriate tag-restricted posts" do
user = insert(:user)
- {: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"})
+ {: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_one = ActivityPub.fetch_activities([], %{"type" => "Create", "tag" => "test"})
+ fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"})
- fetch_two =
- ActivityPub.fetch_activities([], %{"type" => "Create", "tag" => ["test", "essais"]})
+ fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]})
fetch_three =
ActivityPub.fetch_activities([], %{
- "type" => "Create",
- "tag" => ["test", "essais"],
- "tag_reject" => ["reject"]
+ type: "Create",
+ tag: ["test", "essais"],
+ tag_reject: ["reject"]
})
fetch_four =
ActivityPub.fetch_activities([], %{
- "type" => "Create",
- "tag" => ["test"],
- "tag_all" => ["test", "reject"]
+ type: "Create",
+ tag: ["test"],
+ tag_all: ["test", "reject"]
})
assert fetch_one == [status_one, status_three]
@@ -379,7 +372,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
_listen_activity_2 = insert(:listen)
_listen_activity_3 = insert(:listen)
- timeline = ActivityPub.fetch_activities([], %{"type" => ["Listen"]})
+ timeline = ActivityPub.fetch_activities([], %{type: ["Listen"]})
assert length(timeline) == 3
end
@@ -432,26 +425,26 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _} =
CommonAPI.post(User.get_cached_by_id(user.id), %{
- "status" => "1",
- "visibility" => "public"
+ status: "1",
+ visibility: "public"
})
{:ok, _} =
CommonAPI.post(User.get_cached_by_id(user.id), %{
- "status" => "2",
- "visibility" => "unlisted"
+ status: "2",
+ visibility: "unlisted"
})
{:ok, _} =
CommonAPI.post(User.get_cached_by_id(user.id), %{
- "status" => "2",
- "visibility" => "private"
+ status: "2",
+ visibility: "private"
})
{:ok, _} =
CommonAPI.post(User.get_cached_by_id(user.id), %{
- "status" => "3",
- "visibility" => "direct"
+ status: "3",
+ visibility: "direct"
})
user = User.get_cached_by_id(user.id)
@@ -462,27 +455,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
user = insert(:user)
user2 = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "1", "visibility" => "public"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"})
ap_id = activity.data["id"]
- reply_data = %{"status" => "1", "in_reply_to_status_id" => activity.id}
+ reply_data = %{status: "1", in_reply_to_status_id: activity.id}
# public
- {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "public"))
+ {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "public"))
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
assert object.data["repliesCount"] == 1
# unlisted
- {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "unlisted"))
+ {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "unlisted"))
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
assert object.data["repliesCount"] == 2
# private
- {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "private"))
+ {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "private"))
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
assert object.data["repliesCount"] == 2
# direct
- {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "direct"))
+ {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "direct"))
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
assert object.data["repliesCount"] == 2
end
@@ -511,7 +504,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _user_relationship} = User.block(user, %{ap_id: activity_five.data["actor"]})
- activities = ActivityPub.fetch_activities_for_context("2hu", %{"blocking_user" => user})
+ activities = ActivityPub.fetch_activities_for_context("2hu", %{blocking_user: user})
assert activities == [activity_two, activity]
end
end
@@ -524,8 +517,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
booster = insert(:user)
{:ok, _user_relationship} = User.block(user, %{ap_id: activity_one.data["actor"]})
- activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
assert Enum.member?(activities, activity_two)
assert Enum.member?(activities, activity_three)
@@ -533,28 +525,25 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _user_block} = User.unblock(user, %{ap_id: activity_one.data["actor"]})
- activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
assert Enum.member?(activities, activity_two)
assert Enum.member?(activities, activity_three)
assert Enum.member?(activities, activity_one)
{:ok, _user_relationship} = User.block(user, %{ap_id: activity_three.data["actor"]})
- {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
+ {:ok, %{data: %{"object" => id}}} = CommonAPI.repeat(activity_three.id, booster)
%Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
activity_three = Activity.get_by_id(activity_three.id)
- activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
assert Enum.member?(activities, activity_two)
refute Enum.member?(activities, activity_three)
refute Enum.member?(activities, boost_activity)
assert Enum.member?(activities, activity_one)
- activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => nil, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: nil, skip_preload: true})
assert Enum.member?(activities, activity_two)
assert Enum.member?(activities, activity_three)
@@ -569,15 +558,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _user_relationship} = User.block(blocker, blockee)
- {:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
+ {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
- {:ok, activity_two} = CommonAPI.post(friend, %{"status" => "hey! @#{blockee.nickname}"})
+ {:ok, activity_two} = CommonAPI.post(friend, %{status: "hey! @#{blockee.nickname}"})
- {:ok, activity_three} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
+ {:ok, activity_three} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
- {:ok, activity_four} = CommonAPI.post(blockee, %{"status" => "hey! @#{blocker.nickname}"})
+ {:ok, activity_four} = CommonAPI.post(blockee, %{status: "hey! @#{blocker.nickname}"})
- activities = ActivityPub.fetch_activities([], %{"blocking_user" => blocker})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: blocker})
assert Enum.member?(activities, activity_one)
refute Enum.member?(activities, activity_two)
@@ -585,21 +574,54 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
refute Enum.member?(activities, activity_four)
end
- test "doesn't return announce activities concerning blocked users" do
+ test "doesn't return announce activities with blocked users in 'to'" do
+ blocker = insert(:user)
+ blockee = insert(:user)
+ friend = insert(:user)
+
+ {:ok, _user_relationship} = User.block(blocker, blockee)
+
+ {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
+
+ {:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
+
+ {:ok, activity_three} = CommonAPI.repeat(activity_two.id, friend)
+
+ activities =
+ ActivityPub.fetch_activities([], %{blocking_user: blocker})
+ |> Enum.map(fn act -> act.id end)
+
+ assert Enum.member?(activities, activity_one.id)
+ refute Enum.member?(activities, activity_two.id)
+ refute Enum.member?(activities, activity_three.id)
+ end
+
+ test "doesn't return announce activities with blocked users in 'cc'" do
blocker = insert(:user)
blockee = insert(:user)
friend = insert(:user)
{:ok, _user_relationship} = User.block(blocker, blockee)
- {:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
+ {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
+
+ {:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
- {:ok, activity_two} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
+ assert object = Pleroma.Object.normalize(activity_two)
- {:ok, activity_three, _} = CommonAPI.repeat(activity_two.id, friend)
+ data = %{
+ "actor" => friend.ap_id,
+ "object" => object.data["id"],
+ "context" => object.data["context"],
+ "type" => "Announce",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [blockee.ap_id]
+ }
+
+ assert {:ok, activity_three} = ActivityPub.insert(data)
activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => blocker})
+ ActivityPub.fetch_activities([], %{blocking_user: blocker})
|> Enum.map(fn act -> act.id end)
assert Enum.member?(activities, activity_one.id)
@@ -615,17 +637,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
user = insert(:user)
{:ok, user} = User.block_domain(user, domain)
- activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
refute activity in activities
followed_user = insert(:user)
ActivityPub.follow(user, followed_user)
- {:ok, repeat_activity, _} = CommonAPI.repeat(activity.id, followed_user)
+ {:ok, repeat_activity} = CommonAPI.repeat(activity.id, followed_user)
- activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
refute repeat_activity in activities
end
@@ -645,8 +665,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
note = insert(:note, %{data: %{"actor" => domain_user.ap_id}})
activity = insert(:note_activity, %{note: note})
- activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => blocker, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: blocker, skip_preload: true})
assert activity in activities
@@ -655,10 +674,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
another_user = insert(:user, %{ap_id: "https://#{domain}/@meanie2"})
bad_note = insert(:note, %{data: %{"actor" => another_user.ap_id}})
bad_activity = insert(:note_activity, %{note: bad_note})
- {:ok, repeat_activity, _} = CommonAPI.repeat(bad_activity.id, domain_user)
+ {:ok, repeat_activity} = CommonAPI.repeat(bad_activity.id, domain_user)
- activities =
- ActivityPub.fetch_activities([], %{"blocking_user" => blocker, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{blocking_user: blocker, skip_preload: true})
refute repeat_activity in activities
end
@@ -673,8 +691,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activity_one_actor = User.get_by_ap_id(activity_one.data["actor"])
{:ok, _user_relationships} = User.mute(user, activity_one_actor)
- activities =
- ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true})
assert Enum.member?(activities, activity_two)
assert Enum.member?(activities, activity_three)
@@ -683,9 +700,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
# Calling with 'with_muted' will deliver muted activities, too.
activities =
ActivityPub.fetch_activities([], %{
- "muting_user" => user,
- "with_muted" => true,
- "skip_preload" => true
+ muting_user: user,
+ with_muted: true,
+ skip_preload: true
})
assert Enum.member?(activities, activity_two)
@@ -694,8 +711,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _user_mute} = User.unmute(user, activity_one_actor)
- activities =
- ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true})
assert Enum.member?(activities, activity_two)
assert Enum.member?(activities, activity_three)
@@ -703,19 +719,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activity_three_actor = User.get_by_ap_id(activity_three.data["actor"])
{:ok, _user_relationships} = User.mute(user, activity_three_actor)
- {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
+ {:ok, %{data: %{"object" => id}}} = CommonAPI.repeat(activity_three.id, booster)
%Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
activity_three = Activity.get_by_id(activity_three.id)
- activities =
- ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true})
assert Enum.member?(activities, activity_two)
refute Enum.member?(activities, activity_three)
refute Enum.member?(activities, boost_activity)
assert Enum.member?(activities, activity_one)
- activities = ActivityPub.fetch_activities([], %{"muting_user" => nil, "skip_preload" => true})
+ activities = ActivityPub.fetch_activities([], %{muting_user: nil, skip_preload: true})
assert Enum.member?(activities, activity_two)
assert Enum.member?(activities, activity_three)
@@ -731,7 +746,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
- assert [_activity_one] = ActivityPub.fetch_activities([], %{"muting_user" => user})
+ assert [_activity_one] = ActivityPub.fetch_activities([], %{muting_user: user})
end
test "returns thread muted activities when with_muted is set" do
@@ -743,7 +758,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
assert [_activity_two, _activity_one] =
- ActivityPub.fetch_activities([], %{"muting_user" => user, "with_muted" => true})
+ ActivityPub.fetch_activities([], %{muting_user: user, with_muted: true})
end
test "does include announces on request" do
@@ -753,7 +768,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, user} = User.follow(user, booster)
- {:ok, announce, _object} = CommonAPI.repeat(activity_three.id, booster)
+ {:ok, announce} = CommonAPI.repeat(activity_three.id, booster)
[announce_activity] = ActivityPub.fetch_activities([user.ap_id | User.following(user)])
@@ -765,7 +780,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, expected_activity} = ActivityBuilder.insert(%{"type" => "Create"}, %{:user => user})
{:ok, _} = ActivityBuilder.insert(%{"type" => "Announce"}, %{:user => user})
- [activity] = ActivityPub.fetch_user_activities(user, nil, %{"exclude_reblogs" => "true"})
+ [activity] = ActivityPub.fetch_user_activities(user, nil, %{exclude_reblogs: true})
assert activity == expected_activity
end
@@ -774,10 +789,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
test "doesn't retrieve unlisted activities" do
user = insert(:user)
- {:ok, _unlisted_activity} =
- CommonAPI.post(user, %{"status" => "yeah", "visibility" => "unlisted"})
+ {:ok, _unlisted_activity} = CommonAPI.post(user, %{status: "yeah", visibility: "unlisted"})
- {:ok, listed_activity} = CommonAPI.post(user, %{"status" => "yeah"})
+ {:ok, listed_activity} = CommonAPI.post(user, %{status: "yeah"})
[activity] = ActivityPub.fetch_public_activities()
@@ -809,7 +823,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
expected_activities = ActivityBuilder.insert_list(10)
since_id = List.last(activities).id
- activities = ActivityPub.fetch_public_activities(%{"since_id" => since_id})
+ activities = ActivityPub.fetch_public_activities(%{since_id: since_id})
assert collect_ids(activities) == collect_ids(expected_activities)
assert length(activities) == 10
@@ -824,7 +838,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|> ActivityBuilder.insert_list()
|> List.first()
- activities = ActivityPub.fetch_public_activities(%{"max_id" => max_id})
+ activities = ActivityPub.fetch_public_activities(%{max_id: max_id})
assert length(activities) == 20
assert collect_ids(activities) == collect_ids(expected_activities)
@@ -836,8 +850,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
later_activities = ActivityBuilder.insert_list(10)
- activities =
- ActivityPub.fetch_public_activities(%{"page" => "2", "page_size" => "20"}, :offset)
+ activities = ActivityPub.fetch_public_activities(%{page: "2", page_size: "20"}, :offset)
assert length(activities) == 20
@@ -851,9 +864,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
booster = insert(:user)
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
- {:ok, activity, _} = CommonAPI.repeat(activity.id, booster)
+ {:ok, activity} = CommonAPI.repeat(activity.id, booster)
- activities = ActivityPub.fetch_activities([], %{"muting_user" => user})
+ activities = ActivityPub.fetch_activities([], %{muting_user: user})
refute Enum.any?(activities, fn %{id: id} -> id == activity.id end)
end
@@ -865,373 +878,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
{:ok, _reblog_mute} = CommonAPI.show_reblogs(user, booster)
- {:ok, activity, _} = CommonAPI.repeat(activity.id, booster)
+ {:ok, activity} = CommonAPI.repeat(activity.id, booster)
- activities = ActivityPub.fetch_activities([], %{"muting_user" => user})
+ activities = ActivityPub.fetch_activities([], %{muting_user: user})
assert Enum.any?(activities, fn %{id: id} -> id == activity.id end)
end
end
- describe "react to an object" do
- test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
- Config.put([:instance, :federating], true)
- user = insert(:user)
- reactor = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
- assert object = Object.normalize(activity)
-
- {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
-
- assert called(Federator.publish(reaction_activity))
- end
-
- test "adds an emoji reaction activity to the db" do
- user = insert(:user)
- reactor = insert(:user)
- third_user = insert(:user)
- fourth_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
- assert object = Object.normalize(activity)
-
- {:ok, reaction_activity, object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
-
- assert reaction_activity
-
- assert reaction_activity.data["actor"] == reactor.ap_id
- assert reaction_activity.data["type"] == "EmojiReact"
- assert reaction_activity.data["content"] == "🔥"
- assert reaction_activity.data["object"] == object.data["id"]
- assert reaction_activity.data["to"] == [User.ap_followers(reactor), activity.data["actor"]]
- assert reaction_activity.data["context"] == object.data["context"]
- assert object.data["reaction_count"] == 1
- assert object.data["reactions"] == [["🔥", [reactor.ap_id]]]
-
- {:ok, _reaction_activity, object} = ActivityPub.react_with_emoji(third_user, object, "☕")
-
- assert object.data["reaction_count"] == 2
- assert object.data["reactions"] == [["🔥", [reactor.ap_id]], ["☕", [third_user.ap_id]]]
-
- {:ok, _reaction_activity, object} = ActivityPub.react_with_emoji(fourth_user, object, "🔥")
-
- assert object.data["reaction_count"] == 3
-
- assert object.data["reactions"] == [
- ["🔥", [fourth_user.ap_id, reactor.ap_id]],
- ["☕", [third_user.ap_id]]
- ]
- end
-
- test "reverts emoji reaction on error" do
- [user, reactor] = insert_list(2, :user)
-
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Status"})
- object = Object.normalize(activity)
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.react_with_emoji(reactor, object, "😀")
- end
-
- object = Object.get_by_ap_id(object.data["id"])
- refute object.data["reaction_count"]
- refute object.data["reactions"]
- end
- end
-
- describe "unreacting to an object" do
- test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
- Config.put([:instance, :federating], true)
- user = insert(:user)
- reactor = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
- assert object = Object.normalize(activity)
-
- {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
-
- assert called(Federator.publish(reaction_activity))
-
- {:ok, unreaction_activity, _object} =
- ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
-
- assert called(Federator.publish(unreaction_activity))
- end
-
- test "adds an undo activity to the db" do
- user = insert(:user)
- reactor = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
- assert object = Object.normalize(activity)
-
- {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
-
- {:ok, unreaction_activity, _object} =
- ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
-
- assert unreaction_activity.actor == reactor.ap_id
- assert unreaction_activity.data["object"] == reaction_activity.data["id"]
-
- object = Object.get_by_ap_id(object.data["id"])
- assert object.data["reaction_count"] == 0
- assert object.data["reactions"] == []
- end
-
- test "reverts emoji unreact on error" do
- [user, reactor] = insert_list(2, :user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Status"})
- object = Object.normalize(activity)
-
- {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "😀")
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} =
- ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
- end
-
- object = Object.get_by_ap_id(object.data["id"])
-
- assert object.data["reaction_count"] == 1
- assert object.data["reactions"] == [["😀", [reactor.ap_id]]]
- end
- end
-
- describe "like an object" do
- test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
- Config.put([:instance, :federating], true)
- note_activity = insert(:note_activity)
- assert object_activity = Object.normalize(note_activity)
-
- user = insert(:user)
-
- {:ok, like_activity, _object} = ActivityPub.like(user, object_activity)
- assert called(Federator.publish(like_activity))
- end
-
- test "returns exist activity if object already liked" do
- note_activity = insert(:note_activity)
- assert object_activity = Object.normalize(note_activity)
-
- user = insert(:user)
-
- {:ok, like_activity, _object} = ActivityPub.like(user, object_activity)
-
- {:ok, like_activity_exist, _object} = ActivityPub.like(user, object_activity)
- assert like_activity == like_activity_exist
- end
-
- test "reverts like activity on error" do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.like(user, object)
- end
-
- assert Repo.aggregate(Activity, :count, :id) == 1
- assert Repo.get(Object, object.id) == object
- end
-
- test "adds a like activity to the db" do
- note_activity = insert(:note_activity)
- assert object = Object.normalize(note_activity)
-
- user = insert(:user)
- user_two = insert(:user)
-
- {:ok, like_activity, object} = ActivityPub.like(user, object)
-
- assert like_activity.data["actor"] == user.ap_id
- assert like_activity.data["type"] == "Like"
- assert like_activity.data["object"] == object.data["id"]
- assert like_activity.data["to"] == [User.ap_followers(user), note_activity.data["actor"]]
- assert like_activity.data["context"] == object.data["context"]
- assert object.data["like_count"] == 1
- assert object.data["likes"] == [user.ap_id]
-
- # Just return the original activity if the user already liked it.
- {:ok, same_like_activity, object} = ActivityPub.like(user, object)
-
- assert like_activity == same_like_activity
- assert object.data["likes"] == [user.ap_id]
- assert object.data["like_count"] == 1
-
- {:ok, _like_activity, object} = ActivityPub.like(user_two, object)
- assert object.data["like_count"] == 2
- end
- end
-
- describe "unliking" do
- test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
- Config.put([:instance, :federating], true)
-
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- {:ok, object} = ActivityPub.unlike(user, object)
- refute called(Federator.publish())
-
- {:ok, _like_activity, object} = ActivityPub.like(user, object)
- assert object.data["like_count"] == 1
-
- {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)
- assert object.data["like_count"] == 0
-
- assert called(Federator.publish(unlike_activity))
- end
-
- test "reverts unliking on error" do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- {:ok, like_activity, object} = ActivityPub.like(user, object)
- assert object.data["like_count"] == 1
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.unlike(user, object)
- end
-
- assert Object.get_by_ap_id(object.data["id"]) == object
- assert object.data["like_count"] == 1
- assert Activity.get_by_id(like_activity.id)
- end
-
- test "unliking a previously liked object" do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- # Unliking something that hasn't been liked does nothing
- {:ok, object} = ActivityPub.unlike(user, object)
- assert object.data["like_count"] == 0
-
- {:ok, like_activity, object} = ActivityPub.like(user, object)
- assert object.data["like_count"] == 1
-
- {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)
- assert object.data["like_count"] == 0
-
- assert Activity.get_by_id(like_activity.id) == nil
- assert note_activity.actor in unlike_activity.recipients
- end
- end
-
- describe "announcing an object" do
- test "adds an announce activity to the db" do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- {:ok, announce_activity, object} = ActivityPub.announce(user, object)
- assert object.data["announcement_count"] == 1
- assert object.data["announcements"] == [user.ap_id]
-
- assert announce_activity.data["to"] == [
- User.ap_followers(user),
- note_activity.data["actor"]
- ]
-
- assert announce_activity.data["object"] == object.data["id"]
- assert announce_activity.data["actor"] == user.ap_id
- assert announce_activity.data["context"] == object.data["context"]
- end
-
- test "reverts annouce from object on error" do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.announce(user, object)
- end
-
- reloaded_object = Object.get_by_ap_id(object.data["id"])
- assert reloaded_object == object
- refute reloaded_object.data["announcement_count"]
- refute reloaded_object.data["announcements"]
- end
- end
-
- describe "announcing a private object" do
- test "adds an announce activity to the db if the audience is not widened" do
- user = insert(:user)
- {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
- object = Object.normalize(note_activity)
-
- {:ok, announce_activity, object} = ActivityPub.announce(user, object, nil, true, false)
-
- assert announce_activity.data["to"] == [User.ap_followers(user)]
-
- assert announce_activity.data["object"] == object.data["id"]
- assert announce_activity.data["actor"] == user.ap_id
- assert announce_activity.data["context"] == object.data["context"]
- end
-
- test "does not add an announce activity to the db if the audience is widened" do
- user = insert(:user)
- {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
- object = Object.normalize(note_activity)
-
- assert {:error, _} = ActivityPub.announce(user, object, nil, true, true)
- end
-
- test "does not add an announce activity to the db if the announcer is not the author" do
- user = insert(:user)
- announcer = insert(:user)
- {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
- object = Object.normalize(note_activity)
-
- assert {:error, _} = ActivityPub.announce(announcer, object, nil, true, false)
- end
- end
-
- describe "unannouncing an object" do
- test "unannouncing a previously announced object" do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- # Unannouncing an object that is not announced does nothing
- {:ok, object} = ActivityPub.unannounce(user, object)
- refute object.data["announcement_count"]
-
- {:ok, announce_activity, object} = ActivityPub.announce(user, object)
- assert object.data["announcement_count"] == 1
-
- {:ok, unannounce_activity, object} = ActivityPub.unannounce(user, object)
- assert object.data["announcement_count"] == 0
-
- assert unannounce_activity.data["to"] == [
- User.ap_followers(user),
- object.data["actor"]
- ]
-
- assert unannounce_activity.data["type"] == "Undo"
- assert unannounce_activity.data["object"] == announce_activity.data
- assert unannounce_activity.data["actor"] == user.ap_id
- assert unannounce_activity.data["context"] == announce_activity.data["context"]
-
- assert Activity.get_by_id(announce_activity.id) == nil
- end
-
- test "reverts unannouncing on error" do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- {:ok, _announce_activity, object} = ActivityPub.announce(user, object)
- assert object.data["announcement_count"] == 1
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.unannounce(user, object)
- end
-
- object = Object.get_by_ap_id(object.data["id"])
- assert object.data["announcement_count"] == 1
- end
- end
-
describe "uploading files" do
test "copies the file to the configured folder" do
file = %Plug.Upload{
@@ -1246,7 +900,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
test "works with base64 encoded images" do
file = %{
- "img" => data_uri()
+ img: data_uri()
}
{:ok, %Object{}} = ActivityPub.upload(file)
@@ -1338,7 +992,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
- describe "blocking / unblocking" do
+ describe "blocking" do
test "reverts block activity on error" do
[blocker, blocked] = insert_list(2, :user)
@@ -1351,183 +1005,38 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
test "creates a block activity" do
+ clear_config([:instance, :federating], true)
blocker = insert(:user)
blocked = insert(:user)
- {:ok, activity} = ActivityPub.block(blocker, blocked)
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ {:ok, activity} = ActivityPub.block(blocker, blocked)
- assert activity.data["type"] == "Block"
- assert activity.data["actor"] == blocker.ap_id
- assert activity.data["object"] == blocked.ap_id
- end
-
- test "reverts unblock activity on error" do
- [blocker, blocked] = insert_list(2, :user)
- {:ok, block_activity} = ActivityPub.block(blocker, blocked)
+ assert activity.data["type"] == "Block"
+ assert activity.data["actor"] == blocker.ap_id
+ assert activity.data["object"] == blocked.ap_id
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.unblock(blocker, blocked)
+ assert called(Pleroma.Web.Federator.publish(activity))
end
-
- assert block_activity.data["type"] == "Block"
- assert block_activity.data["actor"] == blocker.ap_id
-
- assert Repo.aggregate(Activity, :count, :id) == 1
- assert Repo.aggregate(Object, :count, :id) == 1
end
- test "creates an undo activity for the last block" do
+ test "works with outgoing blocks disabled, but doesn't federate" do
+ clear_config([:instance, :federating], true)
+ clear_config([:activitypub, :outgoing_blocks], false)
blocker = insert(:user)
blocked = insert(:user)
- {:ok, block_activity} = ActivityPub.block(blocker, blocked)
- {:ok, activity} = ActivityPub.unblock(blocker, blocked)
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ {:ok, activity} = ActivityPub.block(blocker, blocked)
- assert activity.data["type"] == "Undo"
- assert activity.data["actor"] == blocker.ap_id
-
- embedded_object = activity.data["object"]
- assert is_map(embedded_object)
- assert embedded_object["type"] == "Block"
- assert embedded_object["object"] == blocked.ap_id
- assert embedded_object["id"] == block_activity.data["id"]
- end
- end
+ assert activity.data["type"] == "Block"
+ assert activity.data["actor"] == blocker.ap_id
+ assert activity.data["object"] == blocked.ap_id
- describe "deletion" do
- setup do: clear_config([:instance, :rewrite_policy])
-
- test "it reverts deletion on error" do
- note = insert(:note_activity)
- object = Object.normalize(note)
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.delete(object)
+ refute called(Pleroma.Web.Federator.publish(:_))
end
-
- assert Repo.aggregate(Activity, :count, :id) == 1
- assert Repo.get(Object, object.id) == object
- assert Activity.get_by_id(note.id) == note
- end
-
- test "it creates a delete activity and deletes the original object" do
- note = insert(:note_activity)
- object = Object.normalize(note)
- {:ok, delete} = ActivityPub.delete(object)
-
- assert delete.data["type"] == "Delete"
- assert delete.data["actor"] == note.data["actor"]
- assert delete.data["object"] == object.data["id"]
-
- assert Activity.get_by_id(delete.id) != nil
-
- assert Repo.get(Object, object.id).data["type"] == "Tombstone"
- end
-
- test "it doesn't fail when an activity was already deleted" do
- {:ok, delete} = insert(:note_activity) |> Object.normalize() |> ActivityPub.delete()
-
- assert {:ok, ^delete} = delete |> Object.normalize() |> ActivityPub.delete()
- end
-
- test "decrements user note count only for public activities" do
- user = insert(:user, note_count: 10)
-
- {:ok, a1} =
- CommonAPI.post(User.get_cached_by_id(user.id), %{
- "status" => "yeah",
- "visibility" => "public"
- })
-
- {:ok, a2} =
- CommonAPI.post(User.get_cached_by_id(user.id), %{
- "status" => "yeah",
- "visibility" => "unlisted"
- })
-
- {:ok, a3} =
- CommonAPI.post(User.get_cached_by_id(user.id), %{
- "status" => "yeah",
- "visibility" => "private"
- })
-
- {:ok, a4} =
- CommonAPI.post(User.get_cached_by_id(user.id), %{
- "status" => "yeah",
- "visibility" => "direct"
- })
-
- {:ok, _} = Object.normalize(a1) |> ActivityPub.delete()
- {:ok, _} = Object.normalize(a2) |> ActivityPub.delete()
- {:ok, _} = Object.normalize(a3) |> ActivityPub.delete()
- {:ok, _} = Object.normalize(a4) |> ActivityPub.delete()
-
- user = User.get_cached_by_id(user.id)
- assert user.note_count == 10
- end
-
- test "it creates a delete activity and checks that it is also sent to users mentioned by the deleted object" do
- user = insert(:user)
- note = insert(:note_activity)
- object = Object.normalize(note)
-
- {:ok, object} =
- object
- |> Object.change(%{
- data: %{
- "actor" => object.data["actor"],
- "id" => object.data["id"],
- "to" => [user.ap_id],
- "type" => "Note"
- }
- })
- |> Object.update_and_set_cache()
-
- {:ok, delete} = ActivityPub.delete(object)
-
- assert user.ap_id in delete.data["to"]
- end
-
- test "decreases reply count" do
- user = insert(:user)
- user2 = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{"status" => "1", "visibility" => "public"})
- reply_data = %{"status" => "1", "in_reply_to_status_id" => activity.id}
- ap_id = activity.data["id"]
-
- {:ok, public_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "public"))
- {:ok, unlisted_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "unlisted"))
- {:ok, private_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "private"))
- {:ok, direct_reply} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "direct"))
-
- _ = CommonAPI.delete(direct_reply.id, user2)
- assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
- assert object.data["repliesCount"] == 2
-
- _ = CommonAPI.delete(private_reply.id, user2)
- assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
- assert object.data["repliesCount"] == 2
-
- _ = CommonAPI.delete(public_reply.id, user2)
- assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
- assert object.data["repliesCount"] == 1
-
- _ = CommonAPI.delete(unlisted_reply.id, user2)
- assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
- assert object.data["repliesCount"] == 0
- end
-
- test "it passes delete activity through MRF before deleting the object" do
- Pleroma.Config.put([:instance, :rewrite_policy], Pleroma.Web.ActivityPub.MRF.DropPolicy)
-
- note = insert(:note_activity)
- object = Object.normalize(note)
-
- {:error, {:reject, _}} = ActivityPub.delete(object)
-
- assert Activity.get_by_id(note.id)
- assert Repo.get(Object, object.id).data["type"] == object.data["type"]
end
end
@@ -1546,23 +1055,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, user3} = User.follow(user3, user2)
assert User.following?(user3, user2)
- {:ok, public_activity} = CommonAPI.post(user3, %{"status" => "hi 1"})
+ {:ok, public_activity} = CommonAPI.post(user3, %{status: "hi 1"})
- {:ok, private_activity_1} =
- CommonAPI.post(user3, %{"status" => "hi 2", "visibility" => "private"})
+ {:ok, private_activity_1} = CommonAPI.post(user3, %{status: "hi 2", visibility: "private"})
{:ok, private_activity_2} =
CommonAPI.post(user2, %{
- "status" => "hi 3",
- "visibility" => "private",
- "in_reply_to_status_id" => private_activity_1.id
+ status: "hi 3",
+ visibility: "private",
+ in_reply_to_status_id: private_activity_1.id
})
{:ok, private_activity_3} =
CommonAPI.post(user3, %{
- "status" => "hi 4",
- "visibility" => "private",
- "in_reply_to_status_id" => private_activity_2.id
+ status: "hi 4",
+ visibility: "private",
+ in_reply_to_status_id: private_activity_2.id
})
activities =
@@ -1576,7 +1084,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert length(activities) == 3
activities =
- ActivityPub.fetch_activities([user1.ap_id | User.following(user1)], %{"user" => user1})
+ ActivityPub.fetch_activities([user1.ap_id | User.following(user1)], %{user: user1})
|> Enum.map(fn a -> a.id end)
assert [public_activity.id, private_activity_1.id] == activities
@@ -1612,9 +1120,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
Config.put([:instance, :max_pinned_statuses], 3)
user = insert(:user)
- {:ok, activity_one} = CommonAPI.post(user, %{"status" => "HI!!!"})
- {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
- {:ok, activity_three} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ {:ok, activity_one} = CommonAPI.post(user, %{status: "HI!!!"})
+ {:ok, activity_two} = CommonAPI.post(user, %{status: "HI!!!"})
+ {:ok, activity_three} = CommonAPI.post(user, %{status: "HI!!!"})
CommonAPI.pin(activity_one.id, user)
user = refresh_record(user)
@@ -1625,7 +1133,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
CommonAPI.pin(activity_three.id, user)
user = refresh_record(user)
- activities = ActivityPub.fetch_user_activities(user, nil, %{"pinned" => "true"})
+ activities = ActivityPub.fetch_user_activities(user, nil, %{pinned: true})
assert 3 = length(activities)
end
@@ -1635,7 +1143,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
reporter = insert(:user)
target_account = insert(:user)
content = "foobar"
- {:ok, activity} = CommonAPI.post(target_account, %{"status" => content})
+ {:ok, activity} = CommonAPI.post(target_account, %{status: content})
context = Utils.generate_context_id()
reporter_ap_id = reporter.ap_id
@@ -1731,13 +1239,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, list} = Pleroma.List.create("foo", user)
{:ok, list} = Pleroma.List.follow(list, member)
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
activity = Repo.preload(activity, :bookmark)
activity = %Activity{activity | thread_muted?: !!activity.thread_muted?}
- assert ActivityPub.fetch_activities([], %{"user" => user}) == [activity]
+ assert ActivityPub.fetch_activities([], %{user: user}) == [activity]
end
def data_uri do
@@ -1750,8 +1257,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "thought I looked cute might delete later :3",
- "visibility" => "private"
+ status: "thought I looked cute might delete later :3",
+ visibility: "private"
})
[result] = ActivityPub.fetch_activities_bounded([user.follower_address], [])
@@ -1760,12 +1267,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
test "fetches only public posts for other users" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe", "visibility" => "public"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "#cofe", visibility: "public"})
{:ok, _private_activity} =
CommonAPI.post(user, %{
- "status" => "why is tenshi eating a corndog so cute?",
- "visibility" => "private"
+ status: "why is tenshi eating a corndog so cute?",
+ visibility: "private"
})
[result] = ActivityPub.fetch_activities_bounded([], [user.follower_address])
@@ -1893,11 +1400,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
other_user = insert(:user)
user1 = insert(:user)
user2 = insert(:user)
- {:ok, a1} = CommonAPI.post(user1, %{"status" => "bla"})
- {:ok, _a2} = CommonAPI.post(user2, %{"status" => "traps are happy"})
- {:ok, a3} = CommonAPI.post(user2, %{"status" => "Trees Are "})
- {:ok, a4} = CommonAPI.post(user2, %{"status" => "Agent Smith "})
- {:ok, a5} = CommonAPI.post(user1, %{"status" => "Red or Blue "})
+ {:ok, a1} = CommonAPI.post(user1, %{status: "bla"})
+ {:ok, _a2} = CommonAPI.post(user2, %{status: "traps are happy"})
+ {:ok, a3} = CommonAPI.post(user2, %{status: "Trees Are "})
+ {:ok, a4} = CommonAPI.post(user2, %{status: "Agent Smith "})
+ {:ok, a5} = CommonAPI.post(user1, %{status: "Red or Blue "})
{:ok, _} = CommonAPI.favorite(user, a4.id)
{:ok, _} = CommonAPI.favorite(other_user, a3.id)
@@ -1911,7 +1418,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id]
- result = ActivityPub.fetch_favourites(user, %{"limit" => 2})
+ result = ActivityPub.fetch_favourites(user, %{limit: 2})
assert Enum.map(result, & &1.id) == [a1.id, a5.id]
end
end
@@ -1973,4 +1480,593 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
ActivityPub.move(old_user, new_user)
end
end
+
+ test "doesn't retrieve replies activities with exclude_replies" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
+
+ {:ok, _reply} = CommonAPI.post(user, %{status: "yeah", in_reply_to_status_id: activity.id})
+
+ [result] = ActivityPub.fetch_public_activities(%{exclude_replies: true})
+
+ assert result.id == activity.id
+
+ assert length(ActivityPub.fetch_public_activities()) == 2
+ end
+
+ describe "replies filtering with public messages" do
+ setup :public_messages
+
+ test "public timeline", %{users: %{u1: user}} do
+ activities_ids =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:local_only, false)
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:reply_filtering_user, user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 16
+ end
+
+ test "public timeline with reply_visibility `following`", %{
+ users: %{u1: user},
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4,
+ activities: activities
+ } do
+ activities_ids =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:local_only, false)
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:reply_visibility, "following")
+ |> Map.put(:reply_filtering_user, user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 14
+
+ visible_ids =
+ Map.values(u1) ++ Map.values(u2) ++ Map.values(u4) ++ Map.values(activities) ++ [u3[:r1]]
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "public timeline with reply_visibility `self`", %{
+ users: %{u1: user},
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4,
+ activities: activities
+ } do
+ activities_ids =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:local_only, false)
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:reply_visibility, "self")
+ |> Map.put(:reply_filtering_user, user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 10
+ visible_ids = Map.values(u1) ++ [u2[:r1], u3[:r1], u4[:r1]] ++ Map.values(activities)
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "home timeline", %{
+ users: %{u1: user},
+ activities: activities,
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4
+ } do
+ params =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:user, user)
+ |> Map.put(:reply_filtering_user, user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 13
+
+ visible_ids =
+ Map.values(u1) ++
+ Map.values(u3) ++
+ [
+ activities[:a1],
+ activities[:a2],
+ activities[:a4],
+ u2[:r1],
+ u2[:r3],
+ u4[:r1],
+ u4[:r2]
+ ]
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "home timeline with reply_visibility `following`", %{
+ users: %{u1: user},
+ activities: activities,
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4
+ } do
+ params =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:user, user)
+ |> Map.put(:reply_visibility, "following")
+ |> Map.put(:reply_filtering_user, user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 11
+
+ visible_ids =
+ Map.values(u1) ++
+ [
+ activities[:a1],
+ activities[:a2],
+ activities[:a4],
+ u2[:r1],
+ u2[:r3],
+ u3[:r1],
+ u4[:r1],
+ u4[:r2]
+ ]
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "home timeline with reply_visibility `self`", %{
+ users: %{u1: user},
+ activities: activities,
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4
+ } do
+ params =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:user, user)
+ |> Map.put(:reply_visibility, "self")
+ |> Map.put(:reply_filtering_user, user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 9
+
+ visible_ids =
+ Map.values(u1) ++
+ [
+ activities[:a1],
+ activities[:a2],
+ activities[:a4],
+ u2[:r1],
+ u3[:r1],
+ u4[:r1]
+ ]
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "filtering out announces where the user is the actor of the announced message" do
+ user = insert(:user)
+ other_user = insert(:user)
+ third_user = insert(:user)
+ User.follow(user, other_user)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "yo"})
+ {:ok, other_post} = CommonAPI.post(third_user, %{status: "yo"})
+ {:ok, _announce} = CommonAPI.repeat(post.id, other_user)
+ {:ok, _announce} = CommonAPI.repeat(post.id, third_user)
+ {:ok, announce} = CommonAPI.repeat(other_post.id, other_user)
+
+ params = %{
+ type: ["Announce"]
+ }
+
+ results =
+ [user.ap_id | User.following(user)]
+ |> ActivityPub.fetch_activities(params)
+
+ assert length(results) == 3
+
+ params = %{
+ type: ["Announce"],
+ announce_filtering_user: user
+ }
+
+ [result] =
+ [user.ap_id | User.following(user)]
+ |> ActivityPub.fetch_activities(params)
+
+ assert result.id == announce.id
+ end
+ end
+
+ describe "replies filtering with private messages" do
+ setup :private_messages
+
+ test "public timeline", %{users: %{u1: user}} do
+ activities_ids =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:local_only, false)
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:user, user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert activities_ids == []
+ end
+
+ test "public timeline with default reply_visibility `following`", %{users: %{u1: user}} do
+ activities_ids =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:local_only, false)
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:reply_visibility, "following")
+ |> Map.put(:reply_filtering_user, user)
+ |> Map.put(:user, user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert activities_ids == []
+ end
+
+ test "public timeline with default reply_visibility `self`", %{users: %{u1: user}} do
+ activities_ids =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:local_only, false)
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:reply_visibility, "self")
+ |> Map.put(:reply_filtering_user, user)
+ |> Map.put(:user, user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert activities_ids == []
+ end
+
+ test "home timeline", %{users: %{u1: user}} do
+ params =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:user, user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 12
+ end
+
+ test "home timeline with default reply_visibility `following`", %{users: %{u1: user}} do
+ params =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:user, user)
+ |> Map.put(:reply_visibility, "following")
+ |> Map.put(:reply_filtering_user, user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 12
+ end
+
+ test "home timeline with default reply_visibility `self`", %{
+ users: %{u1: user},
+ activities: activities,
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4
+ } do
+ params =
+ %{}
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:user, user)
+ |> Map.put(:reply_visibility, "self")
+ |> Map.put(:reply_filtering_user, user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 10
+
+ visible_ids =
+ Map.values(u1) ++ Map.values(u4) ++ [u2[:r1], u3[:r1]] ++ Map.values(activities)
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+ end
+
+ defp public_messages(_) do
+ [u1, u2, u3, u4] = insert_list(4, :user)
+ {:ok, u1} = User.follow(u1, u2)
+ {:ok, u2} = User.follow(u2, u1)
+ {:ok, u1} = User.follow(u1, u4)
+ {:ok, u4} = User.follow(u4, u1)
+
+ {:ok, u2} = User.follow(u2, u3)
+ {:ok, u3} = User.follow(u3, u2)
+
+ {:ok, a1} = CommonAPI.post(u1, %{status: "Status"})
+
+ {:ok, r1_1} =
+ CommonAPI.post(u2, %{
+ status: "@#{u1.nickname} reply from u2 to u1",
+ in_reply_to_status_id: a1.id
+ })
+
+ {:ok, r1_2} =
+ CommonAPI.post(u3, %{
+ status: "@#{u1.nickname} reply from u3 to u1",
+ in_reply_to_status_id: a1.id
+ })
+
+ {:ok, r1_3} =
+ CommonAPI.post(u4, %{
+ status: "@#{u1.nickname} reply from u4 to u1",
+ in_reply_to_status_id: a1.id
+ })
+
+ {:ok, a2} = CommonAPI.post(u2, %{status: "Status"})
+
+ {:ok, r2_1} =
+ CommonAPI.post(u1, %{
+ status: "@#{u2.nickname} reply from u1 to u2",
+ in_reply_to_status_id: a2.id
+ })
+
+ {:ok, r2_2} =
+ CommonAPI.post(u3, %{
+ status: "@#{u2.nickname} reply from u3 to u2",
+ in_reply_to_status_id: a2.id
+ })
+
+ {:ok, r2_3} =
+ CommonAPI.post(u4, %{
+ status: "@#{u2.nickname} reply from u4 to u2",
+ in_reply_to_status_id: a2.id
+ })
+
+ {:ok, a3} = CommonAPI.post(u3, %{status: "Status"})
+
+ {:ok, r3_1} =
+ CommonAPI.post(u1, %{
+ status: "@#{u3.nickname} reply from u1 to u3",
+ in_reply_to_status_id: a3.id
+ })
+
+ {:ok, r3_2} =
+ CommonAPI.post(u2, %{
+ status: "@#{u3.nickname} reply from u2 to u3",
+ in_reply_to_status_id: a3.id
+ })
+
+ {:ok, r3_3} =
+ CommonAPI.post(u4, %{
+ status: "@#{u3.nickname} reply from u4 to u3",
+ in_reply_to_status_id: a3.id
+ })
+
+ {:ok, a4} = CommonAPI.post(u4, %{status: "Status"})
+
+ {:ok, r4_1} =
+ CommonAPI.post(u1, %{
+ status: "@#{u4.nickname} reply from u1 to u4",
+ in_reply_to_status_id: a4.id
+ })
+
+ {:ok, r4_2} =
+ CommonAPI.post(u2, %{
+ status: "@#{u4.nickname} reply from u2 to u4",
+ in_reply_to_status_id: a4.id
+ })
+
+ {:ok, r4_3} =
+ CommonAPI.post(u3, %{
+ status: "@#{u4.nickname} reply from u3 to u4",
+ in_reply_to_status_id: a4.id
+ })
+
+ {:ok,
+ users: %{u1: u1, u2: u2, u3: u3, u4: u4},
+ activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id},
+ u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id},
+ u2: %{r1: r2_1.id, r2: r2_2.id, r3: r2_3.id},
+ u3: %{r1: r3_1.id, r2: r3_2.id, r3: r3_3.id},
+ u4: %{r1: r4_1.id, r2: r4_2.id, r3: r4_3.id}}
+ end
+
+ defp private_messages(_) do
+ [u1, u2, u3, u4] = insert_list(4, :user)
+ {:ok, u1} = User.follow(u1, u2)
+ {:ok, u2} = User.follow(u2, u1)
+ {:ok, u1} = User.follow(u1, u3)
+ {:ok, u3} = User.follow(u3, u1)
+ {:ok, u1} = User.follow(u1, u4)
+ {:ok, u4} = User.follow(u4, u1)
+
+ {:ok, u2} = User.follow(u2, u3)
+ {:ok, u3} = User.follow(u3, u2)
+
+ {:ok, a1} = CommonAPI.post(u1, %{status: "Status", visibility: "private"})
+
+ {:ok, r1_1} =
+ CommonAPI.post(u2, %{
+ status: "@#{u1.nickname} reply from u2 to u1",
+ in_reply_to_status_id: a1.id,
+ visibility: "private"
+ })
+
+ {:ok, r1_2} =
+ CommonAPI.post(u3, %{
+ status: "@#{u1.nickname} reply from u3 to u1",
+ in_reply_to_status_id: a1.id,
+ visibility: "private"
+ })
+
+ {:ok, r1_3} =
+ CommonAPI.post(u4, %{
+ status: "@#{u1.nickname} reply from u4 to u1",
+ in_reply_to_status_id: a1.id,
+ visibility: "private"
+ })
+
+ {:ok, a2} = CommonAPI.post(u2, %{status: "Status", visibility: "private"})
+
+ {:ok, r2_1} =
+ CommonAPI.post(u1, %{
+ status: "@#{u2.nickname} reply from u1 to u2",
+ in_reply_to_status_id: a2.id,
+ visibility: "private"
+ })
+
+ {:ok, r2_2} =
+ CommonAPI.post(u3, %{
+ status: "@#{u2.nickname} reply from u3 to u2",
+ in_reply_to_status_id: a2.id,
+ visibility: "private"
+ })
+
+ {:ok, a3} = CommonAPI.post(u3, %{status: "Status", visibility: "private"})
+
+ {:ok, r3_1} =
+ CommonAPI.post(u1, %{
+ status: "@#{u3.nickname} reply from u1 to u3",
+ in_reply_to_status_id: a3.id,
+ visibility: "private"
+ })
+
+ {:ok, r3_2} =
+ CommonAPI.post(u2, %{
+ status: "@#{u3.nickname} reply from u2 to u3",
+ in_reply_to_status_id: a3.id,
+ visibility: "private"
+ })
+
+ {:ok, a4} = CommonAPI.post(u4, %{status: "Status", visibility: "private"})
+
+ {:ok, r4_1} =
+ CommonAPI.post(u1, %{
+ status: "@#{u4.nickname} reply from u1 to u4",
+ in_reply_to_status_id: a4.id,
+ visibility: "private"
+ })
+
+ {:ok,
+ users: %{u1: u1, u2: u2, u3: u3, u4: u4},
+ activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id},
+ u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id},
+ u2: %{r1: r2_1.id, r2: r2_2.id},
+ u3: %{r1: r3_1.id, r2: r3_2.id},
+ u4: %{r1: r4_1.id}}
+ end
+
+ describe "maybe_update_follow_information/1" do
+ setup do
+ clear_config([:instance, :external_user_synchronization], true)
+
+ user = %{
+ local: false,
+ ap_id: "https://gensokyo.2hu/users/raymoo",
+ following_address: "https://gensokyo.2hu/users/following",
+ follower_address: "https://gensokyo.2hu/users/followers",
+ type: "Person"
+ }
+
+ %{user: user}
+ end
+
+ test "logs an error when it can't fetch the info", %{user: user} do
+ assert capture_log(fn ->
+ ActivityPub.maybe_update_follow_information(user)
+ end) =~ "Follower/Following counter update for #{user.ap_id} failed"
+ end
+
+ test "just returns the input if the user type is Application", %{
+ user: user
+ } do
+ user =
+ user
+ |> Map.put(:type, "Application")
+
+ refute capture_log(fn ->
+ assert ^user = ActivityPub.maybe_update_follow_information(user)
+ end) =~ "Follower/Following counter update for #{user.ap_id} failed"
+ end
+
+ test "it just returns the input if the user has no following/follower addresses", %{
+ user: user
+ } do
+ user =
+ user
+ |> Map.put(:following_address, nil)
+ |> Map.put(:follower_address, nil)
+
+ refute capture_log(fn ->
+ assert ^user = ActivityPub.maybe_update_follow_information(user)
+ end) =~ "Follower/Following counter update for #{user.ap_id} failed"
+ end
+ end
+
+ describe "global activity expiration" do
+ setup do: clear_config([:instance, :rewrite_policy])
+
+ test "creates an activity expiration for local Create activities" do
+ Pleroma.Config.put(
+ [:instance, :rewrite_policy],
+ Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy
+ )
+
+ {:ok, %{id: id_create}} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
+ {:ok, _follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"})
+
+ assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all()
+ end
+ end
end
diff --git a/test/web/activity_pub/mrf/activity_expiration_policy_test.exs b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs
new file mode 100644
index 000000000..8babf49e7
--- /dev/null
+++ b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs
@@ -0,0 +1,77 @@
+# 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.MRF.ActivityExpirationPolicyTest do
+ use ExUnit.Case, async: true
+ alias Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy
+
+ @id Pleroma.Web.Endpoint.url() <> "/activities/cofe"
+
+ test "adds `expires_at` property" do
+ assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => @id,
+ "type" => "Create",
+ "object" => %{"type" => "Note"}
+ })
+
+ assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364
+ end
+
+ test "keeps existing `expires_at` if it less than the config setting" do
+ expires_at = NaiveDateTime.utc_now() |> Timex.shift(days: 1)
+
+ assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => @id,
+ "type" => "Create",
+ "expires_at" => expires_at,
+ "object" => %{"type" => "Note"}
+ })
+ end
+
+ test "overwrites existing `expires_at` if it greater than the config setting" do
+ too_distant_future = NaiveDateTime.utc_now() |> Timex.shift(years: 2)
+
+ assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => @id,
+ "type" => "Create",
+ "expires_at" => too_distant_future,
+ "object" => %{"type" => "Note"}
+ })
+
+ assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364
+ end
+
+ test "ignores remote activities" do
+ assert {:ok, activity} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => "https://example.com/123",
+ "type" => "Create",
+ "object" => %{"type" => "Note"}
+ })
+
+ refute Map.has_key?(activity, "expires_at")
+ end
+
+ test "ignores non-Create/Note activities" do
+ assert {:ok, activity} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => "https://example.com/123",
+ "type" => "Follow"
+ })
+
+ refute Map.has_key?(activity, "expires_at")
+
+ assert {:ok, activity} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => "https://example.com/123",
+ "type" => "Create",
+ "object" => %{"type" => "Cofe"}
+ })
+
+ refute Map.has_key?(activity, "expires_at")
+ end
+end
diff --git a/test/web/activity_pub/mrf/object_age_policy_test.exs b/test/web/activity_pub/mrf/object_age_policy_test.exs
index 7ee195eeb..b0fb753bd 100644
--- a/test/web/activity_pub/mrf/object_age_policy_test.exs
+++ b/test/web/activity_pub/mrf/object_age_policy_test.exs
@@ -20,26 +20,38 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
:ok
end
+ defp get_old_message do
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ end
+
+ defp get_new_message do
+ old_message = get_old_message()
+
+ new_object =
+ old_message
+ |> Map.get("object")
+ |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+
+ old_message
+ |> Map.put("object", new_object)
+ end
+
describe "with reject action" do
test "it rejects an old post" do
Config.put([:mrf_object_age, :actions], [:reject])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
+ data = get_old_message()
- {:reject, _} = ObjectAgePolicy.filter(data)
+ assert match?({:reject, _}, ObjectAgePolicy.filter(data))
end
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:reject])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+ data = get_new_message()
- {:ok, _} = ObjectAgePolicy.filter(data)
+ assert match?({:ok, _}, ObjectAgePolicy.filter(data))
end
end
@@ -47,9 +59,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
test "it delists an old post" do
Config.put([:mrf_object_age, :actions], [:delist])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
+ data = get_old_message()
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
@@ -61,14 +71,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:delist])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+ data = get_new_message()
{:ok, _user} = User.get_or_fetch_by_ap_id(data["actor"])
- {:ok, ^data} = ObjectAgePolicy.filter(data)
+ assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))
end
end
@@ -76,9 +83,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
test "it strips followers collections from an old post" do
Config.put([:mrf_object_age, :actions], [:strip_followers])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
+ data = get_old_message()
{:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
@@ -91,14 +96,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:strip_followers])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+ data = get_new_message()
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
- {:ok, ^data} = ObjectAgePolicy.filter(data)
+ assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))
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 91c24c2d9..b7b9bc6a2 100644
--- a/test/web/activity_pub/mrf/simple_policy_test.exs
+++ b/test/web/activity_pub/mrf/simple_policy_test.exs
@@ -17,7 +17,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
reject: [],
accept: [],
avatar_removal: [],
- banner_removal: []
+ banner_removal: [],
+ reject_deletes: []
)
describe "when :media_removal" do
@@ -382,6 +383,66 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
end
end
+ describe "when :reject_deletes is empty" do
+ setup do: Config.put([:mrf_simple, :reject_deletes], [])
+
+ test "it accepts deletions even from rejected servers" do
+ Config.put([:mrf_simple, :reject], ["remote.instance"])
+
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+ end
+
+ test "it accepts deletions even from non-whitelisted servers" do
+ Config.put([:mrf_simple, :accept], ["non.matching.remote"])
+
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+ end
+ end
+
+ describe "when :reject_deletes is not empty but it doesn't have a matching host" do
+ setup do: Config.put([:mrf_simple, :reject_deletes], ["non.matching.remote"])
+
+ test "it accepts deletions even from rejected servers" do
+ Config.put([:mrf_simple, :reject], ["remote.instance"])
+
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+ end
+
+ test "it accepts deletions even from non-whitelisted servers" do
+ Config.put([:mrf_simple, :accept], ["non.matching.remote"])
+
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+ end
+ end
+
+ describe "when :reject_deletes has a matching host" do
+ setup do: Config.put([:mrf_simple, :reject_deletes], ["remote.instance"])
+
+ test "it rejects the deletion" do
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:reject, nil}
+ end
+ end
+
+ describe "when :reject_deletes match with wildcard domain" do
+ setup do: Config.put([:mrf_simple, :reject_deletes], ["*.remote.instance"])
+
+ test "it rejects the deletion" do
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:reject, nil}
+ end
+ end
+
defp build_local_message do
%{
"actor" => "#{Pleroma.Web.base_url()}/users/alice",
@@ -408,4 +469,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
"type" => "Person"
}
end
+
+ defp build_remote_deletion_message do
+ %{
+ "type" => "Delete",
+ "actor" => "https://remote.instance/users/bob"
+ }
+ end
end
diff --git a/test/web/activity_pub/mrf/steal_emoji_policy_test.exs b/test/web/activity_pub/mrf/steal_emoji_policy_test.exs
new file mode 100644
index 000000000..3f8222736
--- /dev/null
+++ b/test/web/activity_pub/mrf/steal_emoji_policy_test.exs
@@ -0,0 +1,68 @@
+# 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.MRF.StealEmojiPolicyTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Config
+ alias Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy
+
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
+ setup do
+ emoji_path = Path.join(Config.get([:instance, :static_dir]), "emoji/stolen")
+ File.rm_rf!(emoji_path)
+ File.mkdir!(emoji_path)
+
+ Pleroma.Emoji.reload()
+
+ on_exit(fn ->
+ File.rm_rf!(emoji_path)
+ end)
+
+ :ok
+ end
+
+ test "does nothing by default" do
+ installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
+ refute "firedfox" in installed_emoji
+
+ message = %{
+ "type" => "Create",
+ "object" => %{
+ "emoji" => [{"firedfox", "https://example.org/emoji/firedfox.png"}],
+ "actor" => "https://example.org/users/admin"
+ }
+ }
+
+ assert {:ok, message} == StealEmojiPolicy.filter(message)
+
+ installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
+ refute "firedfox" in installed_emoji
+ end
+
+ test "Steals emoji on unknown shortcode from allowed remote host" do
+ installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
+ refute "firedfox" in installed_emoji
+
+ message = %{
+ "type" => "Create",
+ "object" => %{
+ "emoji" => [{"firedfox", "https://example.org/emoji/firedfox.png"}],
+ "actor" => "https://example.org/users/admin"
+ }
+ }
+
+ clear_config([:mrf_steal_emoji, :hosts], ["example.org"])
+ clear_config([:mrf_steal_emoji, :size_limit], 284_468)
+
+ assert {:ok, message} == StealEmojiPolicy.filter(message)
+
+ installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
+ assert "firedfox" in installed_emoji
+ end
+end
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 724bae058..ba1b69658 100644
--- a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
+++ b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
@@ -7,7 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
alias Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy
- setup do: clear_config([:mrf_user_allowlist, :localhost])
+ setup do: clear_config(:mrf_user_allowlist)
test "pass filter if allow list is empty" do
actor = insert(:user)
@@ -17,14 +17,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
test "pass filter if allow list isn't empty and user in allow list" do
actor = insert(:user)
- Pleroma.Config.put([:mrf_user_allowlist, :localhost], [actor.ap_id, "test-ap-id"])
+ Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => [actor.ap_id, "test-ap-id"]})
message = %{"actor" => actor.ap_id}
assert UserAllowListPolicy.filter(message) == {:ok, message}
end
test "rejected if allow list isn't empty and user not in allow list" do
actor = insert(:user)
- Pleroma.Config.put([:mrf_user_allowlist, :localhost], ["test-ap-id"])
+ Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => ["test-ap-id"]})
message = %{"actor" => actor.ap_id}
assert UserAllowListPolicy.filter(message) == {:reject, nil}
end
diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs
index 3c5c3696e..31224abe0 100644
--- a/test/web/activity_pub/object_validator_test.exs
+++ b/test/web/activity_pub/object_validator_test.exs
@@ -1,17 +1,441 @@
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(&#39;uguu&#39;)"
+ 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"})
+ {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
valid_like = %{
"to" => [user.ap_id],
@@ -36,6 +460,32 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest 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")
@@ -80,4 +530,96 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
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
end
diff --git a/test/web/activity_pub/object_validators/types/date_time_test.exs b/test/web/activity_pub/object_validators/types/date_time_test.exs
index 3e17a9497..43be8e936 100644
--- a/test/web/activity_pub/object_validators/types/date_time_test.exs
+++ b/test/web/activity_pub/object_validators/types/date_time_test.exs
@@ -1,5 +1,5 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTimeTest do
- alias Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTime
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime
use Pleroma.DataCase
test "it validates an xsd:Datetime" do
diff --git a/test/web/activity_pub/object_validators/types/object_id_test.exs b/test/web/activity_pub/object_validators/types/object_id_test.exs
index 834213182..e0ab76379 100644
--- a/test/web/activity_pub/object_validators/types/object_id_test.exs
+++ b/test/web/activity_pub/object_validators/types/object_id_test.exs
@@ -1,5 +1,9 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
defmodule Pleroma.Web.ObjectValidators.Types.ObjectIDTest do
- alias Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectID
use Pleroma.DataCase
@uris [
diff --git a/test/web/activity_pub/object_validators/types/recipients_test.exs b/test/web/activity_pub/object_validators/types/recipients_test.exs
new file mode 100644
index 000000000..053916bdd
--- /dev/null
+++ b/test/web/activity_pub/object_validators/types/recipients_test.exs
@@ -0,0 +1,27 @@
+defmodule Pleroma.Web.ObjectValidators.Types.RecipientsTest do
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.Recipients
+ use Pleroma.DataCase
+
+ test "it asserts that all elements of the list are object ids" do
+ list = ["https://lain.com/users/lain", "invalid"]
+
+ assert :error == Recipients.cast(list)
+ end
+
+ test "it works with a list" do
+ list = ["https://lain.com/users/lain"]
+ assert {:ok, list} == Recipients.cast(list)
+ end
+
+ test "it works with a list with whole objects" do
+ list = ["https://lain.com/users/lain", %{"id" => "https://gensokyo.2hu/users/raymoo"}]
+ resulting_list = ["https://gensokyo.2hu/users/raymoo", "https://lain.com/users/lain"]
+ assert {:ok, resulting_list} == Recipients.cast(list)
+ end
+
+ test "it turns a single string into a list" do
+ recipient = "https://lain.com/users/lain"
+
+ assert {:ok, [recipient]} == Recipients.cast(recipient)
+ end
+end
diff --git a/test/web/activity_pub/object_validators/types/safe_text_test.exs b/test/web/activity_pub/object_validators/types/safe_text_test.exs
new file mode 100644
index 000000000..9c08606f6
--- /dev/null
+++ b/test/web/activity_pub/object_validators/types/safe_text_test.exs
@@ -0,0 +1,30 @@
+# 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.Types.SafeTextTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.SafeText
+
+ test "it lets normal text go through" do
+ text = "hey how are you"
+ assert {:ok, text} == SafeText.cast(text)
+ end
+
+ test "it removes html tags from text" do
+ text = "hey look xss <script>alert('foo')</script>"
+ assert {:ok, "hey look xss alert(&#39;foo&#39;)"} == SafeText.cast(text)
+ end
+
+ test "it keeps basic html tags" do
+ text = "hey <a href='http://gensokyo.2hu'>look</a> xss <script>alert('foo')</script>"
+
+ assert {:ok, "hey <a href=\"http://gensokyo.2hu\">look</a> xss alert(&#39;foo&#39;)"} ==
+ SafeText.cast(text)
+ end
+
+ test "errors for non-text" do
+ assert :error == SafeText.cast(1)
+ end
+end
diff --git a/test/web/activity_pub/pipeline_test.exs b/test/web/activity_pub/pipeline_test.exs
index f3c437498..8deb64501 100644
--- a/test/web/activity_pub/pipeline_test.exs
+++ b/test/web/activity_pub/pipeline_test.exs
@@ -9,6 +9,11 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
import Pleroma.Factory
describe "common_pipeline/2" do
+ setup do
+ clear_config([:instance, :federating], true)
+ :ok
+ end
+
test "it goes through validation, filtering, persisting, side effects and federation for local activities" do
activity = insert(:note_activity)
meta = [local: true]
@@ -28,7 +33,10 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
{
Pleroma.Web.ActivityPub.SideEffects,
[],
- [handle: fn o, m -> {:ok, o, m} end]
+ [
+ handle: fn o, m -> {:ok, o, m} end,
+ handle_after_transaction: fn m -> m end
+ ]
},
{
Pleroma.Web.Federator,
@@ -66,7 +74,46 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
{
Pleroma.Web.ActivityPub.SideEffects,
[],
- [handle: fn o, m -> {:ok, o, m} end]
+ [handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end]
+ },
+ {
+ Pleroma.Web.Federator,
+ [],
+ []
+ }
+ ]) do
+ assert {:ok, ^activity, ^meta} =
+ Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
+
+ assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
+ assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity))
+ assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
+ assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
+ end
+ end
+
+ test "it goes through validation, filtering, persisting, side effects without federation for local activities if federation is deactivated" do
+ clear_config([:instance, :federating], false)
+
+ activity = insert(:note_activity)
+ meta = [local: true]
+
+ with_mocks([
+ {Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
+ {
+ Pleroma.Web.ActivityPub.MRF,
+ [],
+ [filter: fn o -> {:ok, o} end]
+ },
+ {
+ Pleroma.Web.ActivityPub.ActivityPub,
+ [],
+ [persist: fn o, m -> {:ok, o, m} end]
+ },
+ {
+ Pleroma.Web.ActivityPub.SideEffects,
+ [],
+ [handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end]
},
{
Pleroma.Web.Federator,
diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs
index 9e16e39c4..b3b573c9b 100644
--- a/test/web/activity_pub/relay_test.exs
+++ b/test/web/activity_pub/relay_test.exs
@@ -6,7 +6,6 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
use Pleroma.DataCase
alias Pleroma.Activity
- alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Relay
@@ -95,21 +94,21 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
end)
assert capture_log(fn ->
- assert Relay.publish(activity) == {:error, nil}
- end) =~ "[error] error: nil"
+ assert Relay.publish(activity) == {:error, false}
+ end) =~ "[error] error: false"
end
test_with_mock "returns announce activity and publish to federate",
Pleroma.Web.Federator,
[:passthrough],
[] do
- Pleroma.Config.put([:instance, :federating], true)
+ clear_config([:instance, :federating], true)
service_actor = Relay.get_actor()
note = insert(:note_activity)
- assert {:ok, %Activity{} = activity, %Object{} = obj} = Relay.publish(note)
+ assert {:ok, %Activity{} = activity} = Relay.publish(note)
assert activity.data["type"] == "Announce"
assert activity.data["actor"] == service_actor.ap_id
- assert activity.data["object"] == obj.data["id"]
+ assert activity.data["to"] == [service_actor.follower_address]
assert called(Pleroma.Web.Federator.publish(activity))
end
@@ -117,13 +116,12 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
Pleroma.Web.Federator,
[:passthrough],
[] do
- Pleroma.Config.put([:instance, :federating], false)
+ clear_config([:instance, :federating], false)
service_actor = Relay.get_actor()
note = insert(:note_activity)
- assert {:ok, %Activity{} = activity, %Object{} = obj} = Relay.publish(note)
+ assert {:ok, %Activity{} = activity} = Relay.publish(note)
assert activity.data["type"] == "Announce"
assert activity.data["actor"] == service_actor.ap_id
- assert activity.data["object"] == obj.data["id"]
refute called(Pleroma.Web.Federator.publish(activity))
end
end
diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs
index b67bd14b3..6bbbaae87 100644
--- a/test/web/activity_pub/side_effects_test.exs
+++ b/test/web/activity_pub/side_effects_test.exs
@@ -3,25 +3,322 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
+ use Oban.Testing, repo: Pleroma.Repo
use Pleroma.DataCase
+ alias Pleroma.Activity
+ alias Pleroma.Chat
+ alias Pleroma.Chat.MessageReference
+ alias Pleroma.Notification
alias Pleroma.Object
+ alias Pleroma.Repo
+ alias Pleroma.Tests.ObanHelpers
+ alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.SideEffects
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
+ import Mock
+
+ describe "handle_after_transaction" do
+ test "it streams out notifications and streams" do
+ author = insert(:user, local: true)
+ recipient = insert(:user, local: true)
+
+ {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
+
+ {:ok, create_activity_data, _meta} =
+ Builder.create(author, chat_message_data["id"], [recipient.ap_id])
+
+ {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
+
+ {:ok, _create_activity, meta} =
+ SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
+
+ assert [notification] = meta[:notifications]
+
+ with_mocks([
+ {
+ Pleroma.Web.Streamer,
+ [],
+ [
+ stream: fn _, _ -> nil end
+ ]
+ },
+ {
+ Pleroma.Web.Push,
+ [],
+ [
+ send: fn _ -> nil end
+ ]
+ }
+ ]) do
+ SideEffects.handle_after_transaction(meta)
+
+ assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
+ assert called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
+ assert called(Pleroma.Web.Push.send(notification))
+ end
+ end
+ end
+
+ describe "delete objects" do
+ setup do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
+ {:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
+ {:ok, favorite} = CommonAPI.favorite(user, post.id)
+ object = Object.normalize(post)
+ {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
+ {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
+ {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
+ {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
+
+ %{
+ user: user,
+ delete: delete,
+ post: post,
+ object: object,
+ delete_user: delete_user,
+ op: op,
+ favorite: favorite
+ }
+ end
+
+ test "it handles object deletions", %{
+ delete: delete,
+ post: post,
+ object: object,
+ user: user,
+ op: op,
+ favorite: favorite
+ } do
+ with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
+ stream_out: fn _ -> nil end,
+ stream_out_participations: fn _, _ -> nil end do
+ {:ok, delete, _} = SideEffects.handle(delete)
+ user = User.get_cached_by_ap_id(object.data["actor"])
+
+ assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
+ assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
+ end
+
+ object = Object.get_by_id(object.id)
+ assert object.data["type"] == "Tombstone"
+ refute Activity.get_by_id(post.id)
+ refute Activity.get_by_id(favorite.id)
+
+ user = User.get_by_id(user.id)
+ assert user.note_count == 0
+
+ object = Object.normalize(op.data["object"], false)
+
+ assert object.data["repliesCount"] == 0
+ end
+
+ test "it handles object deletions when the object itself has been pruned", %{
+ delete: delete,
+ post: post,
+ object: object,
+ user: user,
+ op: op
+ } do
+ with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
+ stream_out: fn _ -> nil end,
+ stream_out_participations: fn _, _ -> nil end do
+ {:ok, delete, _} = SideEffects.handle(delete)
+ user = User.get_cached_by_ap_id(object.data["actor"])
+
+ assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
+ assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
+ end
+
+ object = Object.get_by_id(object.id)
+ assert object.data["type"] == "Tombstone"
+ refute Activity.get_by_id(post.id)
+
+ user = User.get_by_id(user.id)
+ assert user.note_count == 0
+
+ object = Object.normalize(op.data["object"], false)
+
+ assert object.data["repliesCount"] == 0
+ end
+
+ test "it handles user deletions", %{delete_user: delete, user: user} do
+ {:ok, _delete, _} = SideEffects.handle(delete)
+ ObanHelpers.perform_all()
+
+ assert User.get_cached_by_ap_id(user.ap_id).deactivated
+ end
+ end
+
+ describe "EmojiReact objects" do
+ setup do
+ poster = insert(:user)
+ user = insert(:user)
+
+ {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
+
+ {:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
+ {:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
+
+ %{emoji_react: emoji_react, user: user, poster: poster}
+ end
+
+ test "adds the reaction to the object", %{emoji_react: emoji_react, user: user} do
+ {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
+ object = Object.get_by_ap_id(emoji_react.data["object"])
+
+ assert object.data["reaction_count"] == 1
+ assert ["👌", [user.ap_id]] in object.data["reactions"]
+ end
+
+ test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
+ {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
+ assert Repo.get_by(Notification, user_id: poster.id, activity_id: emoji_react.id)
+ end
+ end
+
+ describe "delete users with confirmation pending" do
+ setup do
+ user = insert(:user, confirmation_pending: true)
+ {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
+ {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
+ {:ok, delete: delete_user, user: user}
+ end
+
+ test "when activation is not required", %{delete: delete, user: user} do
+ clear_config([:instance, :account_activation_required], false)
+ {:ok, _, _} = SideEffects.handle(delete)
+ ObanHelpers.perform_all()
+
+ assert User.get_cached_by_id(user.id).deactivated
+ end
+
+ test "when activation is required", %{delete: delete, user: user} do
+ clear_config([:instance, :account_activation_required], true)
+ {:ok, _, _} = SideEffects.handle(delete)
+ ObanHelpers.perform_all()
+
+ refute User.get_cached_by_id(user.id)
+ end
+ end
+
+ describe "Undo objects" do
+ setup do
+ poster = insert(:user)
+ user = insert(:user)
+ {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
+ {:ok, like} = CommonAPI.favorite(user, post.id)
+ {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
+ {:ok, announce} = CommonAPI.repeat(post.id, user)
+ {:ok, block} = ActivityPub.block(user, poster)
+ User.block(user, poster)
+
+ {:ok, undo_data, _meta} = Builder.undo(user, like)
+ {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
+
+ {:ok, undo_data, _meta} = Builder.undo(user, reaction)
+ {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true)
+
+ {:ok, undo_data, _meta} = Builder.undo(user, announce)
+ {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true)
+
+ {:ok, undo_data, _meta} = Builder.undo(user, block)
+ {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
+
+ %{
+ like_undo: like_undo,
+ post: post,
+ like: like,
+ reaction_undo: reaction_undo,
+ reaction: reaction,
+ announce_undo: announce_undo,
+ announce: announce,
+ block_undo: block_undo,
+ block: block,
+ poster: poster,
+ user: user
+ }
+ end
+
+ test "deletes the original block", %{block_undo: block_undo, block: block} do
+ {:ok, _block_undo, _} = SideEffects.handle(block_undo)
+ refute Activity.get_by_id(block.id)
+ end
+
+ test "unblocks the blocked user", %{block_undo: block_undo, block: block} do
+ blocker = User.get_by_ap_id(block.data["actor"])
+ blocked = User.get_by_ap_id(block.data["object"])
+
+ {:ok, _block_undo, _} = SideEffects.handle(block_undo)
+ refute User.blocks?(blocker, blocked)
+ end
+
+ test "an announce undo removes the announce from the object", %{
+ announce_undo: announce_undo,
+ post: post
+ } do
+ {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
+
+ object = Object.get_by_ap_id(post.data["object"])
+
+ assert object.data["announcement_count"] == 0
+ assert object.data["announcements"] == []
+ end
+
+ test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do
+ {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
+ refute Activity.get_by_id(announce.id)
+ end
+
+ test "a reaction undo removes the reaction from the object", %{
+ reaction_undo: reaction_undo,
+ post: post
+ } do
+ {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
+
+ object = Object.get_by_ap_id(post.data["object"])
+
+ assert object.data["reaction_count"] == 0
+ assert object.data["reactions"] == []
+ end
+
+ test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do
+ {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
+ refute Activity.get_by_id(reaction.id)
+ end
+
+ test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do
+ {:ok, _like_undo, _} = SideEffects.handle(like_undo)
+
+ object = Object.get_by_ap_id(post.data["object"])
+
+ assert object.data["like_count"] == 0
+ assert object.data["likes"] == []
+ end
+
+ test "deletes the original like", %{like_undo: like_undo, like: like} do
+ {:ok, _like_undo, _} = SideEffects.handle(like_undo)
+ refute Activity.get_by_id(like.id)
+ end
+ end
describe "like objects" do
setup do
+ poster = insert(:user)
user = insert(:user)
- {:ok, post} = CommonAPI.post(user, %{"status" => "hey"})
+ {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
{:ok, like_data, _meta} = Builder.like(user, post.object)
{:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
- %{like: like, user: user}
+ %{like: like, user: user, poster: poster}
end
test "add the like to the original object", %{like: like, user: user} do
@@ -30,5 +327,208 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
assert object.data["like_count"] == 1
assert user.ap_id in object.data["likes"]
end
+
+ test "creates a notification", %{like: like, poster: poster} do
+ {:ok, like, _} = SideEffects.handle(like)
+ assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
+ end
+ end
+
+ describe "creation of ChatMessages" do
+ test "notifies the recipient" do
+ author = insert(:user, local: false)
+ recipient = insert(:user, local: true)
+
+ {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
+
+ {:ok, create_activity_data, _meta} =
+ Builder.create(author, chat_message_data["id"], [recipient.ap_id])
+
+ {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
+
+ {:ok, _create_activity, _meta} =
+ SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
+
+ assert Repo.get_by(Notification, user_id: recipient.id, activity_id: create_activity.id)
+ end
+
+ test "it streams the created ChatMessage" do
+ author = insert(:user, local: true)
+ recipient = insert(:user, local: true)
+
+ {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
+
+ {:ok, create_activity_data, _meta} =
+ Builder.create(author, chat_message_data["id"], [recipient.ap_id])
+
+ {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
+
+ {:ok, _create_activity, meta} =
+ SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
+
+ assert [_, _] = meta[:streamables]
+ end
+
+ test "it creates a Chat and MessageReferences for the local users and bumps the unread count, except for the author" do
+ author = insert(:user, local: true)
+ recipient = insert(:user, local: true)
+
+ {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
+
+ {:ok, create_activity_data, _meta} =
+ Builder.create(author, chat_message_data["id"], [recipient.ap_id])
+
+ {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
+
+ with_mocks([
+ {
+ Pleroma.Web.Streamer,
+ [],
+ [
+ stream: fn _, _ -> nil end
+ ]
+ },
+ {
+ Pleroma.Web.Push,
+ [],
+ [
+ send: fn _ -> nil end
+ ]
+ }
+ ]) do
+ {:ok, _create_activity, meta} =
+ SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
+
+ # The notification gets created
+ assert [notification] = meta[:notifications]
+ assert notification.activity_id == create_activity.id
+
+ # But it is not sent out
+ refute called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
+ refute called(Pleroma.Web.Push.send(notification))
+
+ # Same for the user chat stream
+ assert [{topics, _}, _] = meta[:streamables]
+ assert topics == ["user", "user:pleroma_chat"]
+ refute called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
+
+ chat = Chat.get(author.id, recipient.ap_id)
+
+ [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all()
+
+ assert cm_ref.object.data["content"] == "hey"
+ assert cm_ref.unread == false
+
+ chat = Chat.get(recipient.id, author.ap_id)
+
+ [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all()
+
+ assert cm_ref.object.data["content"] == "hey"
+ assert cm_ref.unread == true
+ end
+ end
+
+ test "it creates a Chat for the local users and bumps the unread count" do
+ author = insert(:user, local: false)
+ recipient = insert(:user, local: true)
+
+ {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
+
+ {:ok, create_activity_data, _meta} =
+ Builder.create(author, chat_message_data["id"], [recipient.ap_id])
+
+ {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
+
+ {:ok, _create_activity, _meta} =
+ SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
+
+ # An object is created
+ assert Object.get_by_ap_id(chat_message_data["id"])
+
+ # The remote user won't get a chat
+ chat = Chat.get(author.id, recipient.ap_id)
+ refute chat
+
+ # The local user will get a chat
+ chat = Chat.get(recipient.id, author.ap_id)
+ assert chat
+
+ author = insert(:user, local: true)
+ recipient = insert(:user, local: true)
+
+ {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
+
+ {:ok, create_activity_data, _meta} =
+ Builder.create(author, chat_message_data["id"], [recipient.ap_id])
+
+ {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
+
+ {:ok, _create_activity, _meta} =
+ SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
+
+ # Both users are local and get the chat
+ chat = Chat.get(author.id, recipient.ap_id)
+ assert chat
+
+ chat = Chat.get(recipient.id, author.ap_id)
+ assert chat
+ end
+ end
+
+ describe "announce objects" do
+ setup do
+ poster = insert(:user)
+ user = insert(:user)
+ {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
+ {:ok, private_post} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
+
+ {:ok, announce_data, _meta} = Builder.announce(user, post.object, public: true)
+
+ {:ok, private_announce_data, _meta} =
+ Builder.announce(user, private_post.object, public: false)
+
+ {:ok, relay_announce_data, _meta} =
+ Builder.announce(Pleroma.Web.ActivityPub.Relay.get_actor(), post.object, public: true)
+
+ {:ok, announce, _meta} = ActivityPub.persist(announce_data, local: true)
+ {:ok, private_announce, _meta} = ActivityPub.persist(private_announce_data, local: true)
+ {:ok, relay_announce, _meta} = ActivityPub.persist(relay_announce_data, local: true)
+
+ %{
+ announce: announce,
+ user: user,
+ poster: poster,
+ private_announce: private_announce,
+ relay_announce: relay_announce
+ }
+ end
+
+ test "adds the announce to the original object", %{announce: announce, user: user} do
+ {:ok, announce, _} = SideEffects.handle(announce)
+ object = Object.get_by_ap_id(announce.data["object"])
+ assert object.data["announcement_count"] == 1
+ assert user.ap_id in object.data["announcements"]
+ end
+
+ test "does not add the announce to the original object if the actor is a service actor", %{
+ relay_announce: announce
+ } do
+ {:ok, announce, _} = SideEffects.handle(announce)
+ object = Object.get_by_ap_id(announce.data["object"])
+ assert object.data["announcement_count"] == nil
+ end
+
+ test "creates a notification", %{announce: announce, poster: poster} do
+ {:ok, announce, _} = SideEffects.handle(announce)
+ assert Repo.get_by(Notification, user_id: poster.id, activity_id: announce.id)
+ end
+
+ test "it streams out the announce", %{announce: announce} do
+ with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough], stream_out: fn _ -> nil end do
+ {:ok, announce, _} = SideEffects.handle(announce)
+
+ assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(announce))
+ end
+ end
end
end
diff --git a/test/web/activity_pub/transmogrifier/announce_handling_test.exs b/test/web/activity_pub/transmogrifier/announce_handling_test.exs
new file mode 100644
index 000000000..e895636b5
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/announce_handling_test.exs
@@ -0,0 +1,172 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "it works for incoming honk announces" do
+ user = insert(:user, ap_id: "https://honktest/u/test", local: false)
+ other_user = insert(:user)
+ {:ok, post} = CommonAPI.post(other_user, %{status: "bonkeronk"})
+
+ announce = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "actor" => "https://honktest/u/test",
+ "id" => "https://honktest/u/test/bonk/1793M7B9MQ48847vdx",
+ "object" => post.data["object"],
+ "published" => "2019-06-25T19:33:58Z",
+ "to" => "https://www.w3.org/ns/activitystreams#Public",
+ "type" => "Announce"
+ }
+
+ {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(announce)
+
+ object = Object.get_by_ap_id(post.data["object"])
+
+ assert length(object.data["announcements"]) == 1
+ assert user.ap_id in object.data["announcements"]
+ end
+
+ test "it works for incoming announces with actor being inlined (kroeg)" do
+ data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!()
+
+ _user = insert(:user, local: false, ap_id: data["actor"]["id"])
+ other_user = insert(:user)
+
+ {:ok, post} = CommonAPI.post(other_user, %{status: "kroegeroeg"})
+
+ data =
+ data
+ |> put_in(["object", "id"], post.data["object"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "https://puckipedia.com/"
+ end
+
+ test "it works for incoming announces, fetching the announced object" do
+ data =
+ File.read!("test/fixtures/mastodon-announce.json")
+ |> Poison.decode!()
+ |> Map.put("object", "http://mastodon.example.org/users/admin/statuses/99541947525187367")
+
+ Tesla.Mock.mock(fn
+ %{method: :get} ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/mastodon-note-object.json")}
+ end)
+
+ _user = insert(:user, local: false, ap_id: data["actor"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "Announce"
+
+ assert data["id"] ==
+ "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
+
+ assert data["object"] ==
+ "http://mastodon.example.org/users/admin/statuses/99541947525187367"
+
+ assert(Activity.get_create_by_object_ap_id(data["object"]))
+ end
+
+ @tag capture_log: true
+ test "it works for incoming announces with an existing activity" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
+
+ data =
+ File.read!("test/fixtures/mastodon-announce.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _user = insert(:user, local: false, ap_id: data["actor"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "Announce"
+
+ assert data["id"] ==
+ "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
+
+ assert data["object"] == activity.data["object"]
+
+ assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id
+ end
+
+ # Ignore inlined activities for now
+ @tag skip: true
+ test "it works for incoming announces with an inlined activity" do
+ data =
+ File.read!("test/fixtures/mastodon-announce-private.json")
+ |> Poison.decode!()
+
+ _user =
+ insert(:user,
+ local: false,
+ ap_id: data["actor"],
+ follower_address: data["actor"] <> "/followers"
+ )
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "Announce"
+
+ assert data["id"] ==
+ "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
+
+ object = Object.normalize(data["object"])
+
+ assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368"
+ assert object.data["content"] == "this is a private toot"
+ end
+
+ @tag capture_log: true
+ test "it rejects incoming announces with an inlined activity from another origin" do
+ Tesla.Mock.mock(fn
+ %{method: :get} -> %Tesla.Env{status: 404, body: ""}
+ end)
+
+ data =
+ File.read!("test/fixtures/bogus-mastodon-announce.json")
+ |> Poison.decode!()
+
+ _user = insert(:user, local: false, ap_id: data["actor"])
+
+ assert {:error, e} = Transmogrifier.handle_incoming(data)
+ end
+
+ test "it does not clobber the addressing on announce activities" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
+
+ data =
+ File.read!("test/fixtures/mastodon-announce.json")
+ |> Poison.decode!()
+ |> Map.put("object", Object.normalize(activity).data["id"])
+ |> Map.put("to", ["http://mastodon.example.org/users/admin/followers"])
+ |> Map.put("cc", [])
+
+ _user =
+ insert(:user,
+ local: false,
+ ap_id: data["actor"],
+ follower_address: "http://mastodon.example.org/users/admin/followers"
+ )
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["to"] == ["http://mastodon.example.org/users/admin/followers"]
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/chat_message_test.exs b/test/web/activity_pub/transmogrifier/chat_message_test.exs
new file mode 100644
index 000000000..d6736dc3e
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/chat_message_test.exs
@@ -0,0 +1,153 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do
+ use Pleroma.DataCase
+
+ import Pleroma.Factory
+
+ alias Pleroma.Activity
+ alias Pleroma.Chat
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+
+ describe "handle_incoming" do
+ test "handles chonks with attachment" do
+ data = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "actor" => "https://honk.tedunangst.com/u/tedu",
+ "id" => "https://honk.tedunangst.com/u/tedu/honk/x6gt8X8PcyGkQcXxzg1T",
+ "object" => %{
+ "attachment" => [
+ %{
+ "mediaType" => "image/jpeg",
+ "name" => "298p3RG7j27tfsZ9RQ.jpg",
+ "summary" => "298p3RG7j27tfsZ9RQ.jpg",
+ "type" => "Document",
+ "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg"
+ }
+ ],
+ "attributedTo" => "https://honk.tedunangst.com/u/tedu",
+ "content" => "",
+ "id" => "https://honk.tedunangst.com/u/tedu/chonk/26L4wl5yCbn4dr4y1b",
+ "published" => "2020-05-18T01:13:03Z",
+ "to" => [
+ "https://dontbulling.me/users/lain"
+ ],
+ "type" => "ChatMessage"
+ },
+ "published" => "2020-05-18T01:13:03Z",
+ "to" => [
+ "https://dontbulling.me/users/lain"
+ ],
+ "type" => "Create"
+ }
+
+ _user = insert(:user, ap_id: data["actor"])
+ _user = insert(:user, ap_id: hd(data["to"]))
+
+ assert {:ok, _activity} = Transmogrifier.handle_incoming(data)
+ end
+
+ test "it rejects messages that don't contain content" do
+ data =
+ File.read!("test/fixtures/create-chat-message.json")
+ |> Poison.decode!()
+
+ object =
+ data["object"]
+ |> Map.delete("content")
+
+ data =
+ data
+ |> Map.put("object", object)
+
+ _author =
+ insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now())
+
+ _recipient =
+ insert(:user,
+ ap_id: List.first(data["to"]),
+ local: true,
+ last_refreshed_at: DateTime.utc_now()
+ )
+
+ {:error, _} = Transmogrifier.handle_incoming(data)
+ end
+
+ test "it rejects messages that don't concern local users" do
+ data =
+ File.read!("test/fixtures/create-chat-message.json")
+ |> Poison.decode!()
+
+ _author =
+ insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now())
+
+ _recipient =
+ insert(:user,
+ ap_id: List.first(data["to"]),
+ local: false,
+ last_refreshed_at: DateTime.utc_now()
+ )
+
+ {:error, _} = Transmogrifier.handle_incoming(data)
+ end
+
+ test "it rejects messages where the `to` field of activity and object don't match" do
+ data =
+ File.read!("test/fixtures/create-chat-message.json")
+ |> Poison.decode!()
+
+ author = insert(:user, ap_id: data["actor"])
+ _recipient = insert(:user, ap_id: List.first(data["to"]))
+
+ data =
+ data
+ |> Map.put("to", author.ap_id)
+
+ assert match?({:error, _}, Transmogrifier.handle_incoming(data))
+ refute Object.get_by_ap_id(data["object"]["id"])
+ end
+
+ test "it fetches the actor if they aren't in our system" do
+ Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
+
+ data =
+ File.read!("test/fixtures/create-chat-message.json")
+ |> Poison.decode!()
+ |> Map.put("actor", "http://mastodon.example.org/users/admin")
+ |> put_in(["object", "actor"], "http://mastodon.example.org/users/admin")
+
+ _recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
+
+ {:ok, %Activity{} = _activity} = Transmogrifier.handle_incoming(data)
+ end
+
+ test "it inserts it and creates a chat" do
+ data =
+ File.read!("test/fixtures/create-chat-message.json")
+ |> Poison.decode!()
+
+ author =
+ insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now())
+
+ recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
+
+ {:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(data)
+ assert activity.local == false
+
+ assert activity.actor == author.ap_id
+ assert activity.recipients == [recipient.ap_id, author.ap_id]
+
+ %Object{} = object = Object.get_by_ap_id(activity.data["object"])
+
+ assert object
+ assert object.data["content"] == "You expected a cute girl? Too bad. alert(&#39;XSS&#39;)"
+ assert match?(%{"firefox" => _}, object.data["emoji"])
+
+ refute Chat.get(author.id, recipient.ap_id)
+ assert Chat.get(recipient.id, author.ap_id)
+ end
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/delete_handling_test.exs b/test/web/activity_pub/transmogrifier/delete_handling_test.exs
new file mode 100644
index 000000000..c9a53918c
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/delete_handling_test.exs
@@ -0,0 +1,114 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do
+ use Oban.Testing, repo: Pleroma.Repo
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Tests.ObanHelpers
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+
+ import Pleroma.Factory
+
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
+ test "it works for incoming deletes" do
+ activity = insert(:note_activity)
+ deleting_user = insert(:user)
+
+ data =
+ File.read!("test/fixtures/mastodon-delete.json")
+ |> Poison.decode!()
+ |> Map.put("actor", deleting_user.ap_id)
+ |> put_in(["object", "id"], activity.data["object"])
+
+ {:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
+ Transmogrifier.handle_incoming(data)
+
+ assert id == data["id"]
+
+ # We delete the Create activity because we base our timelines on it.
+ # This should be changed after we unify objects and activities
+ refute Activity.get_by_id(activity.id)
+ assert actor == deleting_user.ap_id
+
+ # Objects are replaced by a tombstone object.
+ object = Object.normalize(activity.data["object"])
+ assert object.data["type"] == "Tombstone"
+ end
+
+ test "it works for incoming when the object has been pruned" do
+ activity = insert(:note_activity)
+
+ {:ok, object} =
+ Object.normalize(activity.data["object"])
+ |> Repo.delete()
+
+ Cachex.del(:object_cache, "object:#{object.data["id"]}")
+
+ deleting_user = insert(:user)
+
+ data =
+ File.read!("test/fixtures/mastodon-delete.json")
+ |> Poison.decode!()
+ |> Map.put("actor", deleting_user.ap_id)
+ |> put_in(["object", "id"], activity.data["object"])
+
+ {:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
+ Transmogrifier.handle_incoming(data)
+
+ assert id == data["id"]
+
+ # We delete the Create activity because we base our timelines on it.
+ # This should be changed after we unify objects and activities
+ refute Activity.get_by_id(activity.id)
+ assert actor == deleting_user.ap_id
+ end
+
+ test "it fails for incoming deletes with spoofed origin" do
+ activity = insert(:note_activity)
+ %{ap_id: ap_id} = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo")
+
+ data =
+ File.read!("test/fixtures/mastodon-delete.json")
+ |> Poison.decode!()
+ |> Map.put("actor", ap_id)
+ |> put_in(["object", "id"], activity.data["object"])
+
+ assert match?({:error, _}, Transmogrifier.handle_incoming(data))
+ end
+
+ @tag capture_log: true
+ test "it works for incoming user deletes" do
+ %{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
+
+ data =
+ File.read!("test/fixtures/mastodon-delete-user.json")
+ |> Poison.decode!()
+
+ {:ok, _} = Transmogrifier.handle_incoming(data)
+ ObanHelpers.perform_all()
+
+ assert User.get_cached_by_ap_id(ap_id).deactivated
+ end
+
+ test "it fails for incoming user deletes with spoofed origin" do
+ %{ap_id: ap_id} = insert(:user)
+
+ data =
+ File.read!("test/fixtures/mastodon-delete-user.json")
+ |> Poison.decode!()
+ |> Map.put("actor", ap_id)
+
+ assert match?({:error, _}, Transmogrifier.handle_incoming(data))
+
+ assert User.get_cached_by_ap_id(ap_id)
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs b/test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs
new file mode 100644
index 000000000..0fb056b50
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs
@@ -0,0 +1,61 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "it works for incoming emoji reactions" do
+ user = insert(:user)
+ other_user = insert(:user, local: false)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/emoji-reaction.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+ |> Map.put("actor", other_user.ap_id)
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == other_user.ap_id
+ assert data["type"] == "EmojiReact"
+ assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
+ assert data["object"] == activity.data["object"]
+ assert data["content"] == "👌"
+
+ object = Object.get_by_ap_id(data["object"])
+
+ assert object.data["reaction_count"] == 1
+ assert match?([["👌", _]], object.data["reactions"])
+ end
+
+ test "it reject invalid emoji reactions" do
+ user = insert(:user)
+ other_user = insert(:user, local: false)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/emoji-reaction-too-long.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+ |> Map.put("actor", other_user.ap_id)
+
+ assert {:error, _} = Transmogrifier.handle_incoming(data)
+
+ data =
+ File.read!("test/fixtures/emoji-reaction-no-emoji.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+ |> Map.put("actor", other_user.ap_id)
+
+ assert {:error, _} = Transmogrifier.handle_incoming(data)
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs
index 967389fae..06c39eed6 100644
--- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs
+++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs
@@ -5,6 +5,7 @@
defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
use Pleroma.DataCase
alias Pleroma.Activity
+ alias Pleroma.Notification
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Transmogrifier
@@ -12,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
import Pleroma.Factory
import Ecto.Query
+ import Mock
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
@@ -57,9 +59,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
activity = Repo.get(Activity, activity.id)
assert activity.data["state"] == "accept"
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
+
+ [notification] = Notification.for_user(user)
+ assert notification.type == "follow"
end
- test "with locked accounts, it does not create a follow or an accept" do
+ test "with locked accounts, it does create a Follow, but not an Accept" do
user = insert(:user, locked: true)
data =
@@ -81,6 +86,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
|> Repo.all()
assert Enum.empty?(accepts)
+
+ [notification] = Notification.for_user(user)
+ assert notification.type == "follow_request"
end
test "it works for follow requests when you are already followed, creating a new accept activity" do
@@ -144,6 +152,23 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
assert activity.data["state"] == "reject"
end
+ test "it rejects incoming follow requests if the following errors for some reason" do
+ user = insert(:user)
+
+ data =
+ File.read!("test/fixtures/mastodon-follow-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", user.ap_id)
+
+ 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)
+
+ assert activity.data["state"] == "reject"
+ end
+ end
+
test "it works for incoming follow requests from hubzilla" do
user = insert(:user)
diff --git a/test/web/activity_pub/transmogrifier/like_handling_test.exs b/test/web/activity_pub/transmogrifier/like_handling_test.exs
new file mode 100644
index 000000000..53fe1d550
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/like_handling_test.exs
@@ -0,0 +1,78 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "it works for incoming likes" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/mastodon-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _actor = insert(:user, ap_id: data["actor"], local: false)
+
+ {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ refute Enum.empty?(activity.recipients)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "Like"
+ assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
+ assert data["object"] == activity.data["object"]
+ end
+
+ test "it works for incoming misskey likes, turning them into EmojiReacts" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/misskey-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _actor = insert(:user, ap_id: data["actor"], local: false)
+
+ {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert activity_data["actor"] == data["actor"]
+ assert activity_data["type"] == "EmojiReact"
+ assert activity_data["id"] == data["id"]
+ assert activity_data["object"] == activity.data["object"]
+ assert activity_data["content"] == "🍮"
+ end
+
+ test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReacts" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/misskey-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+ |> Map.put("_misskey_reaction", "⭐")
+
+ _actor = insert(:user, ap_id: data["actor"], local: false)
+
+ {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert activity_data["actor"] == data["actor"]
+ assert activity_data["type"] == "EmojiReact"
+ assert activity_data["id"] == data["id"]
+ assert activity_data["object"] == activity.data["object"]
+ assert activity_data["content"] == "⭐"
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs
new file mode 100644
index 000000000..01dd6c370
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/undo_handling_test.exs
@@ -0,0 +1,185 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "it works for incoming emoji reaction undos" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+ {:ok, reaction_activity} = CommonAPI.react_with_emoji(activity.id, user, "👌")
+
+ data =
+ File.read!("test/fixtures/mastodon-undo-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", reaction_activity.data["id"])
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, activity} = Transmogrifier.handle_incoming(data)
+
+ assert activity.actor == user.ap_id
+ assert activity.data["id"] == data["id"]
+ assert activity.data["type"] == "Undo"
+ end
+
+ test "it returns an error for incoming unlikes wihout a like activity" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
+
+ data =
+ File.read!("test/fixtures/mastodon-undo-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ assert Transmogrifier.handle_incoming(data) == :error
+ end
+
+ test "it works for incoming unlikes with an existing like activity" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
+
+ like_data =
+ File.read!("test/fixtures/mastodon-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _liker = insert(:user, ap_id: like_data["actor"], local: false)
+
+ {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
+
+ data =
+ File.read!("test/fixtures/mastodon-undo-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", like_data)
+ |> Map.put("actor", like_data["actor"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "Undo"
+ assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
+ assert data["object"] == "http://mastodon.example.org/users/admin#likes/2"
+
+ note = Object.get_by_ap_id(like_data["object"])
+ assert note.data["like_count"] == 0
+ assert note.data["likes"] == []
+ end
+
+ test "it works for incoming unlikes with an existing like activity and a compact object" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
+
+ like_data =
+ File.read!("test/fixtures/mastodon-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _liker = insert(:user, ap_id: like_data["actor"], local: false)
+
+ {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
+
+ data =
+ File.read!("test/fixtures/mastodon-undo-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", like_data["id"])
+ |> Map.put("actor", like_data["actor"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "Undo"
+ assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
+ assert data["object"] == "http://mastodon.example.org/users/admin#likes/2"
+ end
+
+ test "it works for incoming unannounces with an existing notice" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
+
+ announce_data =
+ File.read!("test/fixtures/mastodon-announce.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _announcer = insert(:user, ap_id: announce_data["actor"], local: false)
+
+ {:ok, %Activity{data: announce_data, local: false}} =
+ Transmogrifier.handle_incoming(announce_data)
+
+ data =
+ File.read!("test/fixtures/mastodon-undo-announce.json")
+ |> Poison.decode!()
+ |> Map.put("object", announce_data)
+ |> Map.put("actor", announce_data["actor"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["type"] == "Undo"
+
+ assert data["object"] ==
+ "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
+ end
+
+ test "it works for incomming unfollows with an existing follow" do
+ user = insert(:user)
+
+ follow_data =
+ File.read!("test/fixtures/mastodon-follow-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", user.ap_id)
+
+ _follower = insert(:user, ap_id: follow_data["actor"], local: false)
+
+ {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data)
+
+ data =
+ File.read!("test/fixtures/mastodon-unfollow-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", follow_data)
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["type"] == "Undo"
+ assert data["object"]["type"] == "Follow"
+ assert data["object"]["object"] == user.ap_id
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+
+ refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
+ end
+
+ test "it works for incoming unblocks with an existing block" do
+ user = insert(:user)
+
+ block_data =
+ File.read!("test/fixtures/mastodon-block-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", user.ap_id)
+
+ _blocker = insert(:user, ap_id: block_data["actor"], local: false)
+
+ {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data)
+
+ data =
+ File.read!("test/fixtures/mastodon-unblock-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", block_data)
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+ assert data["type"] == "Undo"
+ assert data["object"] == block_data["id"]
+
+ blocker = User.get_cached_by_ap_id(data["actor"])
+
+ refute User.blocks?(blocker, user)
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 6057e360a..47d6e843a 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -28,6 +28,63 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
setup do: clear_config([:instance, :max_remote_account_fields])
describe "handle_incoming" do
+ test "it works for incoming notices with tag not being an array (kroeg)" do
+ data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Poison.decode!()
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+ object = Object.normalize(data["object"])
+
+ assert object.data["emoji"] == %{
+ "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
+ }
+
+ data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Poison.decode!()
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+ object = Object.normalize(data["object"])
+
+ assert "test" in object.data["tag"]
+ end
+
+ test "it works for incoming notices with url not being a string (prismo)" do
+ data = File.read!("test/fixtures/prismo-url-map.json") |> Poison.decode!()
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+ object = Object.normalize(data["object"])
+
+ assert object.data["url"] == "https://prismo.news/posts/83"
+ end
+
+ test "it cleans up incoming notices which are not really DMs" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ to = [user.ap_id, other_user.ap_id]
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ |> Map.put("to", to)
+ |> Map.put("cc", [])
+
+ object =
+ data["object"]
+ |> Map.put("to", to)
+ |> Map.put("cc", [])
+
+ data = Map.put(data, "object", object)
+
+ {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ assert data["to"] == []
+ assert data["cc"] == to
+
+ object_data = Object.normalize(activity).data
+
+ assert object_data["to"] == []
+ assert object_data["cc"] == to
+ end
+
test "it ignores an incoming notice if we already have it" do
activity = insert(:note_activity)
@@ -212,8 +269,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "suya...",
- "poll" => %{"options" => ["suya", "suya.", "suya.."], "expires_in" => 10}
+ status: "suya...",
+ poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
})
object = Object.normalize(activity)
@@ -260,328 +317,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
end
- test "it works for incoming announces with actor being inlined (kroeg)" do
- data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "https://puckipedia.com/"
- end
-
- test "it works for incoming notices with tag not being an array (kroeg)" do
- data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert object.data["emoji"] == %{
- "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
- }
-
- data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert "test" in object.data["tag"]
- end
-
- test "it works for incoming notices with url not being a string (prismo)" do
- data = File.read!("test/fixtures/prismo-url-map.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert object.data["url"] == "https://prismo.news/posts/83"
- end
-
- test "it cleans up incoming notices which are not really DMs" do
- user = insert(:user)
- other_user = insert(:user)
-
- to = [user.ap_id, other_user.ap_id]
-
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("to", to)
- |> Map.put("cc", [])
-
- object =
- data["object"]
- |> Map.put("to", to)
- |> Map.put("cc", [])
-
- data = Map.put(data, "object", object)
-
- {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- assert data["to"] == []
- assert data["cc"] == to
-
- object_data = Object.normalize(activity).data
-
- assert object_data["to"] == []
- assert object_data["cc"] == to
- end
-
- test "it works for incoming likes" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
-
- data =
- File.read!("test/fixtures/mastodon-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- refute Enum.empty?(activity.recipients)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Like"
- assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
- assert data["object"] == activity.data["object"]
- end
-
- test "it works for incoming misskey likes, turning them into EmojiReacts" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
-
- data =
- File.read!("test/fixtures/misskey-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == data["actor"]
- assert data["type"] == "EmojiReact"
- assert data["id"] == data["id"]
- assert data["object"] == activity.data["object"]
- assert data["content"] == "🍮"
- end
-
- test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReacts" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
-
- data =
- File.read!("test/fixtures/misskey-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
- |> Map.put("_misskey_reaction", "⭐")
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == data["actor"]
- assert data["type"] == "EmojiReact"
- assert data["id"] == data["id"]
- assert data["object"] == activity.data["object"]
- assert data["content"] == "⭐"
- end
-
- test "it works for incoming emoji reactions" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
-
- data =
- File.read!("test/fixtures/emoji-reaction.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "EmojiReact"
- assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
- assert data["object"] == activity.data["object"]
- assert data["content"] == "👌"
- end
-
- test "it reject invalid emoji reactions" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
-
- data =
- File.read!("test/fixtures/emoji-reaction-too-long.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- assert :error = Transmogrifier.handle_incoming(data)
-
- data =
- File.read!("test/fixtures/emoji-reaction-no-emoji.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- assert :error = Transmogrifier.handle_incoming(data)
- end
-
- test "it works for incoming emoji reaction undos" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
- {:ok, reaction_activity, _object} = CommonAPI.react_with_emoji(activity.id, user, "👌")
-
- data =
- File.read!("test/fixtures/mastodon-undo-like.json")
- |> Poison.decode!()
- |> Map.put("object", reaction_activity.data["id"])
- |> Map.put("actor", user.ap_id)
-
- {:ok, activity} = Transmogrifier.handle_incoming(data)
-
- assert activity.actor == user.ap_id
- assert activity.data["id"] == data["id"]
- assert activity.data["type"] == "Undo"
- end
-
- test "it returns an error for incoming unlikes wihout a like activity" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
-
- data =
- File.read!("test/fixtures/mastodon-undo-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- assert Transmogrifier.handle_incoming(data) == :error
- end
-
- test "it works for incoming unlikes with an existing like activity" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
-
- like_data =
- File.read!("test/fixtures/mastodon-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
-
- data =
- File.read!("test/fixtures/mastodon-undo-like.json")
- |> Poison.decode!()
- |> Map.put("object", like_data)
- |> Map.put("actor", like_data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Undo"
- assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
- assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"
- end
-
- test "it works for incoming unlikes with an existing like activity and a compact object" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
-
- like_data =
- File.read!("test/fixtures/mastodon-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
-
- data =
- File.read!("test/fixtures/mastodon-undo-like.json")
- |> Poison.decode!()
- |> Map.put("object", like_data["id"])
- |> Map.put("actor", like_data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Undo"
- assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
- assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"
- end
-
- test "it works for incoming announces" do
- data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Announce"
-
- assert data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
-
- assert data["object"] ==
- "http://mastodon.example.org/users/admin/statuses/99541947525187367"
-
- assert Activity.get_create_by_object_ap_id(data["object"])
- end
-
- test "it works for incoming announces with an existing activity" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
-
- data =
- File.read!("test/fixtures/mastodon-announce.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Announce"
-
- assert data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
-
- assert data["object"] == activity.data["object"]
-
- assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id
- end
-
- test "it works for incoming announces with an inlined activity" do
- data =
- File.read!("test/fixtures/mastodon-announce-private.json")
- |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Announce"
-
- assert data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
-
- object = Object.normalize(data["object"])
-
- assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368"
- assert object.data["content"] == "this is a private toot"
- end
-
- @tag capture_log: true
- test "it rejects incoming announces with an inlined activity from another origin" do
- data =
- File.read!("test/fixtures/bogus-mastodon-announce.json")
- |> Poison.decode!()
-
- assert :error = Transmogrifier.handle_incoming(data)
- end
-
- test "it does not clobber the addressing on announce activities" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
-
- data =
- File.read!("test/fixtures/mastodon-announce.json")
- |> Poison.decode!()
- |> Map.put("object", Object.normalize(activity).data["id"])
- |> Map.put("to", ["http://mastodon.example.org/users/admin/followers"])
- |> Map.put("cc", [])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["to"] == ["http://mastodon.example.org/users/admin/followers"]
- end
-
test "it ensures that as:Public activities make it to their followers collection" do
user = insert(:user)
@@ -654,8 +389,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it strips internal reactions" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
- {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, user, "📢")
+ {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "📢")
%{object: object} = Activity.get_by_id_with_object(activity.id)
assert Map.has_key?(object.data, "reactions")
@@ -822,112 +557,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert user.locked == true
end
- test "it works for incoming deletes" do
- activity = insert(:note_activity)
- deleting_user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-delete.json")
- |> Poison.decode!()
-
- object =
- data["object"]
- |> Map.put("id", activity.data["object"])
-
- data =
- data
- |> Map.put("object", object)
- |> Map.put("actor", deleting_user.ap_id)
-
- {:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
- Transmogrifier.handle_incoming(data)
-
- assert id == data["id"]
- refute Activity.get_by_id(activity.id)
- assert actor == deleting_user.ap_id
- end
-
- test "it fails for incoming deletes with spoofed origin" do
- activity = insert(:note_activity)
-
- data =
- File.read!("test/fixtures/mastodon-delete.json")
- |> Poison.decode!()
-
- object =
- data["object"]
- |> Map.put("id", activity.data["object"])
-
- data =
- data
- |> Map.put("object", object)
-
- assert capture_log(fn ->
- :error = Transmogrifier.handle_incoming(data)
- end) =~
- "[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, :nxdomain}"
-
- assert Activity.get_by_id(activity.id)
- end
-
- @tag capture_log: true
- test "it works for incoming user deletes" do
- %{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
-
- data =
- File.read!("test/fixtures/mastodon-delete-user.json")
- |> Poison.decode!()
-
- {:ok, _} = Transmogrifier.handle_incoming(data)
- ObanHelpers.perform_all()
-
- refute User.get_cached_by_ap_id(ap_id)
- end
-
- test "it fails for incoming user deletes with spoofed origin" do
- %{ap_id: ap_id} = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-delete-user.json")
- |> Poison.decode!()
- |> Map.put("actor", ap_id)
-
- assert capture_log(fn ->
- assert :error == Transmogrifier.handle_incoming(data)
- end) =~ "Object containment failed"
-
- assert User.get_cached_by_ap_id(ap_id)
- end
-
- test "it works for incoming unannounces with an existing notice" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
-
- announce_data =
- File.read!("test/fixtures/mastodon-announce.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- {:ok, %Activity{data: announce_data, local: false}} =
- Transmogrifier.handle_incoming(announce_data)
-
- data =
- File.read!("test/fixtures/mastodon-undo-announce.json")
- |> Poison.decode!()
- |> Map.put("object", announce_data)
- |> Map.put("actor", announce_data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Undo"
- assert object_data = data["object"]
- assert object_data["type"] == "Announce"
- assert object_data["object"] == activity.data["object"]
-
- assert object_data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
- end
-
test "it works for incomming unfollows with an existing follow" do
user = insert(:user)
@@ -1022,32 +651,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute User.following?(blocked, blocker)
end
- test "it works for incoming unblocks with an existing block" do
- user = insert(:user)
-
- block_data =
- File.read!("test/fixtures/mastodon-block-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data)
-
- data =
- File.read!("test/fixtures/mastodon-unblock-activity.json")
- |> Poison.decode!()
- |> Map.put("object", block_data)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- assert data["type"] == "Undo"
- assert data["object"]["type"] == "Block"
- assert data["object"]["object"] == user.ap_id
- assert data["actor"] == "http://mastodon.example.org/users/admin"
-
- blocker = User.get_cached_by_ap_id(data["actor"])
-
- refute User.blocks?(blocker, user)
- end
-
test "it works for incoming accepts which were pre-accepted" do
follower = insert(:user)
followed = insert(:user)
@@ -1121,6 +724,12 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, followed) == true
+
+ follower = User.get_by_id(follower.id)
+ assert follower.following_count == 1
+
+ followed = User.get_by_id(followed.id)
+ assert followed.follower_count == 1
end
test "it fails for incoming accepts which cannot be correlated" do
@@ -1221,6 +830,35 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
:error = Transmogrifier.handle_incoming(data)
end
+ test "skip converting the content when it is nil" do
+ object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe"
+
+ {:ok, object} = Fetcher.fetch_and_contain_remote_object_from_id(object_id)
+
+ result =
+ Pleroma.Web.ActivityPub.Transmogrifier.fix_object(Map.merge(object, %{"content" => nil}))
+
+ assert result["content"] == nil
+ end
+
+ test "it converts content of object to html" do
+ object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe"
+
+ {:ok, %{"content" => content_markdown}} =
+ Fetcher.fetch_and_contain_remote_object_from_id(object_id)
+
+ {:ok, %Pleroma.Object{data: %{"content" => content}} = object} =
+ Fetcher.fetch_object_from_id(object_id)
+
+ assert content_markdown ==
+ "Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership\n\nTwenty Years in Jail: FreeBSD's Jails, Then and Now\n\nJails started as a limited virtualization system, but over the last two years they've..."
+
+ assert content ==
+ "<p>Support this and our other Michigan!/usr/group videos and meetings. Learn more at <a href=\"http://mug.org/membership\">http://mug.org/membership</a></p><p>Twenty Years in Jail: FreeBSD’s Jails, Then and Now</p><p>Jails started as a limited virtualization system, but over the last two years they’ve…</p>"
+
+ assert object.data["mediaType"] == "text/html"
+ end
+
test "it remaps video URLs as attachments if necessary" do
{:ok, object} =
Fetcher.fetch_object_from_id(
@@ -1249,7 +887,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
object = Object.normalize(activity)
note_obj = %{
@@ -1393,13 +1031,13 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
setup do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "post1"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "post1"})
{:ok, reply1} =
- CommonAPI.post(user, %{"status" => "reply1", "in_reply_to_status_id" => activity.id})
+ CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: activity.id})
{:ok, reply2} =
- CommonAPI.post(user, %{"status" => "reply2", "in_reply_to_status_id" => activity.id})
+ CommonAPI.post(user, %{status: "reply2", in_reply_to_status_id: activity.id})
replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end)
@@ -1439,9 +1077,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it inlines private announced objects" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey", "visibility" => "private"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey", visibility: "private"})
- {:ok, announce_activity, _} = CommonAPI.repeat(activity.id, user)
+ {:ok, announce_activity} = CommonAPI.repeat(activity.id, user)
{:ok, modified} = Transmogrifier.prepare_outgoing(announce_activity.data)
@@ -1454,31 +1092,36 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
other_user = insert(:user)
{:ok, activity} =
- CommonAPI.post(user, %{"status" => "hey, @#{other_user.nickname}, how are ya? #2hu"})
+ CommonAPI.post(user, %{status: "hey, @#{other_user.nickname}, how are ya? #2hu"})
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
- object = modified["object"]
+ with_mock Pleroma.Notification,
+ get_notified_from_activity: fn _, _ -> [] end do
+ {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
- expected_mention = %{
- "href" => other_user.ap_id,
- "name" => "@#{other_user.nickname}",
- "type" => "Mention"
- }
+ object = modified["object"]
- expected_tag = %{
- "href" => Pleroma.Web.Endpoint.url() <> "/tags/2hu",
- "type" => "Hashtag",
- "name" => "#2hu"
- }
+ expected_mention = %{
+ "href" => other_user.ap_id,
+ "name" => "@#{other_user.nickname}",
+ "type" => "Mention"
+ }
- assert Enum.member?(object["tag"], expected_tag)
- assert Enum.member?(object["tag"], expected_mention)
+ expected_tag = %{
+ "href" => Pleroma.Web.Endpoint.url() <> "/tags/2hu",
+ "type" => "Hashtag",
+ "name" => "#2hu"
+ }
+
+ refute called(Pleroma.Notification.get_notified_from_activity(:_, :_))
+ assert Enum.member?(object["tag"], expected_tag)
+ assert Enum.member?(object["tag"], expected_mention)
+ end
end
test "it adds the sensitive property" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#nsfw hey"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "#nsfw hey"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["object"]["sensitive"]
@@ -1487,7 +1130,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it adds the json-ld context and the conversation property" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["@context"] ==
@@ -1499,7 +1142,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["object"]["actor"] == modified["object"]["attributedTo"]
@@ -1508,7 +1151,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it strips internal hashtag data" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "#2hu"})
expected_tag = %{
"href" => Pleroma.Web.Endpoint.url() <> "/tags/2hu",
@@ -1524,7 +1167,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it strips internal fields" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu :firefox:"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "#2hu :firefox:"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
@@ -1556,14 +1199,13 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu :moominmamma:"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "2hu :moominmamma:"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["directMessage"] == false
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "@#{other_user.nickname} :moominmamma:"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "@#{other_user.nickname} :moominmamma:"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
@@ -1571,8 +1213,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "@#{other_user.nickname} :moominmamma:",
- "visibility" => "direct"
+ status: "@#{other_user.nickname} :moominmamma:",
+ visibility: "direct"
})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
@@ -1584,8 +1226,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user = insert(:user)
{:ok, list} = Pleroma.List.create("foo", user)
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
@@ -1620,8 +1261,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user_two = insert(:user)
Pleroma.FollowingRelationship.follow(user_two, user, :follow_accept)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
- {:ok, unrelated_activity} = CommonAPI.post(user_two, %{"status" => "test"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test"})
+ {:ok, unrelated_activity} = CommonAPI.post(user_two, %{status: "test"})
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
user = User.get_cached_by_id(user.id)
@@ -1693,7 +1334,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
}
assert capture_log(fn ->
- :error = Transmogrifier.handle_incoming(data)
+ {:error, _} = Transmogrifier.handle_incoming(data)
end) =~ "Object containment failed"
end
@@ -1708,7 +1349,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
}
assert capture_log(fn ->
- :error = Transmogrifier.handle_incoming(data)
+ {:error, _} = Transmogrifier.handle_incoming(data)
end) =~ "Object containment failed"
end
@@ -1723,7 +1364,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
}
assert capture_log(fn ->
- :error = Transmogrifier.handle_incoming(data)
+ {:error, _} = Transmogrifier.handle_incoming(data)
end) =~ "Object containment failed"
end
end
@@ -1787,8 +1428,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, poll_activity} =
CommonAPI.post(user, %{
- "status" => "suya...",
- "poll" => %{"options" => ["suya", "suya.", "suya.."], "expires_in" => 10}
+ status: "suya...",
+ poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
})
poll_object = Object.normalize(poll_activity)
@@ -1930,9 +1571,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
- assert modified_object["conversation"] ==
- "tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26"
-
assert modified_object["context"] ==
"tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26"
end
@@ -2131,28 +1769,27 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "sets `replies` collection with a limited number of self-replies" do
[user, another_user] = insert_list(2, :user)
- {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{"status" => "1"})
+ {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{status: "1"})
{:ok, %{id: id2} = self_reply1} =
- CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => id1})
+ CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: id1})
{:ok, self_reply2} =
- CommonAPI.post(user, %{"status" => "self-reply 2", "in_reply_to_status_id" => id1})
+ CommonAPI.post(user, %{status: "self-reply 2", in_reply_to_status_id: id1})
# Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2
- {:ok, _} =
- CommonAPI.post(user, %{"status" => "self-reply 3", "in_reply_to_status_id" => id1})
+ {:ok, _} = CommonAPI.post(user, %{status: "self-reply 3", in_reply_to_status_id: id1})
{:ok, _} =
CommonAPI.post(user, %{
- "status" => "self-reply to self-reply",
- "in_reply_to_status_id" => id2
+ status: "self-reply to self-reply",
+ in_reply_to_status_id: id2
})
{:ok, _} =
CommonAPI.post(another_user, %{
- "status" => "another user's reply",
- "in_reply_to_status_id" => id1
+ status: "another user's reply",
+ in_reply_to_status_id: id1
})
object = Object.normalize(activity)
diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs
index e913a5148..15f03f193 100644
--- a/test/web/activity_pub/utils_test.exs
+++ b/test/web/activity_pub/utils_test.exs
@@ -102,34 +102,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
end
end
- describe "make_unlike_data/3" do
- test "returns data for unlike activity" do
- user = insert(:user)
- like_activity = insert(:like_activity, data_attrs: %{"context" => "test context"})
-
- object = Object.normalize(like_activity.data["object"])
-
- assert Utils.make_unlike_data(user, like_activity, nil) == %{
- "type" => "Undo",
- "actor" => user.ap_id,
- "object" => like_activity.data,
- "to" => [user.follower_address, object.data["actor"]],
- "cc" => [Pleroma.Constants.as_public()],
- "context" => like_activity.data["context"]
- }
-
- assert Utils.make_unlike_data(user, like_activity, "9mJEZK0tky1w2xD2vY") == %{
- "type" => "Undo",
- "actor" => user.ap_id,
- "object" => like_activity.data,
- "to" => [user.follower_address, object.data["actor"]],
- "cc" => [Pleroma.Constants.as_public()],
- "context" => like_activity.data["context"],
- "id" => "9mJEZK0tky1w2xD2vY"
- }
- end
- end
-
describe "make_like_data" do
setup do
user = insert(:user)
@@ -148,7 +120,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"hey @#{other_user.nickname}, @#{third_user.nickname} how about beering together this weekend?"
})
@@ -167,8 +139,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!",
- "visibility" => "private"
+ status: "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!",
+ visibility: "private"
})
%{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
@@ -196,11 +168,11 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "How do I pronounce LaTeX?",
- "poll" => %{
- "options" => ["laytekh", "lahtekh", "latex"],
- "expires_in" => 20,
- "multiple" => true
+ status: "How do I pronounce LaTeX?",
+ poll: %{
+ options: ["laytekh", "lahtekh", "latex"],
+ expires_in: 20,
+ multiple: true
}
})
@@ -215,17 +187,16 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "Are we living in a society?",
- "poll" => %{
- "options" => ["yes", "no"],
- "expires_in" => 20
+ status: "Are we living in a society?",
+ poll: %{
+ options: ["yes", "no"],
+ expires_in: 20
}
})
object = Object.normalize(activity)
{:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
- vote_object = Object.normalize(vote)
- {:ok, _activity, _object} = ActivityPub.like(user, vote_object)
+ {:ok, _activity} = CommonAPI.favorite(user, activity.id)
[fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
assert fetched_vote.id == vote.id
end
@@ -346,7 +317,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
user = insert(:user)
refute Utils.get_existing_like(user.ap_id, object)
- {:ok, like_activity, _object} = ActivityPub.like(user, object)
+ {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
end
@@ -363,7 +334,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
assert object = Object.normalize(note_activity)
actor = insert(:user)
- {:ok, announce, _object} = ActivityPub.announce(actor, object)
+ {:ok, announce} = CommonAPI.repeat(note_activity.id, actor)
assert Utils.get_existing_announce(actor.ap_id, object) == announce
end
end
@@ -498,7 +469,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
test "returns map with Flag object" do
reporter = insert(:user)
target_account = insert(:user)
- {:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
+ {:ok, activity} = CommonAPI.post(target_account, %{status: "foobar"})
context = Utils.generate_context_id()
content = "foobar"
diff --git a/test/web/activity_pub/views/object_view_test.exs b/test/web/activity_pub/views/object_view_test.exs
index 6c006206b..f0389845d 100644
--- a/test/web/activity_pub/views/object_view_test.exs
+++ b/test/web/activity_pub/views/object_view_test.exs
@@ -44,7 +44,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
activity = insert(:note_activity, user: user)
{:ok, self_reply1} =
- CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => activity.id})
+ CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: activity.id})
replies_uris = [self_reply1.object.data["id"]]
result = ObjectView.render("object.json", %{object: refresh_record(activity)})
@@ -73,7 +73,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
object = Object.normalize(note)
user = insert(:user)
- {:ok, announce_activity, _} = CommonAPI.repeat(note.id, user)
+ {:ok, announce_activity} = CommonAPI.repeat(note.id, user)
result = ObjectView.render("object.json", %{object: announce_activity})
diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs
index 8d00893a5..bec15a996 100644
--- a/test/web/activity_pub/views/user_view_test.exs
+++ b/test/web/activity_pub/views/user_view_test.exs
@@ -158,35 +158,4 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
end
end
-
- test "activity collection page aginates correctly" do
- user = insert(:user)
-
- posts =
- for i <- 0..25 do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "post #{i}"})
- activity
- end
-
- # outbox sorts chronologically, newest first, with ten per page
- posts = Enum.reverse(posts)
-
- %{"next" => next_url} =
- UserView.render("activity_collection_page.json", %{
- iri: "#{user.ap_id}/outbox",
- activities: Enum.take(posts, 10)
- })
-
- next_id = Enum.at(posts, 9).id
- assert next_url =~ next_id
-
- %{"next" => next_url} =
- UserView.render("activity_collection_page.json", %{
- iri: "#{user.ap_id}/outbox",
- activities: Enum.take(Enum.drop(posts, 10), 10)
- })
-
- next_id = Enum.at(posts, 19).id
- assert next_url =~ next_id
- end
end
diff --git a/test/web/activity_pub/visibilty_test.exs b/test/web/activity_pub/visibilty_test.exs
index 5b91630d4..8e9354c65 100644
--- a/test/web/activity_pub/visibilty_test.exs
+++ b/test/web/activity_pub/visibilty_test.exs
@@ -21,21 +21,21 @@ defmodule Pleroma.Web.ActivityPub.VisibilityTest do
Pleroma.List.follow(list, unrelated)
{:ok, public} =
- CommonAPI.post(user, %{"status" => "@#{mentioned.nickname}", "visibility" => "public"})
+ CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "public"})
{:ok, private} =
- CommonAPI.post(user, %{"status" => "@#{mentioned.nickname}", "visibility" => "private"})
+ CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "private"})
{:ok, direct} =
- CommonAPI.post(user, %{"status" => "@#{mentioned.nickname}", "visibility" => "direct"})
+ CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "direct"})
{:ok, unlisted} =
- CommonAPI.post(user, %{"status" => "@#{mentioned.nickname}", "visibility" => "unlisted"})
+ CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "unlisted"})
{:ok, list} =
CommonAPI.post(user, %{
- "status" => "@#{mentioned.nickname}",
- "visibility" => "list:#{list.id}"
+ status: "@#{mentioned.nickname}",
+ visibility: "list:#{list.id}"
})
%{
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
deleted file mode 100644
index 158966365..000000000
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ /dev/null
@@ -1,3527 +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.AdminAPI.AdminAPIControllerTest do
- use Pleroma.Web.ConnCase
- use Oban.Testing, repo: Pleroma.Repo
-
- import Pleroma.Factory
- import ExUnit.CaptureLog
-
- alias Pleroma.Activity
- alias Pleroma.Config
- alias Pleroma.ConfigDB
- alias Pleroma.HTML
- alias Pleroma.ModerationLog
- alias Pleroma.Repo
- alias Pleroma.ReportNote
- alias Pleroma.Tests.ObanHelpers
- alias Pleroma.User
- alias Pleroma.UserInviteToken
- alias Pleroma.Web.ActivityPub.Relay
- alias Pleroma.Web.CommonAPI
- alias Pleroma.Web.MediaProxy
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
-
- :ok
- end
-
- setup do
- admin = insert(:user, is_admin: true)
- token = insert(:oauth_admin_token, user: admin)
-
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, token)
-
- {:ok, %{admin: admin, token: token, conn: conn}}
- end
-
- describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
- setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
-
- test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
- %{admin: admin} do
- user = insert(:user)
- url = "/api/pleroma/admin/users/#{user.nickname}"
-
- good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
- good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
- good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
-
- bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
- bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
- bad_token3 = nil
-
- for good_token <- [good_token1, good_token2, good_token3] do
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, good_token)
- |> get(url)
-
- assert json_response(conn, 200)
- end
-
- for good_token <- [good_token1, good_token2, good_token3] do
- conn =
- build_conn()
- |> assign(:user, nil)
- |> assign(:token, good_token)
- |> get(url)
-
- assert json_response(conn, :forbidden)
- end
-
- for bad_token <- [bad_token1, bad_token2, bad_token3] do
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, bad_token)
- |> get(url)
-
- assert json_response(conn, :forbidden)
- end
- end
- end
-
- describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
- setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
-
- test "GET /api/pleroma/admin/users/:nickname requires " <>
- "read:accounts or admin:read:accounts or broader scope",
- %{admin: admin} do
- user = insert(:user)
- url = "/api/pleroma/admin/users/#{user.nickname}"
-
- good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
- good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
- good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
- good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
- good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])
-
- good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]
-
- bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
- bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
- bad_token3 = nil
-
- for good_token <- good_tokens do
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, good_token)
- |> get(url)
-
- assert json_response(conn, 200)
- end
-
- for good_token <- good_tokens do
- conn =
- build_conn()
- |> assign(:user, nil)
- |> assign(:token, good_token)
- |> get(url)
-
- assert json_response(conn, :forbidden)
- end
-
- for bad_token <- [bad_token1, bad_token2, bad_token3] do
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, bad_token)
- |> get(url)
-
- assert json_response(conn, :forbidden)
- end
- end
- end
-
- describe "DELETE /api/pleroma/admin/users" do
- test "single user", %{admin: admin, conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} deleted users: @#{user.nickname}"
-
- assert json_response(conn, 200) == user.nickname
- end
-
- test "multiple users", %{admin: admin, conn: conn} do
- user_one = insert(:user)
- user_two = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> delete("/api/pleroma/admin/users", %{
- nicknames: [user_one.nickname, user_two.nickname]
- })
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
-
- response = json_response(conn, 200)
- assert response -- [user_one.nickname, user_two.nickname] == []
- end
- end
-
- describe "/api/pleroma/admin/users" do
- test "Create", %{conn: conn} do
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> post("/api/pleroma/admin/users", %{
- "users" => [
- %{
- "nickname" => "lain",
- "email" => "lain@example.org",
- "password" => "test"
- },
- %{
- "nickname" => "lain2",
- "email" => "lain2@example.org",
- "password" => "test"
- }
- ]
- })
-
- response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
- assert response == ["success", "success"]
-
- log_entry = Repo.one(ModerationLog)
-
- assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
- end
-
- test "Cannot create user with existing email", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> post("/api/pleroma/admin/users", %{
- "users" => [
- %{
- "nickname" => "lain",
- "email" => user.email,
- "password" => "test"
- }
- ]
- })
-
- assert json_response(conn, 409) == [
- %{
- "code" => 409,
- "data" => %{
- "email" => user.email,
- "nickname" => "lain"
- },
- "error" => "email has already been taken",
- "type" => "error"
- }
- ]
- end
-
- test "Cannot create user with existing nickname", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> post("/api/pleroma/admin/users", %{
- "users" => [
- %{
- "nickname" => user.nickname,
- "email" => "someuser@plerama.social",
- "password" => "test"
- }
- ]
- })
-
- assert json_response(conn, 409) == [
- %{
- "code" => 409,
- "data" => %{
- "email" => "someuser@plerama.social",
- "nickname" => user.nickname
- },
- "error" => "nickname has already been taken",
- "type" => "error"
- }
- ]
- end
-
- test "Multiple user creation works in transaction", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> post("/api/pleroma/admin/users", %{
- "users" => [
- %{
- "nickname" => "newuser",
- "email" => "newuser@pleroma.social",
- "password" => "test"
- },
- %{
- "nickname" => "lain",
- "email" => user.email,
- "password" => "test"
- }
- ]
- })
-
- assert json_response(conn, 409) == [
- %{
- "code" => 409,
- "data" => %{
- "email" => user.email,
- "nickname" => "lain"
- },
- "error" => "email has already been taken",
- "type" => "error"
- },
- %{
- "code" => 409,
- "data" => %{
- "email" => "newuser@pleroma.social",
- "nickname" => "newuser"
- },
- "error" => "",
- "type" => "error"
- }
- ]
-
- assert User.get_by_nickname("newuser") === nil
- end
- end
-
- describe "/api/pleroma/admin/users/:nickname" do
- test "Show", %{conn: conn} do
- user = insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
-
- expected = %{
- "deactivated" => false,
- "id" => to_string(user.id),
- "local" => true,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
-
- assert expected == json_response(conn, 200)
- end
-
- test "when the user doesn't exist", %{conn: conn} do
- user = build(:user)
-
- conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
-
- assert "Not found" == json_response(conn, 404)
- end
- end
-
- describe "/api/pleroma/admin/users/follow" do
- test "allows to force-follow another user", %{admin: admin, conn: conn} do
- user = insert(:user)
- follower = insert(:user)
-
- conn
- |> put_req_header("accept", "application/json")
- |> post("/api/pleroma/admin/users/follow", %{
- "follower" => follower.nickname,
- "followed" => user.nickname
- })
-
- user = User.get_cached_by_id(user.id)
- follower = User.get_cached_by_id(follower.id)
-
- assert User.following?(follower, user)
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
- end
- end
-
- describe "/api/pleroma/admin/users/unfollow" do
- test "allows to force-unfollow another user", %{admin: admin, conn: conn} do
- user = insert(:user)
- follower = insert(:user)
-
- User.follow(follower, user)
-
- conn
- |> put_req_header("accept", "application/json")
- |> post("/api/pleroma/admin/users/unfollow", %{
- "follower" => follower.nickname,
- "followed" => user.nickname
- })
-
- user = User.get_cached_by_id(user.id)
- follower = User.get_cached_by_id(follower.id)
-
- refute User.following?(follower, user)
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
- end
- end
-
- describe "PUT /api/pleroma/admin/users/tag" do
- setup %{conn: conn} do
- user1 = insert(:user, %{tags: ["x"]})
- user2 = insert(:user, %{tags: ["y"]})
- user3 = insert(:user, %{tags: ["unchanged"]})
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> put(
- "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
- "#{user2.nickname}&tags[]=foo&tags[]=bar"
- )
-
- %{conn: conn, user1: user1, user2: user2, user3: user3}
- end
-
- test "it appends specified tags to users with specified nicknames", %{
- conn: conn,
- admin: admin,
- user1: user1,
- user2: user2
- } do
- assert json_response(conn, :no_content)
- assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
- assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
-
- log_entry = Repo.one(ModerationLog)
-
- users =
- [user1.nickname, user2.nickname]
- |> Enum.map(&"@#{&1}")
- |> Enum.join(", ")
-
- tags = ["foo", "bar"] |> Enum.join(", ")
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} added tags: #{tags} to users: #{users}"
- end
-
- test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
- assert json_response(conn, :no_content)
- assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
- end
- end
-
- describe "DELETE /api/pleroma/admin/users/tag" do
- setup %{conn: conn} do
- user1 = insert(:user, %{tags: ["x"]})
- user2 = insert(:user, %{tags: ["y", "z"]})
- user3 = insert(:user, %{tags: ["unchanged"]})
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> delete(
- "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
- "#{user2.nickname}&tags[]=x&tags[]=z"
- )
-
- %{conn: conn, user1: user1, user2: user2, user3: user3}
- end
-
- test "it removes specified tags from users with specified nicknames", %{
- conn: conn,
- admin: admin,
- user1: user1,
- user2: user2
- } do
- assert json_response(conn, :no_content)
- assert User.get_cached_by_id(user1.id).tags == []
- assert User.get_cached_by_id(user2.id).tags == ["y"]
-
- log_entry = Repo.one(ModerationLog)
-
- users =
- [user1.nickname, user2.nickname]
- |> Enum.map(&"@#{&1}")
- |> Enum.join(", ")
-
- tags = ["x", "z"] |> Enum.join(", ")
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
- end
-
- test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
- assert json_response(conn, :no_content)
- assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
- end
- end
-
- describe "/api/pleroma/admin/users/:nickname/permission_group" do
- test "GET is giving user_info", %{admin: admin, conn: conn} do
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
-
- assert json_response(conn, 200) == %{
- "is_admin" => true,
- "is_moderator" => false
- }
- end
-
- test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
-
- assert json_response(conn, 200) == %{
- "is_admin" => true
- }
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} made @#{user.nickname} admin"
- end
-
- test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do
- user_one = insert(:user)
- user_two = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> post("/api/pleroma/admin/users/permission_group/admin", %{
- nicknames: [user_one.nickname, user_two.nickname]
- })
-
- assert json_response(conn, 200) == %{"is_admin" => true}
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
- end
-
- test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do
- user = insert(:user, is_admin: true)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
-
- assert json_response(conn, 200) == %{"is_admin" => false}
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} revoked admin role from @#{user.nickname}"
- end
-
- test "/:right DELETE, can remove from a permission group (multiple)", %{
- admin: admin,
- conn: conn
- } do
- user_one = insert(:user, is_admin: true)
- user_two = insert(:user, is_admin: true)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> delete("/api/pleroma/admin/users/permission_group/admin", %{
- nicknames: [user_one.nickname, user_two.nickname]
- })
-
- assert json_response(conn, 200) == %{"is_admin" => false}
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
- user_two.nickname
- }"
- end
- end
-
- describe "POST /api/pleroma/admin/email_invite, with valid config" do
- setup do: clear_config([:instance, :registrations_open], false)
- setup do: clear_config([:instance, :invites_enabled], true)
-
- test "sends invitation and returns 204", %{admin: admin, conn: conn} do
- recipient_email = "foo@bar.com"
- recipient_name = "J. D."
-
- conn =
- post(
- conn,
- "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
- )
-
- assert json_response(conn, :no_content)
-
- token_record = List.last(Repo.all(Pleroma.UserInviteToken))
- assert token_record
- refute token_record.used
-
- notify_email = Config.get([:instance, :notify_email])
- instance_name = Config.get([:instance, :name])
-
- email =
- Pleroma.Emails.UserEmail.user_invitation_email(
- admin,
- token_record,
- recipient_email,
- recipient_name
- )
-
- Swoosh.TestAssertions.assert_email_sent(
- from: {instance_name, notify_email},
- to: {recipient_name, recipient_email},
- html_body: email.html_body
- )
- end
-
- test "it returns 403 if requested by a non-admin" do
- non_admin_user = insert(:user)
- token = insert(:oauth_token, user: non_admin_user)
-
- conn =
- build_conn()
- |> assign(:user, non_admin_user)
- |> assign(:token, token)
- |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
-
- assert json_response(conn, :forbidden)
- end
-
- test "email with +", %{conn: conn, admin: admin} do
- recipient_email = "foo+bar@baz.com"
-
- conn
- |> put_req_header("content-type", "application/json;charset=utf-8")
- |> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email})
- |> json_response(:no_content)
-
- token_record =
- Pleroma.UserInviteToken
- |> Repo.all()
- |> List.last()
-
- assert token_record
- refute token_record.used
-
- notify_email = Config.get([:instance, :notify_email])
- instance_name = Config.get([:instance, :name])
-
- email =
- Pleroma.Emails.UserEmail.user_invitation_email(
- admin,
- token_record,
- recipient_email
- )
-
- Swoosh.TestAssertions.assert_email_sent(
- from: {instance_name, notify_email},
- to: recipient_email,
- html_body: email.html_body
- )
- end
- end
-
- describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
- setup do: clear_config([:instance, :registrations_open])
- setup do: clear_config([:instance, :invites_enabled])
-
- test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do
- Config.put([:instance, :registrations_open], false)
- Config.put([:instance, :invites_enabled], false)
-
- conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
-
- assert json_response(conn, :bad_request) ==
- "To send invites you need to set the `invites_enabled` option to true."
- end
-
- test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do
- Config.put([:instance, :registrations_open], true)
- Config.put([:instance, :invites_enabled], true)
-
- conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
-
- assert json_response(conn, :bad_request) ==
- "To send invites you need to set the `registrations_open` option to false."
- end
- end
-
- test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
-
- resp = json_response(conn, 200)
-
- assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
- end
-
- describe "GET /api/pleroma/admin/users" do
- test "renders users array for the first page", %{conn: conn, admin: admin} do
- user = insert(:user, local: false, tags: ["foo", "bar"])
- conn = get(conn, "/api/pleroma/admin/users?page=1")
-
- users =
- [
- %{
- "deactivated" => admin.deactivated,
- "id" => admin.id,
- "nickname" => admin.nickname,
- "roles" => %{"admin" => true, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(admin.name || admin.nickname),
- "confirmation_pending" => false
- },
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => false,
- "tags" => ["foo", "bar"],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- |> Enum.sort_by(& &1["nickname"])
-
- assert json_response(conn, 200) == %{
- "count" => 2,
- "page_size" => 50,
- "users" => users
- }
- end
-
- test "renders empty array for the second page", %{conn: conn} do
- insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users?page=2")
-
- assert json_response(conn, 200) == %{
- "count" => 2,
- "page_size" => 50,
- "users" => []
- }
- end
-
- test "regular search", %{conn: conn} do
- user = insert(:user, nickname: "bob")
-
- conn = get(conn, "/api/pleroma/admin/users?query=bo")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "search by domain", %{conn: conn} do
- user = insert(:user, nickname: "nickname@domain.com")
- insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "search by full nickname", %{conn: conn} do
- user = insert(:user, nickname: "nickname@domain.com")
- insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "search by display name", %{conn: conn} do
- user = insert(:user, name: "Display name")
- insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users?name=display")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "search by email", %{conn: conn} do
- user = insert(:user, email: "email@example.com")
- insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "regular search with page size", %{conn: conn} do
- user = insert(:user, nickname: "aalice")
- user2 = insert(:user, nickname: "alice")
-
- conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
-
- assert json_response(conn1, 200) == %{
- "count" => 2,
- "page_size" => 1,
- "users" => [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- }
-
- conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
-
- assert json_response(conn2, 200) == %{
- "count" => 2,
- "page_size" => 1,
- "users" => [
- %{
- "deactivated" => user2.deactivated,
- "id" => user2.id,
- "nickname" => user2.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user2.name || user2.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "only local users" do
- admin = insert(:user, is_admin: true, nickname: "john")
- token = insert(:oauth_admin_token, user: admin)
- user = insert(:user, nickname: "bob")
-
- insert(:user, nickname: "bobb", local: false)
-
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, token)
- |> get("/api/pleroma/admin/users?query=bo&filters=local")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "only local users with no query", %{conn: conn, admin: old_admin} do
- admin = insert(:user, is_admin: true, nickname: "john")
- user = insert(:user, nickname: "bob")
-
- insert(:user, nickname: "bobb", local: false)
-
- conn = get(conn, "/api/pleroma/admin/users?filters=local")
-
- users =
- [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- },
- %{
- "deactivated" => admin.deactivated,
- "id" => admin.id,
- "nickname" => admin.nickname,
- "roles" => %{"admin" => true, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(admin.name || admin.nickname),
- "confirmation_pending" => false
- },
- %{
- "deactivated" => false,
- "id" => old_admin.id,
- "local" => true,
- "nickname" => old_admin.nickname,
- "roles" => %{"admin" => true, "moderator" => false},
- "tags" => [],
- "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
- "confirmation_pending" => false
- }
- ]
- |> Enum.sort_by(& &1["nickname"])
-
- assert json_response(conn, 200) == %{
- "count" => 3,
- "page_size" => 50,
- "users" => users
- }
- end
-
- test "load only admins", %{conn: conn, admin: admin} do
- second_admin = insert(:user, is_admin: true)
- insert(:user)
- insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
-
- users =
- [
- %{
- "deactivated" => false,
- "id" => admin.id,
- "nickname" => admin.nickname,
- "roles" => %{"admin" => true, "moderator" => false},
- "local" => admin.local,
- "tags" => [],
- "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(admin.name || admin.nickname),
- "confirmation_pending" => false
- },
- %{
- "deactivated" => false,
- "id" => second_admin.id,
- "nickname" => second_admin.nickname,
- "roles" => %{"admin" => true, "moderator" => false},
- "local" => second_admin.local,
- "tags" => [],
- "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
- "confirmation_pending" => false
- }
- ]
- |> Enum.sort_by(& &1["nickname"])
-
- assert json_response(conn, 200) == %{
- "count" => 2,
- "page_size" => 50,
- "users" => users
- }
- end
-
- test "load only moderators", %{conn: conn} do
- moderator = insert(:user, is_moderator: true)
- insert(:user)
- insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => false,
- "id" => moderator.id,
- "nickname" => moderator.nickname,
- "roles" => %{"admin" => false, "moderator" => true},
- "local" => moderator.local,
- "tags" => [],
- "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "load users with tags list", %{conn: conn} do
- user1 = insert(:user, tags: ["first"])
- user2 = insert(:user, tags: ["second"])
- insert(:user)
- insert(:user)
-
- conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
-
- users =
- [
- %{
- "deactivated" => false,
- "id" => user1.id,
- "nickname" => user1.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => user1.local,
- "tags" => ["first"],
- "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user1.name || user1.nickname),
- "confirmation_pending" => false
- },
- %{
- "deactivated" => false,
- "id" => user2.id,
- "nickname" => user2.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => user2.local,
- "tags" => ["second"],
- "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user2.name || user2.nickname),
- "confirmation_pending" => false
- }
- ]
- |> Enum.sort_by(& &1["nickname"])
-
- assert json_response(conn, 200) == %{
- "count" => 2,
- "page_size" => 50,
- "users" => users
- }
- end
-
- test "it works with multiple filters" do
- admin = insert(:user, nickname: "john", is_admin: true)
- token = insert(:oauth_admin_token, user: admin)
- user = insert(:user, nickname: "bob", local: false, deactivated: true)
-
- insert(:user, nickname: "ken", local: true, deactivated: true)
- insert(:user, nickname: "bobb", local: false, deactivated: false)
-
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, token)
- |> get("/api/pleroma/admin/users?filters=deactivated,external")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => user.local,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
-
- test "it omits relay user", %{admin: admin, conn: conn} do
- assert %User{} = Relay.get_actor()
-
- conn = get(conn, "/api/pleroma/admin/users")
-
- assert json_response(conn, 200) == %{
- "count" => 1,
- "page_size" => 50,
- "users" => [
- %{
- "deactivated" => admin.deactivated,
- "id" => admin.id,
- "nickname" => admin.nickname,
- "roles" => %{"admin" => true, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(admin.name || admin.nickname),
- "confirmation_pending" => false
- }
- ]
- }
- end
- end
-
- test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
- user_one = insert(:user, deactivated: true)
- user_two = insert(:user, deactivated: true)
-
- conn =
- patch(
- conn,
- "/api/pleroma/admin/users/activate",
- %{nicknames: [user_one.nickname, user_two.nickname]}
- )
-
- response = json_response(conn, 200)
- assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
- end
-
- test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
- user_one = insert(:user, deactivated: false)
- user_two = insert(:user, deactivated: false)
-
- conn =
- patch(
- conn,
- "/api/pleroma/admin/users/deactivate",
- %{nicknames: [user_one.nickname, user_two.nickname]}
- )
-
- response = json_response(conn, 200)
- assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
- end
-
- test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
- user = insert(:user)
-
- conn = patch(conn, "/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
-
- assert json_response(conn, 200) ==
- %{
- "deactivated" => !user.deactivated,
- "id" => user.id,
- "nickname" => user.nickname,
- "roles" => %{"admin" => false, "moderator" => false},
- "local" => true,
- "tags" => [],
- "avatar" => User.avatar_url(user) |> MediaProxy.url(),
- "display_name" => HTML.strip_tags(user.name || user.nickname),
- "confirmation_pending" => false
- }
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} deactivated users: @#{user.nickname}"
- end
-
- describe "POST /api/pleroma/admin/users/invite_token" do
- test "without options", %{conn: conn} do
- conn = post(conn, "/api/pleroma/admin/users/invite_token")
-
- invite_json = json_response(conn, 200)
- invite = UserInviteToken.find_by_token!(invite_json["token"])
- refute invite.used
- refute invite.expires_at
- refute invite.max_use
- assert invite.invite_type == "one_time"
- end
-
- test "with expires_at", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/users/invite_token", %{
- "expires_at" => Date.to_string(Date.utc_today())
- })
-
- invite_json = json_response(conn, 200)
- invite = UserInviteToken.find_by_token!(invite_json["token"])
-
- refute invite.used
- assert invite.expires_at == Date.utc_today()
- refute invite.max_use
- assert invite.invite_type == "date_limited"
- end
-
- test "with max_use", %{conn: conn} do
- conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
-
- invite_json = json_response(conn, 200)
- invite = UserInviteToken.find_by_token!(invite_json["token"])
- refute invite.used
- refute invite.expires_at
- assert invite.max_use == 150
- assert invite.invite_type == "reusable"
- end
-
- test "with max use and expires_at", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/users/invite_token", %{
- "max_use" => 150,
- "expires_at" => Date.to_string(Date.utc_today())
- })
-
- invite_json = json_response(conn, 200)
- invite = UserInviteToken.find_by_token!(invite_json["token"])
- refute invite.used
- assert invite.expires_at == Date.utc_today()
- assert invite.max_use == 150
- assert invite.invite_type == "reusable_date_limited"
- end
- end
-
- describe "GET /api/pleroma/admin/users/invites" do
- test "no invites", %{conn: conn} do
- conn = get(conn, "/api/pleroma/admin/users/invites")
-
- assert json_response(conn, 200) == %{"invites" => []}
- end
-
- test "with invite", %{conn: conn} do
- {:ok, invite} = UserInviteToken.create_invite()
-
- conn = get(conn, "/api/pleroma/admin/users/invites")
-
- assert json_response(conn, 200) == %{
- "invites" => [
- %{
- "expires_at" => nil,
- "id" => invite.id,
- "invite_type" => "one_time",
- "max_use" => nil,
- "token" => invite.token,
- "used" => false,
- "uses" => 0
- }
- ]
- }
- end
- end
-
- describe "POST /api/pleroma/admin/users/revoke_invite" do
- test "with token", %{conn: conn} do
- {:ok, invite} = UserInviteToken.create_invite()
-
- conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
-
- assert json_response(conn, 200) == %{
- "expires_at" => nil,
- "id" => invite.id,
- "invite_type" => "one_time",
- "max_use" => nil,
- "token" => invite.token,
- "used" => true,
- "uses" => 0
- }
- end
-
- test "with invalid token", %{conn: conn} do
- conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
-
- assert json_response(conn, :not_found) == "Not found"
- end
- end
-
- describe "GET /api/pleroma/admin/reports/:id" do
- test "returns report by its id", %{conn: conn} do
- [reporter, target_user] = insert_pair(:user)
- activity = insert(:note_activity, user: target_user)
-
- {:ok, %{id: report_id}} =
- CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel offended",
- "status_ids" => [activity.id]
- })
-
- response =
- conn
- |> get("/api/pleroma/admin/reports/#{report_id}")
- |> json_response(:ok)
-
- assert response["id"] == report_id
- end
-
- test "returns 404 when report id is invalid", %{conn: conn} do
- conn = get(conn, "/api/pleroma/admin/reports/test")
-
- assert json_response(conn, :not_found) == "Not found"
- end
- end
-
- describe "PATCH /api/pleroma/admin/reports" do
- setup do
- [reporter, target_user] = insert_pair(:user)
- activity = insert(:note_activity, user: target_user)
-
- {:ok, %{id: report_id}} =
- CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel offended",
- "status_ids" => [activity.id]
- })
-
- {:ok, %{id: second_report_id}} =
- CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel very offended",
- "status_ids" => [activity.id]
- })
-
- %{
- id: report_id,
- second_report_id: second_report_id
- }
- end
-
- test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} do
- read_token = insert(:oauth_token, user: admin, scopes: ["admin:read"])
- write_token = insert(:oauth_token, user: admin, scopes: ["admin:write:reports"])
-
- response =
- conn
- |> assign(:token, read_token)
- |> patch("/api/pleroma/admin/reports", %{
- "reports" => [%{"state" => "resolved", "id" => id}]
- })
- |> json_response(403)
-
- assert response == %{
- "error" => "Insufficient permissions: admin:write:reports."
- }
-
- conn
- |> assign(:token, write_token)
- |> patch("/api/pleroma/admin/reports", %{
- "reports" => [%{"state" => "resolved", "id" => id}]
- })
- |> json_response(:no_content)
- end
-
- test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
- conn
- |> patch("/api/pleroma/admin/reports", %{
- "reports" => [
- %{"state" => "resolved", "id" => id}
- ]
- })
- |> json_response(:no_content)
-
- activity = Activity.get_by_id(id)
- assert activity.data["state"] == "resolved"
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} updated report ##{id} with 'resolved' state"
- end
-
- test "closes report", %{conn: conn, id: id, admin: admin} do
- conn
- |> patch("/api/pleroma/admin/reports", %{
- "reports" => [
- %{"state" => "closed", "id" => id}
- ]
- })
- |> json_response(:no_content)
-
- activity = Activity.get_by_id(id)
- assert activity.data["state"] == "closed"
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} updated report ##{id} with 'closed' state"
- end
-
- test "returns 400 when state is unknown", %{conn: conn, id: id} do
- conn =
- conn
- |> patch("/api/pleroma/admin/reports", %{
- "reports" => [
- %{"state" => "test", "id" => id}
- ]
- })
-
- assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
- end
-
- test "returns 404 when report is not exist", %{conn: conn} do
- conn =
- conn
- |> patch("/api/pleroma/admin/reports", %{
- "reports" => [
- %{"state" => "closed", "id" => "test"}
- ]
- })
-
- assert hd(json_response(conn, :bad_request))["error"] == "not_found"
- end
-
- test "updates state of multiple reports", %{
- conn: conn,
- id: id,
- admin: admin,
- second_report_id: second_report_id
- } do
- conn
- |> patch("/api/pleroma/admin/reports", %{
- "reports" => [
- %{"state" => "resolved", "id" => id},
- %{"state" => "closed", "id" => second_report_id}
- ]
- })
- |> json_response(:no_content)
-
- activity = Activity.get_by_id(id)
- second_activity = Activity.get_by_id(second_report_id)
- assert activity.data["state"] == "resolved"
- assert second_activity.data["state"] == "closed"
-
- [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(first_log_entry) ==
- "@#{admin.nickname} updated report ##{id} with 'resolved' state"
-
- assert ModerationLog.get_log_entry_message(second_log_entry) ==
- "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
- end
- end
-
- describe "GET /api/pleroma/admin/reports" do
- test "returns empty response when no reports created", %{conn: conn} do
- response =
- conn
- |> get("/api/pleroma/admin/reports")
- |> json_response(:ok)
-
- assert Enum.empty?(response["reports"])
- assert response["total"] == 0
- end
-
- test "returns reports", %{conn: conn} do
- [reporter, target_user] = insert_pair(:user)
- activity = insert(:note_activity, user: target_user)
-
- {:ok, %{id: report_id}} =
- CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel offended",
- "status_ids" => [activity.id]
- })
-
- response =
- conn
- |> get("/api/pleroma/admin/reports")
- |> json_response(:ok)
-
- [report] = response["reports"]
-
- assert length(response["reports"]) == 1
- assert report["id"] == report_id
-
- assert response["total"] == 1
- end
-
- test "returns reports with specified state", %{conn: conn} do
- [reporter, target_user] = insert_pair(:user)
- activity = insert(:note_activity, user: target_user)
-
- {:ok, %{id: first_report_id}} =
- CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel offended",
- "status_ids" => [activity.id]
- })
-
- {:ok, %{id: second_report_id}} =
- CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I don't like this user"
- })
-
- CommonAPI.update_report_state(second_report_id, "closed")
-
- response =
- conn
- |> get("/api/pleroma/admin/reports", %{
- "state" => "open"
- })
- |> json_response(:ok)
-
- [open_report] = response["reports"]
-
- assert length(response["reports"]) == 1
- assert open_report["id"] == first_report_id
-
- assert response["total"] == 1
-
- response =
- conn
- |> get("/api/pleroma/admin/reports", %{
- "state" => "closed"
- })
- |> json_response(:ok)
-
- [closed_report] = response["reports"]
-
- assert length(response["reports"]) == 1
- assert closed_report["id"] == second_report_id
-
- assert response["total"] == 1
-
- response =
- conn
- |> get("/api/pleroma/admin/reports", %{
- "state" => "resolved"
- })
- |> json_response(:ok)
-
- assert Enum.empty?(response["reports"])
- assert response["total"] == 0
- end
-
- test "returns 403 when requested by a non-admin" do
- user = insert(:user)
- token = insert(:oauth_token, user: user)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> assign(:token, token)
- |> get("/api/pleroma/admin/reports")
-
- assert json_response(conn, :forbidden) ==
- %{"error" => "User is not an admin or OAuth admin scope is not granted."}
- end
-
- test "returns 403 when requested by anonymous" do
- conn = get(build_conn(), "/api/pleroma/admin/reports")
-
- assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
- end
- end
-
- describe "PUT /api/pleroma/admin/statuses/:id" do
- setup do
- activity = insert(:note_activity)
-
- %{id: activity.id}
- end
-
- test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
- response =
- conn
- |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
- |> json_response(:ok)
-
- assert response["sensitive"]
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
-
- response =
- conn
- |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
- |> json_response(:ok)
-
- refute response["sensitive"]
- end
-
- test "change visibility flag", %{conn: conn, id: id, admin: admin} do
- response =
- conn
- |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
- |> json_response(:ok)
-
- assert response["visibility"] == "public"
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
-
- response =
- conn
- |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
- |> json_response(:ok)
-
- assert response["visibility"] == "private"
-
- response =
- conn
- |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
- |> json_response(:ok)
-
- assert response["visibility"] == "unlisted"
- end
-
- test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
- conn = put(conn, "/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
-
- assert json_response(conn, :bad_request) == "Unsupported visibility"
- end
- end
-
- describe "DELETE /api/pleroma/admin/statuses/:id" do
- setup do
- activity = insert(:note_activity)
-
- %{id: activity.id}
- end
-
- test "deletes status", %{conn: conn, id: id, admin: admin} do
- conn
- |> delete("/api/pleroma/admin/statuses/#{id}")
- |> json_response(:ok)
-
- refute Activity.get_by_id(id)
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} deleted status ##{id}"
- end
-
- test "returns 404 when the status does not exist", %{conn: conn} do
- conn = delete(conn, "/api/pleroma/admin/statuses/test")
-
- assert json_response(conn, :not_found) == "Not found"
- end
- end
-
- describe "GET /api/pleroma/admin/config" do
- setup do: clear_config(:configurable_from_database, true)
-
- test "when configuration from database is off", %{conn: conn} do
- Config.put(:configurable_from_database, false)
- conn = get(conn, "/api/pleroma/admin/config")
-
- assert json_response(conn, 400) ==
- "To use this endpoint you need to enable configuration from database."
- end
-
- test "with settings only in db", %{conn: conn} do
- config1 = insert(:config)
- config2 = insert(:config)
-
- conn = get(conn, "/api/pleroma/admin/config", %{"only_db" => true})
-
- %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => key1,
- "value" => _
- },
- %{
- "group" => ":pleroma",
- "key" => key2,
- "value" => _
- }
- ]
- } = json_response(conn, 200)
-
- assert key1 == config1.key
- assert key2 == config2.key
- end
-
- test "db is added to settings that are in db", %{conn: conn} do
- _config = insert(:config, key: ":instance", value: ConfigDB.to_binary(name: "Some name"))
-
- %{"configs" => configs} =
- conn
- |> get("/api/pleroma/admin/config")
- |> json_response(200)
-
- [instance_config] =
- Enum.filter(configs, fn %{"group" => group, "key" => key} ->
- group == ":pleroma" and key == ":instance"
- end)
-
- assert instance_config["db"] == [":name"]
- end
-
- test "merged default setting with db settings", %{conn: conn} do
- config1 = insert(:config)
- config2 = insert(:config)
-
- config3 =
- insert(:config,
- value: ConfigDB.to_binary(k1: :v1, k2: :v2)
- )
-
- %{"configs" => configs} =
- conn
- |> get("/api/pleroma/admin/config")
- |> json_response(200)
-
- assert length(configs) > 3
-
- received_configs =
- Enum.filter(configs, fn %{"group" => group, "key" => key} ->
- group == ":pleroma" and key in [config1.key, config2.key, config3.key]
- end)
-
- assert length(received_configs) == 3
-
- db_keys =
- config3.value
- |> ConfigDB.from_binary()
- |> Keyword.keys()
- |> ConfigDB.convert()
-
- Enum.each(received_configs, fn %{"value" => value, "db" => db} ->
- assert db in [[config1.key], [config2.key], db_keys]
-
- assert value in [
- ConfigDB.from_binary_with_convert(config1.value),
- ConfigDB.from_binary_with_convert(config2.value),
- ConfigDB.from_binary_with_convert(config3.value)
- ]
- end)
- end
-
- test "subkeys with full update right merge", %{conn: conn} do
- config1 =
- insert(:config,
- key: ":emoji",
- value: ConfigDB.to_binary(groups: [a: 1, b: 2], key: [a: 1])
- )
-
- config2 =
- insert(:config,
- key: ":assets",
- value: ConfigDB.to_binary(mascots: [a: 1, b: 2], key: [a: 1])
- )
-
- %{"configs" => configs} =
- conn
- |> get("/api/pleroma/admin/config")
- |> json_response(200)
-
- vals =
- Enum.filter(configs, fn %{"group" => group, "key" => key} ->
- group == ":pleroma" and key in [config1.key, config2.key]
- end)
-
- emoji = Enum.find(vals, fn %{"key" => key} -> key == ":emoji" end)
- assets = Enum.find(vals, fn %{"key" => key} -> key == ":assets" end)
-
- emoji_val = ConfigDB.transform_with_out_binary(emoji["value"])
- assets_val = ConfigDB.transform_with_out_binary(assets["value"])
-
- assert emoji_val[:groups] == [a: 1, b: 2]
- assert assets_val[:mascots] == [a: 1, b: 2]
- end
- end
-
- test "POST /api/pleroma/admin/config error", %{conn: conn} do
- conn = post(conn, "/api/pleroma/admin/config", %{"configs" => []})
-
- assert json_response(conn, 400) ==
- "To use this endpoint you need to enable configuration from database."
- end
-
- describe "POST /api/pleroma/admin/config" do
- setup do
- http = Application.get_env(:pleroma, :http)
-
- on_exit(fn ->
- Application.delete_env(:pleroma, :key1)
- Application.delete_env(:pleroma, :key2)
- Application.delete_env(:pleroma, :key3)
- Application.delete_env(:pleroma, :key4)
- Application.delete_env(:pleroma, :keyaa1)
- Application.delete_env(:pleroma, :keyaa2)
- Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
- Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
- Application.put_env(:pleroma, :http, http)
- Application.put_env(:tesla, :adapter, Tesla.Mock)
- Restarter.Pleroma.refresh()
- end)
- end
-
- setup do: clear_config(:configurable_from_database, true)
-
- @tag capture_log: true
- test "create new config setting in db", %{conn: conn} do
- ueberauth = Application.get_env(:ueberauth, Ueberauth)
- on_exit(fn -> Application.put_env(:ueberauth, Ueberauth, ueberauth) end)
-
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{group: ":pleroma", key: ":key1", value: "value1"},
- %{
- group: ":ueberauth",
- key: "Ueberauth",
- value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
- },
- %{
- group: ":pleroma",
- key: ":key2",
- value: %{
- ":nested_1" => "nested_value1",
- ":nested_2" => [
- %{":nested_22" => "nested_value222"},
- %{":nested_33" => %{":nested_44" => "nested_444"}}
- ]
- }
- },
- %{
- group: ":pleroma",
- key: ":key3",
- value: [
- %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
- %{"nested_4" => true}
- ]
- },
- %{
- group: ":pleroma",
- key: ":key4",
- value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
- },
- %{
- group: ":idna",
- key: ":key5",
- value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => "value1",
- "db" => [":key1"]
- },
- %{
- "group" => ":ueberauth",
- "key" => "Ueberauth",
- "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}],
- "db" => [":consumer_secret"]
- },
- %{
- "group" => ":pleroma",
- "key" => ":key2",
- "value" => %{
- ":nested_1" => "nested_value1",
- ":nested_2" => [
- %{":nested_22" => "nested_value222"},
- %{":nested_33" => %{":nested_44" => "nested_444"}}
- ]
- },
- "db" => [":key2"]
- },
- %{
- "group" => ":pleroma",
- "key" => ":key3",
- "value" => [
- %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
- %{"nested_4" => true}
- ],
- "db" => [":key3"]
- },
- %{
- "group" => ":pleroma",
- "key" => ":key4",
- "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"},
- "db" => [":key4"]
- },
- %{
- "group" => ":idna",
- "key" => ":key5",
- "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]},
- "db" => [":key5"]
- }
- ]
- }
-
- assert Application.get_env(:pleroma, :key1) == "value1"
-
- assert Application.get_env(:pleroma, :key2) == %{
- nested_1: "nested_value1",
- nested_2: [
- %{nested_22: "nested_value222"},
- %{nested_33: %{nested_44: "nested_444"}}
- ]
- }
-
- assert Application.get_env(:pleroma, :key3) == [
- %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
- %{"nested_4" => true}
- ]
-
- assert Application.get_env(:pleroma, :key4) == %{
- "endpoint" => "https://example.com",
- nested_5: :upload
- }
-
- assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
- end
-
- test "save configs setting without explicit key", %{conn: conn} do
- level = Application.get_env(:quack, :level)
- meta = Application.get_env(:quack, :meta)
- webhook_url = Application.get_env(:quack, :webhook_url)
-
- on_exit(fn ->
- Application.put_env(:quack, :level, level)
- Application.put_env(:quack, :meta, meta)
- Application.put_env(:quack, :webhook_url, webhook_url)
- end)
-
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- group: ":quack",
- key: ":level",
- value: ":info"
- },
- %{
- group: ":quack",
- key: ":meta",
- value: [":none"]
- },
- %{
- group: ":quack",
- key: ":webhook_url",
- value: "https://hooks.slack.com/services/KEY"
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":quack",
- "key" => ":level",
- "value" => ":info",
- "db" => [":level"]
- },
- %{
- "group" => ":quack",
- "key" => ":meta",
- "value" => [":none"],
- "db" => [":meta"]
- },
- %{
- "group" => ":quack",
- "key" => ":webhook_url",
- "value" => "https://hooks.slack.com/services/KEY",
- "db" => [":webhook_url"]
- }
- ]
- }
-
- assert Application.get_env(:quack, :level) == :info
- assert Application.get_env(:quack, :meta) == [:none]
- assert Application.get_env(:quack, :webhook_url) == "https://hooks.slack.com/services/KEY"
- end
-
- test "saving config with partial update", %{conn: conn} do
- config = insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2))
-
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{group: config.group, key: config.key, value: [%{"tuple" => [":key3", 3]}]}
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => [
- %{"tuple" => [":key1", 1]},
- %{"tuple" => [":key2", 2]},
- %{"tuple" => [":key3", 3]}
- ],
- "db" => [":key1", ":key2", ":key3"]
- }
- ]
- }
- end
-
- test "saving config which need pleroma reboot", %{conn: conn} do
- chat = Config.get(:chat)
- on_exit(fn -> Config.put(:chat, chat) end)
-
- assert post(
- conn,
- "/api/pleroma/admin/config",
- %{
- configs: [
- %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]}
- ]
- }
- )
- |> json_response(200) == %{
- "configs" => [
- %{
- "db" => [":enabled"],
- "group" => ":pleroma",
- "key" => ":chat",
- "value" => [%{"tuple" => [":enabled", true]}]
- }
- ],
- "need_reboot" => true
- }
-
- configs =
- conn
- |> get("/api/pleroma/admin/config")
- |> json_response(200)
-
- assert configs["need_reboot"]
-
- capture_log(fn ->
- assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
- end) =~ "pleroma restarted"
-
- configs =
- conn
- |> get("/api/pleroma/admin/config")
- |> json_response(200)
-
- assert configs["need_reboot"] == false
- end
-
- test "update setting which need reboot, don't change reboot flag until reboot", %{conn: conn} do
- chat = Config.get(:chat)
- on_exit(fn -> Config.put(:chat, chat) end)
-
- assert post(
- conn,
- "/api/pleroma/admin/config",
- %{
- configs: [
- %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]}
- ]
- }
- )
- |> json_response(200) == %{
- "configs" => [
- %{
- "db" => [":enabled"],
- "group" => ":pleroma",
- "key" => ":chat",
- "value" => [%{"tuple" => [":enabled", true]}]
- }
- ],
- "need_reboot" => true
- }
-
- assert post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
- ]
- })
- |> json_response(200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => [
- %{"tuple" => [":key3", 3]}
- ],
- "db" => [":key3"]
- }
- ],
- "need_reboot" => true
- }
-
- capture_log(fn ->
- assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
- end) =~ "pleroma restarted"
-
- configs =
- conn
- |> get("/api/pleroma/admin/config")
- |> json_response(200)
-
- assert configs["need_reboot"] == false
- end
-
- test "saving config with nested merge", %{conn: conn} do
- config =
- insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: [k1: 1, k2: 2]))
-
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- group: config.group,
- key: config.key,
- value: [
- %{"tuple" => [":key3", 3]},
- %{
- "tuple" => [
- ":key2",
- [
- %{"tuple" => [":k2", 1]},
- %{"tuple" => [":k3", 3]}
- ]
- ]
- }
- ]
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => [
- %{"tuple" => [":key1", 1]},
- %{"tuple" => [":key3", 3]},
- %{
- "tuple" => [
- ":key2",
- [
- %{"tuple" => [":k1", 1]},
- %{"tuple" => [":k2", 1]},
- %{"tuple" => [":k3", 3]}
- ]
- ]
- }
- ],
- "db" => [":key1", ":key3", ":key2"]
- }
- ]
- }
- end
-
- test "saving special atoms", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => [
- %{
- "tuple" => [
- ":ssl_options",
- [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
- ]
- }
- ]
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => [
- %{
- "tuple" => [
- ":ssl_options",
- [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
- ]
- }
- ],
- "db" => [":ssl_options"]
- }
- ]
- }
-
- assert Application.get_env(:pleroma, :key1) == [
- ssl_options: [versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]]
- ]
- end
-
- test "saving full setting if value is in full_key_update list", %{conn: conn} do
- backends = Application.get_env(:logger, :backends)
- on_exit(fn -> Application.put_env(:logger, :backends, backends) end)
-
- config =
- insert(:config,
- group: ":logger",
- key: ":backends",
- value: :erlang.term_to_binary([])
- )
-
- Pleroma.Config.TransferTask.load_and_update_env([], false)
-
- assert Application.get_env(:logger, :backends) == []
-
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- group: config.group,
- key: config.key,
- value: [":console"]
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":logger",
- "key" => ":backends",
- "value" => [
- ":console"
- ],
- "db" => [":backends"]
- }
- ]
- }
-
- assert Application.get_env(:logger, :backends) == [
- :console
- ]
- end
-
- test "saving full setting if value is not keyword", %{conn: conn} do
- config =
- insert(:config,
- group: ":tesla",
- key: ":adapter",
- value: :erlang.term_to_binary(Tesla.Adapter.Hackey)
- )
-
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{group: config.group, key: config.key, value: "Tesla.Adapter.Httpc"}
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":tesla",
- "key" => ":adapter",
- "value" => "Tesla.Adapter.Httpc",
- "db" => [":adapter"]
- }
- ]
- }
- end
-
- test "update config setting & delete with fallback to default value", %{
- conn: conn,
- admin: admin,
- token: token
- } do
- ueberauth = Application.get_env(:ueberauth, Ueberauth)
- config1 = insert(:config, key: ":keyaa1")
- config2 = insert(:config, key: ":keyaa2")
-
- config3 =
- insert(:config,
- group: ":ueberauth",
- key: "Ueberauth"
- )
-
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{group: config1.group, key: config1.key, value: "another_value"},
- %{group: config2.group, key: config2.key, value: "another_value"}
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => config1.key,
- "value" => "another_value",
- "db" => [":keyaa1"]
- },
- %{
- "group" => ":pleroma",
- "key" => config2.key,
- "value" => "another_value",
- "db" => [":keyaa2"]
- }
- ]
- }
-
- assert Application.get_env(:pleroma, :keyaa1) == "another_value"
- assert Application.get_env(:pleroma, :keyaa2) == "another_value"
- assert Application.get_env(:ueberauth, Ueberauth) == ConfigDB.from_binary(config3.value)
-
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, token)
- |> post("/api/pleroma/admin/config", %{
- configs: [
- %{group: config2.group, key: config2.key, delete: true},
- %{
- group: ":ueberauth",
- key: "Ueberauth",
- delete: true
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => []
- }
-
- assert Application.get_env(:ueberauth, Ueberauth) == ueberauth
- refute Keyword.has_key?(Application.get_all_env(:pleroma), :keyaa2)
- end
-
- test "common config example", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- "group" => ":pleroma",
- "key" => "Pleroma.Captcha.NotReal",
- "value" => [
- %{"tuple" => [":enabled", false]},
- %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
- %{"tuple" => [":seconds_valid", 60]},
- %{"tuple" => [":path", ""]},
- %{"tuple" => [":key1", nil]},
- %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
- %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
- %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
- %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},
- %{"tuple" => [":name", "Pleroma"]}
- ]
- }
- ]
- })
-
- assert Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => "Pleroma.Captcha.NotReal",
- "value" => [
- %{"tuple" => [":enabled", false]},
- %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
- %{"tuple" => [":seconds_valid", 60]},
- %{"tuple" => [":path", ""]},
- %{"tuple" => [":key1", nil]},
- %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
- %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
- %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
- %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]},
- %{"tuple" => [":name", "Pleroma"]}
- ],
- "db" => [
- ":enabled",
- ":method",
- ":seconds_valid",
- ":path",
- ":key1",
- ":regex1",
- ":regex2",
- ":regex3",
- ":regex4",
- ":name"
- ]
- }
- ]
- }
- end
-
- test "tuples with more than two values", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- "group" => ":pleroma",
- "key" => "Pleroma.Web.Endpoint.NotReal",
- "value" => [
- %{
- "tuple" => [
- ":http",
- [
- %{
- "tuple" => [
- ":key2",
- [
- %{
- "tuple" => [
- ":_",
- [
- %{
- "tuple" => [
- "/api/v1/streaming",
- "Pleroma.Web.MastodonAPI.WebsocketHandler",
- []
- ]
- },
- %{
- "tuple" => [
- "/websocket",
- "Phoenix.Endpoint.CowboyWebSocket",
- %{
- "tuple" => [
- "Phoenix.Transports.WebSocket",
- %{
- "tuple" => [
- "Pleroma.Web.Endpoint",
- "Pleroma.Web.UserSocket",
- []
- ]
- }
- ]
- }
- ]
- },
- %{
- "tuple" => [
- ":_",
- "Phoenix.Endpoint.Cowboy2Handler",
- %{"tuple" => ["Pleroma.Web.Endpoint", []]}
- ]
- }
- ]
- ]
- }
- ]
- ]
- }
- ]
- ]
- }
- ]
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => "Pleroma.Web.Endpoint.NotReal",
- "value" => [
- %{
- "tuple" => [
- ":http",
- [
- %{
- "tuple" => [
- ":key2",
- [
- %{
- "tuple" => [
- ":_",
- [
- %{
- "tuple" => [
- "/api/v1/streaming",
- "Pleroma.Web.MastodonAPI.WebsocketHandler",
- []
- ]
- },
- %{
- "tuple" => [
- "/websocket",
- "Phoenix.Endpoint.CowboyWebSocket",
- %{
- "tuple" => [
- "Phoenix.Transports.WebSocket",
- %{
- "tuple" => [
- "Pleroma.Web.Endpoint",
- "Pleroma.Web.UserSocket",
- []
- ]
- }
- ]
- }
- ]
- },
- %{
- "tuple" => [
- ":_",
- "Phoenix.Endpoint.Cowboy2Handler",
- %{"tuple" => ["Pleroma.Web.Endpoint", []]}
- ]
- }
- ]
- ]
- }
- ]
- ]
- }
- ]
- ]
- }
- ],
- "db" => [":http"]
- }
- ]
- }
- end
-
- test "settings with nesting map", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => [
- %{"tuple" => [":key2", "some_val"]},
- %{
- "tuple" => [
- ":key3",
- %{
- ":max_options" => 20,
- ":max_option_chars" => 200,
- ":min_expiration" => 0,
- ":max_expiration" => 31_536_000,
- "nested" => %{
- ":max_options" => 20,
- ":max_option_chars" => 200,
- ":min_expiration" => 0,
- ":max_expiration" => 31_536_000
- }
- }
- ]
- }
- ]
- }
- ]
- })
-
- assert json_response(conn, 200) ==
- %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => [
- %{"tuple" => [":key2", "some_val"]},
- %{
- "tuple" => [
- ":key3",
- %{
- ":max_expiration" => 31_536_000,
- ":max_option_chars" => 200,
- ":max_options" => 20,
- ":min_expiration" => 0,
- "nested" => %{
- ":max_expiration" => 31_536_000,
- ":max_option_chars" => 200,
- ":max_options" => 20,
- ":min_expiration" => 0
- }
- }
- ]
- }
- ],
- "db" => [":key2", ":key3"]
- }
- ]
- }
- end
-
- test "value as map", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => %{"key" => "some_val"}
- }
- ]
- })
-
- assert json_response(conn, 200) ==
- %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":key1",
- "value" => %{"key" => "some_val"},
- "db" => [":key1"]
- }
- ]
- }
- end
-
- test "queues key as atom", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- "group" => ":oban",
- "key" => ":queues",
- "value" => [
- %{"tuple" => [":federator_incoming", 50]},
- %{"tuple" => [":federator_outgoing", 50]},
- %{"tuple" => [":web_push", 50]},
- %{"tuple" => [":mailer", 10]},
- %{"tuple" => [":transmogrifier", 20]},
- %{"tuple" => [":scheduled_activities", 10]},
- %{"tuple" => [":background", 5]}
- ]
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":oban",
- "key" => ":queues",
- "value" => [
- %{"tuple" => [":federator_incoming", 50]},
- %{"tuple" => [":federator_outgoing", 50]},
- %{"tuple" => [":web_push", 50]},
- %{"tuple" => [":mailer", 10]},
- %{"tuple" => [":transmogrifier", 20]},
- %{"tuple" => [":scheduled_activities", 10]},
- %{"tuple" => [":background", 5]}
- ],
- "db" => [
- ":federator_incoming",
- ":federator_outgoing",
- ":web_push",
- ":mailer",
- ":transmogrifier",
- ":scheduled_activities",
- ":background"
- ]
- }
- ]
- }
- end
-
- test "delete part of settings by atom subkeys", %{conn: conn} do
- config =
- insert(:config,
- key: ":keyaa1",
- value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
- )
-
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- group: config.group,
- key: config.key,
- subkeys: [":subkey1", ":subkey3"],
- delete: true
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":keyaa1",
- "value" => [%{"tuple" => [":subkey2", "val2"]}],
- "db" => [":subkey2"]
- }
- ]
- }
- end
-
- test "proxy tuple localhost", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- group: ":pleroma",
- key: ":http",
- value: [
- %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]},
- %{"tuple" => [":send_user_agent", false]}
- ]
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":http",
- "value" => [
- %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]},
- %{"tuple" => [":send_user_agent", false]}
- ],
- "db" => [":proxy_url", ":send_user_agent"]
- }
- ]
- }
- end
-
- test "proxy tuple domain", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- group: ":pleroma",
- key: ":http",
- value: [
- %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]},
- %{"tuple" => [":send_user_agent", false]}
- ]
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":http",
- "value" => [
- %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]},
- %{"tuple" => [":send_user_agent", false]}
- ],
- "db" => [":proxy_url", ":send_user_agent"]
- }
- ]
- }
- end
-
- test "proxy tuple ip", %{conn: conn} do
- conn =
- post(conn, "/api/pleroma/admin/config", %{
- configs: [
- %{
- group: ":pleroma",
- key: ":http",
- value: [
- %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]},
- %{"tuple" => [":send_user_agent", false]}
- ]
- }
- ]
- })
-
- assert json_response(conn, 200) == %{
- "configs" => [
- %{
- "group" => ":pleroma",
- "key" => ":http",
- "value" => [
- %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]},
- %{"tuple" => [":send_user_agent", false]}
- ],
- "db" => [":proxy_url", ":send_user_agent"]
- }
- ]
- }
- end
- end
-
- describe "GET /api/pleroma/admin/restart" do
- setup do: clear_config(:configurable_from_database, true)
-
- test "pleroma restarts", %{conn: conn} do
- capture_log(fn ->
- assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
- end) =~ "pleroma restarted"
-
- refute Restarter.Pleroma.need_reboot?()
- end
- end
-
- test "need_reboot flag", %{conn: conn} do
- assert conn
- |> get("/api/pleroma/admin/need_reboot")
- |> json_response(200) == %{"need_reboot" => false}
-
- Restarter.Pleroma.need_reboot()
-
- assert conn
- |> get("/api/pleroma/admin/need_reboot")
- |> json_response(200) == %{"need_reboot" => true}
-
- on_exit(fn -> Restarter.Pleroma.refresh() end)
- end
-
- describe "GET /api/pleroma/admin/statuses" do
- test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do
- blocked = insert(:user)
- user = insert(:user)
- User.block(admin, blocked)
-
- {:ok, _} =
- CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"})
-
- {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
- {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
- {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
- {:ok, _} = CommonAPI.post(blocked, %{"status" => ".", "visibility" => "public"})
-
- response =
- conn
- |> get("/api/pleroma/admin/statuses")
- |> json_response(200)
-
- refute "private" in Enum.map(response, & &1["visibility"])
- assert length(response) == 3
- end
-
- test "returns only local statuses with local_only on", %{conn: conn} do
- user = insert(:user)
- remote_user = insert(:user, local: false, nickname: "archaeme@archae.me")
- insert(:note_activity, user: user, local: true)
- insert(:note_activity, user: remote_user, local: false)
-
- response =
- conn
- |> get("/api/pleroma/admin/statuses?local_only=true")
- |> json_response(200)
-
- assert length(response) == 1
- end
-
- test "returns private and direct statuses with godmode on", %{conn: conn, admin: admin} do
- user = insert(:user)
-
- {:ok, _} =
- CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"})
-
- {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
- {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
- conn = get(conn, "/api/pleroma/admin/statuses?godmode=true")
- assert json_response(conn, 200) |> length() == 3
- end
- end
-
- describe "GET /api/pleroma/admin/users/:nickname/statuses" do
- setup do
- user = insert(:user)
-
- date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
- date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
- date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
-
- insert(:note_activity, user: user, published: date1)
- insert(:note_activity, user: user, published: date2)
- insert(:note_activity, user: user, published: date3)
-
- %{user: user}
- end
-
- test "renders user's statuses", %{conn: conn, user: user} do
- conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
-
- assert json_response(conn, 200) |> length() == 3
- end
-
- test "renders user's statuses with a limit", %{conn: conn, user: user} do
- conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
-
- assert json_response(conn, 200) |> length() == 2
- end
-
- test "doesn't return private statuses by default", %{conn: conn, user: user} do
- {:ok, _private_status} =
- CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
-
- {:ok, _public_status} =
- CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
-
- conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
-
- assert json_response(conn, 200) |> length() == 4
- end
-
- test "returns private statuses with godmode on", %{conn: conn, user: user} do
- {:ok, _private_status} =
- CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
-
- {:ok, _public_status} =
- CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
-
- conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
-
- assert json_response(conn, 200) |> length() == 5
- end
-
- test "excludes reblogs by default", %{conn: conn, user: user} do
- other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "."})
- {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, other_user)
-
- conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses")
- assert json_response(conn_res, 200) |> length() == 0
-
- conn_res =
- get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true")
-
- assert json_response(conn_res, 200) |> length() == 1
- end
- end
-
- describe "GET /api/pleroma/admin/moderation_log" do
- setup do
- moderator = insert(:user, is_moderator: true)
-
- %{moderator: moderator}
- end
-
- test "returns the log", %{conn: conn, admin: admin} do
- Repo.insert(%ModerationLog{
- data: %{
- actor: %{
- "id" => admin.id,
- "nickname" => admin.nickname,
- "type" => "user"
- },
- action: "relay_follow",
- target: "https://example.org/relay"
- },
- inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
- })
-
- Repo.insert(%ModerationLog{
- data: %{
- actor: %{
- "id" => admin.id,
- "nickname" => admin.nickname,
- "type" => "user"
- },
- action: "relay_unfollow",
- target: "https://example.org/relay"
- },
- inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
- })
-
- conn = get(conn, "/api/pleroma/admin/moderation_log")
-
- response = json_response(conn, 200)
- [first_entry, second_entry] = response["items"]
-
- assert response["total"] == 2
- assert first_entry["data"]["action"] == "relay_unfollow"
-
- assert first_entry["message"] ==
- "@#{admin.nickname} unfollowed relay: https://example.org/relay"
-
- assert second_entry["data"]["action"] == "relay_follow"
-
- assert second_entry["message"] ==
- "@#{admin.nickname} followed relay: https://example.org/relay"
- end
-
- test "returns the log with pagination", %{conn: conn, admin: admin} do
- Repo.insert(%ModerationLog{
- data: %{
- actor: %{
- "id" => admin.id,
- "nickname" => admin.nickname,
- "type" => "user"
- },
- action: "relay_follow",
- target: "https://example.org/relay"
- },
- inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
- })
-
- Repo.insert(%ModerationLog{
- data: %{
- actor: %{
- "id" => admin.id,
- "nickname" => admin.nickname,
- "type" => "user"
- },
- action: "relay_unfollow",
- target: "https://example.org/relay"
- },
- inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
- })
-
- conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
-
- response1 = json_response(conn1, 200)
- [first_entry] = response1["items"]
-
- assert response1["total"] == 2
- assert response1["items"] |> length() == 1
- assert first_entry["data"]["action"] == "relay_unfollow"
-
- assert first_entry["message"] ==
- "@#{admin.nickname} unfollowed relay: https://example.org/relay"
-
- conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
-
- response2 = json_response(conn2, 200)
- [second_entry] = response2["items"]
-
- assert response2["total"] == 2
- assert response2["items"] |> length() == 1
- assert second_entry["data"]["action"] == "relay_follow"
-
- assert second_entry["message"] ==
- "@#{admin.nickname} followed relay: https://example.org/relay"
- end
-
- test "filters log by date", %{conn: conn, admin: admin} do
- first_date = "2017-08-15T15:47:06Z"
- second_date = "2017-08-20T15:47:06Z"
-
- Repo.insert(%ModerationLog{
- data: %{
- actor: %{
- "id" => admin.id,
- "nickname" => admin.nickname,
- "type" => "user"
- },
- action: "relay_follow",
- target: "https://example.org/relay"
- },
- inserted_at: NaiveDateTime.from_iso8601!(first_date)
- })
-
- Repo.insert(%ModerationLog{
- data: %{
- actor: %{
- "id" => admin.id,
- "nickname" => admin.nickname,
- "type" => "user"
- },
- action: "relay_unfollow",
- target: "https://example.org/relay"
- },
- inserted_at: NaiveDateTime.from_iso8601!(second_date)
- })
-
- conn1 =
- get(
- conn,
- "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
- )
-
- response1 = json_response(conn1, 200)
- [first_entry] = response1["items"]
-
- assert response1["total"] == 1
- assert first_entry["data"]["action"] == "relay_unfollow"
-
- assert first_entry["message"] ==
- "@#{admin.nickname} unfollowed relay: https://example.org/relay"
- end
-
- test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
- Repo.insert(%ModerationLog{
- data: %{
- actor: %{
- "id" => admin.id,
- "nickname" => admin.nickname,
- "type" => "user"
- },
- action: "relay_follow",
- target: "https://example.org/relay"
- }
- })
-
- Repo.insert(%ModerationLog{
- data: %{
- actor: %{
- "id" => moderator.id,
- "nickname" => moderator.nickname,
- "type" => "user"
- },
- action: "relay_unfollow",
- target: "https://example.org/relay"
- }
- })
-
- conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
-
- response1 = json_response(conn1, 200)
- [first_entry] = response1["items"]
-
- assert response1["total"] == 1
- assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
- end
-
- test "returns log filtered by search", %{conn: conn, moderator: moderator} do
- ModerationLog.insert_log(%{
- actor: moderator,
- action: "relay_follow",
- target: "https://example.org/relay"
- })
-
- ModerationLog.insert_log(%{
- actor: moderator,
- action: "relay_unfollow",
- target: "https://example.org/relay"
- })
-
- conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
-
- response1 = json_response(conn1, 200)
- [first_entry] = response1["items"]
-
- assert response1["total"] == 1
-
- assert get_in(first_entry, ["data", "message"]) ==
- "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
- end
- end
-
- describe "GET /users/:nickname/credentials" do
- test "gets the user credentials", %{conn: conn} do
- user = insert(:user)
- conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
-
- response = assert json_response(conn, 200)
- assert response["email"] == user.email
- end
-
- test "returns 403 if requested by a non-admin" do
- user = insert(:user)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
-
- assert json_response(conn, :forbidden)
- end
- end
-
- describe "PATCH /users/:nickname/credentials" do
- test "changes password and email", %{conn: conn, admin: admin} do
- user = insert(:user)
- assert user.password_reset_pending == false
-
- conn =
- patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
- "password" => "new_password",
- "email" => "new_email@example.com",
- "name" => "new_name"
- })
-
- assert json_response(conn, 200) == %{"status" => "success"}
-
- ObanHelpers.perform_all()
-
- updated_user = User.get_by_id(user.id)
-
- assert updated_user.email == "new_email@example.com"
- assert updated_user.name == "new_name"
- assert updated_user.password_hash != user.password_hash
- assert updated_user.password_reset_pending == true
-
- [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
-
- assert ModerationLog.get_log_entry_message(log_entry1) ==
- "@#{admin.nickname} updated users: @#{user.nickname}"
-
- assert ModerationLog.get_log_entry_message(log_entry2) ==
- "@#{admin.nickname} forced password reset for users: @#{user.nickname}"
- end
-
- test "returns 403 if requested by a non-admin" do
- user = insert(:user)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
- "password" => "new_password",
- "email" => "new_email@example.com",
- "name" => "new_name"
- })
-
- assert json_response(conn, :forbidden)
- end
- end
-
- describe "PATCH /users/:nickname/force_password_reset" do
- test "sets password_reset_pending to true", %{conn: conn} do
- user = insert(:user)
- assert user.password_reset_pending == false
-
- conn =
- patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
-
- assert json_response(conn, 204) == ""
-
- ObanHelpers.perform_all()
-
- assert User.get_by_id(user.id).password_reset_pending == true
- end
- end
-
- describe "relays" do
- test "POST /relay", %{conn: conn, admin: admin} do
- conn =
- post(conn, "/api/pleroma/admin/relay", %{
- relay_url: "http://mastodon.example.org/users/admin"
- })
-
- assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
- end
-
- test "GET /relay", %{conn: conn} do
- relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
-
- ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
- |> Enum.each(fn ap_id ->
- {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
- User.follow(relay_user, user)
- end)
-
- conn = get(conn, "/api/pleroma/admin/relay")
-
- assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
- end
-
- test "DELETE /relay", %{conn: conn, admin: admin} do
- post(conn, "/api/pleroma/admin/relay", %{
- relay_url: "http://mastodon.example.org/users/admin"
- })
-
- conn =
- delete(conn, "/api/pleroma/admin/relay", %{
- relay_url: "http://mastodon.example.org/users/admin"
- })
-
- assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
-
- [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry_one) ==
- "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
-
- assert ModerationLog.get_log_entry_message(log_entry_two) ==
- "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
- end
- end
-
- describe "instances" do
- test "GET /instances/:instance/statuses", %{conn: conn} do
- user = insert(:user, local: false, nickname: "archaeme@archae.me")
- user2 = insert(:user, local: false, nickname: "test@test.com")
- insert_pair(:note_activity, user: user)
- activity = insert(:note_activity, user: user2)
-
- ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
-
- response = json_response(ret_conn, 200)
-
- assert length(response) == 2
-
- ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses")
-
- response = json_response(ret_conn, 200)
-
- assert length(response) == 1
-
- ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses")
-
- response = json_response(ret_conn, 200)
-
- assert Enum.empty?(response)
-
- CommonAPI.repeat(activity.id, user)
-
- ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
- response = json_response(ret_conn, 200)
- assert length(response) == 2
-
- ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
- response = json_response(ret_conn, 200)
- assert length(response) == 3
- end
- end
-
- describe "PATCH /confirm_email" do
- test "it confirms emails of two users", %{conn: conn, admin: admin} do
- [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
-
- assert first_user.confirmation_pending == true
- assert second_user.confirmation_pending == true
-
- ret_conn =
- patch(conn, "/api/pleroma/admin/users/confirm_email", %{
- nicknames: [
- first_user.nickname,
- second_user.nickname
- ]
- })
-
- assert ret_conn.status == 200
-
- assert first_user.confirmation_pending == true
- assert second_user.confirmation_pending == true
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
- second_user.nickname
- }"
- end
- end
-
- describe "PATCH /resend_confirmation_email" do
- test "it resend emails for two users", %{conn: conn, admin: admin} do
- [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
-
- ret_conn =
- patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{
- nicknames: [
- first_user.nickname,
- second_user.nickname
- ]
- })
-
- assert ret_conn.status == 200
-
- log_entry = Repo.one(ModerationLog)
-
- assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
- second_user.nickname
- }"
- end
- end
-
- describe "POST /reports/:id/notes" do
- setup %{conn: conn, admin: admin} do
- [reporter, target_user] = insert_pair(:user)
- activity = insert(:note_activity, user: target_user)
-
- {:ok, %{id: report_id}} =
- CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel offended",
- "status_ids" => [activity.id]
- })
-
- post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
- content: "this is disgusting!"
- })
-
- post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
- content: "this is disgusting2!"
- })
-
- %{
- admin_id: admin.id,
- report_id: report_id
- }
- end
-
- test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
- [note, _] = Repo.all(ReportNote)
-
- assert %{
- activity_id: ^report_id,
- content: "this is disgusting!",
- user_id: ^admin_id
- } = note
- end
-
- test "it returns reports with notes", %{conn: conn, admin: admin} do
- conn = get(conn, "/api/pleroma/admin/reports")
-
- response = json_response(conn, 200)
- notes = hd(response["reports"])["notes"]
- [note, _] = notes
-
- assert note["user"]["nickname"] == admin.nickname
- assert note["content"] == "this is disgusting!"
- assert note["created_at"]
- assert response["total"] == 1
- end
-
- test "it deletes the note", %{conn: conn, report_id: report_id} do
- assert ReportNote |> Repo.all() |> length() == 2
-
- [note, _] = Repo.all(ReportNote)
-
- delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
-
- assert ReportNote |> Repo.all() |> length() == 1
- end
- end
-
- test "GET /api/pleroma/admin/config/descriptions", %{conn: conn} do
- admin = insert(:user, is_admin: true)
-
- conn =
- assign(conn, :user, admin)
- |> get("/api/pleroma/admin/config/descriptions")
-
- assert [child | _others] = json_response(conn, 200)
-
- assert child["children"]
- assert child["key"]
- assert String.starts_with?(child["group"], ":")
- assert child["description"]
- end
-
- describe "/api/pleroma/admin/stats" do
- test "status visibility count", %{conn: conn} do
- admin = insert(:user, is_admin: true)
- user = insert(:user)
- CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
- CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"})
- CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"})
-
- response =
- conn
- |> assign(:user, admin)
- |> get("/api/pleroma/admin/stats")
- |> json_response(200)
-
- assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
- response["status_visibility"]
- end
- end
-end
-
-# Needed for testing
-defmodule Pleroma.Web.Endpoint.NotReal do
-end
-
-defmodule Pleroma.Captcha.NotReal do
-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
new file mode 100644
index 000000000..e3d3ccb8d
--- /dev/null
+++ b/test/web/admin_api/controllers/admin_api_controller_test.exs
@@ -0,0 +1,1743 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
+ use Pleroma.Web.ConnCase
+ use Oban.Testing, repo: Pleroma.Repo
+
+ import ExUnit.CaptureLog
+ import Mock
+ import Pleroma.Factory
+
+ alias Pleroma.Activity
+ alias Pleroma.Config
+ alias Pleroma.HTML
+ alias Pleroma.MFA
+ alias Pleroma.ModerationLog
+ alias Pleroma.Repo
+ alias Pleroma.Tests.ObanHelpers
+ alias Pleroma.User
+ alias Pleroma.Web
+ alias Pleroma.Web.ActivityPub.Relay
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.MediaProxy
+
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+
+ :ok
+ end
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
+ setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
+
+ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
+ %{admin: admin} do
+ user = insert(:user)
+ url = "/api/pleroma/admin/users/#{user.nickname}"
+
+ good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
+ good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
+ good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
+
+ bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
+ bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
+ bad_token3 = nil
+
+ for good_token <- [good_token1, good_token2, good_token3] do
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, good_token)
+ |> get(url)
+
+ assert json_response(conn, 200)
+ end
+
+ for good_token <- [good_token1, good_token2, good_token3] do
+ conn =
+ build_conn()
+ |> assign(:user, nil)
+ |> assign(:token, good_token)
+ |> get(url)
+
+ assert json_response(conn, :forbidden)
+ end
+
+ for bad_token <- [bad_token1, bad_token2, bad_token3] do
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, bad_token)
+ |> get(url)
+
+ assert json_response(conn, :forbidden)
+ end
+ end
+ end
+
+ describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
+ setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
+
+ test "GET /api/pleroma/admin/users/:nickname requires " <>
+ "read:accounts or admin:read:accounts or broader scope",
+ %{admin: admin} do
+ user = insert(:user)
+ url = "/api/pleroma/admin/users/#{user.nickname}"
+
+ good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
+ good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
+ good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
+ good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
+ good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])
+
+ good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]
+
+ bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
+ bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
+ bad_token3 = nil
+
+ for good_token <- good_tokens do
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, good_token)
+ |> get(url)
+
+ assert json_response(conn, 200)
+ end
+
+ for good_token <- good_tokens do
+ conn =
+ build_conn()
+ |> assign(:user, nil)
+ |> assign(:token, good_token)
+ |> get(url)
+
+ assert json_response(conn, :forbidden)
+ end
+
+ for bad_token <- [bad_token1, bad_token2, bad_token3] do
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, bad_token)
+ |> get(url)
+
+ assert json_response(conn, :forbidden)
+ end
+ end
+ end
+
+ describe "DELETE /api/pleroma/admin/users" do
+ test "single user", %{admin: admin, conn: conn} do
+ user = insert(:user)
+ clear_config([:instance, :federating], true)
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
+
+ ObanHelpers.perform_all()
+
+ assert User.get_by_nickname(user.nickname).deactivated
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} deleted users: @#{user.nickname}"
+
+ assert json_response(conn, 200) == [user.nickname]
+
+ assert called(Pleroma.Web.Federator.publish(:_))
+ end
+ end
+
+ test "multiple users", %{admin: admin, conn: conn} do
+ user_one = insert(:user)
+ user_two = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> delete("/api/pleroma/admin/users", %{
+ nicknames: [user_one.nickname, user_two.nickname]
+ })
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
+
+ response = json_response(conn, 200)
+ assert response -- [user_one.nickname, user_two.nickname] == []
+ end
+ end
+
+ describe "/api/pleroma/admin/users" do
+ test "Create", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> post("/api/pleroma/admin/users", %{
+ "users" => [
+ %{
+ "nickname" => "lain",
+ "email" => "lain@example.org",
+ "password" => "test"
+ },
+ %{
+ "nickname" => "lain2",
+ "email" => "lain2@example.org",
+ "password" => "test"
+ }
+ ]
+ })
+
+ response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
+ assert response == ["success", "success"]
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
+ end
+
+ test "Cannot create user with existing email", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> post("/api/pleroma/admin/users", %{
+ "users" => [
+ %{
+ "nickname" => "lain",
+ "email" => user.email,
+ "password" => "test"
+ }
+ ]
+ })
+
+ assert json_response(conn, 409) == [
+ %{
+ "code" => 409,
+ "data" => %{
+ "email" => user.email,
+ "nickname" => "lain"
+ },
+ "error" => "email has already been taken",
+ "type" => "error"
+ }
+ ]
+ end
+
+ test "Cannot create user with existing nickname", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> post("/api/pleroma/admin/users", %{
+ "users" => [
+ %{
+ "nickname" => user.nickname,
+ "email" => "someuser@plerama.social",
+ "password" => "test"
+ }
+ ]
+ })
+
+ assert json_response(conn, 409) == [
+ %{
+ "code" => 409,
+ "data" => %{
+ "email" => "someuser@plerama.social",
+ "nickname" => user.nickname
+ },
+ "error" => "nickname has already been taken",
+ "type" => "error"
+ }
+ ]
+ end
+
+ test "Multiple user creation works in transaction", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> post("/api/pleroma/admin/users", %{
+ "users" => [
+ %{
+ "nickname" => "newuser",
+ "email" => "newuser@pleroma.social",
+ "password" => "test"
+ },
+ %{
+ "nickname" => "lain",
+ "email" => user.email,
+ "password" => "test"
+ }
+ ]
+ })
+
+ assert json_response(conn, 409) == [
+ %{
+ "code" => 409,
+ "data" => %{
+ "email" => user.email,
+ "nickname" => "lain"
+ },
+ "error" => "email has already been taken",
+ "type" => "error"
+ },
+ %{
+ "code" => 409,
+ "data" => %{
+ "email" => "newuser@pleroma.social",
+ "nickname" => "newuser"
+ },
+ "error" => "",
+ "type" => "error"
+ }
+ ]
+
+ assert User.get_by_nickname("newuser") === nil
+ end
+ end
+
+ describe "/api/pleroma/admin/users/:nickname" do
+ test "Show", %{conn: conn} do
+ user = insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
+
+ expected = %{
+ "deactivated" => false,
+ "id" => to_string(user.id),
+ "local" => true,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+
+ assert expected == json_response(conn, 200)
+ end
+
+ test "when the user doesn't exist", %{conn: conn} do
+ user = build(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
+
+ assert %{"error" => "Not found"} == json_response(conn, 404)
+ end
+ end
+
+ describe "/api/pleroma/admin/users/follow" do
+ test "allows to force-follow another user", %{admin: admin, conn: conn} do
+ user = insert(:user)
+ follower = insert(:user)
+
+ conn
+ |> put_req_header("accept", "application/json")
+ |> post("/api/pleroma/admin/users/follow", %{
+ "follower" => follower.nickname,
+ "followed" => user.nickname
+ })
+
+ user = User.get_cached_by_id(user.id)
+ follower = User.get_cached_by_id(follower.id)
+
+ assert User.following?(follower, user)
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
+ end
+ end
+
+ describe "/api/pleroma/admin/users/unfollow" do
+ test "allows to force-unfollow another user", %{admin: admin, conn: conn} do
+ user = insert(:user)
+ follower = insert(:user)
+
+ User.follow(follower, user)
+
+ conn
+ |> put_req_header("accept", "application/json")
+ |> post("/api/pleroma/admin/users/unfollow", %{
+ "follower" => follower.nickname,
+ "followed" => user.nickname
+ })
+
+ user = User.get_cached_by_id(user.id)
+ follower = User.get_cached_by_id(follower.id)
+
+ refute User.following?(follower, user)
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
+ end
+ end
+
+ describe "PUT /api/pleroma/admin/users/tag" do
+ setup %{conn: conn} do
+ user1 = insert(:user, %{tags: ["x"]})
+ user2 = insert(:user, %{tags: ["y"]})
+ user3 = insert(:user, %{tags: ["unchanged"]})
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> put(
+ "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
+ "#{user2.nickname}&tags[]=foo&tags[]=bar"
+ )
+
+ %{conn: conn, user1: user1, user2: user2, user3: user3}
+ end
+
+ test "it appends specified tags to users with specified nicknames", %{
+ conn: conn,
+ admin: admin,
+ user1: user1,
+ user2: user2
+ } do
+ assert json_response(conn, :no_content)
+ assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
+ assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
+
+ log_entry = Repo.one(ModerationLog)
+
+ users =
+ [user1.nickname, user2.nickname]
+ |> Enum.map(&"@#{&1}")
+ |> Enum.join(", ")
+
+ tags = ["foo", "bar"] |> Enum.join(", ")
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} added tags: #{tags} to users: #{users}"
+ end
+
+ test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
+ assert json_response(conn, :no_content)
+ assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
+ end
+ end
+
+ describe "DELETE /api/pleroma/admin/users/tag" do
+ setup %{conn: conn} do
+ user1 = insert(:user, %{tags: ["x"]})
+ user2 = insert(:user, %{tags: ["y", "z"]})
+ user3 = insert(:user, %{tags: ["unchanged"]})
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> delete(
+ "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
+ "#{user2.nickname}&tags[]=x&tags[]=z"
+ )
+
+ %{conn: conn, user1: user1, user2: user2, user3: user3}
+ end
+
+ test "it removes specified tags from users with specified nicknames", %{
+ conn: conn,
+ admin: admin,
+ user1: user1,
+ user2: user2
+ } do
+ assert json_response(conn, :no_content)
+ assert User.get_cached_by_id(user1.id).tags == []
+ assert User.get_cached_by_id(user2.id).tags == ["y"]
+
+ log_entry = Repo.one(ModerationLog)
+
+ users =
+ [user1.nickname, user2.nickname]
+ |> Enum.map(&"@#{&1}")
+ |> Enum.join(", ")
+
+ tags = ["x", "z"] |> Enum.join(", ")
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
+ end
+
+ test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
+ assert json_response(conn, :no_content)
+ assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
+ end
+ end
+
+ describe "/api/pleroma/admin/users/:nickname/permission_group" do
+ test "GET is giving user_info", %{admin: admin, conn: conn} do
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
+
+ assert json_response(conn, 200) == %{
+ "is_admin" => true,
+ "is_moderator" => false
+ }
+ end
+
+ test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
+
+ assert json_response(conn, 200) == %{
+ "is_admin" => true
+ }
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} made @#{user.nickname} admin"
+ end
+
+ test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do
+ user_one = insert(:user)
+ user_two = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> post("/api/pleroma/admin/users/permission_group/admin", %{
+ nicknames: [user_one.nickname, user_two.nickname]
+ })
+
+ assert json_response(conn, 200) == %{"is_admin" => true}
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
+ end
+
+ test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do
+ user = insert(:user, is_admin: true)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
+
+ assert json_response(conn, 200) == %{"is_admin" => false}
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} revoked admin role from @#{user.nickname}"
+ end
+
+ test "/:right DELETE, can remove from a permission group (multiple)", %{
+ admin: admin,
+ conn: conn
+ } do
+ user_one = insert(:user, is_admin: true)
+ user_two = insert(:user, is_admin: true)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> delete("/api/pleroma/admin/users/permission_group/admin", %{
+ nicknames: [user_one.nickname, user_two.nickname]
+ })
+
+ assert json_response(conn, 200) == %{"is_admin" => false}
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
+ user_two.nickname
+ }"
+ end
+ end
+
+ test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
+
+ resp = json_response(conn, 200)
+
+ assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
+ end
+
+ describe "GET /api/pleroma/admin/users" do
+ test "renders users array for the first page", %{conn: conn, admin: admin} do
+ user = insert(:user, local: false, tags: ["foo", "bar"])
+ conn = get(conn, "/api/pleroma/admin/users?page=1")
+
+ users =
+ [
+ %{
+ "deactivated" => admin.deactivated,
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "roles" => %{"admin" => true, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(admin.name || admin.nickname),
+ "confirmation_pending" => false,
+ "url" => admin.ap_id
+ },
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => false,
+ "tags" => ["foo", "bar"],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ |> Enum.sort_by(& &1["nickname"])
+
+ assert json_response(conn, 200) == %{
+ "count" => 2,
+ "page_size" => 50,
+ "users" => users
+ }
+ end
+
+ test "pagination works correctly with service users", %{conn: conn} do
+ service1 = User.get_or_create_service_actor_by_ap_id(Web.base_url() <> "/meido", "meido")
+
+ insert_list(25, :user)
+
+ assert %{"count" => 26, "page_size" => 10, "users" => users1} =
+ conn
+ |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"})
+ |> json_response(200)
+
+ assert Enum.count(users1) == 10
+ assert service1 not in users1
+
+ assert %{"count" => 26, "page_size" => 10, "users" => users2} =
+ conn
+ |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"})
+ |> json_response(200)
+
+ assert Enum.count(users2) == 10
+ assert service1 not in users2
+
+ assert %{"count" => 26, "page_size" => 10, "users" => users3} =
+ conn
+ |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"})
+ |> json_response(200)
+
+ assert Enum.count(users3) == 6
+ assert service1 not in users3
+ end
+
+ test "renders empty array for the second page", %{conn: conn} do
+ insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users?page=2")
+
+ assert json_response(conn, 200) == %{
+ "count" => 2,
+ "page_size" => 50,
+ "users" => []
+ }
+ end
+
+ test "regular search", %{conn: conn} do
+ user = insert(:user, nickname: "bob")
+
+ conn = get(conn, "/api/pleroma/admin/users?query=bo")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ }
+ end
+
+ test "search by domain", %{conn: conn} do
+ user = insert(:user, nickname: "nickname@domain.com")
+ insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ }
+ end
+
+ test "search by full nickname", %{conn: conn} do
+ user = insert(:user, nickname: "nickname@domain.com")
+ insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ }
+ end
+
+ test "search by display name", %{conn: conn} do
+ user = insert(:user, name: "Display name")
+ insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users?name=display")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ }
+ end
+
+ test "search by email", %{conn: conn} do
+ user = insert(:user, email: "email@example.com")
+ insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ }
+ end
+
+ test "regular search with page size", %{conn: conn} do
+ user = insert(:user, nickname: "aalice")
+ user2 = insert(:user, nickname: "alice")
+
+ conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
+
+ assert json_response(conn1, 200) == %{
+ "count" => 2,
+ "page_size" => 1,
+ "users" => [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ }
+
+ conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
+
+ assert json_response(conn2, 200) == %{
+ "count" => 2,
+ "page_size" => 1,
+ "users" => [
+ %{
+ "deactivated" => user2.deactivated,
+ "id" => user2.id,
+ "nickname" => user2.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user2.name || user2.nickname),
+ "confirmation_pending" => false,
+ "url" => user2.ap_id
+ }
+ ]
+ }
+ end
+
+ test "only local users" do
+ admin = insert(:user, is_admin: true, nickname: "john")
+ token = insert(:oauth_admin_token, user: admin)
+ user = insert(:user, nickname: "bob")
+
+ insert(:user, nickname: "bobb", local: false)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+ |> get("/api/pleroma/admin/users?query=bo&filters=local")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ }
+ end
+
+ test "only local users with no query", %{conn: conn, admin: old_admin} do
+ admin = insert(:user, is_admin: true, nickname: "john")
+ user = insert(:user, nickname: "bob")
+
+ insert(:user, nickname: "bobb", local: false)
+
+ conn = get(conn, "/api/pleroma/admin/users?filters=local")
+
+ users =
+ [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ },
+ %{
+ "deactivated" => admin.deactivated,
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "roles" => %{"admin" => true, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(admin.name || admin.nickname),
+ "confirmation_pending" => false,
+ "url" => admin.ap_id
+ },
+ %{
+ "deactivated" => false,
+ "id" => old_admin.id,
+ "local" => true,
+ "nickname" => old_admin.nickname,
+ "roles" => %{"admin" => true, "moderator" => false},
+ "tags" => [],
+ "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
+ "confirmation_pending" => false,
+ "url" => old_admin.ap_id
+ }
+ ]
+ |> Enum.sort_by(& &1["nickname"])
+
+ assert json_response(conn, 200) == %{
+ "count" => 3,
+ "page_size" => 50,
+ "users" => users
+ }
+ end
+
+ test "load only admins", %{conn: conn, admin: admin} do
+ second_admin = insert(:user, is_admin: true)
+ insert(:user)
+ insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
+
+ users =
+ [
+ %{
+ "deactivated" => false,
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "roles" => %{"admin" => true, "moderator" => false},
+ "local" => admin.local,
+ "tags" => [],
+ "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(admin.name || admin.nickname),
+ "confirmation_pending" => false,
+ "url" => admin.ap_id
+ },
+ %{
+ "deactivated" => false,
+ "id" => second_admin.id,
+ "nickname" => second_admin.nickname,
+ "roles" => %{"admin" => true, "moderator" => false},
+ "local" => second_admin.local,
+ "tags" => [],
+ "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
+ "confirmation_pending" => false,
+ "url" => second_admin.ap_id
+ }
+ ]
+ |> Enum.sort_by(& &1["nickname"])
+
+ assert json_response(conn, 200) == %{
+ "count" => 2,
+ "page_size" => 50,
+ "users" => users
+ }
+ end
+
+ test "load only moderators", %{conn: conn} do
+ moderator = insert(:user, is_moderator: true)
+ insert(:user)
+ insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => false,
+ "id" => moderator.id,
+ "nickname" => moderator.nickname,
+ "roles" => %{"admin" => false, "moderator" => true},
+ "local" => moderator.local,
+ "tags" => [],
+ "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
+ "confirmation_pending" => false,
+ "url" => moderator.ap_id
+ }
+ ]
+ }
+ end
+
+ test "load users with tags list", %{conn: conn} do
+ user1 = insert(:user, tags: ["first"])
+ user2 = insert(:user, tags: ["second"])
+ insert(:user)
+ insert(:user)
+
+ conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
+
+ users =
+ [
+ %{
+ "deactivated" => false,
+ "id" => user1.id,
+ "nickname" => user1.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => user1.local,
+ "tags" => ["first"],
+ "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user1.name || user1.nickname),
+ "confirmation_pending" => false,
+ "url" => user1.ap_id
+ },
+ %{
+ "deactivated" => false,
+ "id" => user2.id,
+ "nickname" => user2.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => user2.local,
+ "tags" => ["second"],
+ "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user2.name || user2.nickname),
+ "confirmation_pending" => false,
+ "url" => user2.ap_id
+ }
+ ]
+ |> Enum.sort_by(& &1["nickname"])
+
+ assert json_response(conn, 200) == %{
+ "count" => 2,
+ "page_size" => 50,
+ "users" => users
+ }
+ end
+
+ test "it works with multiple filters" do
+ admin = insert(:user, nickname: "john", is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+ user = insert(:user, nickname: "bob", local: false, deactivated: true)
+
+ insert(:user, nickname: "ken", local: true, deactivated: true)
+ insert(:user, nickname: "bobb", local: false, deactivated: false)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+ |> get("/api/pleroma/admin/users?filters=deactivated,external")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => user.local,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+ ]
+ }
+ end
+
+ test "it omits relay user", %{admin: admin, conn: conn} do
+ assert %User{} = Relay.get_actor()
+
+ conn = get(conn, "/api/pleroma/admin/users")
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => [
+ %{
+ "deactivated" => admin.deactivated,
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "roles" => %{"admin" => true, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(admin.name || admin.nickname),
+ "confirmation_pending" => false,
+ "url" => admin.ap_id
+ }
+ ]
+ }
+ end
+ end
+
+ test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
+ user_one = insert(:user, deactivated: true)
+ user_two = insert(:user, deactivated: true)
+
+ conn =
+ patch(
+ conn,
+ "/api/pleroma/admin/users/activate",
+ %{nicknames: [user_one.nickname, user_two.nickname]}
+ )
+
+ response = json_response(conn, 200)
+ assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
+ end
+
+ test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
+ user_one = insert(:user, deactivated: false)
+ user_two = insert(:user, deactivated: false)
+
+ conn =
+ patch(
+ conn,
+ "/api/pleroma/admin/users/deactivate",
+ %{nicknames: [user_one.nickname, user_two.nickname]}
+ )
+
+ response = json_response(conn, 200)
+ assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
+ end
+
+ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
+ user = insert(:user)
+
+ conn = patch(conn, "/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
+
+ assert json_response(conn, 200) ==
+ %{
+ "deactivated" => !user.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname,
+ "roles" => %{"admin" => false, "moderator" => false},
+ "local" => true,
+ "tags" => [],
+ "avatar" => User.avatar_url(user) |> MediaProxy.url(),
+ "display_name" => HTML.strip_tags(user.name || user.nickname),
+ "confirmation_pending" => false,
+ "url" => user.ap_id
+ }
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} deactivated users: @#{user.nickname}"
+ end
+
+ describe "PUT disable_mfa" do
+ test "returns 200 and disable 2fa", %{conn: conn} do
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: "otp_secret", confirmed: true}
+ }
+ )
+
+ response =
+ conn
+ |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: user.nickname})
+ |> json_response(200)
+
+ assert response == user.nickname
+ mfa_settings = refresh_record(user).multi_factor_authentication_settings
+
+ refute mfa_settings.enabled
+ refute mfa_settings.totp.confirmed
+ end
+
+ test "returns 404 if user not found", %{conn: conn} do
+ response =
+ conn
+ |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
+ |> json_response(404)
+
+ assert response == %{"error" => "Not found"}
+ end
+ end
+
+ describe "GET /api/pleroma/admin/restart" do
+ setup do: clear_config(:configurable_from_database, true)
+
+ test "pleroma restarts", %{conn: conn} do
+ capture_log(fn ->
+ assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
+ end) =~ "pleroma restarted"
+
+ refute Restarter.Pleroma.need_reboot?()
+ end
+ end
+
+ test "need_reboot flag", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/admin/need_reboot")
+ |> json_response(200) == %{"need_reboot" => false}
+
+ Restarter.Pleroma.need_reboot()
+
+ assert conn
+ |> get("/api/pleroma/admin/need_reboot")
+ |> json_response(200) == %{"need_reboot" => true}
+
+ on_exit(fn -> Restarter.Pleroma.refresh() end)
+ end
+
+ describe "GET /api/pleroma/admin/users/:nickname/statuses" do
+ setup do
+ user = insert(:user)
+
+ date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
+ date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
+ date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
+
+ insert(:note_activity, user: user, published: date1)
+ insert(:note_activity, user: user, published: date2)
+ insert(:note_activity, user: user, published: date3)
+
+ %{user: user}
+ end
+
+ test "renders user's statuses", %{conn: conn, user: user} do
+ conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
+
+ assert json_response(conn, 200) |> length() == 3
+ end
+
+ test "renders user's statuses with a limit", %{conn: conn, user: user} do
+ conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
+
+ assert json_response(conn, 200) |> length() == 2
+ end
+
+ test "doesn't return private statuses by default", %{conn: conn, user: user} do
+ {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
+
+ {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
+
+ conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
+
+ assert json_response(conn, 200) |> length() == 4
+ end
+
+ test "returns private statuses with godmode on", %{conn: conn, user: user} do
+ {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
+
+ {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
+
+ conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
+
+ assert json_response(conn, 200) |> length() == 5
+ end
+
+ test "excludes reblogs by default", %{conn: conn, user: user} do
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "."})
+ {:ok, %Activity{}} = CommonAPI.repeat(activity.id, other_user)
+
+ conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses")
+ assert json_response(conn_res, 200) |> length() == 0
+
+ conn_res =
+ get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true")
+
+ assert json_response(conn_res, 200) |> length() == 1
+ end
+ end
+
+ describe "GET /api/pleroma/admin/moderation_log" do
+ setup do
+ moderator = insert(:user, is_moderator: true)
+
+ %{moderator: moderator}
+ end
+
+ test "returns the log", %{conn: conn, admin: admin} do
+ Repo.insert(%ModerationLog{
+ data: %{
+ actor: %{
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "type" => "user"
+ },
+ action: "relay_follow",
+ target: "https://example.org/relay"
+ },
+ inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
+ })
+
+ Repo.insert(%ModerationLog{
+ data: %{
+ actor: %{
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "type" => "user"
+ },
+ action: "relay_unfollow",
+ target: "https://example.org/relay"
+ },
+ inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
+ })
+
+ conn = get(conn, "/api/pleroma/admin/moderation_log")
+
+ response = json_response(conn, 200)
+ [first_entry, second_entry] = response["items"]
+
+ assert response["total"] == 2
+ assert first_entry["data"]["action"] == "relay_unfollow"
+
+ assert first_entry["message"] ==
+ "@#{admin.nickname} unfollowed relay: https://example.org/relay"
+
+ assert second_entry["data"]["action"] == "relay_follow"
+
+ assert second_entry["message"] ==
+ "@#{admin.nickname} followed relay: https://example.org/relay"
+ end
+
+ test "returns the log with pagination", %{conn: conn, admin: admin} do
+ Repo.insert(%ModerationLog{
+ data: %{
+ actor: %{
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "type" => "user"
+ },
+ action: "relay_follow",
+ target: "https://example.org/relay"
+ },
+ inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
+ })
+
+ Repo.insert(%ModerationLog{
+ data: %{
+ actor: %{
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "type" => "user"
+ },
+ action: "relay_unfollow",
+ target: "https://example.org/relay"
+ },
+ inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
+ })
+
+ conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
+
+ response1 = json_response(conn1, 200)
+ [first_entry] = response1["items"]
+
+ assert response1["total"] == 2
+ assert response1["items"] |> length() == 1
+ assert first_entry["data"]["action"] == "relay_unfollow"
+
+ assert first_entry["message"] ==
+ "@#{admin.nickname} unfollowed relay: https://example.org/relay"
+
+ conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
+
+ response2 = json_response(conn2, 200)
+ [second_entry] = response2["items"]
+
+ assert response2["total"] == 2
+ assert response2["items"] |> length() == 1
+ assert second_entry["data"]["action"] == "relay_follow"
+
+ assert second_entry["message"] ==
+ "@#{admin.nickname} followed relay: https://example.org/relay"
+ end
+
+ test "filters log by date", %{conn: conn, admin: admin} do
+ first_date = "2017-08-15T15:47:06Z"
+ second_date = "2017-08-20T15:47:06Z"
+
+ Repo.insert(%ModerationLog{
+ data: %{
+ actor: %{
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "type" => "user"
+ },
+ action: "relay_follow",
+ target: "https://example.org/relay"
+ },
+ inserted_at: NaiveDateTime.from_iso8601!(first_date)
+ })
+
+ Repo.insert(%ModerationLog{
+ data: %{
+ actor: %{
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "type" => "user"
+ },
+ action: "relay_unfollow",
+ target: "https://example.org/relay"
+ },
+ inserted_at: NaiveDateTime.from_iso8601!(second_date)
+ })
+
+ conn1 =
+ get(
+ conn,
+ "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
+ )
+
+ response1 = json_response(conn1, 200)
+ [first_entry] = response1["items"]
+
+ assert response1["total"] == 1
+ assert first_entry["data"]["action"] == "relay_unfollow"
+
+ assert first_entry["message"] ==
+ "@#{admin.nickname} unfollowed relay: https://example.org/relay"
+ end
+
+ test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
+ Repo.insert(%ModerationLog{
+ data: %{
+ actor: %{
+ "id" => admin.id,
+ "nickname" => admin.nickname,
+ "type" => "user"
+ },
+ action: "relay_follow",
+ target: "https://example.org/relay"
+ }
+ })
+
+ Repo.insert(%ModerationLog{
+ data: %{
+ actor: %{
+ "id" => moderator.id,
+ "nickname" => moderator.nickname,
+ "type" => "user"
+ },
+ action: "relay_unfollow",
+ target: "https://example.org/relay"
+ }
+ })
+
+ conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
+
+ response1 = json_response(conn1, 200)
+ [first_entry] = response1["items"]
+
+ assert response1["total"] == 1
+ assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
+ end
+
+ test "returns log filtered by search", %{conn: conn, moderator: moderator} do
+ ModerationLog.insert_log(%{
+ actor: moderator,
+ action: "relay_follow",
+ target: "https://example.org/relay"
+ })
+
+ ModerationLog.insert_log(%{
+ actor: moderator,
+ action: "relay_unfollow",
+ target: "https://example.org/relay"
+ })
+
+ conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
+
+ response1 = json_response(conn1, 200)
+ [first_entry] = response1["items"]
+
+ assert response1["total"] == 1
+
+ assert get_in(first_entry, ["data", "message"]) ==
+ "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
+ end
+ end
+
+ describe "GET /users/:nickname/credentials" do
+ test "gets the user credentials", %{conn: conn} do
+ user = insert(:user)
+ conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
+
+ response = assert json_response(conn, 200)
+ assert response["email"] == user.email
+ end
+
+ test "returns 403 if requested by a non-admin" do
+ user = insert(:user)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
+
+ assert json_response(conn, :forbidden)
+ end
+ end
+
+ describe "PATCH /users/:nickname/credentials" do
+ setup do
+ user = insert(:user)
+ [user: user]
+ end
+
+ test "changes password and email", %{conn: conn, admin: admin, user: user} do
+ assert user.password_reset_pending == false
+
+ conn =
+ patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
+ "password" => "new_password",
+ "email" => "new_email@example.com",
+ "name" => "new_name"
+ })
+
+ assert json_response(conn, 200) == %{"status" => "success"}
+
+ ObanHelpers.perform_all()
+
+ updated_user = User.get_by_id(user.id)
+
+ assert updated_user.email == "new_email@example.com"
+ assert updated_user.name == "new_name"
+ assert updated_user.password_hash != user.password_hash
+ assert updated_user.password_reset_pending == true
+
+ [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
+
+ assert ModerationLog.get_log_entry_message(log_entry1) ==
+ "@#{admin.nickname} updated users: @#{user.nickname}"
+
+ assert ModerationLog.get_log_entry_message(log_entry2) ==
+ "@#{admin.nickname} forced password reset for users: @#{user.nickname}"
+ end
+
+ test "returns 403 if requested by a non-admin", %{user: user} do
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
+ "password" => "new_password",
+ "email" => "new_email@example.com",
+ "name" => "new_name"
+ })
+
+ assert json_response(conn, :forbidden)
+ end
+
+ test "changes actor type from permitted list", %{conn: conn, user: user} do
+ assert user.actor_type == "Person"
+
+ assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
+ "actor_type" => "Service"
+ })
+ |> json_response(200) == %{"status" => "success"}
+
+ updated_user = User.get_by_id(user.id)
+
+ assert updated_user.actor_type == "Service"
+
+ assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
+ "actor_type" => "Application"
+ })
+ |> json_response(200) == %{"errors" => %{"actor_type" => "is invalid"}}
+ end
+
+ test "update non existing user", %{conn: conn} do
+ assert patch(conn, "/api/pleroma/admin/users/non-existing/credentials", %{
+ "password" => "new_password"
+ })
+ |> json_response(200) == %{"error" => "Unable to update user."}
+ end
+ end
+
+ describe "PATCH /users/:nickname/force_password_reset" do
+ test "sets password_reset_pending to true", %{conn: conn} do
+ user = insert(:user)
+ assert user.password_reset_pending == false
+
+ conn =
+ patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
+
+ assert json_response(conn, 204) == ""
+
+ ObanHelpers.perform_all()
+
+ assert User.get_by_id(user.id).password_reset_pending == true
+ end
+ end
+
+ describe "instances" do
+ test "GET /instances/:instance/statuses", %{conn: conn} do
+ user = insert(:user, local: false, nickname: "archaeme@archae.me")
+ user2 = insert(:user, local: false, nickname: "test@test.com")
+ insert_pair(:note_activity, user: user)
+ activity = insert(:note_activity, user: user2)
+
+ ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
+
+ response = json_response(ret_conn, 200)
+
+ assert length(response) == 2
+
+ ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses")
+
+ response = json_response(ret_conn, 200)
+
+ assert length(response) == 1
+
+ ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses")
+
+ response = json_response(ret_conn, 200)
+
+ assert Enum.empty?(response)
+
+ CommonAPI.repeat(activity.id, user)
+
+ ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
+ response = json_response(ret_conn, 200)
+ assert length(response) == 2
+
+ ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
+ response = json_response(ret_conn, 200)
+ assert length(response) == 3
+ end
+ end
+
+ describe "PATCH /confirm_email" do
+ test "it confirms emails of two users", %{conn: conn, admin: admin} do
+ [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
+
+ assert first_user.confirmation_pending == true
+ assert second_user.confirmation_pending == true
+
+ ret_conn =
+ patch(conn, "/api/pleroma/admin/users/confirm_email", %{
+ nicknames: [
+ first_user.nickname,
+ second_user.nickname
+ ]
+ })
+
+ assert ret_conn.status == 200
+
+ assert first_user.confirmation_pending == true
+ assert second_user.confirmation_pending == true
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
+ second_user.nickname
+ }"
+ end
+ end
+
+ describe "PATCH /resend_confirmation_email" do
+ test "it resend emails for two users", %{conn: conn, admin: admin} do
+ [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
+
+ ret_conn =
+ patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{
+ nicknames: [
+ first_user.nickname,
+ second_user.nickname
+ ]
+ })
+
+ assert ret_conn.status == 200
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
+ second_user.nickname
+ }"
+ end
+ end
+
+ describe "/api/pleroma/admin/stats" do
+ test "status visibility count", %{conn: conn} do
+ admin = insert(:user, is_admin: true)
+ user = insert(:user)
+ CommonAPI.post(user, %{visibility: "public", status: "hey"})
+ CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
+ CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
+
+ response =
+ conn
+ |> assign(:user, admin)
+ |> get("/api/pleroma/admin/stats")
+ |> json_response(200)
+
+ assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
+ response["status_visibility"]
+ end
+ end
+end
+
+# Needed for testing
+defmodule Pleroma.Web.Endpoint.NotReal do
+end
+
+defmodule Pleroma.Captcha.NotReal do
+end
diff --git a/test/web/admin_api/controllers/config_controller_test.exs b/test/web/admin_api/controllers/config_controller_test.exs
new file mode 100644
index 000000000..064ef9bc7
--- /dev/null
+++ b/test/web/admin_api/controllers/config_controller_test.exs
@@ -0,0 +1,1388 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
+ use Pleroma.Web.ConnCase, async: true
+
+ import ExUnit.CaptureLog
+ import Pleroma.Factory
+
+ alias Pleroma.Config
+ alias Pleroma.ConfigDB
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "GET /api/pleroma/admin/config" do
+ setup do: clear_config(:configurable_from_database, true)
+
+ test "when configuration from database is off", %{conn: conn} do
+ Config.put(:configurable_from_database, false)
+ conn = get(conn, "/api/pleroma/admin/config")
+
+ assert json_response_and_validate_schema(conn, 400) ==
+ %{
+ "error" => "To use this endpoint you need to enable configuration from database."
+ }
+ end
+
+ test "with settings only in db", %{conn: conn} do
+ config1 = insert(:config)
+ config2 = insert(:config)
+
+ conn = get(conn, "/api/pleroma/admin/config?only_db=true")
+
+ %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => key1,
+ "value" => _
+ },
+ %{
+ "group" => ":pleroma",
+ "key" => key2,
+ "value" => _
+ }
+ ]
+ } = json_response_and_validate_schema(conn, 200)
+
+ assert key1 == inspect(config1.key)
+ assert key2 == inspect(config2.key)
+ end
+
+ test "db is added to settings that are in db", %{conn: conn} do
+ _config = insert(:config, key: ":instance", value: [name: "Some name"])
+
+ %{"configs" => configs} =
+ conn
+ |> get("/api/pleroma/admin/config")
+ |> json_response_and_validate_schema(200)
+
+ [instance_config] =
+ Enum.filter(configs, fn %{"group" => group, "key" => key} ->
+ group == ":pleroma" and key == ":instance"
+ end)
+
+ assert instance_config["db"] == [":name"]
+ end
+
+ test "merged default setting with db settings", %{conn: conn} do
+ config1 = insert(:config)
+ config2 = insert(:config)
+
+ config3 =
+ insert(:config,
+ value: [k1: :v1, k2: :v2]
+ )
+
+ %{"configs" => configs} =
+ conn
+ |> get("/api/pleroma/admin/config")
+ |> json_response_and_validate_schema(200)
+
+ assert length(configs) > 3
+
+ saved_configs = [config1, config2, config3]
+ keys = Enum.map(saved_configs, &inspect(&1.key))
+
+ received_configs =
+ Enum.filter(configs, fn %{"group" => group, "key" => key} ->
+ group == ":pleroma" and key in keys
+ end)
+
+ assert length(received_configs) == 3
+
+ db_keys =
+ config3.value
+ |> Keyword.keys()
+ |> ConfigDB.to_json_types()
+
+ keys = Enum.map(saved_configs -- [config3], &inspect(&1.key))
+
+ values = Enum.map(saved_configs, &ConfigDB.to_json_types(&1.value))
+
+ mapset_keys = MapSet.new(keys ++ db_keys)
+
+ Enum.each(received_configs, fn %{"value" => value, "db" => db} ->
+ db = MapSet.new(db)
+ assert MapSet.subset?(db, mapset_keys)
+
+ assert value in values
+ end)
+ end
+
+ test "subkeys with full update right merge", %{conn: conn} do
+ insert(:config,
+ key: ":emoji",
+ value: [groups: [a: 1, b: 2], key: [a: 1]]
+ )
+
+ insert(:config,
+ key: ":assets",
+ value: [mascots: [a: 1, b: 2], key: [a: 1]]
+ )
+
+ %{"configs" => configs} =
+ conn
+ |> get("/api/pleroma/admin/config")
+ |> json_response_and_validate_schema(200)
+
+ vals =
+ Enum.filter(configs, fn %{"group" => group, "key" => key} ->
+ group == ":pleroma" and key in [":emoji", ":assets"]
+ end)
+
+ emoji = Enum.find(vals, fn %{"key" => key} -> key == ":emoji" end)
+ assets = Enum.find(vals, fn %{"key" => key} -> key == ":assets" end)
+
+ emoji_val = ConfigDB.to_elixir_types(emoji["value"])
+ assets_val = ConfigDB.to_elixir_types(assets["value"])
+
+ assert emoji_val[:groups] == [a: 1, b: 2]
+ assert assets_val[:mascots] == [a: 1, b: 2]
+ end
+ end
+
+ test "POST /api/pleroma/admin/config error", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{"configs" => []})
+
+ assert json_response_and_validate_schema(conn, 400) ==
+ %{"error" => "To use this endpoint you need to enable configuration from database."}
+ end
+
+ describe "POST /api/pleroma/admin/config" do
+ setup do
+ http = Application.get_env(:pleroma, :http)
+
+ on_exit(fn ->
+ Application.delete_env(:pleroma, :key1)
+ Application.delete_env(:pleroma, :key2)
+ Application.delete_env(:pleroma, :key3)
+ Application.delete_env(:pleroma, :key4)
+ Application.delete_env(:pleroma, :keyaa1)
+ Application.delete_env(:pleroma, :keyaa2)
+ Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
+ Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
+ Application.put_env(:pleroma, :http, http)
+ Application.put_env(:tesla, :adapter, Tesla.Mock)
+ Restarter.Pleroma.refresh()
+ end)
+ end
+
+ setup do: clear_config(:configurable_from_database, true)
+
+ @tag capture_log: true
+ test "create new config setting in db", %{conn: conn} do
+ ueberauth = Application.get_env(:ueberauth, Ueberauth)
+ on_exit(fn -> Application.put_env(:ueberauth, Ueberauth, ueberauth) end)
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{group: ":pleroma", key: ":key1", value: "value1"},
+ %{
+ group: ":ueberauth",
+ key: "Ueberauth",
+ value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
+ },
+ %{
+ group: ":pleroma",
+ key: ":key2",
+ value: %{
+ ":nested_1" => "nested_value1",
+ ":nested_2" => [
+ %{":nested_22" => "nested_value222"},
+ %{":nested_33" => %{":nested_44" => "nested_444"}}
+ ]
+ }
+ },
+ %{
+ group: ":pleroma",
+ key: ":key3",
+ value: [
+ %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
+ %{"nested_4" => true}
+ ]
+ },
+ %{
+ group: ":pleroma",
+ key: ":key4",
+ value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
+ },
+ %{
+ group: ":idna",
+ key: ":key5",
+ value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => "value1",
+ "db" => [":key1"]
+ },
+ %{
+ "group" => ":ueberauth",
+ "key" => "Ueberauth",
+ "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}],
+ "db" => [":consumer_secret"]
+ },
+ %{
+ "group" => ":pleroma",
+ "key" => ":key2",
+ "value" => %{
+ ":nested_1" => "nested_value1",
+ ":nested_2" => [
+ %{":nested_22" => "nested_value222"},
+ %{":nested_33" => %{":nested_44" => "nested_444"}}
+ ]
+ },
+ "db" => [":key2"]
+ },
+ %{
+ "group" => ":pleroma",
+ "key" => ":key3",
+ "value" => [
+ %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
+ %{"nested_4" => true}
+ ],
+ "db" => [":key3"]
+ },
+ %{
+ "group" => ":pleroma",
+ "key" => ":key4",
+ "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"},
+ "db" => [":key4"]
+ },
+ %{
+ "group" => ":idna",
+ "key" => ":key5",
+ "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]},
+ "db" => [":key5"]
+ }
+ ],
+ "need_reboot" => false
+ }
+
+ assert Application.get_env(:pleroma, :key1) == "value1"
+
+ assert Application.get_env(:pleroma, :key2) == %{
+ nested_1: "nested_value1",
+ nested_2: [
+ %{nested_22: "nested_value222"},
+ %{nested_33: %{nested_44: "nested_444"}}
+ ]
+ }
+
+ assert Application.get_env(:pleroma, :key3) == [
+ %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
+ %{"nested_4" => true}
+ ]
+
+ assert Application.get_env(:pleroma, :key4) == %{
+ "endpoint" => "https://example.com",
+ nested_5: :upload
+ }
+
+ assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
+ end
+
+ test "save configs setting without explicit key", %{conn: conn} do
+ level = Application.get_env(:quack, :level)
+ meta = Application.get_env(:quack, :meta)
+ webhook_url = Application.get_env(:quack, :webhook_url)
+
+ on_exit(fn ->
+ Application.put_env(:quack, :level, level)
+ Application.put_env(:quack, :meta, meta)
+ Application.put_env(:quack, :webhook_url, webhook_url)
+ end)
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":quack",
+ key: ":level",
+ value: ":info"
+ },
+ %{
+ group: ":quack",
+ key: ":meta",
+ value: [":none"]
+ },
+ %{
+ group: ":quack",
+ key: ":webhook_url",
+ value: "https://hooks.slack.com/services/KEY"
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":quack",
+ "key" => ":level",
+ "value" => ":info",
+ "db" => [":level"]
+ },
+ %{
+ "group" => ":quack",
+ "key" => ":meta",
+ "value" => [":none"],
+ "db" => [":meta"]
+ },
+ %{
+ "group" => ":quack",
+ "key" => ":webhook_url",
+ "value" => "https://hooks.slack.com/services/KEY",
+ "db" => [":webhook_url"]
+ }
+ ],
+ "need_reboot" => false
+ }
+
+ assert Application.get_env(:quack, :level) == :info
+ assert Application.get_env(:quack, :meta) == [:none]
+ assert Application.get_env(:quack, :webhook_url) == "https://hooks.slack.com/services/KEY"
+ end
+
+ test "saving config with partial update", %{conn: conn} do
+ insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2))
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => [
+ %{"tuple" => [":key1", 1]},
+ %{"tuple" => [":key2", 2]},
+ %{"tuple" => [":key3", 3]}
+ ],
+ "db" => [":key1", ":key2", ":key3"]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "saving config which need pleroma reboot", %{conn: conn} do
+ chat = Config.get(:chat)
+ on_exit(fn -> Config.put(:chat, chat) end)
+
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post(
+ "/api/pleroma/admin/config",
+ %{
+ configs: [
+ %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]}
+ ]
+ }
+ )
+ |> json_response_and_validate_schema(200) == %{
+ "configs" => [
+ %{
+ "db" => [":enabled"],
+ "group" => ":pleroma",
+ "key" => ":chat",
+ "value" => [%{"tuple" => [":enabled", true]}]
+ }
+ ],
+ "need_reboot" => true
+ }
+
+ configs =
+ conn
+ |> get("/api/pleroma/admin/config")
+ |> json_response_and_validate_schema(200)
+
+ assert configs["need_reboot"]
+
+ capture_log(fn ->
+ assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) ==
+ %{}
+ end) =~ "pleroma restarted"
+
+ configs =
+ conn
+ |> get("/api/pleroma/admin/config")
+ |> json_response_and_validate_schema(200)
+
+ assert configs["need_reboot"] == false
+ end
+
+ test "update setting which need reboot, don't change reboot flag until reboot", %{conn: conn} do
+ chat = Config.get(:chat)
+ on_exit(fn -> Config.put(:chat, chat) end)
+
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post(
+ "/api/pleroma/admin/config",
+ %{
+ configs: [
+ %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]}
+ ]
+ }
+ )
+ |> json_response_and_validate_schema(200) == %{
+ "configs" => [
+ %{
+ "db" => [":enabled"],
+ "group" => ":pleroma",
+ "key" => ":chat",
+ "value" => [%{"tuple" => [":enabled", true]}]
+ }
+ ],
+ "need_reboot" => true
+ }
+
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
+ ]
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => [
+ %{"tuple" => [":key3", 3]}
+ ],
+ "db" => [":key3"]
+ }
+ ],
+ "need_reboot" => true
+ }
+
+ capture_log(fn ->
+ assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) ==
+ %{}
+ end) =~ "pleroma restarted"
+
+ configs =
+ conn
+ |> get("/api/pleroma/admin/config")
+ |> json_response_and_validate_schema(200)
+
+ assert configs["need_reboot"] == false
+ end
+
+ test "saving config with nested merge", %{conn: conn} do
+ insert(:config, key: :key1, value: [key1: 1, key2: [k1: 1, k2: 2]])
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":pleroma",
+ key: ":key1",
+ value: [
+ %{"tuple" => [":key3", 3]},
+ %{
+ "tuple" => [
+ ":key2",
+ [
+ %{"tuple" => [":k2", 1]},
+ %{"tuple" => [":k3", 3]}
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => [
+ %{"tuple" => [":key1", 1]},
+ %{"tuple" => [":key3", 3]},
+ %{
+ "tuple" => [
+ ":key2",
+ [
+ %{"tuple" => [":k1", 1]},
+ %{"tuple" => [":k2", 1]},
+ %{"tuple" => [":k3", 3]}
+ ]
+ ]
+ }
+ ],
+ "db" => [":key1", ":key3", ":key2"]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "saving special atoms", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => [
+ %{
+ "tuple" => [
+ ":ssl_options",
+ [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
+ ]
+ }
+ ]
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => [
+ %{
+ "tuple" => [
+ ":ssl_options",
+ [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}]
+ ]
+ }
+ ],
+ "db" => [":ssl_options"]
+ }
+ ],
+ "need_reboot" => false
+ }
+
+ assert Application.get_env(:pleroma, :key1) == [
+ ssl_options: [versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]]
+ ]
+ end
+
+ test "saving full setting if value is in full_key_update list", %{conn: conn} do
+ backends = Application.get_env(:logger, :backends)
+ on_exit(fn -> Application.put_env(:logger, :backends, backends) end)
+
+ insert(:config,
+ group: :logger,
+ key: :backends,
+ value: []
+ )
+
+ Pleroma.Config.TransferTask.load_and_update_env([], false)
+
+ assert Application.get_env(:logger, :backends) == []
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":logger",
+ key: ":backends",
+ value: [":console"]
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":logger",
+ "key" => ":backends",
+ "value" => [
+ ":console"
+ ],
+ "db" => [":backends"]
+ }
+ ],
+ "need_reboot" => false
+ }
+
+ assert Application.get_env(:logger, :backends) == [
+ :console
+ ]
+ end
+
+ test "saving full setting if value is not keyword", %{conn: conn} do
+ insert(:config,
+ group: :tesla,
+ key: :adapter,
+ value: Tesla.Adapter.Hackey
+ )
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{group: ":tesla", key: ":adapter", value: "Tesla.Adapter.Httpc"}
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":tesla",
+ "key" => ":adapter",
+ "value" => "Tesla.Adapter.Httpc",
+ "db" => [":adapter"]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "update config setting & delete with fallback to default value", %{
+ conn: conn,
+ admin: admin,
+ token: token
+ } do
+ ueberauth = Application.get_env(:ueberauth, Ueberauth)
+ insert(:config, key: :keyaa1)
+ insert(:config, key: :keyaa2)
+
+ config3 =
+ insert(:config,
+ group: :ueberauth,
+ key: Ueberauth
+ )
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{group: ":pleroma", key: ":keyaa1", value: "another_value"},
+ %{group: ":pleroma", key: ":keyaa2", value: "another_value"}
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":keyaa1",
+ "value" => "another_value",
+ "db" => [":keyaa1"]
+ },
+ %{
+ "group" => ":pleroma",
+ "key" => ":keyaa2",
+ "value" => "another_value",
+ "db" => [":keyaa2"]
+ }
+ ],
+ "need_reboot" => false
+ }
+
+ assert Application.get_env(:pleroma, :keyaa1) == "another_value"
+ assert Application.get_env(:pleroma, :keyaa2) == "another_value"
+ assert Application.get_env(:ueberauth, Ueberauth) == config3.value
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{group: ":pleroma", key: ":keyaa2", delete: true},
+ %{
+ group: ":ueberauth",
+ key: "Ueberauth",
+ delete: true
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [],
+ "need_reboot" => false
+ }
+
+ assert Application.get_env(:ueberauth, Ueberauth) == ueberauth
+ refute Keyword.has_key?(Application.get_all_env(:pleroma), :keyaa2)
+ end
+
+ test "common config example", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ "group" => ":pleroma",
+ "key" => "Pleroma.Captcha.NotReal",
+ "value" => [
+ %{"tuple" => [":enabled", false]},
+ %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
+ %{"tuple" => [":seconds_valid", 60]},
+ %{"tuple" => [":path", ""]},
+ %{"tuple" => [":key1", nil]},
+ %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
+ %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
+ %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
+ %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
+ %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},
+ %{"tuple" => [":name", "Pleroma"]}
+ ]
+ }
+ ]
+ })
+
+ assert Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => "Pleroma.Captcha.NotReal",
+ "value" => [
+ %{"tuple" => [":enabled", false]},
+ %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
+ %{"tuple" => [":seconds_valid", 60]},
+ %{"tuple" => [":path", ""]},
+ %{"tuple" => [":key1", nil]},
+ %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
+ %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
+ %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
+ %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
+ %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]},
+ %{"tuple" => [":name", "Pleroma"]}
+ ],
+ "db" => [
+ ":enabled",
+ ":method",
+ ":seconds_valid",
+ ":path",
+ ":key1",
+ ":partial_chain",
+ ":regex1",
+ ":regex2",
+ ":regex3",
+ ":regex4",
+ ":name"
+ ]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "tuples with more than two values", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ "group" => ":pleroma",
+ "key" => "Pleroma.Web.Endpoint.NotReal",
+ "value" => [
+ %{
+ "tuple" => [
+ ":http",
+ [
+ %{
+ "tuple" => [
+ ":key2",
+ [
+ %{
+ "tuple" => [
+ ":_",
+ [
+ %{
+ "tuple" => [
+ "/api/v1/streaming",
+ "Pleroma.Web.MastodonAPI.WebsocketHandler",
+ []
+ ]
+ },
+ %{
+ "tuple" => [
+ "/websocket",
+ "Phoenix.Endpoint.CowboyWebSocket",
+ %{
+ "tuple" => [
+ "Phoenix.Transports.WebSocket",
+ %{
+ "tuple" => [
+ "Pleroma.Web.Endpoint",
+ "Pleroma.Web.UserSocket",
+ []
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ %{
+ "tuple" => [
+ ":_",
+ "Phoenix.Endpoint.Cowboy2Handler",
+ %{"tuple" => ["Pleroma.Web.Endpoint", []]}
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => "Pleroma.Web.Endpoint.NotReal",
+ "value" => [
+ %{
+ "tuple" => [
+ ":http",
+ [
+ %{
+ "tuple" => [
+ ":key2",
+ [
+ %{
+ "tuple" => [
+ ":_",
+ [
+ %{
+ "tuple" => [
+ "/api/v1/streaming",
+ "Pleroma.Web.MastodonAPI.WebsocketHandler",
+ []
+ ]
+ },
+ %{
+ "tuple" => [
+ "/websocket",
+ "Phoenix.Endpoint.CowboyWebSocket",
+ %{
+ "tuple" => [
+ "Phoenix.Transports.WebSocket",
+ %{
+ "tuple" => [
+ "Pleroma.Web.Endpoint",
+ "Pleroma.Web.UserSocket",
+ []
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ %{
+ "tuple" => [
+ ":_",
+ "Phoenix.Endpoint.Cowboy2Handler",
+ %{"tuple" => ["Pleroma.Web.Endpoint", []]}
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ "db" => [":http"]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "settings with nesting map", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => [
+ %{"tuple" => [":key2", "some_val"]},
+ %{
+ "tuple" => [
+ ":key3",
+ %{
+ ":max_options" => 20,
+ ":max_option_chars" => 200,
+ ":min_expiration" => 0,
+ ":max_expiration" => 31_536_000,
+ "nested" => %{
+ ":max_options" => 20,
+ ":max_option_chars" => 200,
+ ":min_expiration" => 0,
+ ":max_expiration" => 31_536_000
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) ==
+ %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => [
+ %{"tuple" => [":key2", "some_val"]},
+ %{
+ "tuple" => [
+ ":key3",
+ %{
+ ":max_expiration" => 31_536_000,
+ ":max_option_chars" => 200,
+ ":max_options" => 20,
+ ":min_expiration" => 0,
+ "nested" => %{
+ ":max_expiration" => 31_536_000,
+ ":max_option_chars" => 200,
+ ":max_options" => 20,
+ ":min_expiration" => 0
+ }
+ }
+ ]
+ }
+ ],
+ "db" => [":key2", ":key3"]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "value as map", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => %{"key" => "some_val"}
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) ==
+ %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":key1",
+ "value" => %{"key" => "some_val"},
+ "db" => [":key1"]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "queues key as atom", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ "group" => ":oban",
+ "key" => ":queues",
+ "value" => [
+ %{"tuple" => [":federator_incoming", 50]},
+ %{"tuple" => [":federator_outgoing", 50]},
+ %{"tuple" => [":web_push", 50]},
+ %{"tuple" => [":mailer", 10]},
+ %{"tuple" => [":transmogrifier", 20]},
+ %{"tuple" => [":scheduled_activities", 10]},
+ %{"tuple" => [":background", 5]}
+ ]
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":oban",
+ "key" => ":queues",
+ "value" => [
+ %{"tuple" => [":federator_incoming", 50]},
+ %{"tuple" => [":federator_outgoing", 50]},
+ %{"tuple" => [":web_push", 50]},
+ %{"tuple" => [":mailer", 10]},
+ %{"tuple" => [":transmogrifier", 20]},
+ %{"tuple" => [":scheduled_activities", 10]},
+ %{"tuple" => [":background", 5]}
+ ],
+ "db" => [
+ ":federator_incoming",
+ ":federator_outgoing",
+ ":web_push",
+ ":mailer",
+ ":transmogrifier",
+ ":scheduled_activities",
+ ":background"
+ ]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "delete part of settings by atom subkeys", %{conn: conn} do
+ insert(:config,
+ key: :keyaa1,
+ value: [subkey1: "val1", subkey2: "val2", subkey3: "val3"]
+ )
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":pleroma",
+ key: ":keyaa1",
+ subkeys: [":subkey1", ":subkey3"],
+ delete: true
+ }
+ ]
+ })
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":keyaa1",
+ "value" => [%{"tuple" => [":subkey2", "val2"]}],
+ "db" => [":subkey2"]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
+
+ test "proxy tuple localhost", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":pleroma",
+ key: ":http",
+ value: [
+ %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]}
+ ]
+ }
+ ]
+ })
+
+ assert %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":http",
+ "value" => value,
+ "db" => db
+ }
+ ]
+ } = json_response_and_validate_schema(conn, 200)
+
+ assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]} in value
+ assert ":proxy_url" in db
+ end
+
+ test "proxy tuple domain", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":pleroma",
+ key: ":http",
+ value: [
+ %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]}
+ ]
+ }
+ ]
+ })
+
+ assert %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":http",
+ "value" => value,
+ "db" => db
+ }
+ ]
+ } = json_response_and_validate_schema(conn, 200)
+
+ assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]} in value
+ assert ":proxy_url" in db
+ end
+
+ test "proxy tuple ip", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":pleroma",
+ key: ":http",
+ value: [
+ %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]}
+ ]
+ }
+ ]
+ })
+
+ assert %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => ":http",
+ "value" => value,
+ "db" => db
+ }
+ ]
+ } = json_response_and_validate_schema(conn, 200)
+
+ assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]} in value
+ assert ":proxy_url" in db
+ end
+
+ @tag capture_log: true
+ test "doesn't set keys not in the whitelist", %{conn: conn} do
+ clear_config(:database_config_whitelist, [
+ {:pleroma, :key1},
+ {:pleroma, :key2},
+ {:pleroma, Pleroma.Captcha.NotReal},
+ {:not_real}
+ ])
+
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{group: ":pleroma", key: ":key1", value: "value1"},
+ %{group: ":pleroma", key: ":key2", value: "value2"},
+ %{group: ":pleroma", key: ":key3", value: "value3"},
+ %{group: ":pleroma", key: "Pleroma.Web.Endpoint.NotReal", value: "value4"},
+ %{group: ":pleroma", key: "Pleroma.Captcha.NotReal", value: "value5"},
+ %{group: ":not_real", key: ":anything", value: "value6"}
+ ]
+ })
+
+ assert Application.get_env(:pleroma, :key1) == "value1"
+ assert Application.get_env(:pleroma, :key2) == "value2"
+ assert Application.get_env(:pleroma, :key3) == nil
+ assert Application.get_env(:pleroma, Pleroma.Web.Endpoint.NotReal) == nil
+ assert Application.get_env(:pleroma, Pleroma.Captcha.NotReal) == "value5"
+ assert Application.get_env(:not_real, :anything) == "value6"
+ end
+
+ test "args for Pleroma.Upload.Filter.Mogrify with custom tuples", %{conn: conn} do
+ clear_config(Pleroma.Upload.Filter.Mogrify)
+
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":pleroma",
+ key: "Pleroma.Upload.Filter.Mogrify",
+ value: [
+ %{"tuple" => [":args", ["auto-orient", "strip"]]}
+ ]
+ }
+ ]
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => "Pleroma.Upload.Filter.Mogrify",
+ "value" => [
+ %{"tuple" => [":args", ["auto-orient", "strip"]]}
+ ],
+ "db" => [":args"]
+ }
+ ],
+ "need_reboot" => false
+ }
+
+ assert Config.get(Pleroma.Upload.Filter.Mogrify) == [args: ["auto-orient", "strip"]]
+
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{
+ configs: [
+ %{
+ group: ":pleroma",
+ key: "Pleroma.Upload.Filter.Mogrify",
+ value: [
+ %{
+ "tuple" => [
+ ":args",
+ [
+ "auto-orient",
+ "strip",
+ "{\"implode\", \"1\"}",
+ "{\"resize\", \"3840x1080>\"}"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ })
+ |> json_response(200) == %{
+ "configs" => [
+ %{
+ "group" => ":pleroma",
+ "key" => "Pleroma.Upload.Filter.Mogrify",
+ "value" => [
+ %{
+ "tuple" => [
+ ":args",
+ [
+ "auto-orient",
+ "strip",
+ "{\"implode\", \"1\"}",
+ "{\"resize\", \"3840x1080>\"}"
+ ]
+ ]
+ }
+ ],
+ "db" => [":args"]
+ }
+ ],
+ "need_reboot" => false
+ }
+
+ assert Config.get(Pleroma.Upload.Filter.Mogrify) == [
+ args: ["auto-orient", "strip", {"implode", "1"}, {"resize", "3840x1080>"}]
+ ]
+ end
+ end
+
+ describe "GET /api/pleroma/admin/config/descriptions" do
+ test "structure", %{conn: conn} do
+ admin = insert(:user, is_admin: true)
+
+ conn =
+ assign(conn, :user, admin)
+ |> get("/api/pleroma/admin/config/descriptions")
+
+ assert [child | _others] = json_response_and_validate_schema(conn, 200)
+
+ assert child["children"]
+ assert child["key"]
+ assert String.starts_with?(child["group"], ":")
+ assert child["description"]
+ end
+
+ test "filters by database configuration whitelist", %{conn: conn} do
+ clear_config(:database_config_whitelist, [
+ {:pleroma, :instance},
+ {:pleroma, :activitypub},
+ {:pleroma, Pleroma.Upload},
+ {:esshd}
+ ])
+
+ admin = insert(:user, is_admin: true)
+
+ conn =
+ assign(conn, :user, admin)
+ |> get("/api/pleroma/admin/config/descriptions")
+
+ children = json_response_and_validate_schema(conn, 200)
+
+ assert length(children) == 4
+
+ assert Enum.count(children, fn c -> c["group"] == ":pleroma" end) == 3
+
+ instance = Enum.find(children, fn c -> c["key"] == ":instance" end)
+ assert instance["children"]
+
+ activitypub = Enum.find(children, fn c -> c["key"] == ":activitypub" end)
+ assert activitypub["children"]
+
+ web_endpoint = Enum.find(children, fn c -> c["key"] == "Pleroma.Upload" end)
+ assert web_endpoint["children"]
+
+ esshd = Enum.find(children, fn c -> c["group"] == ":esshd" end)
+ assert esshd["children"]
+ end
+ end
+end
diff --git a/test/web/admin_api/controllers/invite_controller_test.exs b/test/web/admin_api/controllers/invite_controller_test.exs
new file mode 100644
index 000000000..ab186c5e7
--- /dev/null
+++ b/test/web/admin_api/controllers/invite_controller_test.exs
@@ -0,0 +1,281 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.InviteControllerTest do
+ use Pleroma.Web.ConnCase, async: true
+
+ import Pleroma.Factory
+
+ alias Pleroma.Config
+ alias Pleroma.Repo
+ alias Pleroma.UserInviteToken
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "POST /api/pleroma/admin/users/email_invite, with valid config" do
+ setup do: clear_config([:instance, :registrations_open], false)
+ setup do: clear_config([:instance, :invites_enabled], true)
+
+ test "sends invitation and returns 204", %{admin: admin, conn: conn} do
+ recipient_email = "foo@bar.com"
+ recipient_name = "J. D."
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json;charset=utf-8")
+ |> post("/api/pleroma/admin/users/email_invite", %{
+ email: recipient_email,
+ name: recipient_name
+ })
+
+ assert json_response_and_validate_schema(conn, :no_content)
+
+ token_record = List.last(Repo.all(Pleroma.UserInviteToken))
+ assert token_record
+ refute token_record.used
+
+ notify_email = Config.get([:instance, :notify_email])
+ instance_name = Config.get([:instance, :name])
+
+ email =
+ Pleroma.Emails.UserEmail.user_invitation_email(
+ admin,
+ token_record,
+ recipient_email,
+ recipient_name
+ )
+
+ Swoosh.TestAssertions.assert_email_sent(
+ from: {instance_name, notify_email},
+ to: {recipient_name, recipient_email},
+ html_body: email.html_body
+ )
+ end
+
+ test "it returns 403 if requested by a non-admin" do
+ non_admin_user = insert(:user)
+ token = insert(:oauth_token, user: non_admin_user)
+
+ conn =
+ build_conn()
+ |> assign(:user, non_admin_user)
+ |> assign(:token, token)
+ |> put_req_header("content-type", "application/json;charset=utf-8")
+ |> post("/api/pleroma/admin/users/email_invite", %{
+ email: "foo@bar.com",
+ name: "JD"
+ })
+
+ assert json_response(conn, :forbidden)
+ end
+
+ test "email with +", %{conn: conn, admin: admin} do
+ recipient_email = "foo+bar@baz.com"
+
+ conn
+ |> put_req_header("content-type", "application/json;charset=utf-8")
+ |> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email})
+ |> json_response_and_validate_schema(:no_content)
+
+ token_record =
+ Pleroma.UserInviteToken
+ |> Repo.all()
+ |> List.last()
+
+ assert token_record
+ refute token_record.used
+
+ notify_email = Config.get([:instance, :notify_email])
+ instance_name = Config.get([:instance, :name])
+
+ email =
+ Pleroma.Emails.UserEmail.user_invitation_email(
+ admin,
+ token_record,
+ recipient_email
+ )
+
+ Swoosh.TestAssertions.assert_email_sent(
+ from: {instance_name, notify_email},
+ to: recipient_email,
+ html_body: email.html_body
+ )
+ end
+ end
+
+ describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
+ setup do: clear_config([:instance, :registrations_open])
+ setup do: clear_config([:instance, :invites_enabled])
+
+ test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do
+ Config.put([:instance, :registrations_open], false)
+ Config.put([:instance, :invites_enabled], false)
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/users/email_invite", %{
+ email: "foo@bar.com",
+ name: "JD"
+ })
+
+ assert json_response_and_validate_schema(conn, :bad_request) ==
+ %{
+ "error" =>
+ "To send invites you need to set the `invites_enabled` option to true."
+ }
+ end
+
+ test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do
+ Config.put([:instance, :registrations_open], true)
+ Config.put([:instance, :invites_enabled], true)
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/users/email_invite", %{
+ email: "foo@bar.com",
+ name: "JD"
+ })
+
+ assert json_response_and_validate_schema(conn, :bad_request) ==
+ %{
+ "error" =>
+ "To send invites you need to set the `registrations_open` option to false."
+ }
+ end
+ end
+
+ describe "POST /api/pleroma/admin/users/invite_token" do
+ test "without options", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/users/invite_token")
+
+ invite_json = json_response_and_validate_schema(conn, 200)
+ invite = UserInviteToken.find_by_token!(invite_json["token"])
+ refute invite.used
+ refute invite.expires_at
+ refute invite.max_use
+ assert invite.invite_type == "one_time"
+ end
+
+ test "with expires_at", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/users/invite_token", %{
+ "expires_at" => Date.to_string(Date.utc_today())
+ })
+
+ invite_json = json_response_and_validate_schema(conn, 200)
+ invite = UserInviteToken.find_by_token!(invite_json["token"])
+
+ refute invite.used
+ assert invite.expires_at == Date.utc_today()
+ refute invite.max_use
+ assert invite.invite_type == "date_limited"
+ end
+
+ test "with max_use", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
+
+ invite_json = json_response_and_validate_schema(conn, 200)
+ invite = UserInviteToken.find_by_token!(invite_json["token"])
+ refute invite.used
+ refute invite.expires_at
+ assert invite.max_use == 150
+ assert invite.invite_type == "reusable"
+ end
+
+ test "with max use and expires_at", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/users/invite_token", %{
+ "max_use" => 150,
+ "expires_at" => Date.to_string(Date.utc_today())
+ })
+
+ invite_json = json_response_and_validate_schema(conn, 200)
+ invite = UserInviteToken.find_by_token!(invite_json["token"])
+ refute invite.used
+ assert invite.expires_at == Date.utc_today()
+ assert invite.max_use == 150
+ assert invite.invite_type == "reusable_date_limited"
+ end
+ end
+
+ describe "GET /api/pleroma/admin/users/invites" do
+ test "no invites", %{conn: conn} do
+ conn = get(conn, "/api/pleroma/admin/users/invites")
+
+ assert json_response_and_validate_schema(conn, 200) == %{"invites" => []}
+ end
+
+ test "with invite", %{conn: conn} do
+ {:ok, invite} = UserInviteToken.create_invite()
+
+ conn = get(conn, "/api/pleroma/admin/users/invites")
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "invites" => [
+ %{
+ "expires_at" => nil,
+ "id" => invite.id,
+ "invite_type" => "one_time",
+ "max_use" => nil,
+ "token" => invite.token,
+ "used" => false,
+ "uses" => 0
+ }
+ ]
+ }
+ end
+ end
+
+ describe "POST /api/pleroma/admin/users/revoke_invite" do
+ test "with token", %{conn: conn} do
+ {:ok, invite} = UserInviteToken.create_invite()
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
+
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "expires_at" => nil,
+ "id" => invite.id,
+ "invite_type" => "one_time",
+ "max_use" => nil,
+ "token" => invite.token,
+ "used" => true,
+ "uses" => 0
+ }
+ end
+
+ test "with invalid token", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
+
+ assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
+ end
+ end
+end
diff --git a/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs b/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs
new file mode 100644
index 000000000..5ab6cb78a
--- /dev/null
+++ b/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs
@@ -0,0 +1,145 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.MediaProxyCacheControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+ import Mock
+
+ alias Pleroma.Web.MediaProxy
+
+ setup do: clear_config([:media_proxy])
+
+ setup do
+ on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
+ end
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ Config.put([:media_proxy, :enabled], true)
+ Config.put([:media_proxy, :invalidation, :enabled], true)
+ Config.put([:media_proxy, :invalidation, :provider], MediaProxy.Invalidation.Script)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "GET /api/pleroma/admin/media_proxy_caches" do
+ test "shows banned MediaProxy URLs", %{conn: conn} do
+ MediaProxy.put_in_banned_urls([
+ "http://localhost:4001/media/a688346.jpg",
+ "http://localhost:4001/media/fb1f4d.jpg"
+ ])
+
+ MediaProxy.put_in_banned_urls("http://localhost:4001/media/gb1f44.jpg")
+ MediaProxy.put_in_banned_urls("http://localhost:4001/media/tb13f47.jpg")
+ MediaProxy.put_in_banned_urls("http://localhost:4001/media/wb1f46.jpg")
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/media_proxy_caches?page_size=2")
+ |> json_response_and_validate_schema(200)
+
+ assert response["urls"] == [
+ "http://localhost:4001/media/fb1f4d.jpg",
+ "http://localhost:4001/media/a688346.jpg"
+ ]
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=2")
+ |> json_response_and_validate_schema(200)
+
+ assert response["urls"] == [
+ "http://localhost:4001/media/gb1f44.jpg",
+ "http://localhost:4001/media/tb13f47.jpg"
+ ]
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=3")
+ |> json_response_and_validate_schema(200)
+
+ assert response["urls"] == ["http://localhost:4001/media/wb1f46.jpg"]
+ end
+ end
+
+ describe "POST /api/pleroma/admin/media_proxy_caches/delete" do
+ test "deleted MediaProxy URLs from banned", %{conn: conn} do
+ MediaProxy.put_in_banned_urls([
+ "http://localhost:4001/media/a688346.jpg",
+ "http://localhost:4001/media/fb1f4d.jpg"
+ ])
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/media_proxy_caches/delete", %{
+ urls: ["http://localhost:4001/media/a688346.jpg"]
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert response["urls"] == ["http://localhost:4001/media/a688346.jpg"]
+ refute MediaProxy.in_banned_urls("http://localhost:4001/media/a688346.jpg")
+ assert MediaProxy.in_banned_urls("http://localhost:4001/media/fb1f4d.jpg")
+ end
+ end
+
+ describe "POST /api/pleroma/admin/media_proxy_caches/purge" do
+ test "perform invalidates cache of MediaProxy", %{conn: conn} do
+ urls = [
+ "http://example.com/media/a688346.jpg",
+ "http://example.com/media/fb1f4d.jpg"
+ ]
+
+ with_mocks [
+ {MediaProxy.Invalidation.Script, [],
+ [
+ purge: fn _, _ -> {"ok", 0} end
+ ]}
+ ] do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/media_proxy_caches/purge", %{urls: urls, ban: false})
+ |> json_response_and_validate_schema(200)
+
+ assert response["urls"] == urls
+
+ refute MediaProxy.in_banned_urls("http://example.com/media/a688346.jpg")
+ refute MediaProxy.in_banned_urls("http://example.com/media/fb1f4d.jpg")
+ end
+ end
+
+ test "perform invalidates cache of MediaProxy and adds url to banned", %{conn: conn} do
+ urls = [
+ "http://example.com/media/a688346.jpg",
+ "http://example.com/media/fb1f4d.jpg"
+ ]
+
+ with_mocks [{MediaProxy.Invalidation.Script, [], [purge: fn _, _ -> {"ok", 0} end]}] do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/media_proxy_caches/purge", %{
+ urls: urls,
+ ban: true
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert response["urls"] == urls
+
+ assert MediaProxy.in_banned_urls("http://example.com/media/a688346.jpg")
+ assert MediaProxy.in_banned_urls("http://example.com/media/fb1f4d.jpg")
+ end
+ end
+ end
+end
diff --git a/test/web/admin_api/controllers/oauth_app_controller_test.exs b/test/web/admin_api/controllers/oauth_app_controller_test.exs
new file mode 100644
index 000000000..ed7c4172c
--- /dev/null
+++ b/test/web/admin_api/controllers/oauth_app_controller_test.exs
@@ -0,0 +1,220 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.OAuthAppControllerTest do
+ use Pleroma.Web.ConnCase, async: true
+ use Oban.Testing, repo: Pleroma.Repo
+
+ import Pleroma.Factory
+
+ alias Pleroma.Config
+ alias Pleroma.Web
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "POST /api/pleroma/admin/oauth_app" do
+ test "errors", %{conn: conn} do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/oauth_app", %{})
+ |> json_response_and_validate_schema(400)
+
+ assert %{
+ "error" => "Missing field: name. Missing field: redirect_uris."
+ } = response
+ end
+
+ test "success", %{conn: conn} do
+ base_url = Web.base_url()
+ app_name = "Trusted app"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/oauth_app", %{
+ name: app_name,
+ redirect_uris: base_url
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "name" => ^app_name,
+ "redirect_uri" => ^base_url,
+ "trusted" => false
+ } = response
+ end
+
+ test "with trusted", %{conn: conn} do
+ base_url = Web.base_url()
+ app_name = "Trusted app"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/oauth_app", %{
+ name: app_name,
+ redirect_uris: base_url,
+ trusted: true
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "name" => ^app_name,
+ "redirect_uri" => ^base_url,
+ "trusted" => true
+ } = response
+ end
+ end
+
+ describe "GET /api/pleroma/admin/oauth_app" do
+ setup do
+ app = insert(:oauth_app)
+ {:ok, app: app}
+ end
+
+ test "list", %{conn: conn} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => apps, "count" => count, "page_size" => _} = response
+
+ assert length(apps) == count
+ end
+
+ test "with page size", %{conn: conn} do
+ insert(:oauth_app)
+ page_size = 1
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app?page_size=#{page_size}")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response
+
+ assert length(apps) == page_size
+ end
+
+ test "search by client name", %{conn: conn, app: app} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app?name=#{app.client_name}")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+
+ test "search by client id", %{conn: conn, app: app} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app?client_id=#{app.client_id}")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+
+ test "only trusted", %{conn: conn} do
+ app = insert(:oauth_app, trusted: true)
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app?trusted=true")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+ end
+
+ describe "DELETE /api/pleroma/admin/oauth_app/:id" do
+ test "with id", %{conn: conn} do
+ app = insert(:oauth_app)
+
+ response =
+ conn
+ |> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id))
+ |> json_response_and_validate_schema(:no_content)
+
+ assert response == ""
+ end
+
+ test "with non existance id", %{conn: conn} do
+ response =
+ conn
+ |> delete("/api/pleroma/admin/oauth_app/0")
+ |> json_response_and_validate_schema(:bad_request)
+
+ assert response == ""
+ end
+ end
+
+ describe "PATCH /api/pleroma/admin/oauth_app/:id" do
+ test "with id", %{conn: conn} do
+ app = insert(:oauth_app)
+
+ name = "another name"
+ url = "https://example.com"
+ scopes = ["admin"]
+ id = app.id
+ website = "http://website.com"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/oauth_app/#{id}", %{
+ name: name,
+ trusted: true,
+ redirect_uris: url,
+ scopes: scopes,
+ website: website
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "id" => ^id,
+ "name" => ^name,
+ "redirect_uri" => ^url,
+ "trusted" => true,
+ "website" => ^website
+ } = response
+ end
+
+ test "without id", %{conn: conn} do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/oauth_app/0")
+ |> json_response_and_validate_schema(:bad_request)
+
+ assert response == ""
+ end
+ end
+end
diff --git a/test/web/admin_api/controllers/relay_controller_test.exs b/test/web/admin_api/controllers/relay_controller_test.exs
new file mode 100644
index 000000000..64086adc5
--- /dev/null
+++ b/test/web/admin_api/controllers/relay_controller_test.exs
@@ -0,0 +1,92 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.RelayControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+
+ alias Pleroma.Config
+ alias Pleroma.ModerationLog
+ alias Pleroma.Repo
+ alias Pleroma.User
+
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+
+ :ok
+ end
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "relays" do
+ test "POST /relay", %{conn: conn, admin: admin} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/relay", %{
+ relay_url: "http://mastodon.example.org/users/admin"
+ })
+
+ assert json_response_and_validate_schema(conn, 200) ==
+ "http://mastodon.example.org/users/admin"
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
+ end
+
+ test "GET /relay", %{conn: conn} do
+ relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
+
+ ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
+ |> Enum.each(fn ap_id ->
+ {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
+ User.follow(relay_user, user)
+ end)
+
+ conn = get(conn, "/api/pleroma/admin/relay")
+
+ assert json_response_and_validate_schema(conn, 200)["relays"] --
+ ["mastodon.example.org", "mstdn.io"] == []
+ end
+
+ test "DELETE /relay", %{conn: conn, admin: admin} do
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/relay", %{
+ relay_url: "http://mastodon.example.org/users/admin"
+ })
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> delete("/api/pleroma/admin/relay", %{
+ relay_url: "http://mastodon.example.org/users/admin"
+ })
+
+ assert json_response_and_validate_schema(conn, 200) ==
+ "http://mastodon.example.org/users/admin"
+
+ [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry_one) ==
+ "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
+
+ assert ModerationLog.get_log_entry_message(log_entry_two) ==
+ "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
+ end
+ end
+end
diff --git a/test/web/admin_api/controllers/report_controller_test.exs b/test/web/admin_api/controllers/report_controller_test.exs
new file mode 100644
index 000000000..940bce340
--- /dev/null
+++ b/test/web/admin_api/controllers/report_controller_test.exs
@@ -0,0 +1,374 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+
+ alias Pleroma.Activity
+ alias Pleroma.Config
+ alias Pleroma.ModerationLog
+ alias Pleroma.Repo
+ alias Pleroma.ReportNote
+ alias Pleroma.Web.CommonAPI
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "GET /api/pleroma/admin/reports/:id" do
+ test "returns report by its id", %{conn: conn} do
+ [reporter, target_user] = insert_pair(:user)
+ activity = insert(:note_activity, user: target_user)
+
+ {:ok, %{id: report_id}} =
+ CommonAPI.report(reporter, %{
+ account_id: target_user.id,
+ comment: "I feel offended",
+ status_ids: [activity.id]
+ })
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/reports/#{report_id}")
+ |> json_response_and_validate_schema(:ok)
+
+ assert response["id"] == report_id
+ end
+
+ test "returns 404 when report id is invalid", %{conn: conn} do
+ conn = get(conn, "/api/pleroma/admin/reports/test")
+
+ assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
+ end
+ end
+
+ describe "PATCH /api/pleroma/admin/reports" do
+ setup do
+ [reporter, target_user] = insert_pair(:user)
+ activity = insert(:note_activity, user: target_user)
+
+ {:ok, %{id: report_id}} =
+ CommonAPI.report(reporter, %{
+ account_id: target_user.id,
+ comment: "I feel offended",
+ status_ids: [activity.id]
+ })
+
+ {:ok, %{id: second_report_id}} =
+ CommonAPI.report(reporter, %{
+ account_id: target_user.id,
+ comment: "I feel very offended",
+ status_ids: [activity.id]
+ })
+
+ %{
+ id: report_id,
+ second_report_id: second_report_id
+ }
+ end
+
+ test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} do
+ read_token = insert(:oauth_token, user: admin, scopes: ["admin:read"])
+ write_token = insert(:oauth_token, user: admin, scopes: ["admin:write:reports"])
+
+ response =
+ conn
+ |> assign(:token, read_token)
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [%{"state" => "resolved", "id" => id}]
+ })
+ |> json_response_and_validate_schema(403)
+
+ assert response == %{
+ "error" => "Insufficient permissions: admin:write:reports."
+ }
+
+ conn
+ |> assign(:token, write_token)
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [%{"state" => "resolved", "id" => id}]
+ })
+ |> json_response_and_validate_schema(:no_content)
+ end
+
+ test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "resolved", "id" => id}
+ ]
+ })
+ |> json_response_and_validate_schema(:no_content)
+
+ activity = Activity.get_by_id(id)
+ assert activity.data["state"] == "resolved"
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} updated report ##{id} with 'resolved' state"
+ end
+
+ test "closes report", %{conn: conn, id: id, admin: admin} do
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "closed", "id" => id}
+ ]
+ })
+ |> json_response_and_validate_schema(:no_content)
+
+ activity = Activity.get_by_id(id)
+ assert activity.data["state"] == "closed"
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} updated report ##{id} with 'closed' state"
+ end
+
+ test "returns 400 when state is unknown", %{conn: conn, id: id} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "test", "id" => id}
+ ]
+ })
+
+ assert "Unsupported state" =
+ hd(json_response_and_validate_schema(conn, :bad_request))["error"]
+ end
+
+ test "returns 404 when report is not exist", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "closed", "id" => "test"}
+ ]
+ })
+
+ assert hd(json_response_and_validate_schema(conn, :bad_request))["error"] == "not_found"
+ end
+
+ test "updates state of multiple reports", %{
+ conn: conn,
+ id: id,
+ admin: admin,
+ second_report_id: second_report_id
+ } do
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/reports", %{
+ "reports" => [
+ %{"state" => "resolved", "id" => id},
+ %{"state" => "closed", "id" => second_report_id}
+ ]
+ })
+ |> json_response_and_validate_schema(:no_content)
+
+ activity = Activity.get_by_id(id)
+ second_activity = Activity.get_by_id(second_report_id)
+ assert activity.data["state"] == "resolved"
+ assert second_activity.data["state"] == "closed"
+
+ [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(first_log_entry) ==
+ "@#{admin.nickname} updated report ##{id} with 'resolved' state"
+
+ assert ModerationLog.get_log_entry_message(second_log_entry) ==
+ "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
+ end
+ end
+
+ describe "GET /api/pleroma/admin/reports" do
+ test "returns empty response when no reports created", %{conn: conn} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/reports")
+ |> json_response_and_validate_schema(:ok)
+
+ assert Enum.empty?(response["reports"])
+ assert response["total"] == 0
+ end
+
+ test "returns reports", %{conn: conn} do
+ [reporter, target_user] = insert_pair(:user)
+ activity = insert(:note_activity, user: target_user)
+
+ {:ok, %{id: report_id}} =
+ CommonAPI.report(reporter, %{
+ account_id: target_user.id,
+ comment: "I feel offended",
+ status_ids: [activity.id]
+ })
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/reports")
+ |> json_response_and_validate_schema(:ok)
+
+ [report] = response["reports"]
+
+ assert length(response["reports"]) == 1
+ assert report["id"] == report_id
+
+ assert response["total"] == 1
+ end
+
+ test "returns reports with specified state", %{conn: conn} do
+ [reporter, target_user] = insert_pair(:user)
+ activity = insert(:note_activity, user: target_user)
+
+ {:ok, %{id: first_report_id}} =
+ CommonAPI.report(reporter, %{
+ account_id: target_user.id,
+ comment: "I feel offended",
+ status_ids: [activity.id]
+ })
+
+ {:ok, %{id: second_report_id}} =
+ CommonAPI.report(reporter, %{
+ account_id: target_user.id,
+ comment: "I don't like this user"
+ })
+
+ CommonAPI.update_report_state(second_report_id, "closed")
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/reports?state=open")
+ |> json_response_and_validate_schema(:ok)
+
+ assert [open_report] = response["reports"]
+
+ assert length(response["reports"]) == 1
+ assert open_report["id"] == first_report_id
+
+ assert response["total"] == 1
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/reports?state=closed")
+ |> json_response_and_validate_schema(:ok)
+
+ assert [closed_report] = response["reports"]
+
+ assert length(response["reports"]) == 1
+ assert closed_report["id"] == second_report_id
+
+ assert response["total"] == 1
+
+ assert %{"total" => 0, "reports" => []} ==
+ conn
+ |> get("/api/pleroma/admin/reports?state=resolved", %{
+ "" => ""
+ })
+ |> json_response_and_validate_schema(:ok)
+ end
+
+ test "returns 403 when requested by a non-admin" do
+ user = insert(:user)
+ token = insert(:oauth_token, user: user)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> assign(:token, token)
+ |> get("/api/pleroma/admin/reports")
+
+ assert json_response(conn, :forbidden) ==
+ %{"error" => "User is not an admin or OAuth admin scope is not granted."}
+ end
+
+ test "returns 403 when requested by anonymous" do
+ conn = get(build_conn(), "/api/pleroma/admin/reports")
+
+ assert json_response(conn, :forbidden) == %{
+ "error" => "Invalid credentials."
+ }
+ end
+ end
+
+ describe "POST /api/pleroma/admin/reports/:id/notes" do
+ setup %{conn: conn, admin: admin} do
+ [reporter, target_user] = insert_pair(:user)
+ activity = insert(:note_activity, user: target_user)
+
+ {:ok, %{id: report_id}} =
+ CommonAPI.report(reporter, %{
+ account_id: target_user.id,
+ comment: "I feel offended",
+ status_ids: [activity.id]
+ })
+
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
+ content: "this is disgusting!"
+ })
+
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
+ content: "this is disgusting2!"
+ })
+
+ %{
+ admin_id: admin.id,
+ report_id: report_id
+ }
+ end
+
+ test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
+ assert [note, _] = Repo.all(ReportNote)
+
+ assert %{
+ activity_id: ^report_id,
+ content: "this is disgusting!",
+ user_id: ^admin_id
+ } = note
+ end
+
+ test "it returns reports with notes", %{conn: conn, admin: admin} do
+ conn = get(conn, "/api/pleroma/admin/reports")
+
+ response = json_response_and_validate_schema(conn, 200)
+ notes = hd(response["reports"])["notes"]
+ [note, _] = notes
+
+ assert note["user"]["nickname"] == admin.nickname
+ assert note["content"] == "this is disgusting!"
+ assert note["created_at"]
+ assert response["total"] == 1
+ end
+
+ test "it deletes the note", %{conn: conn, report_id: report_id} do
+ assert ReportNote |> Repo.all() |> length() == 2
+ assert [note, _] = Repo.all(ReportNote)
+
+ delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
+
+ assert ReportNote |> Repo.all() |> length() == 1
+ end
+ end
+end
diff --git a/test/web/admin_api/controllers/status_controller_test.exs b/test/web/admin_api/controllers/status_controller_test.exs
new file mode 100644
index 000000000..eff78fb0a
--- /dev/null
+++ b/test/web/admin_api/controllers/status_controller_test.exs
@@ -0,0 +1,202 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+
+ alias Pleroma.Activity
+ alias Pleroma.Config
+ alias Pleroma.ModerationLog
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "GET /api/pleroma/admin/statuses/:id" do
+ test "not found", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/admin/statuses/not_found")
+ |> json_response_and_validate_schema(:not_found)
+ end
+
+ test "shows activity", %{conn: conn} do
+ activity = insert(:note_activity)
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/statuses/#{activity.id}")
+ |> json_response_and_validate_schema(200)
+
+ assert response["id"] == activity.id
+
+ account = response["account"]
+ actor = User.get_by_ap_id(activity.actor)
+
+ assert account["id"] == actor.id
+ assert account["nickname"] == actor.nickname
+ assert account["deactivated"] == actor.deactivated
+ assert account["confirmation_pending"] == actor.confirmation_pending
+ end
+ end
+
+ describe "PUT /api/pleroma/admin/statuses/:id" do
+ setup do
+ activity = insert(:note_activity)
+
+ %{id: activity.id}
+ end
+
+ test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
+ |> json_response_and_validate_schema(:ok)
+
+ assert response["sensitive"]
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
+ |> json_response_and_validate_schema(:ok)
+
+ refute response["sensitive"]
+ end
+
+ test "change visibility flag", %{conn: conn, id: id, admin: admin} do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "public"})
+ |> json_response_and_validate_schema(:ok)
+
+ assert response["visibility"] == "public"
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "private"})
+ |> json_response_and_validate_schema(:ok)
+
+ assert response["visibility"] == "private"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "unlisted"})
+ |> json_response_and_validate_schema(:ok)
+
+ assert response["visibility"] == "unlisted"
+ end
+
+ test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "test"})
+
+ assert %{"error" => "test - Invalid value for enum."} =
+ json_response_and_validate_schema(conn, :bad_request)
+ end
+ end
+
+ describe "DELETE /api/pleroma/admin/statuses/:id" do
+ setup do
+ activity = insert(:note_activity)
+
+ %{id: activity.id}
+ end
+
+ test "deletes status", %{conn: conn, id: id, admin: admin} do
+ conn
+ |> delete("/api/pleroma/admin/statuses/#{id}")
+ |> json_response_and_validate_schema(:ok)
+
+ refute Activity.get_by_id(id)
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} deleted status ##{id}"
+ end
+
+ test "returns 404 when the status does not exist", %{conn: conn} do
+ conn = delete(conn, "/api/pleroma/admin/statuses/test")
+
+ assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
+ end
+ end
+
+ describe "GET /api/pleroma/admin/statuses" do
+ test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do
+ blocked = insert(:user)
+ user = insert(:user)
+ User.block(admin, blocked)
+
+ {:ok, _} = CommonAPI.post(user, %{status: "@#{admin.nickname}", visibility: "direct"})
+
+ {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
+ {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "private"})
+ {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "public"})
+ {:ok, _} = CommonAPI.post(blocked, %{status: ".", visibility: "public"})
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/statuses")
+ |> json_response_and_validate_schema(200)
+
+ refute "private" in Enum.map(response, & &1["visibility"])
+ assert length(response) == 3
+ end
+
+ test "returns only local statuses with local_only on", %{conn: conn} do
+ user = insert(:user)
+ remote_user = insert(:user, local: false, nickname: "archaeme@archae.me")
+ insert(:note_activity, user: user, local: true)
+ insert(:note_activity, user: remote_user, local: false)
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/statuses?local_only=true")
+ |> json_response_and_validate_schema(200)
+
+ assert length(response) == 1
+ end
+
+ test "returns private and direct statuses with godmode on", %{conn: conn, admin: admin} do
+ user = insert(:user)
+
+ {:ok, _} = CommonAPI.post(user, %{status: "@#{admin.nickname}", visibility: "direct"})
+
+ {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "private"})
+ {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "public"})
+ conn = get(conn, "/api/pleroma/admin/statuses?godmode=true")
+ assert json_response_and_validate_schema(conn, 200) |> length() == 3
+ end
+ end
+end
diff --git a/test/web/admin_api/views/report_view_test.exs b/test/web/admin_api/views/report_view_test.exs
index 5db6629f2..f00b0afb2 100644
--- a/test/web/admin_api/views/report_view_test.exs
+++ b/test/web/admin_api/views/report_view_test.exs
@@ -15,7 +15,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.report(user, %{"account_id" => other_user.id})
+ {:ok, activity} = CommonAPI.report(user, %{account_id: other_user.id})
expected = %{
content: nil,
@@ -45,10 +45,10 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
test "includes reported statuses" do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "toot"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "toot"})
{:ok, report_activity} =
- CommonAPI.report(user, %{"account_id" => other_user.id, "status_ids" => [activity.id]})
+ CommonAPI.report(user, %{account_id: other_user.id, status_ids: [activity.id]})
other_user = Pleroma.User.get_by_id(other_user.id)
@@ -81,7 +81,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.report(user, %{"account_id" => other_user.id})
+ {:ok, activity} = CommonAPI.report(user, %{account_id: other_user.id})
{:ok, activity} = CommonAPI.update_report_state(activity.id, "closed")
assert %{state: "closed"} =
@@ -94,8 +94,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
{:ok, activity} =
CommonAPI.report(user, %{
- "account_id" => other_user.id,
- "comment" => "posts are too good for this instance"
+ account_id: other_user.id,
+ comment: "posts are too good for this instance"
})
assert %{content: "posts are too good for this instance"} =
@@ -108,8 +108,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
{:ok, activity} =
CommonAPI.report(user, %{
- "account_id" => other_user.id,
- "comment" => ""
+ account_id: other_user.id,
+ comment: ""
})
data = Map.put(activity.data, "content", "<script> alert('hecked :D:D:D:D:D:D:D') </script>")
@@ -125,8 +125,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
{:ok, activity} =
CommonAPI.report(user, %{
- "account_id" => other_user.id,
- "comment" => ""
+ account_id: other_user.id,
+ comment: ""
})
Pleroma.User.delete(other_user)
diff --git a/test/web/api_spec/app_operation_test.exs b/test/web/api_spec/app_operation_test.exs
deleted file mode 100644
index 5b96abb44..000000000
--- a/test/web/api_spec/app_operation_test.exs
+++ /dev/null
@@ -1,45 +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.ApiSpec.AppOperationTest do
- use Pleroma.Web.ConnCase, async: true
-
- alias Pleroma.Web.ApiSpec
- alias Pleroma.Web.ApiSpec.Schemas.AppCreateRequest
- alias Pleroma.Web.ApiSpec.Schemas.AppCreateResponse
-
- import OpenApiSpex.TestAssertions
- import Pleroma.Factory
-
- test "AppCreateRequest example matches schema" do
- api_spec = ApiSpec.spec()
- schema = AppCreateRequest.schema()
- assert_schema(schema.example, "AppCreateRequest", api_spec)
- end
-
- test "AppCreateResponse example matches schema" do
- api_spec = ApiSpec.spec()
- schema = AppCreateResponse.schema()
- assert_schema(schema.example, "AppCreateResponse", api_spec)
- end
-
- test "AppController produces a AppCreateResponse", %{conn: conn} do
- api_spec = ApiSpec.spec()
- app_attrs = build(:oauth_app)
-
- json =
- conn
- |> put_req_header("content-type", "application/json")
- |> post(
- "/api/v1/apps",
- Jason.encode!(%{
- client_name: app_attrs.client_name,
- redirect_uris: app_attrs.redirect_uris
- })
- )
- |> json_response(200)
-
- assert_schema(json, "AppCreateResponse", api_spec)
- end
-end
diff --git a/test/web/api_spec/schema_examples_test.exs b/test/web/api_spec/schema_examples_test.exs
new file mode 100644
index 000000000..f00e834fc
--- /dev/null
+++ b/test/web/api_spec/schema_examples_test.exs
@@ -0,0 +1,43 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.SchemaExamplesTest do
+ use ExUnit.Case, async: true
+ import Pleroma.Tests.ApiSpecHelpers
+
+ @content_type "application/json"
+
+ for operation <- api_operations() do
+ describe operation.operationId <> " Request Body" do
+ if operation.requestBody do
+ @media_type operation.requestBody.content[@content_type]
+ @schema resolve_schema(@media_type.schema)
+
+ if @media_type.example do
+ test "request body media type example matches schema" do
+ assert_schema(@media_type.example, @schema)
+ end
+ end
+
+ if @schema.example do
+ test "request body schema example matches schema" do
+ assert_schema(@schema.example, @schema)
+ end
+ end
+ end
+ end
+
+ for {status, response} <- operation.responses, is_map(response.content[@content_type]) do
+ describe "#{operation.operationId} - #{status} Response" do
+ @schema resolve_schema(response.content[@content_type].schema)
+
+ if @schema.example do
+ test "example matches schema" do
+ assert_schema(@schema.example, @schema)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/test/web/auth/auth_test_controller_test.exs b/test/web/auth/auth_test_controller_test.exs
new file mode 100644
index 000000000..fed52b7f3
--- /dev/null
+++ b/test/web/auth/auth_test_controller_test.exs
@@ -0,0 +1,242 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Tests.AuthTestControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+
+ describe "do_oauth_check" do
+ test "serves with proper OAuth token (fulfilling requested scopes)" do
+ %{conn: good_token_conn, user: user} = oauth_access(["read"])
+
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/authenticated_api/do_oauth_check")
+ |> json_response(200)
+
+ # Unintended usage (:api) — use with :authenticated_api instead
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/api/do_oauth_check")
+ |> json_response(200)
+ end
+
+ test "fails on no token / missing scope(s)" do
+ %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
+
+ bad_token_conn
+ |> get("/test/authenticated_api/do_oauth_check")
+ |> json_response(403)
+
+ bad_token_conn
+ |> assign(:token, nil)
+ |> get("/test/api/do_oauth_check")
+ |> json_response(403)
+ end
+ end
+
+ describe "fallback_oauth_check" do
+ test "serves with proper OAuth token (fulfilling requested scopes)" do
+ %{conn: good_token_conn, user: user} = oauth_access(["read"])
+
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(200)
+
+ # Unintended usage (:authenticated_api) — use with :api instead
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/authenticated_api/fallback_oauth_check")
+ |> json_response(200)
+ end
+
+ test "for :api on public instance, drops :user and renders on no token / missing scope(s)" do
+ clear_config([:instance, :public], true)
+
+ %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
+
+ assert %{"user_id" => nil} ==
+ bad_token_conn
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(200)
+
+ assert %{"user_id" => nil} ==
+ bad_token_conn
+ |> assign(:token, nil)
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(200)
+ end
+
+ test "for :api on private instance, fails on no token / missing scope(s)" do
+ clear_config([:instance, :public], false)
+
+ %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
+
+ bad_token_conn
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(403)
+
+ bad_token_conn
+ |> assign(:token, nil)
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(403)
+ end
+ end
+
+ describe "skip_oauth_check" do
+ test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
+ user = insert(:user)
+
+ assert %{"user_id" => user.id} ==
+ build_conn()
+ |> assign(:user, user)
+ |> get("/test/authenticated_api/skip_oauth_check")
+ |> json_response(200)
+
+ %{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
+
+ assert %{"user_id" => user.id} ==
+ bad_token_conn
+ |> get("/test/authenticated_api/skip_oauth_check")
+ |> json_response(200)
+ end
+
+ test "serves via :api on public instance if :user is not set" do
+ clear_config([:instance, :public], true)
+
+ assert %{"user_id" => nil} ==
+ build_conn()
+ |> get("/test/api/skip_oauth_check")
+ |> json_response(200)
+
+ build_conn()
+ |> get("/test/authenticated_api/skip_oauth_check")
+ |> json_response(403)
+ end
+
+ test "fails on private instance if :user is not set" do
+ clear_config([:instance, :public], false)
+
+ build_conn()
+ |> get("/test/api/skip_oauth_check")
+ |> json_response(403)
+
+ build_conn()
+ |> get("/test/authenticated_api/skip_oauth_check")
+ |> json_response(403)
+ end
+ end
+
+ describe "fallback_oauth_skip_publicity_check" do
+ test "serves with proper OAuth token (fulfilling requested scopes)" do
+ %{conn: good_token_conn, user: user} = oauth_access(["read"])
+
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/api/fallback_oauth_skip_publicity_check")
+ |> json_response(200)
+
+ # Unintended usage (:authenticated_api)
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/authenticated_api/fallback_oauth_skip_publicity_check")
+ |> json_response(200)
+ end
+
+ test "for :api on private / public instance, drops :user and renders on token issue" do
+ %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
+
+ for is_public <- [true, false] do
+ clear_config([:instance, :public], is_public)
+
+ assert %{"user_id" => nil} ==
+ bad_token_conn
+ |> get("/test/api/fallback_oauth_skip_publicity_check")
+ |> json_response(200)
+
+ assert %{"user_id" => nil} ==
+ bad_token_conn
+ |> assign(:token, nil)
+ |> get("/test/api/fallback_oauth_skip_publicity_check")
+ |> json_response(200)
+ end
+ end
+ end
+
+ describe "skip_oauth_skip_publicity_check" do
+ test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
+ user = insert(:user)
+
+ assert %{"user_id" => user.id} ==
+ build_conn()
+ |> assign(:user, user)
+ |> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
+ |> json_response(200)
+
+ %{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
+
+ assert %{"user_id" => user.id} ==
+ bad_token_conn
+ |> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
+ |> json_response(200)
+ end
+
+ test "for :api, serves on private and public instances regardless of whether :user is set" do
+ user = insert(:user)
+
+ for is_public <- [true, false] do
+ clear_config([:instance, :public], is_public)
+
+ assert %{"user_id" => nil} ==
+ build_conn()
+ |> get("/test/api/skip_oauth_skip_publicity_check")
+ |> json_response(200)
+
+ assert %{"user_id" => user.id} ==
+ build_conn()
+ |> assign(:user, user)
+ |> get("/test/api/skip_oauth_skip_publicity_check")
+ |> json_response(200)
+ end
+ end
+ end
+
+ describe "missing_oauth_check_definition" do
+ def test_missing_oauth_check_definition_failure(endpoint, expected_error) do
+ %{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
+
+ assert %{"error" => expected_error} ==
+ conn
+ |> get(endpoint)
+ |> json_response(403)
+ end
+
+ test "fails if served via :authenticated_api" do
+ test_missing_oauth_check_definition_failure(
+ "/test/authenticated_api/missing_oauth_check_definition",
+ "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
+ )
+ end
+
+ test "fails if served via :api and the instance is private" do
+ clear_config([:instance, :public], false)
+
+ test_missing_oauth_check_definition_failure(
+ "/test/api/missing_oauth_check_definition",
+ "This resource requires authentication."
+ )
+ end
+
+ test "succeeds with dropped :user if served via :api on public instance" do
+ %{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
+
+ assert %{"user_id" => nil} ==
+ conn
+ |> get("/test/api/missing_oauth_check_definition")
+ |> json_response(200)
+ end
+ end
+end
diff --git a/test/web/auth/basic_auth_test.exs b/test/web/auth/basic_auth_test.exs
new file mode 100644
index 000000000..bf6e3d2fc
--- /dev/null
+++ b/test/web/auth/basic_auth_test.exs
@@ -0,0 +1,46 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Auth.BasicAuthTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+
+ test "with HTTP Basic Auth used, grants access to OAuth scope-restricted endpoints", %{
+ conn: conn
+ } do
+ user = insert(:user)
+ assert Pbkdf2.verify_pass("test", user.password_hash)
+
+ basic_auth_contents =
+ (URI.encode_www_form(user.nickname) <> ":" <> URI.encode_www_form("test"))
+ |> Base.encode64()
+
+ # Succeeds with HTTP Basic Auth
+ response =
+ conn
+ |> put_req_header("authorization", "Basic " <> basic_auth_contents)
+ |> get("/api/v1/accounts/verify_credentials")
+ |> json_response(200)
+
+ user_nickname = user.nickname
+ assert %{"username" => ^user_nickname} = response
+
+ # Succeeds with a properly scoped OAuth token
+ valid_token = insert(:oauth_token, scopes: ["read:accounts"])
+
+ conn
+ |> put_req_header("authorization", "Bearer #{valid_token.token}")
+ |> get("/api/v1/accounts/verify_credentials")
+ |> json_response(200)
+
+ # Fails with a wrong-scoped OAuth token (proof of restriction)
+ invalid_token = insert(:oauth_token, scopes: ["read:something"])
+
+ conn
+ |> put_req_header("authorization", "Bearer #{invalid_token.token}")
+ |> get("/api/v1/accounts/verify_credentials")
+ |> json_response(403)
+ end
+end
diff --git a/test/web/auth/oauth_test_controller_test.exs b/test/web/auth/oauth_test_controller_test.exs
deleted file mode 100644
index a2f6009ac..000000000
--- a/test/web/auth/oauth_test_controller_test.exs
+++ /dev/null
@@ -1,49 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Tests.OAuthTestControllerTest do
- use Pleroma.Web.ConnCase
-
- import Pleroma.Factory
-
- setup %{conn: conn} do
- user = insert(:user)
- conn = assign(conn, :user, user)
- %{conn: conn, user: user}
- end
-
- test "missed_oauth", %{conn: conn} do
- res =
- conn
- |> get("/test/authenticated_api/missed_oauth")
- |> json_response(403)
-
- assert res ==
- %{
- "error" =>
- "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
- }
- end
-
- test "skipped_oauth", %{conn: conn} do
- conn
- |> assign(:token, nil)
- |> get("/test/authenticated_api/skipped_oauth")
- |> json_response(200)
- end
-
- test "performed_oauth", %{user: user} do
- %{conn: good_token_conn} = oauth_access(["read"], user: user)
-
- good_token_conn
- |> get("/test/authenticated_api/performed_oauth")
- |> json_response(200)
-
- %{conn: bad_token_conn} = oauth_access(["follow"], user: user)
-
- bad_token_conn
- |> get("/test/authenticated_api/performed_oauth")
- |> json_response(403)
- end
-end
diff --git a/test/web/auth/pleroma_authenticator_test.exs b/test/web/auth/pleroma_authenticator_test.exs
new file mode 100644
index 000000000..1ba0dfecc
--- /dev/null
+++ b/test/web/auth/pleroma_authenticator_test.exs
@@ -0,0 +1,48 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Auth.PleromaAuthenticatorTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Web.Auth.PleromaAuthenticator
+ import Pleroma.Factory
+
+ setup do
+ password = "testpassword"
+ name = "AgentSmith"
+ user = insert(:user, nickname: name, password_hash: Pbkdf2.hash_pwd_salt(password))
+ {:ok, [user: user, name: name, password: password]}
+ end
+
+ test "get_user/authorization", %{name: name, password: password} do
+ name = name <> "1"
+ user = insert(:user, nickname: name, password_hash: Bcrypt.hash_pwd_salt(password))
+
+ params = %{"authorization" => %{"name" => name, "password" => password}}
+ res = PleromaAuthenticator.get_user(%Plug.Conn{params: params})
+
+ assert {:ok, returned_user} = res
+ assert returned_user.id == user.id
+ assert "$pbkdf2" <> _ = returned_user.password_hash
+ end
+
+ test "get_user/authorization with invalid password", %{name: name} do
+ params = %{"authorization" => %{"name" => name, "password" => "password"}}
+ res = PleromaAuthenticator.get_user(%Plug.Conn{params: params})
+
+ assert {:error, {:checkpw, false}} == res
+ end
+
+ test "get_user/grant_type_password", %{user: user, name: name, password: password} do
+ params = %{"grant_type" => "password", "username" => name, "password" => password}
+ res = PleromaAuthenticator.get_user(%Plug.Conn{params: params})
+
+ assert {:ok, user} == res
+ end
+
+ test "error credintails" do
+ res = PleromaAuthenticator.get_user(%Plug.Conn{params: %{}})
+ assert {:error, :invalid_credentials} == res
+ end
+end
diff --git a/test/web/auth/totp_authenticator_test.exs b/test/web/auth/totp_authenticator_test.exs
new file mode 100644
index 000000000..84d4cd840
--- /dev/null
+++ b/test/web/auth/totp_authenticator_test.exs
@@ -0,0 +1,51 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Auth.TOTPAuthenticatorTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.MFA
+ alias Pleroma.MFA.BackupCodes
+ alias Pleroma.MFA.TOTP
+ alias Pleroma.Web.Auth.TOTPAuthenticator
+
+ import Pleroma.Factory
+
+ test "verify token" do
+ otp_secret = TOTP.generate_secret()
+ otp_token = TOTP.generate_token(otp_secret)
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ assert TOTPAuthenticator.verify(otp_token, user) == {:ok, :pass}
+ assert TOTPAuthenticator.verify(nil, user) == {:error, :invalid_token}
+ assert TOTPAuthenticator.verify("", user) == {:error, :invalid_token}
+ end
+
+ test "checks backup codes" do
+ [code | _] = backup_codes = BackupCodes.generate()
+
+ hashed_codes =
+ backup_codes
+ |> Enum.map(&Pbkdf2.hash_pwd_salt(&1))
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ backup_codes: hashed_codes,
+ totp: %MFA.Settings.TOTP{secret: "otp_secret", confirmed: true}
+ }
+ )
+
+ assert TOTPAuthenticator.verify_recovery_code(user, code) == {:ok, :pass}
+ refute TOTPAuthenticator.verify_recovery_code(code, refresh_record(user)) == {:ok, :pass}
+ end
+end
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index e130736ec..6bd26050e 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -5,15 +5,19 @@
defmodule Pleroma.Web.CommonAPITest do
use Pleroma.DataCase
alias Pleroma.Activity
+ alias Pleroma.Chat
alias Pleroma.Conversation.Participation
+ alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
+ import Mock
require Pleroma.Constants
@@ -21,14 +25,324 @@ defmodule Pleroma.Web.CommonAPITest do
setup do: clear_config([:instance, :limit])
setup do: clear_config([:instance, :max_pinned_statuses])
+ describe "posting chat messages" do
+ setup do: clear_config([:instance, :chat_limit])
+
+ test "it posts a chat message without content but with an attachment" do
+ author = insert(:user)
+ recipient = insert(:user)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, upload} = ActivityPub.upload(file, actor: author.ap_id)
+
+ with_mocks([
+ {
+ Pleroma.Web.Streamer,
+ [],
+ [
+ stream: fn _, _ ->
+ nil
+ end
+ ]
+ },
+ {
+ Pleroma.Web.Push,
+ [],
+ [
+ send: fn _ -> nil end
+ ]
+ }
+ ]) do
+ {:ok, activity} =
+ CommonAPI.post_chat_message(
+ author,
+ recipient,
+ nil,
+ media_id: upload.id
+ )
+
+ notification =
+ Notification.for_user_and_activity(recipient, activity)
+ |> Repo.preload(:activity)
+
+ assert called(Pleroma.Web.Push.send(notification))
+ assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
+ assert called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
+
+ assert activity
+ end
+ end
+
+ test "it adds html newlines" do
+ author = insert(:user)
+ recipient = insert(:user)
+
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post_chat_message(
+ author,
+ recipient,
+ "uguu\nuguuu"
+ )
+
+ assert other_user.ap_id not in activity.recipients
+
+ object = Object.normalize(activity, false)
+
+ assert object.data["content"] == "uguu<br/>uguuu"
+ end
+
+ test "it linkifies" do
+ author = insert(:user)
+ recipient = insert(:user)
+
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post_chat_message(
+ author,
+ recipient,
+ "https://example.org is the site of @#{other_user.nickname} #2hu"
+ )
+
+ assert other_user.ap_id not in activity.recipients
+
+ object = Object.normalize(activity, false)
+
+ assert object.data["content"] ==
+ "<a href=\"https://example.org\" rel=\"ugc\">https://example.org</a> is the site of <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{
+ other_user.id
+ }\" href=\"#{other_user.ap_id}\" rel=\"ugc\">@<span>#{other_user.nickname}</span></a></span> <a class=\"hashtag\" data-tag=\"2hu\" href=\"http://localhost:4001/tag/2hu\">#2hu</a>"
+ end
+
+ test "it posts a chat message" do
+ author = insert(:user)
+ recipient = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post_chat_message(
+ author,
+ recipient,
+ "a test message <script>alert('uuu')</script> :firefox:"
+ )
+
+ assert activity.data["type"] == "Create"
+ assert activity.local
+ object = Object.normalize(activity)
+
+ assert object.data["type"] == "ChatMessage"
+ assert object.data["to"] == [recipient.ap_id]
+
+ assert object.data["content"] ==
+ "a test message &lt;script&gt;alert(&#39;uuu&#39;)&lt;/script&gt; :firefox:"
+
+ assert object.data["emoji"] == %{
+ "firefox" => "http://localhost:4001/emoji/Firefox.gif"
+ }
+
+ assert Chat.get(author.id, recipient.ap_id)
+ assert Chat.get(recipient.id, author.ap_id)
+
+ assert :ok == Pleroma.Web.Federator.perform(:publish, activity)
+ end
+
+ test "it reject messages over the local limit" do
+ Pleroma.Config.put([:instance, :chat_limit], 2)
+
+ author = insert(:user)
+ recipient = insert(:user)
+
+ {:error, message} =
+ CommonAPI.post_chat_message(
+ author,
+ recipient,
+ "123"
+ )
+
+ assert message == :content_too_long
+ end
+ end
+
+ describe "unblocking" do
+ test "it works even without an existing block activity" do
+ blocked = insert(:user)
+ blocker = insert(:user)
+ User.block(blocker, blocked)
+
+ assert User.blocks?(blocker, blocked)
+ assert {:ok, :no_activity} == CommonAPI.unblock(blocker, blocked)
+ refute User.blocks?(blocker, blocked)
+ end
+ end
+
+ describe "deletion" do
+ test "it works with pruned objects" do
+ user = insert(:user)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
+
+ clear_config([:instance, :federating], true)
+
+ Object.normalize(post, false)
+ |> Object.prune()
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ assert {:ok, delete} = CommonAPI.delete(post.id, user)
+ assert delete.local
+ assert called(Pleroma.Web.Federator.publish(delete))
+ end
+
+ refute Activity.get_by_id(post.id)
+ end
+
+ test "it allows users to delete their posts" do
+ user = insert(:user)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
+
+ clear_config([:instance, :federating], true)
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ assert {:ok, delete} = CommonAPI.delete(post.id, user)
+ assert delete.local
+ assert called(Pleroma.Web.Federator.publish(delete))
+ end
+
+ refute Activity.get_by_id(post.id)
+ end
+
+ test "it does not allow a user to delete their posts" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
+
+ assert {:error, "Could not delete"} = CommonAPI.delete(post.id, other_user)
+ assert Activity.get_by_id(post.id)
+ end
+
+ test "it allows moderators to delete other user's posts" do
+ user = insert(:user)
+ moderator = insert(:user, is_moderator: true)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
+
+ assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
+ assert delete.local
+
+ refute Activity.get_by_id(post.id)
+ end
+
+ test "it allows admins to delete other user's posts" do
+ user = insert(:user)
+ moderator = insert(:user, is_admin: true)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
+
+ assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
+ assert delete.local
+
+ refute Activity.get_by_id(post.id)
+ end
+
+ test "superusers deleting non-local posts won't federate the delete" do
+ # This is the user of the ingested activity
+ _user =
+ insert(:user,
+ local: false,
+ ap_id: "http://mastodon.example.org/users/admin",
+ last_refreshed_at: NaiveDateTime.utc_now()
+ )
+
+ moderator = insert(:user, is_admin: true)
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Jason.decode!()
+
+ {:ok, post} = Transmogrifier.handle_incoming(data)
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
+ assert delete.local
+ refute called(Pleroma.Web.Federator.publish(:_))
+ end
+
+ refute Activity.get_by_id(post.id)
+ end
+ end
+
+ test "favoriting race condition" do
+ user = insert(:user)
+ users_serial = insert_list(10, :user)
+ users = insert_list(10, :user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "."})
+
+ users_serial
+ |> Enum.map(fn user ->
+ CommonAPI.favorite(user, activity.id)
+ end)
+
+ object = Object.get_by_ap_id(activity.data["object"])
+ assert object.data["like_count"] == 10
+
+ users
+ |> Enum.map(fn user ->
+ Task.async(fn ->
+ CommonAPI.favorite(user, activity.id)
+ end)
+ end)
+ |> Enum.map(&Task.await/1)
+
+ object = Object.get_by_ap_id(activity.data["object"])
+ assert object.data["like_count"] == 20
+ end
+
+ test "repeating race condition" do
+ user = insert(:user)
+ users_serial = insert_list(10, :user)
+ users = insert_list(10, :user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "."})
+
+ users_serial
+ |> Enum.map(fn user ->
+ CommonAPI.repeat(activity.id, user)
+ end)
+
+ object = Object.get_by_ap_id(activity.data["object"])
+ assert object.data["announcement_count"] == 10
+
+ users
+ |> Enum.map(fn user ->
+ Task.async(fn ->
+ CommonAPI.repeat(activity.id, user)
+ end)
+ end)
+ |> Enum.map(&Task.await/1)
+
+ object = Object.get_by_ap_id(activity.data["object"])
+ assert object.data["announcement_count"] == 20
+ end
+
test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+ {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
[participation] = Participation.for_user(user)
{:ok, convo_reply} =
- CommonAPI.post(user, %{"status" => ".", "in_reply_to_conversation_id" => participation.id})
+ CommonAPI.post(user, %{status: ".", in_reply_to_conversation_id: participation.id})
assert Visibility.is_direct?(convo_reply)
@@ -42,8 +356,8 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.post(har, %{
- "status" => "@#{jafnhar.nickname} hey",
- "visibility" => "direct"
+ status: "@#{jafnhar.nickname} hey",
+ visibility: "direct"
})
assert har.ap_id in activity.recipients
@@ -53,10 +367,10 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.post(har, %{
- "status" => "I don't really like @#{tridi.nickname}",
- "visibility" => "direct",
- "in_reply_to_status_id" => activity.id,
- "in_reply_to_conversation_id" => participation.id
+ status: "I don't really like @#{tridi.nickname}",
+ visibility: "direct",
+ in_reply_to_status_id: activity.id,
+ in_reply_to_conversation_id: participation.id
})
assert har.ap_id in activity.recipients
@@ -73,8 +387,8 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.post(har, %{
- "status" => "@#{jafnhar.nickname} hey, i never want to see @#{tridi.nickname} again",
- "visibility" => "direct"
+ status: "@#{jafnhar.nickname} hey, i never want to see @#{tridi.nickname} again",
+ visibility: "direct"
})
refute tridi.ap_id in activity.recipients
@@ -83,7 +397,7 @@ defmodule Pleroma.Web.CommonAPITest do
test "it de-duplicates tags" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu #2HU"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "#2hu #2HU"})
object = Object.normalize(activity)
@@ -92,7 +406,7 @@ defmodule Pleroma.Web.CommonAPITest do
test "it adds emoji in the object" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => ":firefox:"})
+ {:ok, activity} = CommonAPI.post(user, %{status: ":firefox:"})
assert Object.normalize(activity).data["emoji"]["firefox"]
end
@@ -106,9 +420,9 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"Hey, I think @#{user_three.nickname} is ugly. @#{user_four.nickname} is alright though.",
- "to" => [user_two.nickname, user_four.nickname, "nonexistent"]
+ to: [user_two.nickname, user_four.nickname, "nonexistent"]
})
assert user.ap_id in activity.recipients
@@ -124,8 +438,8 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => post,
- "content_type" => "text/html"
+ status: post,
+ content_type: "text/html"
})
object = Object.normalize(activity)
@@ -140,8 +454,8 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => post,
- "content_type" => "text/markdown"
+ status: post,
+ content_type: "text/markdown"
})
object = Object.normalize(activity)
@@ -152,31 +466,56 @@ defmodule Pleroma.Web.CommonAPITest do
test "it does not allow replies to direct messages that are not direct messages themselves" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "suya..", "visibility" => "direct"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "suya..", visibility: "direct"})
assert {:ok, _} =
CommonAPI.post(user, %{
- "status" => "suya..",
- "visibility" => "direct",
- "in_reply_to_status_id" => activity.id
+ status: "suya..",
+ visibility: "direct",
+ in_reply_to_status_id: activity.id
})
Enum.each(["public", "private", "unlisted"], fn visibility ->
assert {:error, "The message visibility must be direct"} =
CommonAPI.post(user, %{
- "status" => "suya..",
- "visibility" => visibility,
- "in_reply_to_status_id" => activity.id
+ status: "suya..",
+ visibility: visibility,
+ in_reply_to_status_id: activity.id
})
end)
end
+ test "replying with a direct message will NOT auto-add the author of the reply to the recipient list" do
+ user = insert(:user)
+ other_user = insert(:user)
+ third_user = insert(:user)
+
+ {:ok, post} = CommonAPI.post(user, %{status: "I'm stupid"})
+
+ {:ok, open_answer} =
+ CommonAPI.post(other_user, %{status: "No ur smart", in_reply_to_status_id: post.id})
+
+ # The OP is implicitly added
+ assert user.ap_id in open_answer.recipients
+
+ {:ok, secret_answer} =
+ CommonAPI.post(other_user, %{
+ status: "lol, that guy really is stupid, right, @#{third_user.nickname}?",
+ in_reply_to_status_id: post.id,
+ visibility: "direct"
+ })
+
+ assert third_user.ap_id in secret_answer.recipients
+
+ # The OP is not added
+ refute user.ap_id in secret_answer.recipients
+ end
+
test "it allows to address a list" do
user = insert(:user)
{:ok, list} = Pleroma.List.create("foo", user)
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
assert activity.data["bcc"] == [list.ap_id]
assert activity.recipients == [list.ap_id, user.ap_id]
@@ -187,7 +526,7 @@ defmodule Pleroma.Web.CommonAPITest do
user = insert(:user)
assert {:error, "Cannot post an empty status without attachments"} =
- CommonAPI.post(user, %{"status" => ""})
+ CommonAPI.post(user, %{status: ""})
end
test "it validates character limits are correctly enforced" do
@@ -196,9 +535,9 @@ defmodule Pleroma.Web.CommonAPITest do
user = insert(:user)
assert {:error, "The status is over the character limit"} =
- CommonAPI.post(user, %{"status" => "foobar"})
+ CommonAPI.post(user, %{status: "foobar"})
- assert {:ok, activity} = CommonAPI.post(user, %{"status" => "12345"})
+ assert {:ok, activity} = CommonAPI.post(user, %{status: "12345"})
end
test "it can handle activities that expire" do
@@ -209,8 +548,7 @@ defmodule Pleroma.Web.CommonAPITest do
|> NaiveDateTime.truncate(:second)
|> NaiveDateTime.add(1_000_000, :second)
- assert {:ok, activity} =
- CommonAPI.post(user, %{"status" => "chai", "expires_in" => 1_000_000})
+ assert {:ok, activity} = CommonAPI.post(user, %{status: "chai", expires_in: 1_000_000})
assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id)
assert expiration.scheduled_at == expires_at
@@ -222,14 +560,14 @@ defmodule Pleroma.Web.CommonAPITest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
- {:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
+ {:ok, reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍")
assert reaction.data["actor"] == user.ap_id
assert reaction.data["content"] == "👍"
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
{:error, _} = CommonAPI.react_with_emoji(activity.id, user, ".")
end
@@ -238,41 +576,54 @@ defmodule Pleroma.Web.CommonAPITest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
- {:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
+ {:ok, reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍")
- {:ok, unreaction, _} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
+ {:ok, unreaction} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
assert unreaction.data["type"] == "Undo"
assert unreaction.data["object"] == reaction.data["id"]
+ assert unreaction.local
end
test "repeating a status" do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
- {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, user)
+ {:ok, %Activity{} = announce_activity} = CommonAPI.repeat(activity.id, user)
+ assert Visibility.is_public?(announce_activity)
+ end
+
+ test "can't repeat a repeat" do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
+
+ {:ok, %Activity{} = announce} = CommonAPI.repeat(activity.id, other_user)
+
+ refute match?({:ok, %Activity{}}, CommonAPI.repeat(announce.id, user))
end
test "repeating a status privately" do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
- {:ok, %Activity{} = announce_activity, _} =
- CommonAPI.repeat(activity.id, user, %{"visibility" => "private"})
+ {:ok, %Activity{} = announce_activity} =
+ CommonAPI.repeat(activity.id, user, %{visibility: "private"})
assert Visibility.is_private?(announce_activity)
+ refute Visibility.visible_for_user?(announce_activity, nil)
end
test "favoriting a status" do
user = insert(:user)
other_user = insert(:user)
- {:ok, post_activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+ {:ok, post_activity} = CommonAPI.post(other_user, %{status: "cofe"})
{:ok, %Activity{data: data}} = CommonAPI.favorite(user, post_activity.id)
assert data["type"] == "Like"
@@ -284,16 +635,16 @@ defmodule Pleroma.Web.CommonAPITest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
- {:ok, %Activity{} = activity, object} = CommonAPI.repeat(activity.id, user)
- {:ok, ^activity, ^object} = CommonAPI.repeat(activity.id, user)
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
+ {:ok, %Activity{} = announce} = CommonAPI.repeat(activity.id, user)
+ {:ok, ^announce} = CommonAPI.repeat(activity.id, user)
end
test "favoriting a status twice returns ok, but without the like activity" do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
{:ok, %Activity{}} = CommonAPI.favorite(user, activity.id)
assert {:ok, :already_liked} = CommonAPI.favorite(user, activity.id)
end
@@ -304,7 +655,7 @@ defmodule Pleroma.Web.CommonAPITest do
Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"})
[user: user, activity: activity]
end
@@ -321,8 +672,8 @@ defmodule Pleroma.Web.CommonAPITest do
test "pin poll", %{user: user} do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "How is fediverse today?",
- "poll" => %{"options" => ["Absolutely outstanding", "Not good"], "expires_in" => 20}
+ status: "How is fediverse today?",
+ poll: %{options: ["Absolutely outstanding", "Not good"], expires_in: 20}
})
assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
@@ -334,7 +685,7 @@ defmodule Pleroma.Web.CommonAPITest do
end
test "unlisted statuses can be pinned", %{user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!", "visibility" => "unlisted"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!", visibility: "unlisted"})
assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
end
@@ -345,7 +696,7 @@ defmodule Pleroma.Web.CommonAPITest do
end
test "max pinned statuses", %{user: user, activity: activity_one} do
- {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ {:ok, activity_two} = CommonAPI.post(user, %{status: "HI!!!"})
assert {:ok, ^activity_one} = CommonAPI.pin(activity_one.id, user)
@@ -360,7 +711,9 @@ defmodule Pleroma.Web.CommonAPITest do
user = refresh_record(user)
- assert {:ok, ^activity} = CommonAPI.unpin(activity.id, user)
+ id = activity.id
+
+ assert match?({:ok, %{id: ^id}}, CommonAPI.unpin(activity.id, user))
user = refresh_record(user)
@@ -411,7 +764,7 @@ defmodule Pleroma.Web.CommonAPITest do
reporter = insert(:user)
target_user = insert(:user)
- {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
+ {:ok, activity} = CommonAPI.post(target_user, %{status: "foobar"})
reporter_ap_id = reporter.ap_id
target_ap_id = target_user.ap_id
@@ -419,9 +772,9 @@ defmodule Pleroma.Web.CommonAPITest do
comment = "foobar"
report_data = %{
- "account_id" => target_user.id,
- "comment" => comment,
- "status_ids" => [activity.id]
+ account_id: target_user.id,
+ comment: comment,
+ status_ids: [activity.id]
}
note_obj = %{
@@ -451,9 +804,9 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, %Activity{id: report_id}} =
CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel offended",
- "status_ids" => [activity.id]
+ account_id: target_user.id,
+ comment: "I feel offended",
+ status_ids: [activity.id]
})
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
@@ -472,9 +825,9 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, %Activity{id: report_id}} =
CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel offended",
- "status_ids" => [activity.id]
+ account_id: target_user.id,
+ comment: "I feel offended",
+ status_ids: [activity.id]
})
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
@@ -486,16 +839,16 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, %Activity{id: first_report_id}} =
CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel offended",
- "status_ids" => [activity.id]
+ account_id: target_user.id,
+ comment: "I feel offended",
+ status_ids: [activity.id]
})
{:ok, %Activity{id: second_report_id}} =
CommonAPI.report(reporter, %{
- "account_id" => target_user.id,
- "comment" => "I feel very offended!",
- "status_ids" => [activity.id]
+ account_id: target_user.id,
+ comment: "I feel very offended!",
+ status_ids: [activity.id]
})
{:ok, report_ids} =
@@ -631,6 +984,14 @@ defmodule Pleroma.Web.CommonAPITest do
assert Repo.get(Activity, follow_activity_two.id).data["state"] == "reject"
assert Repo.get(Activity, follow_activity_three.id).data["state"] == "pending"
end
+
+ test "doesn't create a following relationship if the corresponding follow request doesn't exist" do
+ user = insert(:user, locked: true)
+ not_follower = insert(:user)
+ CommonAPI.accept_follow_request(not_follower, user)
+
+ assert Pleroma.FollowingRelationship.following?(not_follower, user) == false
+ end
end
describe "vote/3" do
@@ -640,8 +1001,8 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "Am I cute?",
- "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
+ status: "Am I cute?",
+ poll: %{options: ["Yes", "No"], expires_in: 20}
})
object = Object.normalize(activity)
@@ -658,10 +1019,10 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.listen(user, %{
- "title" => "lain radio episode 1",
- "album" => "lain radio",
- "artist" => "lain",
- "length" => 180_000
+ title: "lain radio episode 1",
+ album: "lain radio",
+ artist: "lain",
+ length: 180_000
})
object = Object.normalize(activity)
@@ -676,11 +1037,11 @@ defmodule Pleroma.Web.CommonAPITest do
{:ok, activity} =
CommonAPI.listen(user, %{
- "title" => "lain radio episode 1",
- "album" => "lain radio",
- "artist" => "lain",
- "length" => 180_000,
- "visibility" => "private"
+ title: "lain radio episode 1",
+ album: "lain radio",
+ artist: "lain",
+ length: 180_000,
+ visibility: "private"
})
object = Object.normalize(activity)
diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs
index b21445fe9..e67c10b93 100644
--- a/test/web/common_api/common_api_utils_test.exs
+++ b/test/web/common_api/common_api_utils_test.exs
@@ -14,18 +14,41 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
@public_address "https://www.w3.org/ns/activitystreams#Public"
- test "it adds attachment links to a given text and attachment set" do
- name =
- "Sakura%20Mana%20%E2%80%93%20Turned%20on%20by%20a%20Senior%20OL%20with%20a%20Temptating%20Tight%20Skirt-s%20Full%20Hipline%20and%20Panty%20Shot-%20Beautiful%20Thick%20Thighs-%20and%20Erotic%20Ass-%20-2015-%20--%20Oppaitime%208-28-2017%206-50-33%20PM.png"
+ describe "add_attachments/2" do
+ setup do
+ name =
+ "Sakura Mana – Turned on by a Senior OL with a Temptating Tight Skirt-s Full Hipline and Panty Shot- Beautiful Thick Thighs- and Erotic Ass- -2015- -- Oppaitime 8-28-2017 6-50-33 PM.png"
- attachment = %{
- "url" => [%{"href" => name}]
- }
+ attachment = %{
+ "url" => [%{"href" => URI.encode(name)}]
+ }
- res = Utils.add_attachments("", [attachment])
+ %{name: name, attachment: attachment}
+ end
+
+ test "it adds attachment links to a given text and attachment set", %{
+ name: name,
+ attachment: attachment
+ } do
+ len = 10
+ clear_config([Pleroma.Upload, :filename_display_max_length], len)
+
+ expected =
+ "<br><a href=\"#{URI.encode(name)}\" class='attachment'>#{String.slice(name, 0..len)}…</a>"
+
+ assert Utils.add_attachments("", [attachment]) == expected
+ end
+
+ test "doesn't truncate file name if config for truncate is set to 0", %{
+ name: name,
+ attachment: attachment
+ } do
+ clear_config([Pleroma.Upload, :filename_display_max_length], 0)
- assert res ==
- "<br><a href=\"#{name}\" class='attachment'>Sakura Mana – Turned on by a Se…</a>"
+ expected = "<br><a href=\"#{URI.encode(name)}\" class='attachment'>#{name}</a>"
+
+ assert Utils.add_attachments("", [attachment]) == expected
+ end
end
describe "it confirms the password given is the current users password" do
@@ -228,7 +251,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
user = insert(:user)
mentioned_user = insert(:user)
third_user = insert(:user)
- {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
+ {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
mentions = [mentioned_user.ap_id]
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public", nil)
@@ -261,7 +284,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
user = insert(:user)
mentioned_user = insert(:user)
third_user = insert(:user)
- {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
+ {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
mentions = [mentioned_user.ap_id]
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted", nil)
@@ -292,16 +315,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
user = insert(:user)
mentioned_user = insert(:user)
third_user = insert(:user)
- {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
+ {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
mentions = [mentioned_user.ap_id]
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private", nil)
- assert length(to) == 3
+ assert length(to) == 2
assert Enum.empty?(cc)
assert mentioned_user.ap_id in to
- assert third_user.ap_id in to
assert user.follower_address in to
end
@@ -322,36 +344,25 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
user = insert(:user)
mentioned_user = insert(:user)
third_user = insert(:user)
- {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
+ {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
mentions = [mentioned_user.ap_id]
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct", nil)
- assert length(to) == 2
+ assert length(to) == 1
assert Enum.empty?(cc)
assert mentioned_user.ap_id in to
- assert third_user.ap_id in to
- end
- end
- describe "get_by_id_or_ap_id/1" do
- test "get activity by id" do
- activity = insert(:note_activity)
- %Pleroma.Activity{} = note = Utils.get_by_id_or_ap_id(activity.id)
- assert note.id == activity.id
- end
+ {:ok, direct_activity} = CommonAPI.post(third_user, %{status: "uguu", visibility: "direct"})
- test "get activity by ap_id" do
- activity = insert(:note_activity)
- %Pleroma.Activity{} = note = Utils.get_by_id_or_ap_id(activity.data["object"])
- assert note.id == activity.id
- end
+ {to, cc} = Utils.get_to_and_cc(user, mentions, direct_activity, "direct", nil)
- test "get activity by object when type isn't `Create` " do
- activity = insert(:like_activity)
- %Pleroma.Activity{} = like = Utils.get_by_id_or_ap_id(activity.id)
- assert like.data["object"] == activity.data["object"]
+ assert length(to) == 2
+ assert Enum.empty?(cc)
+
+ assert mentioned_user.ap_id in to
+ assert third_user.ap_id in to
end
end
@@ -483,8 +494,8 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
desc = Jason.encode!(%{object.id => "test-desc"})
assert Utils.attachments_from_ids(%{
- "media_ids" => ["#{object.id}"],
- "descriptions" => desc
+ media_ids: ["#{object.id}"],
+ descriptions: desc
}) == [
Map.merge(object.data, %{"name" => "test-desc"})
]
@@ -492,7 +503,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
test "returns attachments without descs" do
object = insert(:note)
- assert Utils.attachments_from_ids(%{"media_ids" => ["#{object.id}"]}) == [object.data]
+ assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}) == [object.data]
end
test "returns [] when not pass media_ids" do
diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs
index 59e53bb03..de90aa6e0 100644
--- a/test/web/federator_test.exs
+++ b/test/web/federator_test.exs
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.FederatorTest do
describe "Publish an activity" do
setup do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "HI"})
relay_mock = {
Pleroma.Web.ActivityPub.Relay,
@@ -96,7 +96,7 @@ defmodule Pleroma.Web.FederatorTest do
Instances.set_consistently_unreachable(URI.parse(inbox2).host)
{:ok, _activity} =
- CommonAPI.post(user, %{"status" => "HI @nick1@domain.com, @nick2@domain2.com!"})
+ CommonAPI.post(user, %{status: "HI @nick1@domain.com, @nick2@domain2.com!"})
expected_dt = NaiveDateTime.to_iso8601(dt)
@@ -130,6 +130,9 @@ defmodule Pleroma.Web.FederatorTest do
assert {:ok, job} = Federator.incoming_ap_doc(params)
assert {:ok, _activity} = ObanHelpers.perform(job)
+
+ assert {:ok, job} = Federator.incoming_ap_doc(params)
+ assert {:error, :already_present} = ObanHelpers.perform(job)
end
test "rejects incoming AP docs with incorrect origin" do
@@ -148,7 +151,7 @@ defmodule Pleroma.Web.FederatorTest do
}
assert {:ok, job} = Federator.incoming_ap_doc(params)
- assert :error = ObanHelpers.perform(job)
+ assert {:error, :origin_containment_failed} = ObanHelpers.perform(job)
end
test "it does not crash if MRF rejects the post" do
@@ -164,7 +167,7 @@ defmodule Pleroma.Web.FederatorTest do
|> Poison.decode!()
assert {:ok, job} = Federator.incoming_ap_doc(params)
- assert :error = ObanHelpers.perform(job)
+ assert {:error, _} = ObanHelpers.perform(job)
end
end
end
diff --git a/test/web/feed/tag_controller_test.exs b/test/web/feed/tag_controller_test.exs
index d95aac108..3c29cd94f 100644
--- a/test/web/feed/tag_controller_test.exs
+++ b/test/web/feed/tag_controller_test.exs
@@ -21,7 +21,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
)
user = insert(:user)
- {:ok, activity1} = CommonAPI.post(user, %{"status" => "yeah #PleromaArt"})
+ {:ok, activity1} = CommonAPI.post(user, %{status: "yeah #PleromaArt"})
object = Object.normalize(activity1)
@@ -43,9 +43,9 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|> Ecto.Changeset.change(data: object_data)
|> Pleroma.Repo.update()
- {:ok, activity2} = CommonAPI.post(user, %{"status" => "42 This is :moominmamma #PleromaArt"})
+ {:ok, activity2} = CommonAPI.post(user, %{status: "42 This is :moominmamma #PleromaArt"})
- {:ok, _activity3} = CommonAPI.post(user, %{"status" => "This is :moominmamma"})
+ {:ok, _activity3} = CommonAPI.post(user, %{status: "This is :moominmamma"})
response =
conn
@@ -88,7 +88,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
)
user = insert(:user)
- {:ok, activity1} = CommonAPI.post(user, %{"status" => "yeah #PleromaArt"})
+ {:ok, activity1} = CommonAPI.post(user, %{status: "yeah #PleromaArt"})
object = Object.normalize(activity1)
@@ -110,9 +110,9 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|> Ecto.Changeset.change(data: object_data)
|> Pleroma.Repo.update()
- {:ok, activity2} = CommonAPI.post(user, %{"status" => "42 This is :moominmamma #PleromaArt"})
+ {:ok, activity2} = CommonAPI.post(user, %{status: "42 This is :moominmamma #PleromaArt"})
- {:ok, _activity3} = CommonAPI.post(user, %{"status" => "This is :moominmamma"})
+ {:ok, _activity3} = CommonAPI.post(user, %{status: "This is :moominmamma"})
response =
conn
@@ -138,8 +138,8 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
]
assert xpath(xml, ~x"//channel/item/pubDate/text()"sl) == [
- FeedView.pub_date(activity1.data["published"]),
- FeedView.pub_date(activity2.data["published"])
+ FeedView.pub_date(activity2.data["published"]),
+ FeedView.pub_date(activity1.data["published"])
]
assert xpath(xml, ~x"//channel/item/enclosure/@url"sl) == [
diff --git a/test/web/feed/user_controller_test.exs b/test/web/feed/user_controller_test.exs
index 05ad427c2..fa2ed1ea5 100644
--- a/test/web/feed/user_controller_test.exs
+++ b/test/web/feed/user_controller_test.exs
@@ -11,13 +11,14 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
alias Pleroma.Config
alias Pleroma.Object
alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
setup do: clear_config([:instance, :federating], true)
describe "feed" do
setup do: clear_config([:feed])
- test "gets a feed", %{conn: conn} do
+ test "gets an atom feed", %{conn: conn} do
Config.put(
[:feed, :post_title],
%{max_length: 10, omission: "..."}
@@ -157,6 +158,29 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
assert response(conn, 404)
end
+
+ test "returns feed with public and unlisted activities", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, _} = CommonAPI.post(user, %{status: "public", visibility: "public"})
+ {:ok, _} = CommonAPI.post(user, %{status: "direct", visibility: "direct"})
+ {:ok, _} = CommonAPI.post(user, %{status: "unlisted", visibility: "unlisted"})
+ {:ok, _} = CommonAPI.post(user, %{status: "private", visibility: "private"})
+
+ resp =
+ conn
+ |> put_req_header("accept", "application/atom+xml")
+ |> get(user_feed_path(conn, :feed, user.nickname))
+ |> response(200)
+
+ activity_titles =
+ resp
+ |> SweetXml.parse()
+ |> SweetXml.xpath(~x"//entry/title/text()"l)
+ |> Enum.sort()
+
+ assert activity_titles == ['public', 'unlisted']
+ end
end
# Note: see ActivityPubControllerTest for JSON format tests
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 2d256f63c..f67d294ba 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
@@ -8,12 +8,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
use Pleroma.Web.ConnCase
+ import Mock
import Pleroma.Factory
setup do: clear_config([:instance, :max_account_fields])
describe "updating credentials" do
setup do: oauth_access(["write:accounts"])
+ setup :request_content_type
test "sets user settings in a generic way", %{conn: conn} do
res_conn =
@@ -25,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
}
})
- assert user_data = json_response(res_conn, 200)
+ assert user_data = json_response_and_validate_schema(res_conn, 200)
assert user_data["pleroma"]["settings_store"] == %{"pleroma_fe" => %{"theme" => "bla"}}
user = Repo.get(User, user_data["id"])
@@ -41,7 +43,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
}
})
- assert user_data = json_response(res_conn, 200)
+ assert user_data = json_response_and_validate_schema(res_conn, 200)
assert user_data["pleroma"]["settings_store"] ==
%{
@@ -51,46 +53,58 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
user = Repo.get(User, user_data["id"])
- res_conn =
- conn
- |> assign(:user, user)
- |> patch("/api/v1/accounts/update_credentials", %{
- "pleroma_settings_store" => %{
- masto_fe: %{
- theme: "blub"
+ clear_config([:instance, :federating], true)
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _activity -> :ok end do
+ res_conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{
+ "pleroma_settings_store" => %{
+ masto_fe: %{
+ theme: "blub"
+ }
}
- }
- })
+ })
- assert user_data = json_response(res_conn, 200)
+ assert user_data = json_response_and_validate_schema(res_conn, 200)
- assert user_data["pleroma"]["settings_store"] ==
- %{
- "pleroma_fe" => %{"theme" => "bla"},
- "masto_fe" => %{"theme" => "blub"}
- }
+ assert user_data["pleroma"]["settings_store"] ==
+ %{
+ "pleroma_fe" => %{"theme" => "bla"},
+ "masto_fe" => %{"theme" => "blub"}
+ }
+
+ assert_called(Pleroma.Web.Federator.publish(:_))
+ end
end
test "updates the user's bio", %{conn: conn} do
user2 = insert(:user)
- conn =
- patch(conn, "/api/v1/accounts/update_credentials", %{
- "note" => "I drink #cofe with @#{user2.nickname}\n\nsuya.."
- })
+ raw_bio = "I drink #cofe with @#{user2.nickname}\n\nsuya.."
- assert user_data = json_response(conn, 200)
+ conn = patch(conn, "/api/v1/accounts/update_credentials", %{"note" => raw_bio})
+
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["note"] ==
~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a class="u-url mention" data-user="#{
user2.id
}" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..)
+
+ assert user_data["source"]["note"] == raw_bio
+
+ user = Repo.get(User, user_data["id"])
+
+ assert user.raw_bio == raw_bio
end
test "updates the user's locking status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{locked: "true"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["locked"] == true
end
@@ -100,21 +114,28 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{allow_following_move: "false"})
assert refresh_record(user).allow_following_move == false
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["allow_following_move"] == false
end
test "updates the user's default scope", %{conn: conn} do
- conn = patch(conn, "/api/v1/accounts/update_credentials", %{default_scope: "cofe"})
+ conn = patch(conn, "/api/v1/accounts/update_credentials", %{default_scope: "unlisted"})
- assert user_data = json_response(conn, 200)
- assert user_data["source"]["privacy"] == "cofe"
+ assert user_data = json_response_and_validate_schema(conn, 200)
+ assert user_data["source"]["privacy"] == "unlisted"
+ end
+
+ test "updates the user's privacy", %{conn: conn} do
+ conn = patch(conn, "/api/v1/accounts/update_credentials", %{source: %{privacy: "unlisted"}})
+
+ assert user_data = json_response_and_validate_schema(conn, 200)
+ assert user_data["source"]["privacy"] == "unlisted"
end
test "updates the user's hide_followers status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_followers: "true"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["hide_followers"] == true
end
@@ -122,12 +143,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
assert %{"source" => %{"pleroma" => %{"discoverable" => true}}} =
conn
|> patch("/api/v1/accounts/update_credentials", %{discoverable: "true"})
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert %{"source" => %{"pleroma" => %{"discoverable" => false}}} =
conn
|> patch("/api/v1/accounts/update_credentials", %{discoverable: "false"})
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
end
test "updates the user's hide_followers_count and hide_follows_count", %{conn: conn} do
@@ -137,7 +158,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
hide_follows_count: "true"
})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["hide_followers_count"] == true
assert user_data["pleroma"]["hide_follows_count"] == true
end
@@ -146,7 +167,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
response =
conn
|> patch("/api/v1/accounts/update_credentials", %{skip_thread_containment: "true"})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response["pleroma"]["skip_thread_containment"] == true
assert refresh_record(user).skip_thread_containment
@@ -155,28 +176,28 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
test "updates the user's hide_follows status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_follows: "true"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["hide_follows"] == true
end
test "updates the user's hide_favorites status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_favorites: "true"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["hide_favorites"] == true
end
test "updates the user's show_role status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{show_role: "false"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["source"]["pleroma"]["show_role"] == false
end
test "updates the user's no_rich_text status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{no_rich_text: "true"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["source"]["pleroma"]["no_rich_text"] == true
end
@@ -184,7 +205,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
conn =
patch(conn, "/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["display_name"] == "markorepairs"
end
@@ -197,7 +218,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
- assert user_response = json_response(conn, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["avatar"] != User.avatar_url(user)
end
@@ -210,7 +231,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header})
- assert user_response = json_response(conn, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["header"] != User.banner_url(user)
end
@@ -226,7 +247,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
"pleroma_background_image" => new_header
})
- assert user_response = json_response(conn, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["pleroma"]["background_image"]
end
@@ -237,14 +258,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
for token <- [token1, token2] do
conn =
build_conn()
+ |> put_req_header("content-type", "multipart/form-data")
|> put_req_header("authorization", "Bearer #{token.token}")
|> patch("/api/v1/accounts/update_credentials", %{})
if token == token1 do
assert %{"error" => "Insufficient permissions: write:accounts."} ==
- json_response(conn, 403)
+ json_response_and_validate_schema(conn, 403)
else
- assert json_response(conn, 200)
+ assert json_response_and_validate_schema(conn, 200)
end
end
end
@@ -259,11 +281,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
"display_name" => name
})
- assert json_response(ret_conn, 200)
+ assert json_response_and_validate_schema(ret_conn, 200)
conn = get(conn, "/api/v1/accounts/#{user.id}")
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["note"] == note
assert user_data["display_name"] == name
@@ -279,7 +301,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
account_data =
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert account_data["fields"] == [
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
@@ -312,7 +334,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
conn
|> put_req_header("content-type", "application/x-www-form-urlencoded")
|> patch("/api/v1/accounts/update_credentials", fields)
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert account["fields"] == [
%{"name" => "foo", "value" => "bar"},
@@ -337,7 +359,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
account =
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert account["fields"] == [
%{"name" => "foo", "value" => ""}
@@ -356,14 +378,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
assert %{"error" => "Invalid request"} ==
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(403)
+ |> json_response_and_validate_schema(403)
fields = [%{"name" => long_name, "value" => "bar"}]
assert %{"error" => "Invalid request"} ==
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(403)
+ |> json_response_and_validate_schema(403)
Pleroma.Config.put([:instance, :max_account_fields], 1)
@@ -375,7 +397,74 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
assert %{"error" => "Invalid request"} ==
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(403)
+ |> json_response_and_validate_schema(403)
+ end
+ end
+
+ describe "Mark account as bot" do
+ setup do: oauth_access(["write:accounts"])
+ setup :request_content_type
+
+ test "changing actor_type to Service makes account a bot", %{conn: conn} do
+ account =
+ conn
+ |> patch("/api/v1/accounts/update_credentials", %{actor_type: "Service"})
+ |> json_response_and_validate_schema(200)
+
+ assert account["bot"]
+ assert account["source"]["pleroma"]["actor_type"] == "Service"
+ end
+
+ test "changing actor_type to Person makes account a human", %{conn: conn} do
+ account =
+ conn
+ |> patch("/api/v1/accounts/update_credentials", %{actor_type: "Person"})
+ |> json_response_and_validate_schema(200)
+
+ refute account["bot"]
+ assert account["source"]["pleroma"]["actor_type"] == "Person"
+ end
+
+ test "changing actor_type to Application causes error", %{conn: conn} do
+ response =
+ conn
+ |> patch("/api/v1/accounts/update_credentials", %{actor_type: "Application"})
+ |> json_response_and_validate_schema(403)
+
+ assert %{"error" => "Invalid request"} == response
+ end
+
+ test "changing bot field to true changes actor_type to Service", %{conn: conn} do
+ account =
+ conn
+ |> patch("/api/v1/accounts/update_credentials", %{bot: "true"})
+ |> json_response_and_validate_schema(200)
+
+ assert account["bot"]
+ assert account["source"]["pleroma"]["actor_type"] == "Service"
+ end
+
+ test "changing bot field to false changes actor_type to Person", %{conn: conn} do
+ account =
+ conn
+ |> patch("/api/v1/accounts/update_credentials", %{bot: "false"})
+ |> json_response_and_validate_schema(200)
+
+ refute account["bot"]
+ assert account["source"]["pleroma"]["actor_type"] == "Person"
+ end
+
+ test "actor_type field has a higher priority than bot", %{conn: conn} do
+ account =
+ conn
+ |> patch("/api/v1/accounts/update_credentials", %{
+ actor_type: "Person",
+ bot: "true"
+ })
+ |> json_response_and_validate_schema(200)
+
+ refute account["bot"]
+ assert account["source"]["pleroma"]["actor_type"] == "Person"
end
end
end
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
index a450a732c..1ce97378d 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -19,43 +19,37 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: clear_config([:instance, :limit_to_local_content])
test "works by id" do
- user = insert(:user)
-
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.id}")
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == to_string(user.id)
+ %User{id: user_id} = insert(:user)
- conn =
- build_conn()
- |> get("/api/v1/accounts/-1")
+ assert %{"id" => ^user_id} =
+ build_conn()
+ |> get("/api/v1/accounts/#{user_id}")
+ |> json_response_and_validate_schema(200)
- assert %{"error" => "Can't find user"} = json_response(conn, 404)
+ assert %{"error" => "Can't find user"} =
+ build_conn()
+ |> get("/api/v1/accounts/-1")
+ |> json_response_and_validate_schema(404)
end
test "works by nickname" do
user = insert(:user)
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.nickname}")
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == user.id
+ assert %{"id" => user_id} =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+ |> json_response_and_validate_schema(200)
end
test "works by nickname for remote users" do
Config.put([:instance, :limit_to_local_content], false)
- user = insert(:user, nickname: "user@example.com", local: false)
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.nickname}")
+ user = insert(:user, nickname: "user@example.com", local: false)
- assert %{"id" => id} = json_response(conn, 200)
- assert id == user.id
+ assert %{"id" => user_id} =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+ |> json_response_and_validate_schema(200)
end
test "respects limit_to_local_content == :all for remote user nicknames" do
@@ -63,11 +57,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
user = insert(:user, nickname: "user@example.com", local: false)
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.nickname}")
-
- assert json_response(conn, 404)
+ assert build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+ |> json_response_and_validate_schema(404)
end
test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
@@ -80,7 +72,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
build_conn()
|> get("/api/v1/accounts/#{user.nickname}")
- assert json_response(conn, 404)
+ assert json_response_and_validate_schema(conn, 404)
conn =
build_conn()
@@ -88,7 +80,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> assign(:token, insert(:oauth_token, user: reading_user, scopes: ["read:accounts"]))
|> get("/api/v1/accounts/#{user.nickname}")
- assert %{"id" => id} = json_response(conn, 200)
+ assert %{"id" => id} = json_response_and_validate_schema(conn, 200)
assert id == user.id
end
@@ -99,21 +91,21 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
user_one = insert(:user, %{id: 1212})
user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
- resp_one =
+ acc_one =
conn
|> get("/api/v1/accounts/#{user_one.id}")
+ |> json_response_and_validate_schema(:ok)
- resp_two =
+ acc_two =
conn
|> get("/api/v1/accounts/#{user_two.nickname}")
+ |> json_response_and_validate_schema(:ok)
- resp_three =
+ acc_three =
conn
|> get("/api/v1/accounts/#{user_two.id}")
+ |> json_response_and_validate_schema(:ok)
- acc_one = json_response(resp_one, 200)
- acc_two = json_response(resp_two, 200)
- acc_three = json_response(resp_three, 200)
refute acc_one == acc_two
assert acc_two == acc_three
end
@@ -121,23 +113,19 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
test "returns 404 when user is invisible", %{conn: conn} do
user = insert(:user, %{invisible: true})
- resp =
- conn
- |> get("/api/v1/accounts/#{user.nickname}")
- |> json_response(404)
-
- assert %{"error" => "Can't find user"} = resp
+ assert %{"error" => "Can't find user"} =
+ conn
+ |> get("/api/v1/accounts/#{user.nickname}")
+ |> json_response_and_validate_schema(404)
end
test "returns 404 for internal.fetch actor", %{conn: conn} do
%User{nickname: "internal.fetch"} = InternalFetchActor.get_actor()
- resp =
- conn
- |> get("/api/v1/accounts/internal.fetch")
- |> json_response(404)
-
- assert %{"error" => "Can't find user"} = resp
+ assert %{"error" => "Can't find user"} =
+ conn
+ |> get("/api/v1/accounts/internal.fetch")
+ |> json_response_and_validate_schema(404)
end
end
@@ -155,27 +143,25 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/accounts/#{local.id}")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
-
- res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{local.id}")
+ |> json_response_and_validate_schema(:not_found)
+
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{remote.id}")
+ |> json_response_and_validate_schema(:not_found)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
@@ -187,22 +173,22 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert json_response(res_conn, :not_found) == %{
+ assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Can't find user"
}
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
@@ -213,11 +199,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert json_response(res_conn, :not_found) == %{
+ assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Can't find user"
}
end
@@ -226,46 +212,83 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
describe "user timelines" do
setup do: oauth_access(["read:statuses"])
+ test "works with announces that are just addressed to public", %{conn: conn} do
+ user = insert(:user, ap_id: "https://honktest/u/test", local: false)
+ other_user = insert(:user)
+
+ {:ok, post} = CommonAPI.post(other_user, %{status: "bonkeronk"})
+
+ {:ok, announce, _} =
+ %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "actor" => "https://honktest/u/test",
+ "id" => "https://honktest/u/test/bonk/1793M7B9MQ48847vdx",
+ "object" => post.data["object"],
+ "published" => "2019-06-25T19:33:58Z",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "type" => "Announce"
+ }
+ |> ActivityPub.persist(local: false)
+
+ assert resp =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses")
+ |> json_response_and_validate_schema(200)
+
+ assert [%{"id" => id}] = resp
+ assert id == announce.id
+ end
+
test "respects blocks", %{user: user_one, conn: conn} do
user_two = insert(:user)
user_three = insert(:user)
User.block(user_one, user_two)
- {:ok, activity} = CommonAPI.post(user_two, %{"status" => "User one sux0rz"})
- {:ok, repeat, _} = CommonAPI.repeat(activity.id, user_three)
+ {:ok, activity} = CommonAPI.post(user_two, %{status: "User one sux0rz"})
+ {:ok, repeat} = CommonAPI.repeat(activity.id, user_three)
- resp = get(conn, "/api/v1/accounts/#{user_two.id}/statuses")
+ assert resp =
+ conn
+ |> get("/api/v1/accounts/#{user_two.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id}] = json_response(resp, 200)
+ assert [%{"id" => id}] = resp
assert id == activity.id
# Even a blocked user will deliver the full user timeline, there would be
# no point in looking at a blocked users timeline otherwise
- resp = get(conn, "/api/v1/accounts/#{user_two.id}/statuses")
+ assert resp =
+ conn
+ |> get("/api/v1/accounts/#{user_two.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id}] = json_response(resp, 200)
+ assert [%{"id" => id}] = resp
assert id == activity.id
# Third user's timeline includes the repeat when viewed by unauthenticated user
- resp = get(build_conn(), "/api/v1/accounts/#{user_three.id}/statuses")
- assert [%{"id" => id}] = json_response(resp, 200)
+ resp =
+ build_conn()
+ |> get("/api/v1/accounts/#{user_three.id}/statuses")
+ |> json_response_and_validate_schema(200)
+
+ assert [%{"id" => id}] = resp
assert id == repeat.id
# When viewing a third user's timeline, the blocked users' statuses will NOT be shown
resp = get(conn, "/api/v1/accounts/#{user_three.id}/statuses")
- assert [] = json_response(resp, 200)
+ assert [] == json_response_and_validate_schema(resp, 200)
end
test "gets users statuses", %{conn: conn} do
@@ -275,20 +298,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
{:ok, _user_three} = User.follow(user_three, user_one)
- {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
+ {:ok, activity} = CommonAPI.post(user_one, %{status: "HI!!!"})
{:ok, direct_activity} =
CommonAPI.post(user_one, %{
- "status" => "Hi, @#{user_two.nickname}.",
- "visibility" => "direct"
+ status: "Hi, @#{user_two.nickname}.",
+ visibility: "direct"
})
{:ok, private_activity} =
- CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
+ CommonAPI.post(user_one, %{status: "private", visibility: "private"})
- resp = get(conn, "/api/v1/accounts/#{user_one.id}/statuses")
+ # TODO!!!
+ resp =
+ conn
+ |> get("/api/v1/accounts/#{user_one.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id}] = json_response(resp, 200)
+ assert [%{"id" => id}] = resp
assert id == to_string(activity.id)
resp =
@@ -296,8 +323,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> assign(:user, user_two)
|> assign(:token, insert(:oauth_token, user: user_two, scopes: ["read:statuses"]))
|> get("/api/v1/accounts/#{user_one.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
+ assert [%{"id" => id_one}, %{"id" => id_two}] = resp
assert id_one == to_string(direct_activity.id)
assert id_two == to_string(activity.id)
@@ -306,8 +334,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> assign(:user, user_three)
|> assign(:token, insert(:oauth_token, user: user_three, scopes: ["read:statuses"]))
|> get("/api/v1/accounts/#{user_one.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
+ assert [%{"id" => id_one}, %{"id" => id_two}] = resp
assert id_one == to_string(private_activity.id)
assert id_two == to_string(activity.id)
end
@@ -318,7 +347,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?pinned=true")
- assert json_response(conn, 200) == []
+ assert json_response_and_validate_schema(conn, 200) == []
end
test "gets an users media", %{conn: conn} do
@@ -333,56 +362,47 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
{:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
- {:ok, image_post} = CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
+ {:ok, %{id: image_post_id}} = CommonAPI.post(user, %{status: "cofe", media_ids: [media_id]})
- conn = get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?only_media=true")
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(image_post.id)
+ assert [%{"id" => ^image_post_id}] = json_response_and_validate_schema(conn, 200)
- conn = get(build_conn(), "/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
+ conn = get(build_conn(), "/api/v1/accounts/#{user.id}/statuses?only_media=1")
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(image_post.id)
+ assert [%{"id" => ^image_post_id}] = json_response_and_validate_schema(conn, 200)
end
test "gets a user's statuses without reblogs", %{user: user, conn: conn} do
- {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
- {:ok, _, _} = CommonAPI.repeat(post.id, user)
-
- conn = get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
+ {:ok, %{id: post_id}} = CommonAPI.post(user, %{status: "HI!!!"})
+ {:ok, _} = CommonAPI.repeat(post_id, user)
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_reblogs=true")
+ assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
- conn = get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_reblogs=1")
+ assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
end
test "filters user's statuses by a hashtag", %{user: user, conn: conn} do
- {:ok, post} = CommonAPI.post(user, %{"status" => "#hashtag"})
- {:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"})
-
- conn = get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"tagged" => "hashtag"})
+ {:ok, %{id: post_id}} = CommonAPI.post(user, %{status: "#hashtag"})
+ {:ok, _post} = CommonAPI.post(user, %{status: "hashtag"})
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?tagged=hashtag")
+ assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
end
test "the user views their own timelines and excludes direct messages", %{
user: user,
conn: conn
} do
- {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
- {:ok, _direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+ {:ok, %{id: public_activity_id}} =
+ CommonAPI.post(user, %{status: ".", visibility: "public"})
- conn =
- get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"exclude_visibilities" => ["direct"]})
+ {:ok, _direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(public_activity.id)
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_visibilities[]=direct")
+ assert [%{"id" => ^public_activity_id}] = json_response_and_validate_schema(conn, 200)
end
end
@@ -402,27 +422,25 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
-
- res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{local.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
+
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{remote.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
end
end
@@ -433,24 +451,23 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{local.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
end
end
@@ -462,23 +479,22 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
-
- res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{remote.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
end
end
@@ -487,12 +503,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
test "getting followers", %{user: user, conn: conn} do
other_user = insert(:user)
- {:ok, user} = User.follow(user, other_user)
+ {:ok, %{id: user_id}} = User.follow(user, other_user)
conn = get(conn, "/api/v1/accounts/#{other_user.id}/followers")
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(user.id)
+ assert [%{"id" => ^user_id}] = json_response_and_validate_schema(conn, 200)
end
test "getting followers, hide_followers", %{user: user, conn: conn} do
@@ -501,7 +516,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn = get(conn, "/api/v1/accounts/#{other_user.id}/followers")
- assert [] == json_response(conn, 200)
+ assert [] == json_response_and_validate_schema(conn, 200)
end
test "getting followers, hide_followers, same user requesting" do
@@ -515,37 +530,31 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
|> get("/api/v1/accounts/#{other_user.id}/followers")
- refute [] == json_response(conn, 200)
+ refute [] == json_response_and_validate_schema(conn, 200)
end
test "getting followers, pagination", %{user: user, conn: conn} do
- follower1 = insert(:user)
- follower2 = insert(:user)
- follower3 = insert(:user)
- {:ok, _} = User.follow(follower1, user)
- {:ok, _} = User.follow(follower2, user)
- {:ok, _} = User.follow(follower3, user)
-
- res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
+ {:ok, %User{id: follower1_id}} = :user |> insert() |> User.follow(user)
+ {:ok, %User{id: follower2_id}} = :user |> insert() |> User.follow(user)
+ {:ok, %User{id: follower3_id}} = :user |> insert() |> User.follow(user)
- assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
- assert id3 == follower3.id
- assert id2 == follower2.id
+ assert [%{"id" => ^follower3_id}, %{"id" => ^follower2_id}] =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1_id}")
+ |> json_response_and_validate_schema(200)
- res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
+ assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3_id}")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
- assert id2 == follower2.id
- assert id1 == follower1.id
+ res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3_id}")
- res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
-
- assert [%{"id" => id2}] = json_response(res_conn, 200)
- assert id2 == follower2.id
+ assert [%{"id" => ^follower2_id}] = json_response_and_validate_schema(res_conn, 200)
assert [link_header] = get_resp_header(res_conn, "link")
- assert link_header =~ ~r/min_id=#{follower2.id}/
- assert link_header =~ ~r/max_id=#{follower2.id}/
+ assert link_header =~ ~r/min_id=#{follower2_id}/
+ assert link_header =~ ~r/max_id=#{follower2_id}/
end
end
@@ -558,7 +567,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn = get(conn, "/api/v1/accounts/#{user.id}/following")
- assert [%{"id" => id}] = json_response(conn, 200)
+ assert [%{"id" => id}] = json_response_and_validate_schema(conn, 200)
assert id == to_string(other_user.id)
end
@@ -573,7 +582,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
|> get("/api/v1/accounts/#{user.id}/following")
- assert [] == json_response(conn, 200)
+ assert [] == json_response_and_validate_schema(conn, 200)
end
test "getting following, hide_follows, same user requesting" do
@@ -587,7 +596,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read:accounts"]))
|> get("/api/v1/accounts/#{user.id}/following")
- refute [] == json_response(conn, 200)
+ refute [] == json_response_and_validate_schema(conn, 200)
end
test "getting following, pagination", %{user: user, conn: conn} do
@@ -600,20 +609,20 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
res_conn = get(conn, "/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
- assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
+ assert [%{"id" => id3}, %{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
assert id3 == following3.id
assert id2 == following2.id
res_conn = get(conn, "/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
- assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
+ 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(res_conn, 200)
+ assert [%{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
assert id2 == following2.id
assert [link_header] = get_resp_header(res_conn, "link")
@@ -626,30 +635,37 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: oauth_access(["follow"])
test "following / unfollowing a user", %{conn: conn} do
- other_user = insert(:user)
-
- ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/follow")
-
- assert %{"id" => _id, "following" => true} = json_response(ret_conn, 200)
-
- ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/unfollow")
-
- assert %{"id" => _id, "following" => false} = json_response(ret_conn, 200)
-
- conn = post(conn, "/api/v1/follows", %{"uri" => other_user.nickname})
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == to_string(other_user.id)
+ %{id: other_user_id, nickname: other_user_nickname} = insert(:user)
+
+ assert %{"id" => _id, "following" => true} =
+ conn
+ |> post("/api/v1/accounts/#{other_user_id}/follow")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"id" => _id, "following" => false} =
+ conn
+ |> post("/api/v1/accounts/#{other_user_id}/unfollow")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"id" => ^other_user_id} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/follows", %{"uri" => other_user_nickname})
+ |> json_response_and_validate_schema(200)
end
test "cancelling follow request", %{conn: conn} do
%{id: other_user_id} = insert(:user, %{locked: true})
assert %{"id" => ^other_user_id, "following" => false, "requested" => true} =
- conn |> post("/api/v1/accounts/#{other_user_id}/follow") |> json_response(:ok)
+ conn
+ |> post("/api/v1/accounts/#{other_user_id}/follow")
+ |> json_response_and_validate_schema(:ok)
assert %{"id" => ^other_user_id, "following" => false, "requested" => false} =
- conn |> post("/api/v1/accounts/#{other_user_id}/unfollow") |> json_response(:ok)
+ conn
+ |> post("/api/v1/accounts/#{other_user_id}/unfollow")
+ |> json_response_and_validate_schema(:ok)
end
test "following without reblogs" do
@@ -659,51 +675,65 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow?reblogs=false")
- assert %{"showing_reblogs" => false} = json_response(ret_conn, 200)
-
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
- {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
-
- ret_conn = get(conn, "/api/v1/timelines/home")
-
- assert [] == json_response(ret_conn, 200)
+ assert %{"showing_reblogs" => false} = json_response_and_validate_schema(ret_conn, 200)
- ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow?reblogs=true")
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
+ {:ok, %{id: reblog_id}} = CommonAPI.repeat(activity.id, followed)
- assert %{"showing_reblogs" => true} = json_response(ret_conn, 200)
+ assert [] ==
+ conn
+ |> get("/api/v1/timelines/home")
+ |> json_response(200)
- conn = get(conn, "/api/v1/timelines/home")
+ assert %{"showing_reblogs" => true} =
+ conn
+ |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
+ |> json_response_and_validate_schema(200)
- expected_activity_id = reblog.id
- assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
+ assert [%{"id" => ^reblog_id}] =
+ 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")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ assert %{"error" => "Can not follow yourself"} =
+ json_response_and_validate_schema(conn_res, 400)
# self unfollow
user = User.get_cached_by_id(user.id)
conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ assert %{"error" => "Can not unfollow yourself"} =
+ json_response_and_validate_schema(conn_res, 400)
# self follow via uri
user = User.get_cached_by_id(user.id)
- conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ assert %{"error" => "Can not follow yourself"} =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/follows", %{"uri" => user.nickname})
+ |> json_response_and_validate_schema(400)
# follow non existing user
conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
# follow non existing user via uri
- conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+ conn_res =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/follows", %{"uri" => "doesntexist"})
+
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
# unfollow non existing user
conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
end
end
@@ -713,55 +743,52 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
test "with notifications", %{conn: conn} do
other_user = insert(:user)
- ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/mute")
-
- response = json_response(ret_conn, 200)
-
- assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
+ assert %{"id" => _id, "muting" => true, "muting_notifications" => true} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts/#{other_user.id}/mute")
+ |> json_response_and_validate_schema(200)
conn = post(conn, "/api/v1/accounts/#{other_user.id}/unmute")
- response = json_response(conn, 200)
- assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
+ assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
+ json_response_and_validate_schema(conn, 200)
end
test "without notifications", %{conn: conn} do
other_user = insert(:user)
ret_conn =
- post(conn, "/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
-
- response = json_response(ret_conn, 200)
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
- assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
+ assert %{"id" => _id, "muting" => true, "muting_notifications" => false} =
+ json_response_and_validate_schema(ret_conn, 200)
conn = post(conn, "/api/v1/accounts/#{other_user.id}/unmute")
- response = json_response(conn, 200)
- assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
+ assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
+ json_response_and_validate_schema(conn, 200)
end
end
describe "pinned statuses" do
setup do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"})
%{conn: conn} = oauth_access(["read:statuses"], user: user)
[conn: conn, user: user, activity: activity]
end
- test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
- {:ok, _} = CommonAPI.pin(activity.id, user)
-
- result =
- conn
- |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
- |> json_response(200)
-
- id_str = to_string(activity.id)
+ test "returns pinned statuses", %{conn: conn, user: user, activity: %{id: activity_id}} do
+ {:ok, _} = CommonAPI.pin(activity_id, user)
- assert [%{"id" => ^id_str, "pinned" => true}] = result
+ assert [%{"id" => ^activity_id, "pinned" => true}] =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
+ |> json_response_and_validate_schema(200)
end
end
@@ -771,11 +798,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/block")
- assert %{"id" => _id, "blocking" => true} = json_response(ret_conn, 200)
+ assert %{"id" => _id, "blocking" => true} = json_response_and_validate_schema(ret_conn, 200)
conn = post(conn, "/api/v1/accounts/#{other_user.id}/unblock")
- assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
+ assert %{"id" => _id, "blocking" => false} = json_response_and_validate_schema(conn, 200)
end
describe "create account by app" do
@@ -802,15 +829,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
scopes: "read, write, follow"
})
- %{
- "client_id" => client_id,
- "client_secret" => client_secret,
- "id" => _,
- "name" => "client_name",
- "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
- "vapid_key" => _,
- "website" => nil
- } = json_response(conn, 200)
+ assert %{
+ "client_id" => client_id,
+ "client_secret" => client_secret,
+ "id" => _,
+ "name" => "client_name",
+ "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
+ "vapid_key" => _,
+ "website" => nil
+ } = json_response_and_validate_schema(conn, 200)
conn =
post(conn, "/oauth/token", %{
@@ -830,6 +857,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn =
build_conn()
+ |> put_req_header("content-type", "multipart/form-data")
|> put_req_header("authorization", "Bearer " <> token)
|> post("/api/v1/accounts", %{
username: "lain",
@@ -844,7 +872,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
"created_at" => _created_at,
"scope" => _scope,
"token_type" => "Bearer"
- } = json_response(conn, 200)
+ } = json_response_and_validate_schema(conn, 200)
token_from_db = Repo.get_by(Token, token: token)
assert token_from_db
@@ -858,12 +886,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
_user = insert(:user, email: "lain@example.org")
app_token = insert(:oauth_token, user: nil)
- conn =
+ res =
conn
|> put_req_header("authorization", "Bearer " <> app_token.token)
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts", valid_params)
- res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 400) == %{"error" => "{\"email\":[\"has already been taken\"]}"}
+ assert json_response_and_validate_schema(res, 400) == %{
+ "error" => "{\"email\":[\"has already been taken\"]}"
+ }
end
test "returns bad_request if missing required params", %{
@@ -872,10 +903,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
} do
app_token = insert(:oauth_token, user: nil)
- conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
+ conn =
+ conn
+ |> put_req_header("authorization", "Bearer " <> app_token.token)
+ |> put_req_header("content-type", "application/json")
res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 200)
+ assert json_response_and_validate_schema(res, 200)
[{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
|> Stream.zip(Map.delete(valid_params, :email))
@@ -884,9 +918,18 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn
|> Map.put(:remote_ip, ip)
|> post("/api/v1/accounts", Map.delete(valid_params, attr))
- |> json_response(400)
-
- assert res == %{"error" => "Missing parameters"}
+ |> json_response_and_validate_schema(400)
+
+ assert res == %{
+ "error" => "Missing field: #{attr}.",
+ "errors" => [
+ %{
+ "message" => "Missing field: #{attr}",
+ "source" => %{"pointer" => "/#{attr}"},
+ "title" => "Invalid value"
+ }
+ ]
+ }
end)
end
@@ -897,21 +940,28 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
Pleroma.Config.put([:instance, :account_activation_required], true)
app_token = insert(:oauth_token, user: nil)
- conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
+
+ conn =
+ conn
+ |> put_req_header("authorization", "Bearer " <> app_token.token)
+ |> put_req_header("content-type", "application/json")
res =
conn
|> Map.put(:remote_ip, {127, 0, 0, 5})
|> post("/api/v1/accounts", Map.delete(valid_params, :email))
- assert json_response(res, 400) == %{"error" => "Missing parameters"}
+ assert json_response_and_validate_schema(res, 400) ==
+ %{"error" => "Missing parameter: email"}
res =
conn
|> Map.put(:remote_ip, {127, 0, 0, 6})
|> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
- assert json_response(res, 400) == %{"error" => "{\"email\":[\"can't be blank\"]}"}
+ assert json_response_and_validate_schema(res, 400) == %{
+ "error" => "{\"email\":[\"can't be blank\"]}"
+ }
end
test "allow registration without an email", %{conn: conn, valid_params: valid_params} do
@@ -920,10 +970,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
res =
conn
+ |> put_req_header("content-type", "application/json")
|> Map.put(:remote_ip, {127, 0, 0, 7})
|> post("/api/v1/accounts", Map.delete(valid_params, :email))
- assert json_response(res, 200)
+ assert json_response_and_validate_schema(res, 200)
end
test "allow registration with an empty email", %{conn: conn, valid_params: valid_params} do
@@ -932,17 +983,89 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
res =
conn
+ |> put_req_header("content-type", "application/json")
|> Map.put(:remote_ip, {127, 0, 0, 8})
|> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
- assert json_response(res, 200)
+ assert json_response_and_validate_schema(res, 200)
end
test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
- conn = put_req_header(conn, "authorization", "Bearer " <> "invalid-token")
+ res =
+ conn
+ |> put_req_header("authorization", "Bearer " <> "invalid-token")
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/accounts", valid_params)
- res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 403) == %{"error" => "Invalid credentials"}
+ assert json_response_and_validate_schema(res, 403) == %{"error" => "Invalid credentials"}
+ end
+
+ test "registration from trusted app" do
+ clear_config([Pleroma.Captcha, :enabled], true)
+ app = insert(:oauth_app, trusted: true, scopes: ["read", "write", "follow", "push"])
+
+ conn =
+ build_conn()
+ |> post("/oauth/token", %{
+ "grant_type" => "client_credentials",
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+
+ assert %{"access_token" => token, "token_type" => "Bearer"} = json_response(conn, 200)
+
+ response =
+ build_conn()
+ |> Plug.Conn.put_req_header("authorization", "Bearer " <> token)
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/accounts", %{
+ nickname: "nickanme",
+ agreement: true,
+ email: "email@example.com",
+ fullname: "Lain",
+ username: "Lain",
+ password: "some_password",
+ confirm: "some_password"
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "access_token" => access_token,
+ "created_at" => _,
+ "scope" => ["read", "write", "follow", "push"],
+ "token_type" => "Bearer"
+ } = response
+
+ response =
+ build_conn()
+ |> Plug.Conn.put_req_header("authorization", "Bearer " <> access_token)
+ |> get("/api/v1/accounts/verify_credentials")
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "acct" => "Lain",
+ "bot" => false,
+ "display_name" => "Lain",
+ "follow_requests_count" => 0,
+ "followers_count" => 0,
+ "following_count" => 0,
+ "locked" => false,
+ "note" => "",
+ "source" => %{
+ "fields" => [],
+ "note" => "",
+ "pleroma" => %{
+ "actor_type" => "Person",
+ "discoverable" => false,
+ "no_rich_text" => false,
+ "show_role" => true
+ },
+ "privacy" => "public",
+ "sensitive" => false
+ },
+ "statuses_count" => 0,
+ "username" => "Lain"
+ } = response
end
end
@@ -956,10 +1079,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn
|> put_req_header("authorization", "Bearer " <> app_token.token)
|> Map.put(:remote_ip, {15, 15, 15, 15})
+ |> put_req_header("content-type", "multipart/form-data")
for i <- 1..2 do
conn =
- post(conn, "/api/v1/accounts", %{
+ conn
+ |> post("/api/v1/accounts", %{
username: "#{i}lain",
email: "#{i}lain@example.org",
password: "PlzDontHackLain",
@@ -971,7 +1096,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
"created_at" => _created_at,
"scope" => _scope,
"token_type" => "Bearer"
- } = json_response(conn, 200)
+ } = json_response_and_validate_schema(conn, 200)
token_from_db = Repo.get_by(Token, token: token)
assert token_from_db
@@ -989,7 +1114,94 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
agreement: true
})
- assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
+ assert json_response_and_validate_schema(conn, :too_many_requests) == %{
+ "error" => "Throttled"
+ }
+ end
+ end
+
+ describe "create account with enabled captcha" do
+ setup %{conn: conn} do
+ app_token = insert(:oauth_token, user: nil)
+
+ conn =
+ conn
+ |> put_req_header("authorization", "Bearer " <> app_token.token)
+ |> put_req_header("content-type", "multipart/form-data")
+
+ [conn: conn]
+ end
+
+ setup do: clear_config([Pleroma.Captcha, :enabled], true)
+
+ test "creates an account and returns 200 if captcha is valid", %{conn: conn} do
+ %{token: token, answer_data: answer_data} = Pleroma.Captcha.new()
+
+ params = %{
+ username: "lain",
+ email: "lain@example.org",
+ password: "PlzDontHackLain",
+ agreement: true,
+ captcha_solution: Pleroma.Captcha.Mock.solution(),
+ captcha_token: token,
+ captcha_answer_data: answer_data
+ }
+
+ assert %{
+ "access_token" => access_token,
+ "created_at" => _,
+ "scope" => ["read"],
+ "token_type" => "Bearer"
+ } =
+ conn
+ |> post("/api/v1/accounts", params)
+ |> json_response_and_validate_schema(:ok)
+
+ assert Token |> Repo.get_by(token: access_token) |> Repo.preload(:user) |> Map.get(:user)
+
+ Cachex.del(:used_captcha_cache, token)
+ end
+
+ test "returns 400 if any captcha field is not provided", %{conn: conn} do
+ captcha_fields = [:captcha_solution, :captcha_token, :captcha_answer_data]
+
+ valid_params = %{
+ username: "lain",
+ email: "lain@example.org",
+ password: "PlzDontHackLain",
+ agreement: true,
+ captcha_solution: "xx",
+ captcha_token: "xx",
+ captcha_answer_data: "xx"
+ }
+
+ for field <- captcha_fields do
+ expected = %{
+ "error" => "{\"captcha\":[\"Invalid CAPTCHA (Missing parameter: #{field})\"]}"
+ }
+
+ assert expected ==
+ conn
+ |> post("/api/v1/accounts", Map.delete(valid_params, field))
+ |> json_response_and_validate_schema(:bad_request)
+ end
+ end
+
+ test "returns an error if captcha is invalid", %{conn: conn} do
+ params = %{
+ username: "lain",
+ email: "lain@example.org",
+ password: "PlzDontHackLain",
+ agreement: true,
+ captcha_solution: "cofe",
+ captcha_token: "cofe",
+ captcha_answer_data: "cofe"
+ }
+
+ assert %{"error" => "{\"captcha\":[\"Invalid answer data\"]}"} ==
+ conn
+ |> post("/api/v1/accounts", params)
+ |> json_response_and_validate_schema(:bad_request)
end
end
@@ -997,27 +1209,28 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
test "returns lists to which the account belongs" do
%{user: user, conn: conn} = oauth_access(["read:lists"])
other_user = insert(:user)
- assert {:ok, %Pleroma.List{} = list} = Pleroma.List.create("Test List", user)
+ assert {:ok, %Pleroma.List{id: list_id} = list} = Pleroma.List.create("Test List", user)
{:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
- res =
- conn
- |> get("/api/v1/accounts/#{other_user.id}/lists")
- |> json_response(200)
-
- assert res == [%{"id" => to_string(list.id), "title" => "Test List"}]
+ assert [%{"id" => list_id, "title" => "Test List"}] =
+ conn
+ |> get("/api/v1/accounts/#{other_user.id}/lists")
+ |> json_response_and_validate_schema(200)
end
end
describe "verify_credentials" do
test "verify_credentials" do
%{user: user, conn: conn} = oauth_access(["read:accounts"])
+ [notification | _] = insert_list(7, :notification, user: user)
+ Pleroma.Notification.set_read_up_to(user, notification.id)
conn = get(conn, "/api/v1/accounts/verify_credentials")
- response = json_response(conn, 200)
+ response = json_response_and_validate_schema(conn, 200)
assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
assert response["pleroma"]["chat_token"]
+ assert response["pleroma"]["unread_notifications_count"] == 6
assert id == to_string(user.id)
end
@@ -1027,7 +1240,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn = get(conn, "/api/v1/accounts/verify_credentials")
- assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
+ assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} =
+ json_response_and_validate_schema(conn, 200)
+
assert id == to_string(user.id)
end
@@ -1037,7 +1252,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn = get(conn, "/api/v1/accounts/verify_credentials")
- assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
+ assert %{"id" => id, "source" => %{"privacy" => "private"}} =
+ json_response_and_validate_schema(conn, 200)
+
assert id == to_string(user.id)
end
end
@@ -1046,20 +1263,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: oauth_access(["read:follows"])
test "returns the relationships for the current user", %{user: user, conn: conn} do
- other_user = insert(:user)
+ %{id: other_user_id} = other_user = insert(:user)
{:ok, _user} = User.follow(user, other_user)
- conn = get(conn, "/api/v1/accounts/relationships", %{"id" => [other_user.id]})
-
- assert [relationship] = json_response(conn, 200)
+ assert [%{"id" => ^other_user_id}] =
+ conn
+ |> get("/api/v1/accounts/relationships?id=#{other_user.id}")
+ |> json_response_and_validate_schema(200)
- assert to_string(other_user.id) == relationship["id"]
+ assert [%{"id" => ^other_user_id}] =
+ conn
+ |> get("/api/v1/accounts/relationships?id[]=#{other_user.id}")
+ |> json_response_and_validate_schema(200)
end
test "returns an empty list on a bad request", %{conn: conn} do
conn = get(conn, "/api/v1/accounts/relationships", %{})
- assert [] = json_response(conn, 200)
+ assert [] = json_response_and_validate_schema(conn, 200)
end
end
@@ -1072,7 +1293,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
conn = get(conn, "/api/v1/mutes")
other_user_id = to_string(other_user.id)
- assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
+ assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200)
end
test "getting a list of blocks" do
@@ -1087,6 +1308,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks")
other_user_id = to_string(other_user.id)
- assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
+ assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200)
end
end
diff --git a/test/web/mastodon_api/controllers/app_controller_test.exs b/test/web/mastodon_api/controllers/app_controller_test.exs
index e7b11d14e..a0b8b126c 100644
--- a/test/web/mastodon_api/controllers/app_controller_test.exs
+++ b/test/web/mastodon_api/controllers/app_controller_test.exs
@@ -27,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do
"vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
}
- assert expected == json_response(conn, 200)
+ assert expected == json_response_and_validate_schema(conn, 200)
end
test "creates an oauth app", %{conn: conn} do
@@ -55,6 +55,6 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do
"vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
}
- assert expected == json_response(conn, 200)
+ assert expected == json_response_and_validate_schema(conn, 200)
end
end
diff --git a/test/web/mastodon_api/controllers/conversation_controller_test.exs b/test/web/mastodon_api/controllers/conversation_controller_test.exs
index 801b0259b..3e21e6bf1 100644
--- a/test/web/mastodon_api/controllers/conversation_controller_test.exs
+++ b/test/web/mastodon_api/controllers/conversation_controller_test.exs
@@ -12,133 +12,127 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
setup do: oauth_access(["read:statuses"])
- test "returns a list of conversations", %{user: user_one, conn: conn} do
- user_two = insert(:user)
- user_three = insert(:user)
-
- {:ok, user_two} = User.follow(user_two, user_one)
-
- assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
-
- {:ok, direct} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!",
- "visibility" => "direct"
- })
-
- assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1
-
- {:ok, _follower_only} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}!",
- "visibility" => "private"
- })
-
- res_conn = get(conn, "/api/v1/conversations")
-
- assert response = json_response(res_conn, 200)
-
- assert [
- %{
- "id" => res_id,
- "accounts" => res_accounts,
- "last_status" => res_last_status,
- "unread" => unread
- }
- ] = response
-
- account_ids = Enum.map(res_accounts, & &1["id"])
- assert length(res_accounts) == 2
- assert user_two.id in account_ids
- assert user_three.id in account_ids
- assert is_binary(res_id)
- assert unread == false
- assert res_last_status["id"] == direct.id
- assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
+ describe "returns a list of conversations" do
+ setup(%{user: user_one, conn: conn}) do
+ user_two = insert(:user)
+ user_three = insert(:user)
+
+ {:ok, user_two} = User.follow(user_two, user_one)
+
+ {:ok, %{user: user_one, user_two: user_two, user_three: user_three, conn: conn}}
+ end
+
+ test "returns correct conversations", %{
+ user: user_one,
+ user_two: user_two,
+ user_three: user_three,
+ conn: conn
+ } do
+ assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
+ {:ok, direct} = create_direct_message(user_one, [user_two, user_three])
+
+ assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1
+
+ {:ok, _follower_only} =
+ CommonAPI.post(user_one, %{
+ status: "Hi @#{user_two.nickname}!",
+ visibility: "private"
+ })
+
+ res_conn = get(conn, "/api/v1/conversations")
+
+ assert response = json_response_and_validate_schema(res_conn, 200)
+
+ assert [
+ %{
+ "id" => res_id,
+ "accounts" => res_accounts,
+ "last_status" => res_last_status,
+ "unread" => unread
+ }
+ ] = response
+
+ account_ids = Enum.map(res_accounts, & &1["id"])
+ assert length(res_accounts) == 2
+ assert user_two.id in account_ids
+ assert user_three.id in account_ids
+ assert is_binary(res_id)
+ assert unread == false
+ assert res_last_status["id"] == direct.id
+ assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
+ end
+
+ test "observes limit params", %{
+ user: user_one,
+ user_two: user_two,
+ user_three: user_three,
+ conn: conn
+ } do
+ {:ok, _} = create_direct_message(user_one, [user_two, user_three])
+ {:ok, _} = create_direct_message(user_two, [user_one, user_three])
+ {:ok, _} = create_direct_message(user_three, [user_two, user_one])
+
+ res_conn = get(conn, "/api/v1/conversations?limit=1")
+
+ assert response = json_response_and_validate_schema(res_conn, 200)
+
+ assert Enum.count(response) == 1
+
+ res_conn = get(conn, "/api/v1/conversations?limit=2")
+
+ assert response = json_response_and_validate_schema(res_conn, 200)
+
+ assert Enum.count(response) == 2
+ end
end
test "filters conversations by recipients", %{user: user_one, conn: conn} do
user_two = insert(:user)
user_three = insert(:user)
+ {:ok, direct1} = create_direct_message(user_one, [user_two])
+ {:ok, _direct2} = create_direct_message(user_one, [user_three])
+ {:ok, direct3} = create_direct_message(user_one, [user_two, user_three])
+ {:ok, _direct4} = create_direct_message(user_two, [user_three])
+ {:ok, direct5} = create_direct_message(user_two, [user_one])
- {:ok, direct1} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}!",
- "visibility" => "direct"
- })
-
- {:ok, _direct2} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_three.nickname}!",
- "visibility" => "direct"
- })
-
- {:ok, direct3} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!",
- "visibility" => "direct"
- })
-
- {:ok, _direct4} =
- CommonAPI.post(user_two, %{
- "status" => "Hi @#{user_three.nickname}!",
- "visibility" => "direct"
- })
-
- {:ok, direct5} =
- CommonAPI.post(user_two, %{
- "status" => "Hi @#{user_one.nickname}!",
- "visibility" => "direct"
- })
-
- [conversation1, conversation2] =
- conn
- |> get("/api/v1/conversations", %{"recipients" => [user_two.id]})
- |> json_response(200)
+ assert [conversation1, conversation2] =
+ conn
+ |> get("/api/v1/conversations?recipients[]=#{user_two.id}")
+ |> json_response_and_validate_schema(200)
assert conversation1["last_status"]["id"] == direct5.id
assert conversation2["last_status"]["id"] == direct1.id
[conversation1] =
conn
- |> get("/api/v1/conversations", %{"recipients" => [user_two.id, user_three.id]})
- |> json_response(200)
+ |> get("/api/v1/conversations?recipients[]=#{user_two.id}&recipients[]=#{user_three.id}")
+ |> json_response_and_validate_schema(200)
assert conversation1["last_status"]["id"] == direct3.id
end
test "updates the last_status on reply", %{user: user_one, conn: conn} do
user_two = insert(:user)
-
- {:ok, direct} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}",
- "visibility" => "direct"
- })
+ {:ok, direct} = create_direct_message(user_one, [user_two])
{:ok, direct_reply} =
CommonAPI.post(user_two, %{
- "status" => "reply",
- "visibility" => "direct",
- "in_reply_to_status_id" => direct.id
+ status: "reply",
+ visibility: "direct",
+ in_reply_to_status_id: direct.id
})
[%{"last_status" => res_last_status}] =
conn
|> get("/api/v1/conversations")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert res_last_status["id"] == direct_reply.id
end
test "the user marks a conversation as read", %{user: user_one, conn: conn} do
user_two = insert(:user)
-
- {:ok, direct} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}",
- "visibility" => "direct"
- })
+ {:ok, direct} = create_direct_message(user_one, [user_two])
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1
@@ -154,12 +148,12 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
[%{"id" => direct_conversation_id, "unread" => true}] =
user_two_conn
|> get("/api/v1/conversations")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
%{"unread" => false} =
user_two_conn
|> post("/api/v1/conversations/#{direct_conversation_id}/read")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
@@ -167,15 +161,15 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
# The conversation is marked as unread on reply
{:ok, _} =
CommonAPI.post(user_two, %{
- "status" => "reply",
- "visibility" => "direct",
- "in_reply_to_status_id" => direct.id
+ status: "reply",
+ visibility: "direct",
+ in_reply_to_status_id: direct.id
})
[%{"unread" => true}] =
conn
|> get("/api/v1/conversations")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
@@ -183,9 +177,9 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
# A reply doesn't increment the user's unread_conversation_count if the conversation is unread
{:ok, _} =
CommonAPI.post(user_two, %{
- "status" => "reply",
- "visibility" => "direct",
- "in_reply_to_status_id" => direct.id
+ status: "reply",
+ visibility: "direct",
+ in_reply_to_status_id: direct.id
})
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
@@ -194,15 +188,22 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
test "(vanilla) Mastodon frontend behaviour", %{user: user_one, conn: conn} do
user_two = insert(:user)
-
- {:ok, direct} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}!",
- "visibility" => "direct"
- })
+ {:ok, direct} = create_direct_message(user_one, [user_two])
res_conn = get(conn, "/api/v1/statuses/#{direct.id}/context")
assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
end
+
+ defp create_direct_message(sender, recips) do
+ hellos =
+ recips
+ |> Enum.map(fn s -> "@#{s.nickname}" end)
+ |> Enum.join(", ")
+
+ CommonAPI.post(sender, %{
+ status: "Hi #{hellos}!",
+ visibility: "direct"
+ })
+ end
end
diff --git a/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs
index 6567a0667..ab0027f90 100644
--- a/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs
+++ b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs
@@ -6,11 +6,12 @@ defmodule Pleroma.Web.MastodonAPI.CustomEmojiControllerTest do
use Pleroma.Web.ConnCase, async: true
test "with tags", %{conn: conn} do
- [emoji | _body] =
- conn
- |> get("/api/v1/custom_emojis")
- |> json_response(200)
+ assert resp =
+ conn
+ |> get("/api/v1/custom_emojis")
+ |> json_response_and_validate_schema(200)
+ assert [emoji | _body] = resp
assert Map.has_key?(emoji, "shortcode")
assert Map.has_key?(emoji, "static_url")
assert Map.has_key?(emoji, "tags")
diff --git a/test/web/mastodon_api/controllers/domain_block_controller_test.exs b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
index d66190c90..01a24afcf 100644
--- a/test/web/mastodon_api/controllers/domain_block_controller_test.exs
+++ b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
@@ -6,11 +6,8 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.User
- alias Pleroma.Web.ApiSpec
- alias Pleroma.Web.ApiSpec.Schemas.DomainBlocksResponse
import Pleroma.Factory
- import OpenApiSpex.TestAssertions
test "blocking / unblocking a domain" do
%{user: user, conn: conn} = oauth_access(["write:blocks"])
@@ -21,7 +18,7 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
|> put_req_header("content-type", "application/json")
|> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
- assert %{} = json_response(ret_conn, 200)
+ assert %{} == json_response_and_validate_schema(ret_conn, 200)
user = User.get_cached_by_ap_id(user.ap_id)
assert User.blocks?(user, other_user)
@@ -30,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
|> put_req_header("content-type", "application/json")
|> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
- assert %{} = json_response(ret_conn, 200)
+ assert %{} == json_response_and_validate_schema(ret_conn, 200)
user = User.get_cached_by_ap_id(user.ap_id)
refute User.blocks?(user, other_user)
end
@@ -41,21 +38,10 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
{:ok, user} = User.block_domain(user, "bad.site")
{:ok, user} = User.block_domain(user, "even.worse.site")
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/domain_blocks")
-
- domain_blocks = json_response(conn, 200)
-
- assert "bad.site" in domain_blocks
- assert "even.worse.site" in domain_blocks
- assert_schema(domain_blocks, "DomainBlocksResponse", ApiSpec.spec())
- end
-
- test "DomainBlocksResponse example matches schema" do
- api_spec = ApiSpec.spec()
- schema = DomainBlocksResponse.schema()
- assert_schema(schema.example, "DomainBlocksResponse", api_spec)
+ assert ["even.worse.site", "bad.site"] ==
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/domain_blocks")
+ |> json_response_and_validate_schema(200)
end
end
diff --git a/test/web/mastodon_api/controllers/filter_controller_test.exs b/test/web/mastodon_api/controllers/filter_controller_test.exs
index 97ab005e0..f29547d13 100644
--- a/test/web/mastodon_api/controllers/filter_controller_test.exs
+++ b/test/web/mastodon_api/controllers/filter_controller_test.exs
@@ -15,9 +15,12 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
context: ["home"]
}
- conn = post(conn, "/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
- assert response = json_response(conn, 200)
+ assert response = json_response_and_validate_schema(conn, 200)
assert response["phrase"] == filter.phrase
assert response["context"] == filter.context
assert response["irreversible"] == false
@@ -48,12 +51,12 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
response =
conn
|> get("/api/v1/filters")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response ==
render_json(
FilterView,
- "filters.json",
+ "index.json",
filters: [filter_two, filter_one]
)
end
@@ -72,7 +75,7 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
conn = get(conn, "/api/v1/filters/#{filter.filter_id}")
- assert _response = json_response(conn, 200)
+ assert response = json_response_and_validate_schema(conn, 200)
end
test "update a filter" do
@@ -82,7 +85,8 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
user_id: user.id,
filter_id: 2,
phrase: "knight",
- context: ["home"]
+ context: ["home"],
+ hide: true
}
{:ok, _filter} = Pleroma.Filter.create(query)
@@ -93,14 +97,17 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
}
conn =
- put(conn, "/api/v1/filters/#{query.filter_id}", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/v1/filters/#{query.filter_id}", %{
phrase: new.phrase,
context: new.context
})
- assert response = json_response(conn, 200)
+ assert response = json_response_and_validate_schema(conn, 200)
assert response["phrase"] == new.phrase
assert response["context"] == new.context
+ assert response["irreversible"] == true
end
test "delete a filter" do
@@ -117,7 +124,6 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
conn = delete(conn, "/api/v1/filters/#{filter.filter_id}")
- assert response = json_response(conn, 200)
- assert response == %{}
+ assert json_response_and_validate_schema(conn, 200) == %{}
end
end
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 d8dbe4800..44e12d15a 100644
--- a/test/web/mastodon_api/controllers/follow_request_controller_test.exs
+++ b/test/web/mastodon_api/controllers/follow_request_controller_test.exs
@@ -27,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
conn = get(conn, "/api/v1/follow_requests")
- assert [relationship] = json_response(conn, 200)
+ assert [relationship] = json_response_and_validate_schema(conn, 200)
assert to_string(other_user.id) == relationship["id"]
end
@@ -44,7 +44,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
conn = post(conn, "/api/v1/follow_requests/#{other_user.id}/authorize")
- assert relationship = json_response(conn, 200)
+ assert relationship = json_response_and_validate_schema(conn, 200)
assert to_string(other_user.id) == relationship["id"]
user = User.get_cached_by_id(user.id)
@@ -62,7 +62,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
conn = post(conn, "/api/v1/follow_requests/#{other_user.id}/reject")
- assert relationship = json_response(conn, 200)
+ assert relationship = json_response_and_validate_schema(conn, 200)
assert to_string(other_user.id) == relationship["id"]
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 2737dcaba..8bdfdddd1 100644
--- a/test/web/mastodon_api/controllers/instance_controller_test.exs
+++ b/test/web/mastodon_api/controllers/instance_controller_test.exs
@@ -10,7 +10,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
test "get instance information", %{conn: conn} do
conn = get(conn, "/api/v1/instance")
- assert result = json_response(conn, 200)
+ assert result = json_response_and_validate_schema(conn, 200)
email = Pleroma.Config.get([:instance, :email])
# Note: not checking for "max_toot_chars" since it's optional
@@ -31,9 +31,14 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
"upload_limit" => _,
"avatar_upload_limit" => _,
"background_upload_limit" => _,
- "banner_upload_limit" => _
+ "banner_upload_limit" => _,
+ "background_image" => _
} = result
+ assert result["pleroma"]["metadata"]["features"]
+ assert result["pleroma"]["metadata"]["federation"]
+ assert result["pleroma"]["vapid_public_key"]
+
assert email == from_config_email
end
@@ -46,13 +51,13 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
insert(:user, %{local: false, nickname: "u@peer1.com"})
insert(:user, %{local: false, nickname: "u@peer2.com"})
- {:ok, _} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofe"})
+ {:ok, _} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"})
Pleroma.Stats.force_update()
conn = get(conn, "/api/v1/instance")
- assert result = json_response(conn, 200)
+ assert result = json_response_and_validate_schema(conn, 200)
stats = result["stats"]
@@ -70,7 +75,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
conn = get(conn, "/api/v1/instance/peers")
- assert result = json_response(conn, 200)
+ assert result = json_response_and_validate_schema(conn, 200)
assert ["peer1.com", "peer2.com"] == Enum.sort(result)
end
diff --git a/test/web/mastodon_api/controllers/list_controller_test.exs b/test/web/mastodon_api/controllers/list_controller_test.exs
index c9c4cbb49..57a9ef4a4 100644
--- a/test/web/mastodon_api/controllers/list_controller_test.exs
+++ b/test/web/mastodon_api/controllers/list_controller_test.exs
@@ -12,37 +12,44 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
test "creating a list" do
%{conn: conn} = oauth_access(["write:lists"])
- conn = post(conn, "/api/v1/lists", %{"title" => "cuties"})
-
- assert %{"title" => title} = json_response(conn, 200)
- assert title == "cuties"
+ assert %{"title" => "cuties"} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/lists", %{"title" => "cuties"})
+ |> json_response_and_validate_schema(:ok)
end
test "renders error for invalid params" do
%{conn: conn} = oauth_access(["write:lists"])
- conn = post(conn, "/api/v1/lists", %{"title" => nil})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/lists", %{"title" => nil})
- assert %{"error" => "can't be blank"} == json_response(conn, :unprocessable_entity)
+ assert %{"error" => "title - null value where string expected."} =
+ json_response_and_validate_schema(conn, 400)
end
test "listing a user's lists" do
%{conn: conn} = oauth_access(["read:lists", "write:lists"])
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/lists", %{"title" => "cuties"})
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/lists", %{"title" => "cofe"})
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
conn = get(conn, "/api/v1/lists")
assert [
%{"id" => _, "title" => "cofe"},
%{"id" => _, "title" => "cuties"}
- ] = json_response(conn, :ok)
+ ] = json_response_and_validate_schema(conn, :ok)
end
test "adding users to a list" do
@@ -50,9 +57,12 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
other_user = insert(:user)
{:ok, list} = Pleroma.List.create("name", user)
- conn = post(conn, "/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
+ assert %{} ==
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
+ |> json_response_and_validate_schema(:ok)
- assert %{} == json_response(conn, 200)
%Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
assert following == [other_user.follower_address]
end
@@ -65,9 +75,12 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
{:ok, list} = Pleroma.List.follow(list, other_user)
{:ok, list} = Pleroma.List.follow(list, third_user)
- conn = delete(conn, "/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
+ assert %{} ==
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
+ |> json_response_and_validate_schema(:ok)
- assert %{} == json_response(conn, 200)
%Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
assert following == [third_user.follower_address]
end
@@ -83,7 +96,7 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
|> assign(:user, user)
|> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
- assert [%{"id" => id}] = json_response(conn, 200)
+ assert [%{"id" => id}] = json_response_and_validate_schema(conn, 200)
assert id == to_string(other_user.id)
end
@@ -96,7 +109,7 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
|> assign(:user, user)
|> get("/api/v1/lists/#{list.id}")
- assert %{"id" => id} = json_response(conn, 200)
+ assert %{"id" => id} = json_response_and_validate_schema(conn, 200)
assert id == to_string(list.id)
end
@@ -105,17 +118,18 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
conn = get(conn, "/api/v1/lists/666")
- assert %{"error" => "List not found"} = json_response(conn, :not_found)
+ assert %{"error" => "List not found"} = json_response_and_validate_schema(conn, :not_found)
end
test "renaming a list" do
%{user: user, conn: conn} = oauth_access(["write:lists"])
{:ok, list} = Pleroma.List.create("name", user)
- conn = put(conn, "/api/v1/lists/#{list.id}", %{"title" => "newname"})
-
- assert %{"title" => name} = json_response(conn, 200)
- assert name == "newname"
+ assert %{"title" => "newname"} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
+ |> json_response_and_validate_schema(:ok)
end
test "validates title when renaming a list" do
@@ -125,9 +139,11 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
conn =
conn
|> assign(:user, user)
+ |> put_req_header("content-type", "application/json")
|> put("/api/v1/lists/#{list.id}", %{"title" => " "})
- assert %{"error" => "can't be blank"} == json_response(conn, :unprocessable_entity)
+ assert %{"error" => "can't be blank"} ==
+ json_response_and_validate_schema(conn, :unprocessable_entity)
end
test "deleting a list" do
@@ -136,7 +152,7 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
conn = delete(conn, "/api/v1/lists/#{list.id}")
- assert %{} = json_response(conn, 200)
+ assert %{} = json_response_and_validate_schema(conn, 200)
assert is_nil(Repo.get(Pleroma.List, list.id))
end
end
diff --git a/test/web/mastodon_api/controllers/marker_controller_test.exs b/test/web/mastodon_api/controllers/marker_controller_test.exs
index 919f295bd..6dd40fb4a 100644
--- a/test/web/mastodon_api/controllers/marker_controller_test.exs
+++ b/test/web/mastodon_api/controllers/marker_controller_test.exs
@@ -11,6 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
test "gets markers with correct scopes", %{conn: conn} do
user = insert(:user)
token = insert(:oauth_token, user: user, scopes: ["read:statuses"])
+ insert_list(7, :notification, user: user)
{:ok, %{"notifications" => marker}} =
Pleroma.Marker.upsert(
@@ -22,14 +23,15 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
conn
|> assign(:user, user)
|> assign(:token, token)
- |> get("/api/v1/markers", %{timeline: ["notifications"]})
- |> json_response(200)
+ |> get("/api/v1/markers?timeline[]=notifications")
+ |> json_response_and_validate_schema(200)
assert response == %{
"notifications" => %{
"last_read_id" => "69420",
"updated_at" => NaiveDateTime.to_iso8601(marker.updated_at),
- "version" => 0
+ "version" => 0,
+ "pleroma" => %{"unread_count" => 7}
}
}
end
@@ -45,7 +47,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
|> assign(:user, user)
|> assign(:token, token)
|> get("/api/v1/markers", %{timeline: ["notifications"]})
- |> json_response(403)
+ |> json_response_and_validate_schema(403)
assert response == %{"error" => "Insufficient permissions: read:statuses."}
end
@@ -60,17 +62,19 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
conn
|> assign(:user, user)
|> assign(:token, token)
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/markers", %{
home: %{last_read_id: "777"},
notifications: %{"last_read_id" => "69420"}
})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert %{
"notifications" => %{
"last_read_id" => "69420",
"updated_at" => _,
- "version" => 0
+ "version" => 0,
+ "pleroma" => %{"unread_count" => 0}
}
} = response
end
@@ -89,17 +93,19 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
conn
|> assign(:user, user)
|> assign(:token, token)
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/markers", %{
home: %{last_read_id: "777"},
notifications: %{"last_read_id" => "69888"}
})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response == %{
"notifications" => %{
"last_read_id" => "69888",
"updated_at" => NaiveDateTime.to_iso8601(marker.updated_at),
- "version" => 0
+ "version" => 0,
+ "pleroma" => %{"unread_count" => 0}
}
}
end
@@ -112,11 +118,12 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
conn
|> assign(:user, user)
|> assign(:token, token)
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/markers", %{
home: %{last_read_id: "777"},
notifications: %{"last_read_id" => "69420"}
})
- |> json_response(403)
+ |> json_response_and_validate_schema(403)
assert response == %{"error" => "Insufficient permissions: write:statuses."}
end
diff --git a/test/web/mastodon_api/controllers/media_controller_test.exs b/test/web/mastodon_api/controllers/media_controller_test.exs
index 6ac4cf63b..906fd940f 100644
--- a/test/web/mastodon_api/controllers/media_controller_test.exs
+++ b/test/web/mastodon_api/controllers/media_controller_test.exs
@@ -9,9 +9,9 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
- setup do: oauth_access(["write:media"])
+ describe "Upload media" do
+ setup do: oauth_access(["write:media"])
- describe "media upload" do
setup do
image = %Plug.Upload{
content_type: "image/jpg",
@@ -25,13 +25,14 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
setup do: clear_config([:media_proxy])
setup do: clear_config([Pleroma.Upload])
- test "returns uploaded image", %{conn: conn, image: image} do
+ test "/api/v1/media", %{conn: conn, image: image} do
desc = "Description of the image"
media =
conn
+ |> put_req_header("content-type", "multipart/form-data")
|> post("/api/v1/media", %{"file" => image, "description" => desc})
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert media["type"] == "image"
assert media["description"] == desc
@@ -40,9 +41,37 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
object = Object.get_by_id(media["id"])
assert object.data["actor"] == User.ap_id(conn.assigns[:user])
end
+
+ test "/api/v2/media", %{conn: conn, user: user, image: image} do
+ desc = "Description of the image"
+
+ response =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v2/media", %{"file" => image, "description" => desc})
+ |> json_response_and_validate_schema(202)
+
+ assert media_id = response["id"]
+
+ %{conn: conn} = oauth_access(["read:media"], user: user)
+
+ media =
+ conn
+ |> get("/api/v1/media/#{media_id}")
+ |> json_response_and_validate_schema(200)
+
+ assert media["type"] == "image"
+ assert media["description"] == desc
+ assert media["id"]
+
+ object = Object.get_by_id(media["id"])
+ assert object.data["actor"] == user.ap_id
+ end
end
- describe "PUT /api/v1/media/:id" do
+ describe "Update media description" do
+ setup do: oauth_access(["write:media"])
+
setup %{user: actor} do
file = %Plug.Upload{
content_type: "image/jpg",
@@ -60,23 +89,58 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
[object: object]
end
- test "updates name of media", %{conn: conn, object: object} do
+ test "/api/v1/media/:id good request", %{conn: conn, object: object} do
media =
conn
+ |> put_req_header("content-type", "multipart/form-data")
|> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert media["description"] == "test-media"
assert refresh_record(object).data["name"] == "test-media"
end
+ end
+
+ describe "Get media by id (/api/v1/media/:id)" do
+ setup do: oauth_access(["read:media"])
+
+ setup %{user: actor} do
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, %Object{} = object} =
+ ActivityPub.upload(
+ file,
+ actor: User.ap_id(actor),
+ description: "test-media"
+ )
+
+ [object: object]
+ end
- test "returns error when request is bad", %{conn: conn, object: object} do
+ test "it returns media object when requested by owner", %{conn: conn, object: object} do
media =
conn
- |> put("/api/v1/media/#{object.id}", %{})
- |> json_response(400)
+ |> get("/api/v1/media/#{object.id}")
+ |> json_response_and_validate_schema(:ok)
+
+ assert media["description"] == "test-media"
+ assert media["type"] == "image"
+ assert media["id"]
+ end
+
+ test "it returns 403 if media object requested by non-owner", %{object: object, user: user} do
+ %{conn: conn, user: other_user} = oauth_access(["read:media"])
+
+ assert object.data["actor"] == user.ap_id
+ refute user.id == other_user.id
- assert media == %{"error" => "bad_request"}
+ conn
+ |> get("/api/v1/media/#{object.id}")
+ |> json_response(403)
end
end
end
diff --git a/test/web/mastodon_api/controllers/notification_controller_test.exs b/test/web/mastodon_api/controllers/notification_controller_test.exs
index 8c815b415..70ef0e8b5 100644
--- a/test/web/mastodon_api/controllers/notification_controller_test.exs
+++ b/test/web/mastodon_api/controllers/notification_controller_test.exs
@@ -12,20 +12,18 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
import Pleroma.Factory
- test "does NOT render account/pleroma/relationship if this is disabled by default" do
- clear_config([:extensions, :output_relationships_in_statuses_by_default], false)
-
+ test "does NOT render account/pleroma/relationship by default" do
%{user: user, conn: conn} = oauth_access(["read:notifications"])
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
{:ok, [_notification]} = Notification.create_notifications(activity)
response =
conn
|> assign(:user, user)
|> get("/api/v1/notifications")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert Enum.all?(response, fn n ->
get_in(n, ["account", "pleroma", "relationship"]) == %{}
@@ -36,7 +34,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
%{user: user, conn: conn} = oauth_access(["read:notifications"])
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
{:ok, [_notification]} = Notification.create_notifications(activity)
@@ -50,15 +48,38 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
user.ap_id
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
- assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
+ assert [%{"status" => %{"content" => response}} | _rest] =
+ json_response_and_validate_schema(conn, 200)
+
assert response == expected_response
end
+ test "by default, does not contain pleroma:chat_mention" do
+ %{user: user, conn: conn} = oauth_access(["read:notifications"])
+ other_user = insert(:user)
+
+ {:ok, _activity} = CommonAPI.post_chat_message(other_user, user, "hey")
+
+ result =
+ conn
+ |> get("/api/v1/notifications")
+ |> json_response_and_validate_schema(200)
+
+ assert [] == result
+
+ result =
+ conn
+ |> get("/api/v1/notifications?include_types[]=pleroma:chat_mention")
+ |> json_response_and_validate_schema(200)
+
+ assert [_] = result
+ end
+
test "getting a single notification" do
%{user: user, conn: conn} = oauth_access(["read:notifications"])
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
{:ok, [notification]} = Notification.create_notifications(activity)
@@ -69,7 +90,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
user.ap_id
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
- assert %{"status" => %{"content" => response}} = json_response(conn, 200)
+ assert %{"status" => %{"content" => response}} = json_response_and_validate_schema(conn, 200)
assert response == expected_response
end
@@ -77,23 +98,24 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
%{user: user, conn: conn} = oauth_access(["write:notifications"])
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
{:ok, [notification]} = Notification.create_notifications(activity)
conn =
conn
|> assign(:user, user)
- |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/notifications/dismiss", %{"id" => to_string(notification.id)})
- assert %{} = json_response(conn, 200)
+ assert %{} = json_response_and_validate_schema(conn, 200)
end
test "dismissing a single notification" do
%{user: user, conn: conn} = oauth_access(["write:notifications"])
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
{:ok, [notification]} = Notification.create_notifications(activity)
@@ -102,24 +124,24 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|> assign(:user, user)
|> post("/api/v1/notifications/#{notification.id}/dismiss")
- assert %{} = json_response(conn, 200)
+ assert %{} = json_response_and_validate_schema(conn, 200)
end
test "clearing all notifications" do
%{user: user, conn: conn} = oauth_access(["write:notifications", "read:notifications"])
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
{:ok, [_notification]} = Notification.create_notifications(activity)
ret_conn = post(conn, "/api/v1/notifications/clear")
- assert %{} = json_response(ret_conn, 200)
+ assert %{} = json_response_and_validate_schema(ret_conn, 200)
ret_conn = get(conn, "/api/v1/notifications")
- assert all = json_response(ret_conn, 200)
+ assert all = json_response_and_validate_schema(ret_conn, 200)
assert all == []
end
@@ -127,10 +149,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
%{user: user, conn: conn} = oauth_access(["read:notifications"])
other_user = insert(:user)
- {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity3} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity4} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
+ {:ok, activity1} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
+ {:ok, activity2} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
+ {:ok, activity3} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
+ {:ok, activity4} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
notification1_id = get_notification_id_by_activity(activity1)
notification2_id = get_notification_id_by_activity(activity2)
@@ -143,7 +165,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
result =
conn
|> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
@@ -151,7 +173,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
result =
conn
|> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
@@ -159,7 +181,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
result =
conn
|> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
end
@@ -170,47 +192,39 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
other_user = insert(:user)
{:ok, public_activity} =
- CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "public"})
+ CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "public"})
{:ok, direct_activity} =
- CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"})
+ CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "direct"})
{:ok, unlisted_activity} =
- CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "unlisted"})
+ CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "unlisted"})
{:ok, private_activity} =
- CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "private"})
+ CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "private"})
- conn_res =
- get(conn, "/api/v1/notifications", %{
- exclude_visibilities: ["public", "unlisted", "private"]
- })
+ query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "private"]})
+ conn_res = get(conn, "/api/v1/notifications?" <> query)
- assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+ assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
assert id == direct_activity.id
- conn_res =
- get(conn, "/api/v1/notifications", %{
- exclude_visibilities: ["public", "unlisted", "direct"]
- })
+ query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "direct"]})
+ conn_res = get(conn, "/api/v1/notifications?" <> query)
- assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+ assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
assert id == private_activity.id
- conn_res =
- get(conn, "/api/v1/notifications", %{
- exclude_visibilities: ["public", "private", "direct"]
- })
+ query = params_to_query(%{exclude_visibilities: ["public", "private", "direct"]})
+ conn_res = get(conn, "/api/v1/notifications?" <> query)
- assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+ assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
assert id == unlisted_activity.id
- conn_res =
- get(conn, "/api/v1/notifications", %{
- exclude_visibilities: ["unlisted", "private", "direct"]
- })
+ query = params_to_query(%{exclude_visibilities: ["unlisted", "private", "direct"]})
+ conn_res = get(conn, "/api/v1/notifications?" <> query)
- assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+ assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
assert id == public_activity.id
end
@@ -218,17 +232,15 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
user = insert(:user)
%{user: other_user, conn: conn} = oauth_access(["read:notifications"])
- {:ok, public_activity} =
- CommonAPI.post(other_user, %{"status" => ".", "visibility" => "public"})
+ {:ok, public_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "public"})
{:ok, direct_activity} =
- CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"})
+ CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "direct"})
{:ok, unlisted_activity} =
- CommonAPI.post(other_user, %{"status" => ".", "visibility" => "unlisted"})
+ CommonAPI.post(other_user, %{status: ".", visibility: "unlisted"})
- {:ok, private_activity} =
- CommonAPI.post(other_user, %{"status" => ".", "visibility" => "private"})
+ {:ok, private_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "private"})
{:ok, _} = CommonAPI.favorite(user, public_activity.id)
{:ok, _} = CommonAPI.favorite(user, direct_activity.id)
@@ -237,8 +249,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
activity_ids =
conn
- |> get("/api/v1/notifications", %{exclude_visibilities: ["direct"]})
- |> json_response(200)
+ |> get("/api/v1/notifications?exclude_visibilities[]=direct")
+ |> json_response_and_validate_schema(200)
|> Enum.map(& &1["status"]["id"])
assert public_activity.id in activity_ids
@@ -248,8 +260,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
activity_ids =
conn
- |> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
- |> json_response(200)
+ |> get("/api/v1/notifications?exclude_visibilities[]=unlisted")
+ |> json_response_and_validate_schema(200)
|> Enum.map(& &1["status"]["id"])
assert public_activity.id in activity_ids
@@ -259,8 +271,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
activity_ids =
conn
- |> get("/api/v1/notifications", %{exclude_visibilities: ["private"]})
- |> json_response(200)
+ |> get("/api/v1/notifications?exclude_visibilities[]=private")
+ |> json_response_and_validate_schema(200)
|> Enum.map(& &1["status"]["id"])
assert public_activity.id in activity_ids
@@ -270,8 +282,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
activity_ids =
conn
- |> get("/api/v1/notifications", %{exclude_visibilities: ["public"]})
- |> json_response(200)
+ |> get("/api/v1/notifications?exclude_visibilities[]=public")
+ |> json_response_and_validate_schema(200)
|> Enum.map(& &1["status"]["id"])
refute public_activity.id in activity_ids
@@ -284,34 +296,60 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
user = insert(:user)
%{user: other_user, conn: conn} = oauth_access(["read:notifications"])
- {:ok, public_activity} =
- CommonAPI.post(other_user, %{"status" => ".", "visibility" => "public"})
+ {:ok, public_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "public"})
{:ok, unlisted_activity} =
- CommonAPI.post(other_user, %{"status" => ".", "visibility" => "unlisted"})
+ CommonAPI.post(other_user, %{status: ".", visibility: "unlisted"})
- {:ok, _, _} = CommonAPI.repeat(public_activity.id, user)
- {:ok, _, _} = CommonAPI.repeat(unlisted_activity.id, user)
+ {:ok, _} = CommonAPI.repeat(public_activity.id, user)
+ {:ok, _} = CommonAPI.repeat(unlisted_activity.id, user)
activity_ids =
conn
- |> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
- |> json_response(200)
+ |> get("/api/v1/notifications?exclude_visibilities[]=unlisted")
+ |> json_response_and_validate_schema(200)
|> Enum.map(& &1["status"]["id"])
assert public_activity.id in activity_ids
refute unlisted_activity.id in activity_ids
end
+
+ test "doesn't return less than the requested amount of records when the user's reply is liked" do
+ user = insert(:user)
+ %{user: other_user, conn: conn} = oauth_access(["read:notifications"])
+
+ {:ok, mention} =
+ CommonAPI.post(user, %{status: "@#{other_user.nickname}", visibility: "public"})
+
+ {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
+
+ {:ok, reply} =
+ CommonAPI.post(other_user, %{
+ status: ".",
+ visibility: "public",
+ in_reply_to_status_id: activity.id
+ })
+
+ {:ok, _favorite} = CommonAPI.favorite(user, reply.id)
+
+ activity_ids =
+ conn
+ |> get("/api/v1/notifications?exclude_visibilities[]=direct&limit=2")
+ |> json_response_and_validate_schema(200)
+ |> Enum.map(& &1["status"]["id"])
+
+ assert [reply.id, mention.id] == activity_ids
+ end
end
test "filters notifications using exclude_types" do
%{user: user, conn: conn} = oauth_access(["read:notifications"])
other_user = insert(:user)
- {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
- {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
+ {:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
+ {:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
{:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
- {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
+ {:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, other_user)
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
mention_notification_id = get_notification_id_by_activity(mention_activity)
@@ -319,35 +357,37 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
follow_notification_id = get_notification_id_by_activity(follow_activity)
- conn_res =
- get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
+ query = params_to_query(%{exclude_types: ["mention", "favourite", "reblog"]})
+ conn_res = get(conn, "/api/v1/notifications?" <> query)
- assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
+ assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
- conn_res =
- get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
+ query = params_to_query(%{exclude_types: ["favourite", "reblog", "follow"]})
+ conn_res = get(conn, "/api/v1/notifications?" <> query)
- assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
+ assert [%{"id" => ^mention_notification_id}] =
+ json_response_and_validate_schema(conn_res, 200)
- conn_res =
- get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
+ query = params_to_query(%{exclude_types: ["reblog", "follow", "mention"]})
+ conn_res = get(conn, "/api/v1/notifications?" <> query)
- assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
+ assert [%{"id" => ^favorite_notification_id}] =
+ json_response_and_validate_schema(conn_res, 200)
- conn_res =
- get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
+ query = params_to_query(%{exclude_types: ["follow", "mention", "favourite"]})
+ conn_res = get(conn, "/api/v1/notifications?" <> query)
- assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
+ assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
end
test "filters notifications using include_types" do
%{user: user, conn: conn} = oauth_access(["read:notifications"])
other_user = insert(:user)
- {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
- {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
+ {:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
+ {:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
{:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
- {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
+ {:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, other_user)
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
mention_notification_id = get_notification_id_by_activity(mention_activity)
@@ -355,32 +395,34 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
follow_notification_id = get_notification_id_by_activity(follow_activity)
- conn_res = get(conn, "/api/v1/notifications", %{include_types: ["follow"]})
+ conn_res = get(conn, "/api/v1/notifications?include_types[]=follow")
- assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
+ assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
- conn_res = get(conn, "/api/v1/notifications", %{include_types: ["mention"]})
+ conn_res = get(conn, "/api/v1/notifications?include_types[]=mention")
- assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
+ assert [%{"id" => ^mention_notification_id}] =
+ json_response_and_validate_schema(conn_res, 200)
- conn_res = get(conn, "/api/v1/notifications", %{include_types: ["favourite"]})
+ conn_res = get(conn, "/api/v1/notifications?include_types[]=favourite")
- assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
+ assert [%{"id" => ^favorite_notification_id}] =
+ json_response_and_validate_schema(conn_res, 200)
- conn_res = get(conn, "/api/v1/notifications", %{include_types: ["reblog"]})
+ conn_res = get(conn, "/api/v1/notifications?include_types[]=reblog")
- assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
+ assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
- result = conn |> get("/api/v1/notifications") |> json_response(200)
+ result = conn |> get("/api/v1/notifications") |> json_response_and_validate_schema(200)
assert length(result) == 4
+ query = params_to_query(%{include_types: ["follow", "mention", "favourite", "reblog"]})
+
result =
conn
- |> get("/api/v1/notifications", %{
- include_types: ["follow", "mention", "favourite", "reblog"]
- })
- |> json_response(200)
+ |> get("/api/v1/notifications?" <> query)
+ |> json_response_and_validate_schema(200)
assert length(result) == 4
end
@@ -389,10 +431,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
%{user: user, conn: conn} = oauth_access(["read:notifications", "write:notifications"])
other_user = insert(:user)
- {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity3} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
- {:ok, activity4} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
+ {:ok, activity1} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
+ {:ok, activity2} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
+ {:ok, activity3} = CommonAPI.post(user, %{status: "hi @#{other_user.nickname}"})
+ {:ok, activity4} = CommonAPI.post(user, %{status: "hi @#{other_user.nickname}"})
notification1_id = get_notification_id_by_activity(activity1)
notification2_id = get_notification_id_by_activity(activity2)
@@ -402,7 +444,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
result =
conn
|> get("/api/v1/notifications")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
@@ -414,22 +456,19 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
result =
conn2
|> get("/api/v1/notifications")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
- conn_destroy =
- conn
- |> delete("/api/v1/notifications/destroy_multiple", %{
- "ids" => [notification1_id, notification2_id]
- })
+ query = params_to_query(%{ids: [notification1_id, notification2_id]})
+ conn_destroy = delete(conn, "/api/v1/notifications/destroy_multiple?" <> query)
- assert json_response(conn_destroy, 200) == %{}
+ assert json_response_and_validate_schema(conn_destroy, 200) == %{}
result =
conn2
|> get("/api/v1/notifications")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
end
@@ -439,17 +478,17 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
user2 = insert(:user)
{:ok, _, _, _} = CommonAPI.follow(user, user2)
- {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
ret_conn = get(conn, "/api/v1/notifications")
- assert length(json_response(ret_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
{:ok, _user_relationships} = User.mute(user, user2)
conn = get(conn, "/api/v1/notifications")
- assert json_response(conn, 200) == []
+ assert json_response_and_validate_schema(conn, 200) == []
end
test "see notifications after muting user without notifications" do
@@ -457,17 +496,17 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
user2 = insert(:user)
{:ok, _, _, _} = CommonAPI.follow(user, user2)
- {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
ret_conn = get(conn, "/api/v1/notifications")
- assert length(json_response(ret_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
{:ok, _user_relationships} = User.mute(user, user2, false)
conn = get(conn, "/api/v1/notifications")
- assert length(json_response(conn, 200)) == 1
+ assert length(json_response_and_validate_schema(conn, 200)) == 1
end
test "see notifications after muting user with notifications and with_muted parameter" do
@@ -475,17 +514,17 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
user2 = insert(:user)
{:ok, _, _, _} = CommonAPI.follow(user, user2)
- {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
+ {:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
ret_conn = get(conn, "/api/v1/notifications")
- assert length(json_response(ret_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
{:ok, _user_relationships} = User.mute(user, user2)
- conn = get(conn, "/api/v1/notifications", %{"with_muted" => "true"})
+ conn = get(conn, "/api/v1/notifications?with_muted=true")
- assert length(json_response(conn, 200)) == 1
+ assert length(json_response_and_validate_schema(conn, 200)) == 1
end
@tag capture_log: true
@@ -512,7 +551,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
conn = get(conn, "/api/v1/notifications")
- assert length(json_response(conn, 200)) == 1
+ assert length(json_response_and_validate_schema(conn, 200)) == 1
end
describe "link headers" do
@@ -522,14 +561,14 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
{:ok, activity1} =
CommonAPI.post(other_user, %{
- "status" => "hi @#{user.nickname}",
- "visibility" => "public"
+ status: "hi @#{user.nickname}",
+ visibility: "public"
})
{:ok, activity2} =
CommonAPI.post(other_user, %{
- "status" => "hi @#{user.nickname}",
- "visibility" => "public"
+ status: "hi @#{user.nickname}",
+ visibility: "public"
})
notification1 = Repo.get_by(Notification, activity_id: activity1.id)
@@ -538,10 +577,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
conn =
conn
|> assign(:user, user)
- |> get("/api/v1/notifications", %{media_only: true})
+ |> get("/api/v1/notifications?limit=5")
assert [link_header] = get_resp_header(conn, "link")
- assert link_header =~ ~r/media_only=true/
+ assert link_header =~ ~r/limit=5/
assert link_header =~ ~r/min_id=#{notification2.id}/
assert link_header =~ ~r/max_id=#{notification1.id}/
end
@@ -554,20 +593,20 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
%{id: account_id} = other_user1 = insert(:user)
other_user2 = insert(:user)
- {:ok, _activity} = CommonAPI.post(other_user1, %{"status" => "hi @#{user.nickname}"})
- {:ok, _activity} = CommonAPI.post(other_user2, %{"status" => "bye @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(other_user1, %{status: "hi @#{user.nickname}"})
+ {:ok, _activity} = CommonAPI.post(other_user2, %{status: "bye @#{user.nickname}"})
assert [%{"account" => %{"id" => ^account_id}}] =
conn
|> assign(:user, user)
- |> get("/api/v1/notifications", %{account_id: account_id})
- |> json_response(200)
+ |> get("/api/v1/notifications?account_id=#{account_id}")
+ |> json_response_and_validate_schema(200)
assert %{"error" => "Account is not found"} =
conn
|> assign(:user, user)
- |> get("/api/v1/notifications", %{account_id: "cofe"})
- |> json_response(404)
+ |> get("/api/v1/notifications?account_id=cofe")
+ |> json_response_and_validate_schema(404)
end
end
@@ -577,4 +616,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|> Map.get(:id)
|> to_string()
end
+
+ defp params_to_query(%{} = params) do
+ Enum.map_join(params, "&", fn
+ {k, v} when is_list(v) -> Enum.map_join(v, "&", &"#{k}[]=#{&1}")
+ {k, v} -> k <> "=" <> v
+ end)
+ end
end
diff --git a/test/web/mastodon_api/controllers/poll_controller_test.exs b/test/web/mastodon_api/controllers/poll_controller_test.exs
index 88b13a25a..f41de6448 100644
--- a/test/web/mastodon_api/controllers/poll_controller_test.exs
+++ b/test/web/mastodon_api/controllers/poll_controller_test.exs
@@ -16,15 +16,15 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
test "returns poll entity for object id", %{user: user, conn: conn} do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "Pleroma does",
- "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}
+ status: "Pleroma does",
+ poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20}
})
object = Object.normalize(activity)
conn = get(conn, "/api/v1/polls/#{object.id}")
- response = json_response(conn, 200)
+ response = json_response_and_validate_schema(conn, 200)
id = to_string(object.id)
assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
end
@@ -34,16 +34,16 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
{:ok, activity} =
CommonAPI.post(other_user, %{
- "status" => "Pleroma does",
- "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20},
- "visibility" => "private"
+ status: "Pleroma does",
+ poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20},
+ visibility: "private"
})
object = Object.normalize(activity)
conn = get(conn, "/api/v1/polls/#{object.id}")
- assert json_response(conn, 404)
+ assert json_response_and_validate_schema(conn, 404)
end
end
@@ -55,19 +55,22 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
{:ok, activity} =
CommonAPI.post(other_user, %{
- "status" => "A very delicious sandwich",
- "poll" => %{
- "options" => ["Lettuce", "Grilled Bacon", "Tomato"],
- "expires_in" => 20,
- "multiple" => true
+ status: "A very delicious sandwich",
+ poll: %{
+ options: ["Lettuce", "Grilled Bacon", "Tomato"],
+ expires_in: 20,
+ multiple: true
}
})
object = Object.normalize(activity)
- conn = post(conn, "/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
- assert json_response(conn, 200)
+ assert json_response_and_validate_schema(conn, 200)
object = Object.get_by_id(object.id)
assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
@@ -78,15 +81,16 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
test "author can't vote", %{user: user, conn: conn} do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "Am I cute?",
- "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
+ status: "Am I cute?",
+ poll: %{options: ["Yes", "No"], expires_in: 20}
})
object = Object.normalize(activity)
assert conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
- |> json_response(422) == %{"error" => "Poll's author can't vote"}
+ |> json_response_and_validate_schema(422) == %{"error" => "Poll's author can't vote"}
object = Object.get_by_id(object.id)
@@ -98,15 +102,16 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
{:ok, activity} =
CommonAPI.post(other_user, %{
- "status" => "The glass is",
- "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20}
+ status: "The glass is",
+ poll: %{options: ["half empty", "half full"], expires_in: 20}
})
object = Object.normalize(activity)
assert conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
- |> json_response(422) == %{"error" => "Too many choices"}
+ |> json_response_and_validate_schema(422) == %{"error" => "Too many choices"}
object = Object.get_by_id(object.id)
@@ -120,21 +125,27 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
{:ok, activity} =
CommonAPI.post(other_user, %{
- "status" => "Am I cute?",
- "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
+ status: "Am I cute?",
+ poll: %{options: ["Yes", "No"], expires_in: 20}
})
object = Object.normalize(activity)
- conn = post(conn, "/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
- assert json_response(conn, 422) == %{"error" => "Invalid indices"}
+ assert json_response_and_validate_schema(conn, 422) == %{"error" => "Invalid indices"}
end
test "returns 404 error when object is not exist", %{conn: conn} do
- conn = post(conn, "/api/v1/polls/1/votes", %{"choices" => [0]})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/polls/1/votes", %{"choices" => [0]})
- assert json_response(conn, 404) == %{"error" => "Record not found"}
+ assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
end
test "returns 404 when poll is private and not available for user", %{conn: conn} do
@@ -142,16 +153,19 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
{:ok, activity} =
CommonAPI.post(other_user, %{
- "status" => "Am I cute?",
- "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20},
- "visibility" => "private"
+ status: "Am I cute?",
+ poll: %{options: ["Yes", "No"], expires_in: 20},
+ visibility: "private"
})
object = Object.normalize(activity)
- conn = post(conn, "/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
- assert json_response(conn, 404) == %{"error" => "Record not found"}
+ assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
end
end
end
diff --git a/test/web/mastodon_api/controllers/report_controller_test.exs b/test/web/mastodon_api/controllers/report_controller_test.exs
index 34ec8119e..6636cff96 100644
--- a/test/web/mastodon_api/controllers/report_controller_test.exs
+++ b/test/web/mastodon_api/controllers/report_controller_test.exs
@@ -14,7 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
setup do
target_user = insert(:user)
- {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
+ {:ok, activity} = CommonAPI.post(target_user, %{status: "foobar"})
[target_user: target_user, activity: activity]
end
@@ -22,8 +22,9 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
test "submit a basic report", %{conn: conn, target_user: target_user} do
assert %{"action_taken" => false, "id" => _} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/reports", %{"account_id" => target_user.id})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
end
test "submit a report with statuses and comment", %{
@@ -33,23 +34,25 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
} do
assert %{"action_taken" => false, "id" => _} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/reports", %{
"account_id" => target_user.id,
"status_ids" => [activity.id],
"comment" => "bad status!",
"forward" => "false"
})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
end
test "account_id is required", %{
conn: conn,
activity: activity
} do
- assert %{"error" => "Valid `account_id` required"} =
+ assert %{"error" => "Missing field: account_id."} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/reports", %{"status_ids" => [activity.id]})
- |> json_response(400)
+ |> json_response_and_validate_schema(400)
end
test "comment must be up to the size specified in the config", %{
@@ -63,17 +66,21 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
assert ^error =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
- |> json_response(400)
+ |> json_response_and_validate_schema(400)
end
test "returns error when account is not exist", %{
conn: conn,
activity: activity
} do
- conn = post(conn, "/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
- assert json_response(conn, 400) == %{"error" => "Account not found"}
+ assert json_response_and_validate_schema(conn, 400) == %{"error" => "Account not found"}
end
test "doesn't fail if an admin has no email", %{conn: conn, target_user: target_user} do
@@ -81,7 +88,8 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
assert %{"action_taken" => false, "id" => _} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/reports", %{"account_id" => target_user.id})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
end
end
diff --git a/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs b/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs
index f86274d57..1ff871c89 100644
--- a/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs
+++ b/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs
@@ -24,19 +24,19 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
# min_id
conn_res = get(conn, "/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
- result = json_response(conn_res, 200)
+ result = json_response_and_validate_schema(conn_res, 200)
assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
# since_id
conn_res = get(conn, "/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
- result = json_response(conn_res, 200)
+ result = json_response_and_validate_schema(conn_res, 200)
assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
# max_id
conn_res = get(conn, "/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
- result = json_response(conn_res, 200)
+ result = json_response_and_validate_schema(conn_res, 200)
assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
end
@@ -46,12 +46,12 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
res_conn = get(conn, "/api/v1/scheduled_statuses/#{scheduled_activity.id}")
- assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
+ assert %{"id" => scheduled_activity_id} = json_response_and_validate_schema(res_conn, 200)
assert scheduled_activity_id == scheduled_activity.id |> to_string()
res_conn = get(conn, "/api/v1/scheduled_statuses/404")
- assert %{"error" => "Record not found"} = json_response(res_conn, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(res_conn, 404)
end
test "updates a scheduled activity" do
@@ -74,22 +74,32 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
assert job.args == %{"activity_id" => scheduled_activity.id}
assert DateTime.truncate(job.scheduled_at, :second) == to_datetime(scheduled_at)
- new_scheduled_at = Timex.shift(NaiveDateTime.utc_now(), minutes: 120)
+ new_scheduled_at =
+ NaiveDateTime.utc_now()
+ |> Timex.shift(minutes: 120)
+ |> Timex.format!("%Y-%m-%dT%H:%M:%S.%fZ", :strftime)
res_conn =
- put(conn, "/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
scheduled_at: new_scheduled_at
})
- assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
+ assert %{"scheduled_at" => expected_scheduled_at} =
+ json_response_and_validate_schema(res_conn, 200)
+
assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
job = refresh_record(job)
assert DateTime.truncate(job.scheduled_at, :second) == to_datetime(new_scheduled_at)
- res_conn = put(conn, "/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
+ res_conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
- assert %{"error" => "Record not found"} = json_response(res_conn, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(res_conn, 404)
end
test "deletes a scheduled activity" do
@@ -115,7 +125,7 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
|> assign(:user, user)
|> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
- assert %{} = json_response(res_conn, 200)
+ assert %{} = json_response_and_validate_schema(res_conn, 200)
refute Repo.get(ScheduledActivity, scheduled_activity.id)
refute Repo.get(Oban.Job, job.id)
@@ -124,6 +134,6 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
|> assign(:user, user)
|> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
- assert %{"error" => "Record not found"} = json_response(res_conn, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(res_conn, 404)
end
end
diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs
index 11133ff66..826f37fbc 100644
--- a/test/web/mastodon_api/controllers/search_controller_test.exs
+++ b/test/web/mastodon_api/controllers/search_controller_test.exs
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
import Tesla.Mock
import Mock
- setup do
+ setup_all do
mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
@@ -27,8 +27,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
capture_log(fn ->
results =
conn
- |> get("/api/v2/search", %{"q" => "2hu"})
- |> json_response(200)
+ |> get("/api/v2/search?q=2hu")
+ |> json_response_and_validate_schema(200)
assert results["accounts"] == []
assert results["statuses"] == []
@@ -42,20 +42,20 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
- {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu private 天子"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "This is about 2hu private 天子"})
{:ok, _activity} =
CommonAPI.post(user, %{
- "status" => "This is about 2hu, but private",
- "visibility" => "private"
+ status: "This is about 2hu, but private",
+ visibility: "private"
})
- {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
+ {:ok, _} = CommonAPI.post(user_two, %{status: "This isn't"})
results =
conn
- |> get("/api/v2/search", %{"q" => "2hu #private"})
- |> json_response(200)
+ |> get("/api/v2/search?#{URI.encode_query(%{q: "2hu #private"})}")
+ |> json_response_and_validate_schema(200)
[account | _] = results["accounts"]
assert account["id"] == to_string(user_three.id)
@@ -68,29 +68,121 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
assert status["id"] == to_string(activity.id)
results =
- get(conn, "/api/v2/search", %{"q" => "天子"})
- |> json_response(200)
+ get(conn, "/api/v2/search?q=天子")
+ |> json_response_and_validate_schema(200)
+
+ assert results["hashtags"] == [
+ %{"name" => "天子", "url" => "#{Web.base_url()}/tag/天子"}
+ ]
[status] = results["statuses"]
assert status["id"] == to_string(activity.id)
end
+ test "constructs hashtags from search query", %{conn: conn} do
+ results =
+ conn
+ |> get("/api/v2/search?#{URI.encode_query(%{q: "some text with #explicit #hashtags"})}")
+ |> json_response_and_validate_schema(200)
+
+ assert results["hashtags"] == [
+ %{"name" => "explicit", "url" => "#{Web.base_url()}/tag/explicit"},
+ %{"name" => "hashtags", "url" => "#{Web.base_url()}/tag/hashtags"}
+ ]
+
+ results =
+ conn
+ |> get("/api/v2/search?#{URI.encode_query(%{q: "john doe JOHN DOE"})}")
+ |> json_response_and_validate_schema(200)
+
+ assert results["hashtags"] == [
+ %{"name" => "john", "url" => "#{Web.base_url()}/tag/john"},
+ %{"name" => "doe", "url" => "#{Web.base_url()}/tag/doe"},
+ %{"name" => "JohnDoe", "url" => "#{Web.base_url()}/tag/JohnDoe"}
+ ]
+
+ results =
+ conn
+ |> get("/api/v2/search?#{URI.encode_query(%{q: "accident-prone"})}")
+ |> json_response_and_validate_schema(200)
+
+ assert results["hashtags"] == [
+ %{"name" => "accident", "url" => "#{Web.base_url()}/tag/accident"},
+ %{"name" => "prone", "url" => "#{Web.base_url()}/tag/prone"},
+ %{"name" => "AccidentProne", "url" => "#{Web.base_url()}/tag/AccidentProne"}
+ ]
+
+ results =
+ conn
+ |> get("/api/v2/search?#{URI.encode_query(%{q: "https://shpposter.club/users/shpuld"})}")
+ |> json_response_and_validate_schema(200)
+
+ assert results["hashtags"] == [
+ %{"name" => "shpuld", "url" => "#{Web.base_url()}/tag/shpuld"}
+ ]
+
+ results =
+ conn
+ |> get(
+ "/api/v2/search?#{
+ URI.encode_query(%{
+ q:
+ "https://www.washingtonpost.com/sports/2020/06/10/" <>
+ "nascar-ban-display-confederate-flag-all-events-properties/"
+ })
+ }"
+ )
+ |> json_response_and_validate_schema(200)
+
+ assert results["hashtags"] == [
+ %{"name" => "nascar", "url" => "#{Web.base_url()}/tag/nascar"},
+ %{"name" => "ban", "url" => "#{Web.base_url()}/tag/ban"},
+ %{"name" => "display", "url" => "#{Web.base_url()}/tag/display"},
+ %{"name" => "confederate", "url" => "#{Web.base_url()}/tag/confederate"},
+ %{"name" => "flag", "url" => "#{Web.base_url()}/tag/flag"},
+ %{"name" => "all", "url" => "#{Web.base_url()}/tag/all"},
+ %{"name" => "events", "url" => "#{Web.base_url()}/tag/events"},
+ %{"name" => "properties", "url" => "#{Web.base_url()}/tag/properties"},
+ %{
+ "name" => "NascarBanDisplayConfederateFlagAllEventsProperties",
+ "url" =>
+ "#{Web.base_url()}/tag/NascarBanDisplayConfederateFlagAllEventsProperties"
+ }
+ ]
+ end
+
+ test "supports pagination of hashtags search results", %{conn: conn} do
+ results =
+ conn
+ |> get(
+ "/api/v2/search?#{
+ URI.encode_query(%{q: "#some #text #with #hashtags", limit: 2, offset: 1})
+ }"
+ )
+ |> json_response_and_validate_schema(200)
+
+ assert results["hashtags"] == [
+ %{"name" => "text", "url" => "#{Web.base_url()}/tag/text"},
+ %{"name" => "with", "url" => "#{Web.base_url()}/tag/with"}
+ ]
+ end
+
test "excludes a blocked users from search results", %{conn: conn} do
user = insert(:user)
user_smith = insert(:user, %{nickname: "Agent", name: "I love 2hu"})
user_neo = insert(:user, %{nickname: "Agent Neo", name: "Agent"})
- {:ok, act1} = CommonAPI.post(user, %{"status" => "This is about 2hu private 天子"})
- {:ok, act2} = CommonAPI.post(user_smith, %{"status" => "Agent Smith"})
- {:ok, act3} = CommonAPI.post(user_neo, %{"status" => "Agent Smith"})
+ {:ok, act1} = CommonAPI.post(user, %{status: "This is about 2hu private 天子"})
+ {:ok, act2} = CommonAPI.post(user_smith, %{status: "Agent Smith"})
+ {:ok, act3} = CommonAPI.post(user_neo, %{status: "Agent Smith"})
Pleroma.User.block(user, user_smith)
results =
conn
|> assign(:user, user)
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
- |> get("/api/v2/search", %{"q" => "Agent"})
- |> json_response(200)
+ |> get("/api/v2/search?q=Agent")
+ |> json_response_and_validate_schema(200)
status_ids = Enum.map(results["statuses"], fn g -> g["id"] end)
@@ -107,8 +199,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
results =
conn
- |> get("/api/v1/accounts/search", %{"q" => "shp"})
- |> json_response(200)
+ |> get("/api/v1/accounts/search?q=shp")
+ |> json_response_and_validate_schema(200)
result_ids = for result <- results, do: result["acct"]
@@ -117,8 +209,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
results =
conn
- |> get("/api/v1/accounts/search", %{"q" => "2hu"})
- |> json_response(200)
+ |> get("/api/v1/accounts/search?q=2hu")
+ |> json_response_and_validate_schema(200)
result_ids = for result <- results, do: result["acct"]
@@ -130,8 +222,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
results =
conn
- |> get("/api/v1/accounts/search", %{"q" => "shp@shitposter.club xxx "})
- |> json_response(200)
+ |> get("/api/v1/accounts/search?q=shp@shitposter.club xxx")
+ |> json_response_and_validate_schema(200)
assert length(results) == 1
end
@@ -146,8 +238,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
capture_log(fn ->
results =
conn
- |> get("/api/v1/search", %{"q" => "2hu"})
- |> json_response(200)
+ |> get("/api/v1/search?q=2hu")
+ |> json_response_and_validate_schema(200)
assert results["accounts"] == []
assert results["statuses"] == []
@@ -161,25 +253,25 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
- {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "This is about 2hu"})
{:ok, _activity} =
CommonAPI.post(user, %{
- "status" => "This is about 2hu, but private",
- "visibility" => "private"
+ status: "This is about 2hu, but private",
+ visibility: "private"
})
- {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
+ {:ok, _} = CommonAPI.post(user_two, %{status: "This isn't"})
results =
conn
- |> get("/api/v1/search", %{"q" => "2hu"})
- |> json_response(200)
+ |> get("/api/v1/search?q=2hu")
+ |> json_response_and_validate_schema(200)
[account | _] = results["accounts"]
assert account["id"] == to_string(user_three.id)
- assert results["hashtags"] == []
+ assert results["hashtags"] == ["2hu"]
[status] = results["statuses"]
assert status["id"] == to_string(activity.id)
@@ -189,13 +281,13 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
capture_log(fn ->
{:ok, %{id: activity_id}} =
CommonAPI.post(insert(:user), %{
- "status" => "check out https://shitposter.club/notice/2827873"
+ status: "check out https://shitposter.club/notice/2827873"
})
results =
conn
- |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
- |> json_response(200)
+ |> get("/api/v1/search?q=https://shitposter.club/notice/2827873")
+ |> json_response_and_validate_schema(200)
[status, %{"id" => ^activity_id}] = results["statuses"]
@@ -207,15 +299,17 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
test "search doesn't show statuses that it shouldn't", %{conn: conn} do
{:ok, activity} =
CommonAPI.post(insert(:user), %{
- "status" => "This is about 2hu, but private",
- "visibility" => "private"
+ status: "This is about 2hu, but private",
+ visibility: "private"
})
capture_log(fn ->
+ q = Object.normalize(activity).data["id"]
+
results =
conn
- |> get("/api/v1/search", %{"q" => Object.normalize(activity).data["id"]})
- |> json_response(200)
+ |> get("/api/v1/search?q=#{q}")
+ |> json_response_and_validate_schema(200)
[] = results["statuses"]
end)
@@ -228,8 +322,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
conn
|> assign(:user, user)
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
- |> get("/api/v1/search", %{"q" => "mike@osada.macgirvin.com", "resolve" => "true"})
- |> json_response(200)
+ |> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=true")
+ |> json_response_and_validate_schema(200)
[account] = results["accounts"]
assert account["acct"] == "mike@osada.macgirvin.com"
@@ -238,8 +332,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
test "search doesn't fetch remote accounts if resolve is false", %{conn: conn} do
results =
conn
- |> get("/api/v1/search", %{"q" => "mike@osada.macgirvin.com", "resolve" => "false"})
- |> json_response(200)
+ |> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=false")
+ |> json_response_and_validate_schema(200)
assert [] == results["accounts"]
end
@@ -249,21 +343,21 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
_user_two = insert(:user, %{nickname: "shp@shitposter.club"})
_user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
- {:ok, _activity1} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
- {:ok, _activity2} = CommonAPI.post(user, %{"status" => "This is also about 2hu"})
+ {:ok, _activity1} = CommonAPI.post(user, %{status: "This is about 2hu"})
+ {:ok, _activity2} = CommonAPI.post(user, %{status: "This is also about 2hu"})
result =
conn
- |> get("/api/v1/search", %{"q" => "2hu", "limit" => 1})
+ |> get("/api/v1/search?q=2hu&limit=1")
- assert results = json_response(result, 200)
+ assert results = json_response_and_validate_schema(result, 200)
assert [%{"id" => activity_id1}] = results["statuses"]
assert [_] = results["accounts"]
results =
conn
- |> get("/api/v1/search", %{"q" => "2hu", "limit" => 1, "offset" => 1})
- |> json_response(200)
+ |> get("/api/v1/search?q=2hu&limit=1&offset=1")
+ |> json_response_and_validate_schema(200)
assert [%{"id" => activity_id2}] = results["statuses"]
assert [] = results["accounts"]
@@ -275,30 +369,30 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
user = insert(:user)
_user_two = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
+ {:ok, _activity} = CommonAPI.post(user, %{status: "This is about 2hu"})
assert %{"statuses" => [_activity], "accounts" => [], "hashtags" => []} =
conn
- |> get("/api/v1/search", %{"q" => "2hu", "type" => "statuses"})
- |> json_response(200)
+ |> get("/api/v1/search?q=2hu&type=statuses")
+ |> json_response_and_validate_schema(200)
assert %{"statuses" => [], "accounts" => [_user_two], "hashtags" => []} =
conn
- |> get("/api/v1/search", %{"q" => "2hu", "type" => "accounts"})
- |> json_response(200)
+ |> get("/api/v1/search?q=2hu&type=accounts")
+ |> json_response_and_validate_schema(200)
end
test "search uses account_id to filter statuses by the author", %{conn: conn} do
user = insert(:user, %{nickname: "shp@shitposter.club"})
user_two = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
- {:ok, activity1} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
- {:ok, activity2} = CommonAPI.post(user_two, %{"status" => "This is also about 2hu"})
+ {:ok, activity1} = CommonAPI.post(user, %{status: "This is about 2hu"})
+ {:ok, activity2} = CommonAPI.post(user_two, %{status: "This is also about 2hu"})
results =
conn
- |> get("/api/v1/search", %{"q" => "2hu", "account_id" => user.id})
- |> json_response(200)
+ |> get("/api/v1/search?q=2hu&account_id=#{user.id}")
+ |> json_response_and_validate_schema(200)
assert [%{"id" => activity_id1}] = results["statuses"]
assert activity_id1 == activity1.id
@@ -306,8 +400,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
results =
conn
- |> get("/api/v1/search", %{"q" => "2hu", "account_id" => user_two.id})
- |> json_response(200)
+ |> get("/api/v1/search?q=2hu&account_id=#{user_two.id}")
+ |> json_response_and_validate_schema(200)
assert [%{"id" => activity_id2}] = results["statuses"]
assert activity_id2 == activity2.id
diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs
index 162f7b1b2..a98e939e8 100644
--- a/test/web/mastodon_api/controllers/status_controller_test.exs
+++ b/test/web/mastodon_api/controllers/status_controller_test.exs
@@ -32,13 +32,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
response =
conn
+ |> put_req_header("content-type", "application/json")
|> post("api/v1/statuses", %{
"content_type" => "text/plain",
"source" => "Pleroma FE",
"status" => "Hello world",
"visibility" => "public"
})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response["reblogs_count"] == 0
ObanHelpers.perform_all()
@@ -46,7 +47,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
response =
conn
|> get("api/v1/statuses/#{response["id"]}", %{})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response["reblogs_count"] == 0
end
@@ -56,11 +57,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn_one =
conn
+ |> put_req_header("content-type", "application/json")
|> put_req_header("idempotency-key", idempotency_key)
|> post("/api/v1/statuses", %{
"status" => "cofe",
"spoiler_text" => "2hu",
- "sensitive" => "false"
+ "sensitive" => "0"
})
{:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
@@ -68,17 +70,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
assert ttl > :timer.seconds(6 * 60 * 60 - 1)
assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
- json_response(conn_one, 200)
+ json_response_and_validate_schema(conn_one, 200)
assert Activity.get_by_id(id)
conn_two =
conn
+ |> put_req_header("content-type", "application/json")
|> put_req_header("idempotency-key", idempotency_key)
|> post("/api/v1/statuses", %{
"status" => "cofe",
"spoiler_text" => "2hu",
- "sensitive" => "false"
+ "sensitive" => 0
})
assert %{"id" => second_id} = json_response(conn_two, 200)
@@ -86,13 +89,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn_three =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses", %{
"status" => "cofe",
"spoiler_text" => "2hu",
- "sensitive" => "false"
+ "sensitive" => "False"
})
- assert %{"id" => third_id} = json_response(conn_three, 200)
+ assert %{"id" => third_id} = json_response_and_validate_schema(conn_three, 200)
refute id == third_id
# An activity that will expire:
@@ -101,12 +105,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn_four =
conn
+ |> put_req_header("content-type", "application/json")
|> post("api/v1/statuses", %{
"status" => "oolong",
"expires_in" => expires_in
})
- assert fourth_response = %{"id" => fourth_id} = json_response(conn_four, 200)
+ assert fourth_response =
+ %{"id" => fourth_id} = json_response_and_validate_schema(conn_four, 200)
+
assert activity = Activity.get_by_id(fourth_id)
assert expiration = ActivityExpiration.get_by_activity_id(fourth_id)
@@ -130,22 +137,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
assert %{"error" => "Expiry date is too soon"} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("api/v1/statuses", %{
"status" => "oolong",
"expires_in" => expires_in
})
- |> json_response(422)
+ |> json_response_and_validate_schema(422)
# 30 minutes
expires_in = 30 * 60
assert %{"error" => "Expiry date is too soon"} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("api/v1/statuses", %{
"status" => "oolong",
"expires_in" => expires_in
})
- |> json_response(422)
+ |> json_response_and_validate_schema(422)
end
test "posting an undefined status with an attachment", %{user: user, conn: conn} do
@@ -158,21 +167,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
{:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"media_ids" => [to_string(upload.id)]
})
- assert json_response(conn, 200)
+ assert json_response_and_validate_schema(conn, 200)
end
test "replying to a status", %{user: user, conn: conn} do
- {:ok, replied_to} = CommonAPI.post(user, %{"status" => "cofe"})
+ {:ok, replied_to} = CommonAPI.post(user, %{status: "cofe"})
conn =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
- assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
+ assert %{"content" => "xD", "id" => id} = json_response_and_validate_schema(conn, 200)
activity = Activity.get_by_id(id)
@@ -184,43 +196,56 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
user: user,
conn: conn
} do
- {:ok, replied_to} = CommonAPI.post(user, %{"status" => "suya..", "visibility" => "direct"})
+ {:ok, replied_to} = CommonAPI.post(user, %{status: "suya..", visibility: "direct"})
Enum.each(["public", "private", "unlisted"], fn visibility ->
conn =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses", %{
"status" => "@#{user.nickname} hey",
"in_reply_to_id" => replied_to.id,
"visibility" => visibility
})
- assert json_response(conn, 422) == %{"error" => "The message visibility must be direct"}
+ assert json_response_and_validate_schema(conn, 422) == %{
+ "error" => "The message visibility must be direct"
+ }
end)
end
test "posting a status with an invalid in_reply_to_id", %{conn: conn} do
- conn = post(conn, "/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
- assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
+ assert %{"content" => "xD", "id" => id} = json_response_and_validate_schema(conn, 200)
assert Activity.get_by_id(id)
end
test "posting a sensitive status", %{conn: conn} do
- conn = post(conn, "/api/v1/statuses", %{"status" => "cofe", "sensitive" => true})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true})
+
+ assert %{"content" => "cofe", "id" => id, "sensitive" => true} =
+ json_response_and_validate_schema(conn, 200)
- assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200)
assert Activity.get_by_id(id)
end
test "posting a fake status", %{conn: conn} do
real_conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" =>
"\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it"
})
- real_status = json_response(real_conn, 200)
+ real_status = json_response_and_validate_schema(real_conn, 200)
assert real_status
assert Object.get_by_ap_id(real_status["uri"])
@@ -234,13 +259,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> Kernel.put_in(["pleroma", "conversation_id"], nil)
fake_conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" =>
"\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it",
"preview" => true
})
- fake_status = json_response(fake_conn, 200)
+ fake_status = json_response_and_validate_schema(fake_conn, 200)
assert fake_status
refute Object.get_by_ap_id(fake_status["uri"])
@@ -261,11 +288,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
Config.put([:rich_media, :enabled], true)
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" => "https://example.com/ogp"
})
- assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200)
+ assert %{"id" => id, "card" => %{"title" => "The Rock"}} =
+ json_response_and_validate_schema(conn, 200)
+
assert Activity.get_by_id(id)
end
@@ -273,9 +304,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
user2 = insert(:user)
content = "direct cofe @#{user2.nickname}"
- conn = post(conn, "api/v1/statuses", %{"status" => content, "visibility" => "direct"})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"})
- assert %{"id" => id} = response = json_response(conn, 200)
+ assert %{"id" => id} = response = json_response_and_validate_schema(conn, 200)
assert response["visibility"] == "direct"
assert response["pleroma"]["direct_conversation_id"]
assert activity = Activity.get_by_id(id)
@@ -289,21 +323,45 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: oauth_access(["write:statuses"])
test "creates a scheduled activity", %{conn: conn} do
- scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
+ scheduled_at =
+ NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
+ |> NaiveDateTime.to_iso8601()
+ |> Kernel.<>("Z")
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" => "scheduled",
"scheduled_at" => scheduled_at
})
- assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
+ assert %{"scheduled_at" => expected_scheduled_at} =
+ json_response_and_validate_schema(conn, 200)
+
assert expected_scheduled_at == CommonAPI.Utils.to_masto_date(scheduled_at)
assert [] == Repo.all(Activity)
end
+ test "ignores nil values", %{conn: conn} do
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
+ "status" => "not scheduled",
+ "scheduled_at" => nil
+ })
+
+ assert result = json_response_and_validate_schema(conn, 200)
+ assert Activity.get_by_id(result["id"])
+ end
+
test "creates a scheduled activity with a media attachment", %{user: user, conn: conn} do
- scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
+ scheduled_at =
+ NaiveDateTime.utc_now()
+ |> NaiveDateTime.add(:timer.minutes(120), :millisecond)
+ |> NaiveDateTime.to_iso8601()
+ |> Kernel.<>("Z")
file = %Plug.Upload{
content_type: "image/jpg",
@@ -314,13 +372,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
{:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"media_ids" => [to_string(upload.id)],
"status" => "scheduled",
"scheduled_at" => scheduled_at
})
- assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
+ assert %{"media_attachments" => [media_attachment]} =
+ json_response_and_validate_schema(conn, 200)
+
assert %{"type" => "image"} = media_attachment
end
@@ -328,14 +390,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
%{conn: conn} do
scheduled_at =
NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
+ |> NaiveDateTime.to_iso8601()
+ |> Kernel.<>("Z")
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" => "not scheduled",
"scheduled_at" => scheduled_at
})
- assert %{"content" => "not scheduled"} = json_response(conn, 200)
+ assert %{"content" => "not scheduled"} = json_response_and_validate_schema(conn, 200)
assert [] == Repo.all(ScheduledActivity)
end
@@ -344,14 +410,19 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
NaiveDateTime.utc_now()
|> NaiveDateTime.add(:timer.minutes(6), :millisecond)
|> NaiveDateTime.to_iso8601()
+ # TODO
+ |> Kernel.<>("Z")
attrs = %{params: %{}, scheduled_at: today}
{:ok, _} = ScheduledActivity.create(user, attrs)
{:ok, _} = ScheduledActivity.create(user, attrs)
- conn = post(conn, "/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
- assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
+ assert %{"error" => "daily limit exceeded"} == json_response_and_validate_schema(conn, 422)
end
test "returns error when total user limit is exceeded", %{user: user, conn: conn} do
@@ -359,11 +430,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
NaiveDateTime.utc_now()
|> NaiveDateTime.add(:timer.minutes(6), :millisecond)
|> NaiveDateTime.to_iso8601()
+ |> Kernel.<>("Z")
tomorrow =
NaiveDateTime.utc_now()
|> NaiveDateTime.add(:timer.hours(36), :millisecond)
|> NaiveDateTime.to_iso8601()
+ |> Kernel.<>("Z")
attrs = %{params: %{}, scheduled_at: today}
{:ok, _} = ScheduledActivity.create(user, attrs)
@@ -371,9 +444,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
{:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
conn =
- post(conn, "/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
- assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
+ assert %{"error" => "total limit exceeded"} == json_response_and_validate_schema(conn, 422)
end
end
@@ -384,12 +459,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
time = NaiveDateTime.utc_now()
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" => "Who is the #bestgrill?",
- "poll" => %{"options" => ["Rei", "Asuka", "Misato"], "expires_in" => 420}
+ "poll" => %{
+ "options" => ["Rei", "Asuka", "Misato"],
+ "expires_in" => 420
+ }
})
- response = json_response(conn, 200)
+ response = json_response_and_validate_schema(conn, 200)
assert Enum.all?(response["poll"]["options"], fn %{"title" => title} ->
title in ["Rei", "Asuka", "Misato"]
@@ -408,12 +488,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
limit = Config.get([:instance, :poll_limits, :max_options])
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" => "desu~",
"poll" => %{"options" => Enum.map(0..limit, fn _ -> "desu" end), "expires_in" => 1}
})
- %{"error" => error} = json_response(conn, 422)
+ %{"error" => error} = json_response_and_validate_schema(conn, 422)
assert error == "Poll can't contain more than #{limit} options"
end
@@ -421,7 +503,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
limit = Config.get([:instance, :poll_limits, :max_option_chars])
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" => "...",
"poll" => %{
"options" => [Enum.reduce(0..limit, "", fn _, acc -> acc <> "." end)],
@@ -429,7 +513,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
}
})
- %{"error" => error} = json_response(conn, 422)
+ %{"error" => error} = json_response_and_validate_schema(conn, 422)
assert error == "Poll options cannot be longer than #{limit} characters each"
end
@@ -437,7 +521,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
limit = Config.get([:instance, :poll_limits, :min_expiration])
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" => "imagine arbitrary limits",
"poll" => %{
"options" => ["this post was made by pleroma gang"],
@@ -445,7 +531,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
}
})
- %{"error" => error} = json_response(conn, 422)
+ %{"error" => error} = json_response_and_validate_schema(conn, 422)
assert error == "Expiration date is too soon"
end
@@ -453,7 +539,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
limit = Config.get([:instance, :poll_limits, :max_expiration])
conn =
- post(conn, "/api/v1/statuses", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
"status" => "imagine arbitrary limits",
"poll" => %{
"options" => ["this post was made by pleroma gang"],
@@ -461,7 +549,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
}
})
- %{"error" => error} = json_response(conn, 422)
+ %{"error" => error} = json_response_and_validate_schema(conn, 422)
assert error == "Expiration date is too far in the future"
end
end
@@ -472,7 +560,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn = get(conn, "/api/v1/statuses/#{activity.id}")
- assert %{"id" => id} = json_response(conn, 200)
+ assert %{"id" => id} = json_response_and_validate_schema(conn, 200)
assert id == to_string(activity.id)
end
@@ -492,13 +580,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/statuses/#{local.id}")
- assert json_response(res_conn, :not_found) == %{
+ assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Record not found"
}
res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
- assert json_response(res_conn, :not_found) == %{
+ assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Record not found"
}
end
@@ -506,10 +594,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
@@ -521,21 +609,21 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/statuses/#{local.id}")
- assert json_response(res_conn, :not_found) == %{
+ assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Record not found"
}
res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
@@ -546,11 +634,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/statuses/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
- assert json_response(res_conn, :not_found) == %{
+ assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Record not found"
}
end
@@ -558,10 +646,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/statuses/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
@@ -571,7 +659,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn = get(conn, "/api/v1/statuses/#{String.downcase(activity.id)}")
- assert json_response(conn, 404) == %{"error" => "Record not found"}
+ assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
end
test "get a direct status" do
@@ -579,7 +667,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
other_user = insert(:user)
{:ok, activity} =
- CommonAPI.post(user, %{"status" => "@#{other_user.nickname}", "visibility" => "direct"})
+ CommonAPI.post(user, %{status: "@#{other_user.nickname}", visibility: "direct"})
conn =
conn
@@ -588,7 +676,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
[participation] = Participation.for_user(user)
- res = json_response(conn, 200)
+ res = json_response_and_validate_schema(conn, 200)
assert res["pleroma"]["direct_conversation_id"] == participation.id
end
@@ -600,7 +688,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
query_string = "ids[]=#{id1}&ids[]=#{id2}"
conn = get(conn, "/api/v1/statuses/?#{query_string}")
- assert [%{"id" => ^id1}, %{"id" => ^id2}] = Enum.sort_by(json_response(conn, :ok), & &1["id"])
+ assert [%{"id" => ^id1}, %{"id" => ^id2}] =
+ Enum.sort_by(json_response_and_validate_schema(conn, :ok), & &1["id"])
end
describe "getting statuses by ids with restricted unauthenticated for local and remote" do
@@ -611,17 +700,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+ res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
- assert json_response(res_conn, 200) == []
+ assert json_response_and_validate_schema(res_conn, 200) == []
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
- res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+ res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
- assert length(json_response(res_conn, 200)) == 2
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 2
end
end
@@ -631,18 +720,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+ res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
remote_id = remote.id
- assert [%{"id" => ^remote_id}] = json_response(res_conn, 200)
+ assert [%{"id" => ^remote_id}] = json_response_and_validate_schema(res_conn, 200)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
- res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+ res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
- assert length(json_response(res_conn, 200)) == 2
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 2
end
end
@@ -652,18 +741,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+ res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
local_id = local.id
- assert [%{"id" => ^local_id}] = json_response(res_conn, 200)
+ assert [%{"id" => ^local_id}] = json_response_and_validate_schema(res_conn, 200)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
- res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+ res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
- assert length(json_response(res_conn, 200)) == 2
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 2
end
end
@@ -677,7 +766,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> assign(:user, author)
|> delete("/api/v1/statuses/#{activity.id}")
- assert %{} = json_response(conn, 200)
+ assert %{} = json_response_and_validate_schema(conn, 200)
refute Activity.get_by_id(activity.id)
end
@@ -691,7 +780,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> assign(:user, author)
|> delete("/api/v1/statuses/#{String.downcase(activity.id)}")
- assert %{"error" => "Record not found"} == json_response(conn, 404)
+ assert %{"error" => "Record not found"} == json_response_and_validate_schema(conn, 404)
end
test "when you didn't create it" do
@@ -700,7 +789,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn = delete(conn, "/api/v1/statuses/#{activity.id}")
- assert %{"error" => _} = json_response(conn, 403)
+ assert %{"error" => _} = json_response_and_validate_schema(conn, 403)
assert Activity.get_by_id(activity.id) == activity
end
@@ -717,7 +806,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> assign(:token, insert(:oauth_token, user: admin, scopes: ["write:statuses"]))
|> delete("/api/v1/statuses/#{activity1.id}")
- assert %{} = json_response(res_conn, 200)
+ assert %{} = json_response_and_validate_schema(res_conn, 200)
res_conn =
conn
@@ -725,7 +814,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> assign(:token, insert(:oauth_token, user: moderator, scopes: ["write:statuses"]))
|> delete("/api/v1/statuses/#{activity2.id}")
- assert %{} = json_response(res_conn, 200)
+ assert %{} = json_response_and_validate_schema(res_conn, 200)
refute Activity.get_by_id(activity1.id)
refute Activity.get_by_id(activity2.id)
@@ -738,12 +827,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "reblogs and returns the reblogged status", %{conn: conn} do
activity = insert(:note_activity)
- conn = post(conn, "/api/v1/statuses/#{activity.id}/reblog")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity.id}/reblog")
assert %{
"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1},
"reblogged" => true
- } = json_response(conn, 200)
+ } = json_response_and_validate_schema(conn, 200)
assert to_string(activity.id) == id
end
@@ -751,21 +843,30 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "returns 404 if the reblogged status doesn't exist", %{conn: conn} do
activity = insert(:note_activity)
- conn = post(conn, "/api/v1/statuses/#{String.downcase(activity.id)}/reblog")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{String.downcase(activity.id)}/reblog")
- assert %{"error" => "Record not found"} = json_response(conn, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn, 404)
end
test "reblogs privately and returns the reblogged status", %{conn: conn} do
activity = insert(:note_activity)
- conn = post(conn, "/api/v1/statuses/#{activity.id}/reblog", %{"visibility" => "private"})
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post(
+ "/api/v1/statuses/#{activity.id}/reblog",
+ %{"visibility" => "private"}
+ )
assert %{
"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1},
"reblogged" => true,
"visibility" => "private"
- } = json_response(conn, 200)
+ } = json_response_and_validate_schema(conn, 200)
assert to_string(activity.id) == id
end
@@ -777,8 +878,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
user3 = insert(:user)
{:ok, _} = CommonAPI.favorite(user2, activity.id)
{:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
- {:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
- {:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
+ {:ok, reblog_activity1} = CommonAPI.repeat(activity.id, user1)
+ {:ok, _} = CommonAPI.repeat(activity.id, user2)
conn_res =
build_conn()
@@ -791,7 +892,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
"reblogged" => false,
"favourited" => false,
"bookmarked" => false
- } = json_response(conn_res, 200)
+ } = json_response_and_validate_schema(conn_res, 200)
conn_res =
build_conn()
@@ -804,7 +905,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
"reblogged" => true,
"favourited" => true,
"bookmarked" => true
- } = json_response(conn_res, 200)
+ } = json_response_and_validate_schema(conn_res, 200)
assert to_string(activity.id) == id
end
@@ -816,19 +917,26 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "unreblogs and returns the unreblogged status", %{user: user, conn: conn} do
activity = insert(:note_activity)
- {:ok, _, _} = CommonAPI.repeat(activity.id, user)
+ {:ok, _} = CommonAPI.repeat(activity.id, user)
- conn = post(conn, "/api/v1/statuses/#{activity.id}/unreblog")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity.id}/unreblog")
- assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200)
+ assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} =
+ json_response_and_validate_schema(conn, 200)
assert to_string(activity.id) == id
end
test "returns 404 error when activity does not exist", %{conn: conn} do
- conn = post(conn, "/api/v1/statuses/foo/unreblog")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/foo/unreblog")
- assert json_response(conn, 404) == %{"error" => "Record not found"}
+ assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
end
end
@@ -838,10 +946,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "favs a status and returns it", %{conn: conn} do
activity = insert(:note_activity)
- conn = post(conn, "/api/v1/statuses/#{activity.id}/favourite")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity.id}/favourite")
assert %{"id" => id, "favourites_count" => 1, "favourited" => true} =
- json_response(conn, 200)
+ json_response_and_validate_schema(conn, 200)
assert to_string(activity.id) == id
end
@@ -849,18 +960,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "favoriting twice will just return 200", %{conn: conn} do
activity = insert(:note_activity)
- post(conn, "/api/v1/statuses/#{activity.id}/favourite")
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity.id}/favourite")
- assert post(conn, "/api/v1/statuses/#{activity.id}/favourite")
- |> json_response(200)
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity.id}/favourite")
+ |> json_response_and_validate_schema(200)
end
test "returns 404 error for a wrong id", %{conn: conn} do
conn =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses/1/favourite")
- assert json_response(conn, 404) == %{"error" => "Record not found"}
+ assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
end
end
@@ -872,18 +988,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
{:ok, _} = CommonAPI.favorite(user, activity.id)
- conn = post(conn, "/api/v1/statuses/#{activity.id}/unfavourite")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity.id}/unfavourite")
assert %{"id" => id, "favourites_count" => 0, "favourited" => false} =
- json_response(conn, 200)
+ json_response_and_validate_schema(conn, 200)
assert to_string(activity.id) == id
end
test "returns 404 error for a wrong id", %{conn: conn} do
- conn = post(conn, "/api/v1/statuses/1/unfavourite")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/1/unfavourite")
- assert json_response(conn, 404) == %{"error" => "Record not found"}
+ assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
end
end
@@ -891,7 +1013,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: oauth_access(["write:accounts"])
setup %{user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"})
%{activity: activity}
end
@@ -903,21 +1025,25 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
assert %{"id" => ^id_str, "pinned" => true} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses/#{activity.id}/pin")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert [%{"id" => ^id_str, "pinned" => true}] =
conn
|> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
end
test "/pin: returns 400 error when activity is not public", %{conn: conn, user: user} do
- {:ok, dm} = CommonAPI.post(user, %{"status" => "test", "visibility" => "direct"})
+ {:ok, dm} = CommonAPI.post(user, %{status: "test", visibility: "direct"})
- conn = post(conn, "/api/v1/statuses/#{dm.id}/pin")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{dm.id}/pin")
- assert json_response(conn, 400) == %{"error" => "Could not pin"}
+ assert json_response_and_validate_schema(conn, 400) == %{"error" => "Could not pin"}
end
test "unpin status", %{conn: conn, user: user, activity: activity} do
@@ -930,29 +1056,33 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn
|> assign(:user, user)
|> post("/api/v1/statuses/#{activity.id}/unpin")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert [] =
conn
|> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
end
test "/unpin: returns 400 error when activity is not exist", %{conn: conn} do
- conn = post(conn, "/api/v1/statuses/1/unpin")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/1/unpin")
- assert json_response(conn, 400) == %{"error" => "Could not unpin"}
+ assert json_response_and_validate_schema(conn, 400) == %{"error" => "Could not unpin"}
end
test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
- {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ {:ok, activity_two} = CommonAPI.post(user, %{status: "HI!!!"})
id_str_one = to_string(activity_one.id)
assert %{"id" => ^id_str_one, "pinned" => true} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses/#{id_str_one}/pin")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
user = refresh_record(user)
@@ -960,7 +1090,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn
|> assign(:user, user)
|> post("/api/v1/statuses/#{activity_two.id}/pin")
- |> json_response(400)
+ |> json_response_and_validate_schema(400)
end
end
@@ -974,7 +1104,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "returns rich-media card", %{conn: conn, user: user} do
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "https://example.com/ogp"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "https://example.com/ogp"})
card_data = %{
"image" => "http://ia.media-imdb.com/images/rock.jpg",
@@ -1000,18 +1130,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
response =
conn
|> get("/api/v1/statuses/#{activity.id}/card")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response == card_data
# works with private posts
{:ok, activity} =
- CommonAPI.post(user, %{"status" => "https://example.com/ogp", "visibility" => "direct"})
+ CommonAPI.post(user, %{status: "https://example.com/ogp", visibility: "direct"})
response_two =
conn
|> get("/api/v1/statuses/#{activity.id}/card")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response_two == card_data
end
@@ -1019,13 +1149,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "replaces missing description with an empty string", %{conn: conn, user: user} do
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "https://example.com/ogp-missing-data"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "https://example.com/ogp-missing-data"})
response =
conn
|> get("/api/v1/statuses/#{activity.id}/card")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert response == %{
"type" => "link",
@@ -1047,41 +1176,47 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
end
test "bookmarks" do
- bookmarks_uri = "/api/v1/bookmarks?with_relationships=true"
+ bookmarks_uri = "/api/v1/bookmarks"
%{conn: conn} = oauth_access(["write:bookmarks", "read:bookmarks"])
author = insert(:user)
- {:ok, activity1} =
- CommonAPI.post(author, %{
- "status" => "heweoo?"
- })
-
- {:ok, activity2} =
- CommonAPI.post(author, %{
- "status" => "heweoo!"
- })
+ {:ok, activity1} = CommonAPI.post(author, %{status: "heweoo?"})
+ {:ok, activity2} = CommonAPI.post(author, %{status: "heweoo!"})
- response1 = post(conn, "/api/v1/statuses/#{activity1.id}/bookmark")
+ response1 =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity1.id}/bookmark")
- assert json_response(response1, 200)["bookmarked"] == true
+ assert json_response_and_validate_schema(response1, 200)["bookmarked"] == true
- response2 = post(conn, "/api/v1/statuses/#{activity2.id}/bookmark")
+ response2 =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity2.id}/bookmark")
- assert json_response(response2, 200)["bookmarked"] == true
+ assert json_response_and_validate_schema(response2, 200)["bookmarked"] == true
bookmarks = get(conn, bookmarks_uri)
- assert [json_response(response2, 200), json_response(response1, 200)] ==
- json_response(bookmarks, 200)
+ assert [
+ json_response_and_validate_schema(response2, 200),
+ json_response_and_validate_schema(response1, 200)
+ ] ==
+ json_response_and_validate_schema(bookmarks, 200)
- response1 = post(conn, "/api/v1/statuses/#{activity1.id}/unbookmark")
+ response1 =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
- assert json_response(response1, 200)["bookmarked"] == false
+ assert json_response_and_validate_schema(response1, 200)["bookmarked"] == false
bookmarks = get(conn, bookmarks_uri)
- assert [json_response(response2, 200)] == json_response(bookmarks, 200)
+ assert [json_response_and_validate_schema(response2, 200)] ==
+ json_response_and_validate_schema(bookmarks, 200)
end
describe "conversation muting" do
@@ -1089,7 +1224,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do
post_user = insert(:user)
- {:ok, activity} = CommonAPI.post(post_user, %{"status" => "HIE"})
+ {:ok, activity} = CommonAPI.post(post_user, %{status: "HIE"})
%{activity: activity}
end
@@ -1098,16 +1233,22 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
assert %{"id" => ^id_str, "muted" => true} =
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses/#{activity.id}/mute")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
end
test "cannot mute already muted conversation", %{conn: conn, user: user, activity: activity} do
{:ok, _} = CommonAPI.add_mute(user, activity)
- conn = post(conn, "/api/v1/statuses/#{activity.id}/mute")
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{activity.id}/mute")
- assert json_response(conn, 400) == %{"error" => "conversation is already muted"}
+ assert json_response_and_validate_schema(conn, 400) == %{
+ "error" => "conversation is already muted"
+ }
end
test "unmute conversation", %{conn: conn, user: user, activity: activity} do
@@ -1119,7 +1260,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn
# |> assign(:user, user)
|> post("/api/v1/statuses/#{activity.id}/unmute")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
end
end
@@ -1128,16 +1269,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
user2 = insert(:user)
user3 = insert(:user)
- {:ok, replied_to} = CommonAPI.post(user1, %{"status" => "cofe"})
+ {:ok, replied_to} = CommonAPI.post(user1, %{status: "cofe"})
# Reply to status from another user
conn1 =
conn
|> assign(:user, user2)
|> assign(:token, insert(:oauth_token, user: user2, scopes: ["write:statuses"]))
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
- assert %{"content" => "xD", "id" => id} = json_response(conn1, 200)
+ assert %{"content" => "xD", "id" => id} = json_response_and_validate_schema(conn1, 200)
activity = Activity.get_by_id_with_object(id)
@@ -1149,10 +1291,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn
|> assign(:user, user3)
|> assign(:token, insert(:oauth_token, user: user3, scopes: ["write:statuses"]))
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses/#{activity.id}/reblog")
assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
- json_response(conn2, 200)
+ json_response_and_validate_schema(conn2, 200)
assert to_string(activity.id) == id
@@ -1175,7 +1318,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: oauth_access(["read:accounts"])
setup %{user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test"})
%{activity: activity}
end
@@ -1187,7 +1330,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
response =
conn
|> get("/api/v1/statuses/#{activity.id}/favourited_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
[%{"id" => id}] = response
@@ -1201,7 +1344,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
response =
conn
|> get("/api/v1/statuses/#{activity.id}/favourited_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert Enum.empty?(response)
end
@@ -1218,7 +1361,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
response =
conn
|> get("/api/v1/statuses/#{activity.id}/favourited_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert Enum.empty?(response)
end
@@ -1230,7 +1373,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
response =
build_conn()
|> get("/api/v1/statuses/#{activity.id}/favourited_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
[%{"id" => id}] = response
assert id == other_user.id
@@ -1241,8 +1384,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "@#{other_user.nickname} wanna get some #cofe together?",
- "visibility" => "direct"
+ status: "@#{other_user.nickname} wanna get some #cofe together?",
+ visibility: "direct"
})
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
@@ -1251,7 +1394,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
build_conn()
|> get(favourited_by_url)
- |> json_response(404)
+ |> json_response_and_validate_schema(404)
conn =
build_conn()
@@ -1261,12 +1404,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn
|> assign(:token, nil)
|> get(favourited_by_url)
- |> json_response(404)
+ |> json_response_and_validate_schema(404)
response =
conn
|> get(favourited_by_url)
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
[%{"id" => id}] = response
assert id == other_user.id
@@ -1277,19 +1420,19 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: oauth_access(["read:accounts"])
setup %{user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test"})
%{activity: activity}
end
test "returns users who have reblogged the status", %{conn: conn, activity: activity} do
other_user = insert(:user)
- {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
+ {:ok, _} = CommonAPI.repeat(activity.id, other_user)
response =
conn
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
[%{"id" => id}] = response
@@ -1303,7 +1446,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
response =
conn
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert Enum.empty?(response)
end
@@ -1315,40 +1458,40 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
other_user = insert(:user)
{:ok, _user_relationship} = User.block(user, other_user)
- {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
+ {:ok, _} = CommonAPI.repeat(activity.id, other_user)
response =
conn
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert Enum.empty?(response)
end
test "does not return users who have reblogged the status privately", %{
- conn: conn,
- activity: activity
+ conn: conn
} do
other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "my secret post"})
- {:ok, _, _} = CommonAPI.repeat(activity.id, other_user, %{"visibility" => "private"})
+ {:ok, _} = CommonAPI.repeat(activity.id, other_user, %{visibility: "private"})
response =
conn
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert Enum.empty?(response)
end
test "does not fail on an unauthenticated request", %{activity: activity} do
other_user = insert(:user)
- {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
+ {:ok, _} = CommonAPI.repeat(activity.id, other_user)
response =
build_conn()
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
[%{"id" => id}] = response
assert id == other_user.id
@@ -1359,20 +1502,20 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "@#{other_user.nickname} wanna get some #cofe together?",
- "visibility" => "direct"
+ status: "@#{other_user.nickname} wanna get some #cofe together?",
+ visibility: "direct"
})
build_conn()
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(404)
+ |> json_response_and_validate_schema(404)
response =
build_conn()
|> assign(:user, other_user)
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert [] == response
end
@@ -1381,16 +1524,16 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "context" do
user = insert(:user)
- {:ok, %{id: id1}} = CommonAPI.post(user, %{"status" => "1"})
- {:ok, %{id: id2}} = CommonAPI.post(user, %{"status" => "2", "in_reply_to_status_id" => id1})
- {:ok, %{id: id3}} = CommonAPI.post(user, %{"status" => "3", "in_reply_to_status_id" => id2})
- {:ok, %{id: id4}} = CommonAPI.post(user, %{"status" => "4", "in_reply_to_status_id" => id3})
- {:ok, %{id: id5}} = CommonAPI.post(user, %{"status" => "5", "in_reply_to_status_id" => id4})
+ {:ok, %{id: id1}} = CommonAPI.post(user, %{status: "1"})
+ {:ok, %{id: id2}} = CommonAPI.post(user, %{status: "2", in_reply_to_status_id: id1})
+ {:ok, %{id: id3}} = CommonAPI.post(user, %{status: "3", in_reply_to_status_id: id2})
+ {:ok, %{id: id4}} = CommonAPI.post(user, %{status: "4", in_reply_to_status_id: id3})
+ {:ok, %{id: id5}} = CommonAPI.post(user, %{status: "5", in_reply_to_status_id: id4})
response =
build_conn()
|> get("/api/v1/statuses/#{id3}/context")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert %{
"ancestors" => [%{"id" => ^id1}, %{"id" => ^id2}],
@@ -1398,18 +1541,53 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
} = response
end
+ test "favorites paginate correctly" do
+ %{user: user, conn: conn} = oauth_access(["read:favourites"])
+ other_user = insert(:user)
+ {:ok, first_post} = CommonAPI.post(other_user, %{status: "bla"})
+ {:ok, second_post} = CommonAPI.post(other_user, %{status: "bla"})
+ {:ok, third_post} = CommonAPI.post(other_user, %{status: "bla"})
+
+ {:ok, _first_favorite} = CommonAPI.favorite(user, third_post.id)
+ {:ok, _second_favorite} = CommonAPI.favorite(user, first_post.id)
+ {:ok, third_favorite} = CommonAPI.favorite(user, second_post.id)
+
+ result =
+ conn
+ |> get("/api/v1/favourites?limit=1")
+
+ assert [%{"id" => post_id}] = json_response_and_validate_schema(result, 200)
+ assert post_id == second_post.id
+
+ # Using the header for pagination works correctly
+ [next, _] = get_resp_header(result, "link") |> hd() |> String.split(", ")
+ [_, max_id] = Regex.run(~r/max_id=([^&]+)/, next)
+
+ assert max_id == third_favorite.id
+
+ result =
+ conn
+ |> get("/api/v1/favourites?max_id=#{max_id}")
+
+ assert [%{"id" => first_post_id}, %{"id" => third_post_id}] =
+ json_response_and_validate_schema(result, 200)
+
+ assert first_post_id == first_post.id
+ assert third_post_id == third_post.id
+ end
+
test "returns the favorites of a user" do
%{user: user, conn: conn} = oauth_access(["read:favourites"])
other_user = insert(:user)
- {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
+ {:ok, _} = CommonAPI.post(other_user, %{status: "bla"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "trees are happy"})
- {:ok, _} = CommonAPI.favorite(user, activity.id)
+ {:ok, last_like} = CommonAPI.favorite(user, activity.id)
first_conn = get(conn, "/api/v1/favourites")
- assert [status] = json_response(first_conn, 200)
+ assert [status] = json_response_and_validate_schema(first_conn, 200)
assert status["id"] == to_string(activity.id)
assert [{"link", _link_header}] =
@@ -1418,27 +1596,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
# Honours query params
{:ok, second_activity} =
CommonAPI.post(other_user, %{
- "status" =>
- "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
+ status: "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
})
{:ok, _} = CommonAPI.favorite(user, second_activity.id)
- last_like = status["id"]
-
- second_conn = get(conn, "/api/v1/favourites?since_id=#{last_like}")
+ second_conn = get(conn, "/api/v1/favourites?since_id=#{last_like.id}")
- assert [second_status] = json_response(second_conn, 200)
+ assert [second_status] = json_response_and_validate_schema(second_conn, 200)
assert second_status["id"] == to_string(second_activity.id)
third_conn = get(conn, "/api/v1/favourites?limit=0")
- assert [] = json_response(third_conn, 200)
+ assert [] = json_response_and_validate_schema(third_conn, 200)
end
test "expires_at is nil for another user" do
%{conn: conn, user: user} = oauth_access(["read:statuses"])
- {:ok, activity} = CommonAPI.post(user, %{"status" => "foobar", "expires_in" => 1_000_000})
+ {:ok, activity} = CommonAPI.post(user, %{status: "foobar", expires_in: 1_000_000})
expires_at =
activity.id
@@ -1447,11 +1622,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> NaiveDateTime.to_iso8601()
assert %{"pleroma" => %{"expires_at" => ^expires_at}} =
- conn |> get("/api/v1/statuses/#{activity.id}") |> json_response(:ok)
+ conn
+ |> get("/api/v1/statuses/#{activity.id}")
+ |> json_response_and_validate_schema(:ok)
%{conn: conn} = oauth_access(["read:statuses"])
assert %{"pleroma" => %{"expires_at" => nil}} =
- conn |> get("/api/v1/statuses/#{activity.id}") |> json_response(:ok)
+ conn
+ |> get("/api/v1/statuses/#{activity.id}")
+ |> json_response_and_validate_schema(:ok)
end
end
diff --git a/test/web/mastodon_api/controllers/subscription_controller_test.exs b/test/web/mastodon_api/controllers/subscription_controller_test.exs
index 987158a74..d36bb1ae8 100644
--- a/test/web/mastodon_api/controllers/subscription_controller_test.exs
+++ b/test/web/mastodon_api/controllers/subscription_controller_test.exs
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
+
alias Pleroma.Web.Push
alias Pleroma.Web.Push.Subscription
@@ -27,6 +28,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
build_conn()
|> assign(:user, user)
|> assign(:token, token)
+ |> put_req_header("content-type", "application/json")
%{conn: conn, user: user, token: token}
end
@@ -35,7 +37,10 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
quote do
vapid_details = Application.get_env(:web_push_encryption, :vapid_details, [])
Application.put_env(:web_push_encryption, :vapid_details, [])
- assert "Something went wrong" == unquote(yield)
+
+ assert %{"error" => "Web push subscription is disabled on this Pleroma instance"} ==
+ unquote(yield)
+
Application.put_env(:web_push_encryption, :vapid_details, vapid_details)
end
end
@@ -44,8 +49,8 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
test "returns error when push disabled ", %{conn: conn} do
assert_error_when_disable_push do
conn
- |> post("/api/v1/push/subscription", %{})
- |> json_response(500)
+ |> post("/api/v1/push/subscription", %{subscription: @sub})
+ |> json_response_and_validate_schema(403)
end
end
@@ -53,15 +58,17 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
result =
conn
|> post("/api/v1/push/subscription", %{
- "data" => %{"alerts" => %{"mention" => true, "test" => true}},
+ "data" => %{
+ "alerts" => %{"mention" => true, "test" => true, "pleroma:chat_mention" => true}
+ },
"subscription" => @sub
})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
[subscription] = Pleroma.Repo.all(Subscription)
assert %{
- "alerts" => %{"mention" => true},
+ "alerts" => %{"mention" => true, "pleroma:chat_mention" => true},
"endpoint" => subscription.endpoint,
"id" => to_string(subscription.id),
"server_key" => @server_key
@@ -74,7 +81,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
assert_error_when_disable_push do
conn
|> get("/api/v1/push/subscription", %{})
- |> json_response(500)
+ |> json_response_and_validate_schema(403)
end
end
@@ -82,9 +89,9 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
res =
conn
|> get("/api/v1/push/subscription", %{})
- |> json_response(404)
+ |> json_response_and_validate_schema(404)
- assert "Not found" == res
+ assert %{"error" => "Record not found"} == res
end
test "returns a user subsciption", %{conn: conn, user: user, token: token} do
@@ -98,7 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
res =
conn
|> get("/api/v1/push/subscription", %{})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
expect = %{
"alerts" => %{"mention" => true},
@@ -127,7 +134,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
assert_error_when_disable_push do
conn
|> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}})
- |> json_response(500)
+ |> json_response_and_validate_schema(403)
end
end
@@ -137,7 +144,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
|> put("/api/v1/push/subscription", %{
data: %{"alerts" => %{"mention" => false, "follow" => true}}
})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
expect = %{
"alerts" => %{"follow" => true, "mention" => false},
@@ -155,7 +162,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
assert_error_when_disable_push do
conn
|> delete("/api/v1/push/subscription", %{})
- |> json_response(500)
+ |> json_response_and_validate_schema(403)
end
end
@@ -163,9 +170,9 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
res =
conn
|> delete("/api/v1/push/subscription", %{})
- |> json_response(404)
+ |> json_response_and_validate_schema(404)
- assert "Not found" == res
+ assert %{"error" => "Record not found"} == res
end
test "returns empty result and delete user subsciption", %{
@@ -183,7 +190,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
res =
conn
|> delete("/api/v1/push/subscription", %{})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert %{} == res
refute Pleroma.Repo.get(Subscription, subscription.id)
diff --git a/test/web/mastodon_api/controllers/suggestion_controller_test.exs b/test/web/mastodon_api/controllers/suggestion_controller_test.exs
index 8d0e70db8..7f08e187c 100644
--- a/test/web/mastodon_api/controllers/suggestion_controller_test.exs
+++ b/test/web/mastodon_api/controllers/suggestion_controller_test.exs
@@ -5,15 +5,13 @@
defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
use Pleroma.Web.ConnCase
- alias Pleroma.Config
-
setup do: oauth_access(["read"])
test "returns empty result", %{conn: conn} do
res =
conn
|> get("/api/v1/suggestions")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert res == []
end
diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs
index 06efdc901..f069390c1 100644
--- a/test/web/mastodon_api/controllers/timeline_controller_test.exs
+++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs
@@ -20,106 +20,36 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
describe "home" do
setup do: oauth_access(["read:statuses"])
- test "does NOT render account/pleroma/relationship if this is disabled by default", %{
+ test "does NOT embed account/pleroma/relationship in statuses", %{
user: user,
conn: conn
} do
- clear_config([:extensions, :output_relationships_in_statuses_by_default], false)
-
other_user = insert(:user)
- {:ok, _} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
+ {:ok, _} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
response =
conn
|> assign(:user, user)
|> get("/api/v1/timelines/home")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert Enum.all?(response, fn n ->
get_in(n, ["account", "pleroma", "relationship"]) == %{}
end)
end
- test "the home timeline", %{user: user, conn: conn} do
- uri = "/api/v1/timelines/home?with_relationships=true"
-
- following = insert(:user, nickname: "followed")
- third_user = insert(:user, nickname: "repeated")
-
- {:ok, _activity} = CommonAPI.post(following, %{"status" => "post"})
- {:ok, activity} = CommonAPI.post(third_user, %{"status" => "repeated post"})
- {:ok, _, _} = CommonAPI.repeat(activity.id, following)
-
- ret_conn = get(conn, uri)
-
- assert Enum.empty?(json_response(ret_conn, :ok))
-
- {:ok, _user} = User.follow(user, following)
-
- ret_conn = get(conn, uri)
-
- assert [
- %{
- "reblog" => %{
- "content" => "repeated post",
- "account" => %{
- "pleroma" => %{
- "relationship" => %{"following" => false, "followed_by" => false}
- }
- }
- },
- "account" => %{"pleroma" => %{"relationship" => %{"following" => true}}}
- },
- %{
- "content" => "post",
- "account" => %{
- "acct" => "followed",
- "pleroma" => %{"relationship" => %{"following" => true}}
- }
- }
- ] = json_response(ret_conn, :ok)
-
- {:ok, _user} = User.follow(third_user, user)
-
- ret_conn = get(conn, uri)
-
- assert [
- %{
- "reblog" => %{
- "content" => "repeated post",
- "account" => %{
- "acct" => "repeated",
- "pleroma" => %{
- "relationship" => %{"following" => false, "followed_by" => true}
- }
- }
- },
- "account" => %{"pleroma" => %{"relationship" => %{"following" => true}}}
- },
- %{
- "content" => "post",
- "account" => %{
- "acct" => "followed",
- "pleroma" => %{"relationship" => %{"following" => true}}
- }
- }
- ] = json_response(ret_conn, :ok)
- end
-
test "the home timeline when the direct messages are excluded", %{user: user, conn: conn} do
- {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
- {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+ {:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
+ {:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
- {:ok, unlisted_activity} =
- CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
+ {:ok, unlisted_activity} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
- {:ok, private_activity} =
- CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ {:ok, private_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
- conn = get(conn, "/api/v1/timelines/home", %{"exclude_visibilities" => ["direct"]})
+ conn = get(conn, "/api/v1/timelines/home?exclude_visibilities[]=direct")
- assert status_ids = json_response(conn, :ok) |> Enum.map(& &1["id"])
+ assert status_ids = json_response_and_validate_schema(conn, :ok) |> Enum.map(& &1["id"])
assert public_activity.id in status_ids
assert unlisted_activity.id in status_ids
assert private_activity.id in status_ids
@@ -130,35 +60,85 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
describe "public" do
@tag capture_log: true
test "the public timeline", %{conn: conn} do
- following = insert(:user)
+ user = insert(:user)
- {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "test"})
_activity = insert(:note_activity, local: false)
- conn = get(conn, "/api/v1/timelines/public", %{"local" => "False"})
+ conn = get(conn, "/api/v1/timelines/public?local=False")
+
+ assert length(json_response_and_validate_schema(conn, :ok)) == 2
+
+ conn = get(build_conn(), "/api/v1/timelines/public?local=True")
- assert length(json_response(conn, :ok)) == 2
+ assert [%{"content" => "test"}] = json_response_and_validate_schema(conn, :ok)
- conn = get(build_conn(), "/api/v1/timelines/public", %{"local" => "True"})
+ conn = get(build_conn(), "/api/v1/timelines/public?local=1")
- assert [%{"content" => "test"}] = json_response(conn, :ok)
+ assert [%{"content" => "test"}] = json_response_and_validate_schema(conn, :ok)
- conn = get(build_conn(), "/api/v1/timelines/public", %{"local" => "1"})
+ # does not contain repeats
+ {:ok, _} = CommonAPI.repeat(activity.id, user)
- assert [%{"content" => "test"}] = json_response(conn, :ok)
+ conn = get(build_conn(), "/api/v1/timelines/public?local=true")
+
+ assert [_] = json_response_and_validate_schema(conn, :ok)
end
test "the public timeline includes only public statuses for an authenticated user" do
%{user: user, conn: conn} = oauth_access(["read:statuses"])
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "test"})
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "private"})
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "unlisted"})
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "direct"})
+ {:ok, _activity} = CommonAPI.post(user, %{status: "test"})
+ {:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "private"})
+ {:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "unlisted"})
+ {:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "direct"})
res_conn = get(conn, "/api/v1/timelines/public")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
+ end
+
+ test "doesn't return replies if follower is posting with blocked user" do
+ %{conn: conn, user: blocker} = oauth_access(["read:statuses"])
+ [blockee, friend] = insert_list(2, :user)
+ {:ok, blocker} = User.follow(blocker, friend)
+ {:ok, _} = User.block(blocker, blockee)
+
+ conn = assign(conn, :user, blocker)
+
+ {:ok, %{id: activity_id} = activity} = CommonAPI.post(friend, %{status: "hey!"})
+
+ {:ok, reply_from_blockee} =
+ CommonAPI.post(blockee, %{status: "heya", in_reply_to_status_id: activity})
+
+ {:ok, _reply_from_friend} =
+ CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee})
+
+ res_conn = get(conn, "/api/v1/timelines/public")
+ [%{"id" => ^activity_id}] = json_response_and_validate_schema(res_conn, 200)
+ end
+
+ test "doesn't return replies if follow is posting with users from blocked domain" do
+ %{conn: conn, user: blocker} = oauth_access(["read:statuses"])
+ friend = insert(:user)
+ blockee = insert(:user, ap_id: "https://example.com/users/blocked")
+ {:ok, blocker} = User.follow(blocker, friend)
+ {:ok, blocker} = User.block_domain(blocker, "example.com")
+
+ conn = assign(conn, :user, blocker)
+
+ {:ok, %{id: activity_id} = activity} = CommonAPI.post(friend, %{status: "hey!"})
+
+ {:ok, reply_from_blockee} =
+ CommonAPI.post(blockee, %{status: "heya", in_reply_to_status_id: activity})
+
+ {:ok, _reply_from_friend} =
+ CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee})
+
+ res_conn = get(conn, "/api/v1/timelines/public")
+
+ activities = json_response_and_validate_schema(res_conn, 200)
+ [%{"id" => ^activity_id}] = activities
end
end
@@ -176,15 +156,15 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], true)
test "if user is unauthenticated", %{conn: conn} do
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"})
+ res_conn = get(conn, "/api/v1/timelines/public?local=true")
- assert json_response(res_conn, :unauthorized) == %{
+ assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
"error" => "authorization required for timeline view"
}
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"})
+ res_conn = get(conn, "/api/v1/timelines/public?local=false")
- assert json_response(res_conn, :unauthorized) == %{
+ assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
"error" => "authorization required for timeline view"
}
end
@@ -192,11 +172,11 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
test "if user is authenticated" do
%{conn: conn} = oauth_access(["read:statuses"])
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"})
- assert length(json_response(res_conn, 200)) == 1
+ res_conn = get(conn, "/api/v1/timelines/public?local=true")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"})
- assert length(json_response(res_conn, 200)) == 2
+ res_conn = get(conn, "/api/v1/timelines/public?local=false")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 2
end
end
@@ -206,24 +186,24 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
setup do: clear_config([:restrict_unauthenticated, :timelines, :local], true)
test "if user is unauthenticated", %{conn: conn} do
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"})
+ res_conn = get(conn, "/api/v1/timelines/public?local=true")
- assert json_response(res_conn, :unauthorized) == %{
+ assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
"error" => "authorization required for timeline view"
}
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"})
- assert length(json_response(res_conn, 200)) == 2
+ res_conn = get(conn, "/api/v1/timelines/public?local=false")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 2
end
test "if user is authenticated", %{conn: _conn} do
%{conn: conn} = oauth_access(["read:statuses"])
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"})
- assert length(json_response(res_conn, 200)) == 1
+ res_conn = get(conn, "/api/v1/timelines/public?local=true")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"})
- assert length(json_response(res_conn, 200)) == 2
+ res_conn = get(conn, "/api/v1/timelines/public?local=false")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 2
end
end
@@ -233,12 +213,12 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], true)
test "if user is unauthenticated", %{conn: conn} do
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"})
- assert length(json_response(res_conn, 200)) == 1
+ res_conn = get(conn, "/api/v1/timelines/public?local=true")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"})
+ res_conn = get(conn, "/api/v1/timelines/public?local=false")
- assert json_response(res_conn, :unauthorized) == %{
+ assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
"error" => "authorization required for timeline view"
}
end
@@ -246,11 +226,11 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
test "if user is authenticated", %{conn: _conn} do
%{conn: conn} = oauth_access(["read:statuses"])
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"})
- assert length(json_response(res_conn, 200)) == 1
+ res_conn = get(conn, "/api/v1/timelines/public?local=true")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
- res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"})
- assert length(json_response(res_conn, 200)) == 2
+ res_conn = get(conn, "/api/v1/timelines/public?local=false")
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 2
end
end
@@ -263,14 +243,14 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
{:ok, direct} =
CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}!",
- "visibility" => "direct"
+ status: "Hi @#{user_two.nickname}!",
+ visibility: "direct"
})
{:ok, _follower_only} =
CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}!",
- "visibility" => "private"
+ status: "Hi @#{user_two.nickname}!",
+ visibility: "private"
})
conn_user_two =
@@ -281,7 +261,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
# Only direct should be visible here
res_conn = get(conn_user_two, "api/v1/timelines/direct")
- [status] = json_response(res_conn, :ok)
+ assert [status] = json_response_and_validate_schema(res_conn, :ok)
assert %{"visibility" => "direct"} = status
assert status["url"] != direct.data["id"]
@@ -293,33 +273,34 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
|> assign(:token, insert(:oauth_token, user: user_one, scopes: ["read:statuses"]))
|> get("api/v1/timelines/direct")
- [status] = json_response(res_conn, :ok)
+ [status] = json_response_and_validate_schema(res_conn, :ok)
assert %{"visibility" => "direct"} = status
# Both should be visible here
res_conn = get(conn_user_two, "api/v1/timelines/home")
- [_s1, _s2] = json_response(res_conn, :ok)
+ [_s1, _s2] = json_response_and_validate_schema(res_conn, :ok)
# Test pagination
Enum.each(1..20, fn _ ->
{:ok, _} =
CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}!",
- "visibility" => "direct"
+ status: "Hi @#{user_two.nickname}!",
+ visibility: "direct"
})
end)
res_conn = get(conn_user_two, "api/v1/timelines/direct")
- statuses = json_response(res_conn, :ok)
+ statuses = json_response_and_validate_schema(res_conn, :ok)
assert length(statuses) == 20
- res_conn =
- get(conn_user_two, "api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
+ max_id = List.last(statuses)["id"]
+
+ res_conn = get(conn_user_two, "api/v1/timelines/direct?max_id=#{max_id}")
- [status] = json_response(res_conn, :ok)
+ assert [status] = json_response_and_validate_schema(res_conn, :ok)
assert status["url"] != direct.data["id"]
end
@@ -332,19 +313,19 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
{:ok, _blocked_direct} =
CommonAPI.post(blocked, %{
- "status" => "Hi @#{blocker.nickname}!",
- "visibility" => "direct"
+ status: "Hi @#{blocker.nickname}!",
+ visibility: "direct"
})
{:ok, direct} =
CommonAPI.post(other_user, %{
- "status" => "Hi @#{blocker.nickname}!",
- "visibility" => "direct"
+ status: "Hi @#{blocker.nickname}!",
+ visibility: "direct"
})
res_conn = get(conn, "api/v1/timelines/direct")
- [status] = json_response(res_conn, :ok)
+ [status] = json_response_and_validate_schema(res_conn, :ok)
assert status["id"] == direct.id
end
end
@@ -354,14 +335,14 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
test "list timeline", %{user: user, conn: conn} do
other_user = insert(:user)
- {:ok, _activity_one} = CommonAPI.post(user, %{"status" => "Marisa is cute."})
- {:ok, activity_two} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."})
+ {:ok, _activity_one} = CommonAPI.post(user, %{status: "Marisa is cute."})
+ {:ok, activity_two} = CommonAPI.post(other_user, %{status: "Marisa is cute."})
{:ok, list} = Pleroma.List.create("name", user)
{:ok, list} = Pleroma.List.follow(list, other_user)
conn = get(conn, "/api/v1/timelines/list/#{list.id}")
- assert [%{"id" => id}] = json_response(conn, :ok)
+ assert [%{"id" => id}] = json_response_and_validate_schema(conn, :ok)
assert id == to_string(activity_two.id)
end
@@ -371,12 +352,12 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
conn: conn
} do
other_user = insert(:user)
- {:ok, activity_one} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."})
+ {:ok, activity_one} = CommonAPI.post(other_user, %{status: "Marisa is cute."})
{:ok, _activity_two} =
CommonAPI.post(other_user, %{
- "status" => "Marisa is cute.",
- "visibility" => "private"
+ status: "Marisa is cute.",
+ visibility: "private"
})
{:ok, list} = Pleroma.List.create("name", user)
@@ -384,7 +365,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
conn = get(conn, "/api/v1/timelines/list/#{list.id}")
- assert [%{"id" => id}] = json_response(conn, :ok)
+ assert [%{"id" => id}] = json_response_and_validate_schema(conn, :ok)
assert id == to_string(activity_one.id)
end
@@ -397,18 +378,18 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
test "hashtag timeline", %{conn: conn} do
following = insert(:user)
- {:ok, activity} = CommonAPI.post(following, %{"status" => "test #2hu"})
+ {:ok, activity} = CommonAPI.post(following, %{status: "test #2hu"})
nconn = get(conn, "/api/v1/timelines/tag/2hu")
- assert [%{"id" => id}] = json_response(nconn, :ok)
+ assert [%{"id" => id}] = json_response_and_validate_schema(nconn, :ok)
assert id == to_string(activity.id)
# works for different capitalization too
nconn = get(conn, "/api/v1/timelines/tag/2HU")
- assert [%{"id" => id}] = json_response(nconn, :ok)
+ assert [%{"id" => id}] = json_response_and_validate_schema(nconn, :ok)
assert id == to_string(activity.id)
end
@@ -416,26 +397,25 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
test "multi-hashtag timeline", %{conn: conn} do
user = insert(:user)
- {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
- {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
- {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
+ {:ok, activity_test} = CommonAPI.post(user, %{status: "#test"})
+ {:ok, activity_test1} = CommonAPI.post(user, %{status: "#test #test1"})
+ {:ok, activity_none} = CommonAPI.post(user, %{status: "#test #none"})
- any_test = get(conn, "/api/v1/timelines/tag/test", %{"any" => ["test1"]})
+ any_test = get(conn, "/api/v1/timelines/tag/test?any[]=test1")
- [status_none, status_test1, status_test] = json_response(any_test, :ok)
+ [status_none, status_test1, status_test] = json_response_and_validate_schema(any_test, :ok)
assert to_string(activity_test.id) == status_test["id"]
assert to_string(activity_test1.id) == status_test1["id"]
assert to_string(activity_none.id) == status_none["id"]
- restricted_test =
- get(conn, "/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
+ restricted_test = get(conn, "/api/v1/timelines/tag/test?all[]=test1&none[]=none")
- assert [status_test1] == json_response(restricted_test, :ok)
+ assert [status_test1] == json_response_and_validate_schema(restricted_test, :ok)
- all_test = get(conn, "/api/v1/timelines/tag/test", %{"all" => ["none"]})
+ all_test = get(conn, "/api/v1/timelines/tag/test?all[]=none")
- assert [status_none] == json_response(all_test, :ok)
+ assert [status_none] == json_response_and_validate_schema(all_test, :ok)
end
end
end
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index 75f184242..bb4bc4396 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -7,35 +7,28 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
describe "empty_array/2 (stubs)" do
test "GET /api/v1/accounts/:id/identity_proofs" do
- %{user: user, conn: conn} = oauth_access(["n/a"])
+ %{user: user, conn: conn} = oauth_access(["read:accounts"])
- res =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/#{user.id}/identity_proofs")
- |> json_response(200)
-
- assert res == []
+ assert [] ==
+ conn
+ |> get("/api/v1/accounts/#{user.id}/identity_proofs")
+ |> json_response(200)
end
test "GET /api/v1/endorsements" do
%{conn: conn} = oauth_access(["read:accounts"])
- res =
- conn
- |> get("/api/v1/endorsements")
- |> json_response(200)
-
- assert res == []
+ assert [] ==
+ conn
+ |> get("/api/v1/endorsements")
+ |> json_response(200)
end
test "GET /api/v1/trends", %{conn: conn} do
- res =
- conn
- |> get("/api/v1/trends")
- |> json_response(200)
-
- assert res == []
+ assert [] ==
+ conn
+ |> get("/api/v1/trends")
+ |> json_response(200)
end
end
end
diff --git a/test/web/mastodon_api/mastodon_api_test.exs b/test/web/mastodon_api/mastodon_api_test.exs
index cb971806a..a7f9c5205 100644
--- a/test/web/mastodon_api/mastodon_api_test.exs
+++ b/test/web/mastodon_api/mastodon_api_test.exs
@@ -75,9 +75,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do
User.subscribe(subscriber, user)
- {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
+ {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
- {:ok, status1} = CommonAPI.post(user, %{"status" => "Magi"})
+ {:ok, status1} = CommonAPI.post(user, %{status: "Magi"})
{:ok, [notification]} = Notification.create_notifications(status)
{:ok, [notification1]} = Notification.create_notifications(status1)
res = MastodonAPI.get_notifications(subscriber)
diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs
index 85fa4f6a2..80b1f734c 100644
--- a/test/web/mastodon_api/views/account_view_test.exs
+++ b/test/web/mastodon_api/views/account_view_test.exs
@@ -31,9 +31,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
nickname: "shp@shitposter.club",
name: ":karjalanpiirakka: shp",
bio:
- "<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f",
+ "<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f '&<>\"",
inserted_at: ~N[2017-08-15 15:47:06.597036],
- emoji: %{"karjalanpiirakka" => "/file.png"}
+ emoji: %{"karjalanpiirakka" => "/file.png"},
+ raw_bio: "valid html. a\nb\nc\nd\nf '&<>\""
})
expected = %{
@@ -46,7 +47,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
followers_count: 3,
following_count: 0,
statuses_count: 5,
- note: "<span>valid html</span>. a<br/>b<br/>c<br/>d<br/>f",
+ note: "<span>valid html</span>. a<br/>b<br/>c<br/>d<br/>f &#39;&amp;&lt;&gt;&quot;",
url: user.ap_id,
avatar: "http://localhost:4001/images/avi.png",
avatar_static: "http://localhost:4001/images/avi.png",
@@ -54,16 +55,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
header_static: "http://localhost:4001/images/banner.png",
emojis: [
%{
- "static_url" => "/file.png",
- "url" => "/file.png",
- "shortcode" => "karjalanpiirakka",
- "visible_in_picker" => false
+ static_url: "/file.png",
+ url: "/file.png",
+ shortcode: "karjalanpiirakka",
+ visible_in_picker: false
}
],
fields: [],
bot: false,
source: %{
- note: "valid html. a\nb\nc\nd\nf",
+ note: "valid html. a\nb\nc\nd\nf '&<>\"",
sensitive: false,
pleroma: %{
actor_type: "Person",
@@ -72,6 +73,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
fields: []
},
pleroma: %{
+ ap_id: user.ap_id,
background_image: "https://example.com/images/asuka_hospital.png",
confirmation_pending: false,
tags: [],
@@ -93,7 +95,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
test "Represent the user account for the account owner" do
user = insert(:user)
- notification_settings = %Pleroma.User.NotificationSetting{}
+ notification_settings = %{
+ followers: true,
+ follows: true,
+ non_followers: true,
+ non_follows: true,
+ privacy_option: false
+ }
+
privacy = user.default_scope
assert %{
@@ -141,6 +150,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
fields: []
},
pleroma: %{
+ ap_id: user.ap_id,
background_image: nil,
confirmation_pending: false,
tags: [],
@@ -295,82 +305,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
end
end
- test "represent an embedded relationship" do
- user =
- insert(:user, %{
- follower_count: 0,
- note_count: 5,
- actor_type: "Service",
- nickname: "shp@shitposter.club",
- inserted_at: ~N[2017-08-15 15:47:06.597036]
- })
-
- other_user = insert(:user)
- {:ok, other_user} = User.follow(other_user, user)
- {:ok, _user_relationship} = User.block(other_user, user)
- {:ok, _} = User.follow(insert(:user), user)
-
- expected = %{
- id: to_string(user.id),
- username: "shp",
- acct: user.nickname,
- display_name: user.name,
- locked: false,
- created_at: "2017-08-15T15:47:06.000Z",
- followers_count: 1,
- following_count: 0,
- statuses_count: 5,
- note: user.bio,
- url: user.ap_id,
- avatar: "http://localhost:4001/images/avi.png",
- avatar_static: "http://localhost:4001/images/avi.png",
- header: "http://localhost:4001/images/banner.png",
- header_static: "http://localhost:4001/images/banner.png",
- emojis: [],
- fields: [],
- bot: true,
- source: %{
- note: user.bio,
- sensitive: false,
- pleroma: %{
- actor_type: "Service",
- discoverable: false
- },
- fields: []
- },
- pleroma: %{
- background_image: nil,
- confirmation_pending: false,
- tags: [],
- is_admin: false,
- is_moderator: false,
- hide_favorites: true,
- hide_followers: false,
- hide_follows: false,
- hide_followers_count: false,
- hide_follows_count: false,
- relationship: %{
- id: to_string(user.id),
- following: false,
- followed_by: false,
- blocking: true,
- blocked_by: false,
- subscribing: false,
- muting: false,
- muting_notifications: false,
- requested: false,
- domain_blocking: false,
- showing_reblogs: true,
- endorsed: false
- },
- skip_thread_containment: false
- }
- }
-
- assert expected ==
- AccountView.render("show.json", %{user: refresh_record(user), for: other_user})
- end
-
test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
user = insert(:user, pleroma_settings_store: %{fe: "test"})
@@ -452,8 +386,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
{:ok, _activity} =
CommonAPI.post(other_user, %{
- "status" => "Hey @#{user.nickname}.",
- "visibility" => "direct"
+ status: "Hey @#{user.nickname}.",
+ visibility: "direct"
})
user = User.get_cached_by_ap_id(user.ap_id)
@@ -466,6 +400,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
:unread_conversation_count
] == 1
end
+
+ test "shows unread_count only to the account owner" do
+ user = insert(:user)
+ insert_list(7, :notification, user: user)
+ other_user = insert(:user)
+
+ user = User.get_cached_by_ap_id(user.ap_id)
+
+ assert AccountView.render(
+ "show.json",
+ %{user: user, for: other_user}
+ )[:pleroma][:unread_notifications_count] == nil
+
+ assert AccountView.render(
+ "show.json",
+ %{user: user, for: user}
+ )[:pleroma][:unread_notifications_count] == 7
+ end
end
describe "follow requests counter" do
@@ -542,4 +494,31 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
AccountView.render("show.json", %{user: user, for: user})
end
end
+
+ test "uses mediaproxy urls when it's enabled" do
+ clear_config([:media_proxy, :enabled], true)
+
+ user =
+ insert(:user,
+ avatar: %{"url" => [%{"href" => "https://evil.website/avatar.png"}]},
+ banner: %{"url" => [%{"href" => "https://evil.website/banner.png"}]},
+ emoji: %{"joker_smile" => "https://evil.website/society.png"}
+ )
+
+ AccountView.render("show.json", %{user: user})
+ |> Enum.all?(fn
+ {key, url} when key in [:avatar, :avatar_static, :header, :header_static] ->
+ String.starts_with?(url, Pleroma.Web.base_url())
+
+ {:emojis, emojis} ->
+ Enum.all?(emojis, fn %{url: url, static_url: static_url} ->
+ String.starts_with?(url, Pleroma.Web.base_url()) &&
+ String.starts_with?(static_url, Pleroma.Web.base_url())
+ end)
+
+ _ ->
+ true
+ end)
+ |> assert()
+ end
end
diff --git a/test/web/mastodon_api/views/conversation_view_test.exs b/test/web/mastodon_api/views/conversation_view_test.exs
index dbf3c51e2..2e8203c9b 100644
--- a/test/web/mastodon_api/views/conversation_view_test.exs
+++ b/test/web/mastodon_api/views/conversation_view_test.exs
@@ -15,8 +15,17 @@ defmodule Pleroma.Web.MastodonAPI.ConversationViewTest do
user = insert(:user)
other_user = insert(:user)
+ {:ok, parent} = CommonAPI.post(user, %{status: "parent"})
+
{:ok, activity} =
- CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}", "visibility" => "direct"})
+ CommonAPI.post(user, %{
+ status: "hey @#{other_user.nickname}",
+ visibility: "direct",
+ in_reply_to_id: parent.id
+ })
+
+ {:ok, _reply_activity} =
+ CommonAPI.post(user, %{status: "hu", visibility: "public", in_reply_to_id: parent.id})
[participation] = Participation.for_user_with_last_activity_id(user)
diff --git a/test/web/mastodon_api/views/marker_view_test.exs b/test/web/mastodon_api/views/marker_view_test.exs
index 893cf8857..48a0a6d33 100644
--- a/test/web/mastodon_api/views/marker_view_test.exs
+++ b/test/web/mastodon_api/views/marker_view_test.exs
@@ -8,19 +8,21 @@ defmodule Pleroma.Web.MastodonAPI.MarkerViewTest do
import Pleroma.Factory
test "returns markers" do
- marker1 = insert(:marker, timeline: "notifications", last_read_id: "17")
+ marker1 = insert(:marker, timeline: "notifications", last_read_id: "17", unread_count: 5)
marker2 = insert(:marker, timeline: "home", last_read_id: "42")
assert MarkerView.render("markers.json", %{markers: [marker1, marker2]}) == %{
"home" => %{
last_read_id: "42",
updated_at: NaiveDateTime.to_iso8601(marker2.updated_at),
- version: 0
+ version: 0,
+ pleroma: %{unread_count: 0}
},
"notifications" => %{
last_read_id: "17",
updated_at: NaiveDateTime.to_iso8601(marker1.updated_at),
- version: 0
+ version: 0,
+ pleroma: %{unread_count: 5}
}
}
end
diff --git a/test/web/mastodon_api/views/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs
index c3ec9dfec..9c399b2df 100644
--- a/test/web/mastodon_api/views/notification_view_test.exs
+++ b/test/web/mastodon_api/views/notification_view_test.exs
@@ -6,7 +6,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
use Pleroma.DataCase
alias Pleroma.Activity
+ alias Pleroma.Chat
+ alias Pleroma.Chat.MessageReference
alias Pleroma.Notification
+ alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.CommonAPI
@@ -14,6 +17,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.NotificationView
alias Pleroma.Web.MastodonAPI.StatusView
+ alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
import Pleroma.Factory
defp test_notifications_rendering(notifications, user, expected_result) do
@@ -31,10 +35,34 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
assert expected_result == result
end
+ test "ChatMessage notification" do
+ user = insert(:user)
+ recipient = insert(:user)
+ {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "what's up my dude")
+
+ {:ok, [notification]} = Notification.create_notifications(activity)
+
+ object = Object.normalize(activity)
+ chat = Chat.get(recipient.id, user.ap_id)
+
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ expected = %{
+ id: to_string(notification.id),
+ pleroma: %{is_seen: false},
+ type: "pleroma:chat_mention",
+ account: AccountView.render("show.json", %{user: user, for: recipient}),
+ chat_message: MessageReferenceView.render("show.json", %{chat_message_reference: cm_ref}),
+ created_at: Utils.to_masto_date(notification.inserted_at)
+ }
+
+ test_notifications_rendering([notification], recipient, [expected])
+ end
+
test "Mention notification" do
user = insert(:user)
mentioned_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{mentioned_user.nickname}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{mentioned_user.nickname}"})
{:ok, [notification]} = Notification.create_notifications(activity)
user = User.get_cached_by_id(user.id)
@@ -42,7 +70,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
id: to_string(notification.id),
pleroma: %{is_seen: false},
type: "mention",
- account: AccountView.render("show.json", %{user: user, for: mentioned_user}),
+ account:
+ AccountView.render("show.json", %{
+ user: user,
+ for: mentioned_user
+ }),
status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}),
created_at: Utils.to_masto_date(notification.inserted_at)
}
@@ -53,7 +85,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
test "Favourite notification" do
user = insert(:user)
another_user = insert(:user)
- {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
+ {:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
{:ok, favorite_activity} = CommonAPI.favorite(another_user, create_activity.id)
{:ok, [notification]} = Notification.create_notifications(favorite_activity)
create_activity = Activity.get_by_id(create_activity.id)
@@ -73,8 +105,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
test "Reblog notification" do
user = insert(:user)
another_user = insert(:user)
- {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
- {:ok, reblog_activity, _object} = CommonAPI.repeat(create_activity.id, another_user)
+ {:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
+ {:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, another_user)
{:ok, [notification]} = Notification.create_notifications(reblog_activity)
reblog_activity = Activity.get_by_id(create_activity.id)
@@ -107,9 +139,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
test_notifications_rendering([notification], followed, [expected])
User.perform(:delete, follower)
- notification = Notification |> Repo.one() |> Repo.preload(:activity)
-
- test_notifications_rendering([notification], followed, [])
+ refute Repo.one(Notification)
end
@tag capture_log: true
@@ -155,8 +185,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
user = insert(:user)
other_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
- {:ok, _activity, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
+ {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
+ {:ok, _activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
activity = Repo.get(Activity, activity.id)
diff --git a/test/web/mastodon_api/views/poll_view_test.exs b/test/web/mastodon_api/views/poll_view_test.exs
index 6211fa888..76672f36c 100644
--- a/test/web/mastodon_api/views/poll_view_test.exs
+++ b/test/web/mastodon_api/views/poll_view_test.exs
@@ -22,10 +22,10 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "Is Tenshi eating a corndog cute?",
- "poll" => %{
- "options" => ["absolutely!", "sure", "yes", "why are you even asking?"],
- "expires_in" => 20
+ status: "Is Tenshi eating a corndog cute?",
+ poll: %{
+ options: ["absolutely!", "sure", "yes", "why are you even asking?"],
+ expires_in: 20
}
})
@@ -43,7 +43,8 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
%{title: "why are you even asking?", votes_count: 0}
],
voted: false,
- votes_count: 0
+ votes_count: 0,
+ voters_count: nil
}
result = PollView.render("show.json", %{object: object})
@@ -61,17 +62,28 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "Which Mastodon developer is your favourite?",
- "poll" => %{
- "options" => ["Gargron", "Eugen"],
- "expires_in" => 20,
- "multiple" => true
+ status: "Which Mastodon developer is your favourite?",
+ poll: %{
+ options: ["Gargron", "Eugen"],
+ expires_in: 20,
+ multiple: true
}
})
+ voter = insert(:user)
+
object = Object.normalize(activity)
- assert %{multiple: true} = PollView.render("show.json", %{object: object})
+ {:ok, _votes, object} = CommonAPI.vote(voter, object, [0, 1])
+
+ assert match?(
+ %{
+ multiple: true,
+ voters_count: 1,
+ votes_count: 2
+ },
+ PollView.render("show.json", %{object: object})
+ )
end
test "detects emoji" do
@@ -79,10 +91,10 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "What's with the smug face?",
- "poll" => %{
- "options" => [":blank: sip", ":blank::blank: sip", ":blank::blank::blank: sip"],
- "expires_in" => 20
+ status: "What's with the smug face?",
+ poll: %{
+ options: [":blank: sip", ":blank::blank: sip", ":blank::blank::blank: sip"],
+ expires_in: 20
}
})
@@ -97,11 +109,11 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "Which input devices do you use?",
- "poll" => %{
- "options" => ["mouse", "trackball", "trackpoint"],
- "multiple" => true,
- "expires_in" => 20
+ status: "Which input devices do you use?",
+ poll: %{
+ options: ["mouse", "trackball", "trackpoint"],
+ multiple: true,
+ expires_in: 20
}
})
diff --git a/test/web/mastodon_api/views/scheduled_activity_view_test.exs b/test/web/mastodon_api/views/scheduled_activity_view_test.exs
index 0c0987593..fbfd873ef 100644
--- a/test/web/mastodon_api/views/scheduled_activity_view_test.exs
+++ b/test/web/mastodon_api/views/scheduled_activity_view_test.exs
@@ -14,7 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityViewTest do
test "A scheduled activity with a media attachment" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hi"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hi"})
scheduled_at =
NaiveDateTime.utc_now()
@@ -47,7 +47,7 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityViewTest do
expected = %{
id: to_string(scheduled_activity.id),
media_attachments:
- %{"media_ids" => [upload.id]}
+ %{media_ids: [upload.id]}
|> Utils.attachments_from_ids()
|> Enum.map(&StatusView.render("attachment.json", %{attachment: &1})),
params: %{
diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs
index 6791c2fb0..5cbadf0fc 100644
--- a/test/web/mastodon_api/views/status_view_test.exs
+++ b/test/web/mastodon_api/views/status_view_test.exs
@@ -20,6 +20,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
import Pleroma.Factory
import Tesla.Mock
+ import OpenApiSpex.TestAssertions
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
@@ -30,14 +31,16 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
user = insert(:user)
other_user = insert(:user)
third_user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "dae cofe??"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "dae cofe??"})
- {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, user, "☕")
- {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, third_user, "🍵")
- {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "☕")
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, third_user, "🍵")
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
activity = Repo.get(Activity, activity.id)
status = StatusView.render("show.json", activity: activity)
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
+
assert status[:pleroma][:emoji_reactions] == [
%{name: "☕", count: 2, me: false},
%{name: "🍵", count: 1, me: false}
@@ -45,6 +48,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
status = StatusView.render("show.json", activity: activity, for: user)
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
+
assert status[:pleroma][:emoji_reactions] == [
%{name: "☕", count: 2, me: true},
%{name: "🍵", count: 1, me: false}
@@ -54,7 +59,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
[participation] = Participation.for_user(user)
status =
@@ -68,12 +73,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
status = StatusView.render("show.json", activity: activity, for: user)
assert status[:pleroma][:direct_conversation_id] == nil
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
end
test "returns the direct conversation id when given the `direct_conversation_id` option" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
[participation] = Participation.for_user(user)
status =
@@ -84,12 +90,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
)
assert status[:pleroma][:direct_conversation_id] == participation.id
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
end
test "returns a temporary ap_id based user for activities missing db users" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
Repo.delete(user)
Cachex.clear(:user_cache)
@@ -119,7 +126,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
test "tries to get a user by nickname if fetching by ap_id doesn't work" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
{:ok, user} =
user
@@ -131,6 +138,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
result = StatusView.render("show.json", activity: activity)
assert result[:account][:id] == to_string(user.id)
+ assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
end
test "a note with null content" do
@@ -149,6 +157,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
status = StatusView.render("show.json", %{activity: note})
assert status.content == ""
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
end
test "a note activity" do
@@ -222,6 +231,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
}
assert status == expected
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
end
test "tells if the message is muted for some reason" do
@@ -230,13 +240,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
{:ok, _user_relationships} = User.mute(user, other_user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "test"})
relationships_opt = UserRelationship.view_relationships_option(user, [other_user])
opts = %{activity: activity}
status = StatusView.render("show.json", opts)
assert status.muted == false
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
status = StatusView.render("show.json", Map.put(opts, :relationships, relationships_opt))
assert status.muted == false
@@ -247,6 +258,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
status = StatusView.render("show.json", Map.put(for_opts, :relationships, relationships_opt))
assert status.muted == true
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
end
test "tells if the message is thread muted" do
@@ -255,7 +267,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
{:ok, _user_relationships} = User.mute(user, other_user)
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"})
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "test"})
status = StatusView.render("show.json", %{activity: activity, for: user})
assert status.pleroma.thread_muted == false
@@ -270,7 +282,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
test "tells if the status is bookmarked" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "Cute girls doing cute things"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "Cute girls doing cute things"})
status = StatusView.render("show.json", %{activity: activity})
assert status.bookmarked == false
@@ -292,8 +304,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
note = insert(:note_activity)
user = insert(:user)
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "he", "in_reply_to_status_id" => note.id})
+ {:ok, activity} = CommonAPI.post(user, %{status: "he", in_reply_to_status_id: note.id})
status = StatusView.render("show.json", %{activity: activity})
@@ -308,12 +319,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
user = insert(:user)
mentioned = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "hi @#{mentioned.nickname}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "hi @#{mentioned.nickname}"})
status = StatusView.render("show.json", %{activity: activity})
assert status.mentions ==
Enum.map([mentioned], fn u -> AccountView.render("mention.json", %{user: u}) end)
+
+ assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
end
test "create mentions from the 'to' field" do
@@ -402,11 +415,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
pleroma: %{mime_type: "image/png"}
}
+ api_spec = Pleroma.Web.ApiSpec.spec()
+
assert expected == StatusView.render("attachment.json", %{attachment: object})
+ assert_schema(expected, "Attachment", api_spec)
# If theres a "id", use that instead of the generated one
object = Map.put(object, "id", 2)
- assert %{id: "2"} = StatusView.render("attachment.json", %{attachment: object})
+ result = StatusView.render("attachment.json", %{attachment: object})
+
+ assert %{id: "2"} = result
+ assert_schema(result, "Attachment", api_spec)
end
test "put the url advertised in the Activity in to the url attribute" do
@@ -423,13 +442,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
user = insert(:user)
activity = insert(:note_activity)
- {:ok, reblog, _} = CommonAPI.repeat(activity.id, user)
+ {:ok, reblog} = CommonAPI.repeat(activity.id, user)
represented = StatusView.render("show.json", %{for: user, activity: reblog})
assert represented[:id] == to_string(reblog.id)
assert represented[:reblog][:id] == to_string(activity.id)
assert represented[:emojis] == []
+ assert_schema(represented, "Status", Pleroma.Web.ApiSpec.spec())
end
test "a peertube video" do
@@ -446,6 +466,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
assert represented[:id] == to_string(activity.id)
assert length(represented[:media_attachments]) == 1
+ assert_schema(represented, "Status", Pleroma.Web.ApiSpec.spec())
end
test "funkwhale audio" do
@@ -555,39 +576,37 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
end
end
- test "embeds a relationship in the account" do
+ test "does not embed a relationship in the account" do
user = insert(:user)
other_user = insert(:user)
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "drink more water"
+ status: "drink more water"
})
result = StatusView.render("show.json", %{activity: activity, for: other_user})
- assert result[:account][:pleroma][:relationship] ==
- AccountView.render("relationship.json", %{user: other_user, target: user})
+ assert result[:account][:pleroma][:relationship] == %{}
+ assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
end
- test "embeds a relationship in the account in reposts" do
+ test "does not embed a relationship in the account in reposts" do
user = insert(:user)
other_user = insert(:user)
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "˙˙ɐʎns"
+ status: "˙˙ɐʎns"
})
- {:ok, activity, _object} = CommonAPI.repeat(activity.id, other_user)
+ {:ok, activity} = CommonAPI.repeat(activity.id, other_user)
result = StatusView.render("show.json", %{activity: activity, for: user})
- assert result[:account][:pleroma][:relationship] ==
- AccountView.render("relationship.json", %{user: user, target: other_user})
-
- assert result[:reblog][:account][:pleroma][:relationship] ==
- AccountView.render("relationship.json", %{user: user, target: user})
+ assert result[:account][:pleroma][:relationship] == %{}
+ assert result[:reblog][:account][:pleroma][:relationship] == %{}
+ assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
end
test "visibility/list" do
@@ -595,20 +614,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
{:ok, list} = Pleroma.List.create("foo", user)
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
status = StatusView.render("show.json", activity: activity)
assert status.visibility == "list"
end
-
- test "successfully renders a Listen activity (pleroma extension)" do
- listen_activity = insert(:listen)
-
- status = StatusView.render("listen.json", activity: listen_activity)
-
- assert status.length == listen_activity.data["object"]["length"]
- assert status.title == listen_activity.data["object"]["title"]
- end
end
diff --git a/test/web/mastodon_api/views/push_subscription_view_test.exs b/test/web/mastodon_api/views/subscription_view_test.exs
index 10c6082a5..981524c0e 100644
--- a/test/web/mastodon_api/views/push_subscription_view_test.exs
+++ b/test/web/mastodon_api/views/subscription_view_test.exs
@@ -2,10 +2,10 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Web.MastodonAPI.PushSubscriptionViewTest do
+defmodule Pleroma.Web.MastodonAPI.SubscriptionViewTest do
use Pleroma.DataCase
import Pleroma.Factory
- alias Pleroma.Web.MastodonAPI.PushSubscriptionView, as: View
+ alias Pleroma.Web.MastodonAPI.SubscriptionView, as: View
alias Pleroma.Web.Push
test "Represent a subscription" do
@@ -18,6 +18,6 @@ defmodule Pleroma.Web.MastodonAPI.PushSubscriptionViewTest do
server_key: Keyword.get(Push.vapid_config(), :public_key)
}
- assert expected == View.render("push_subscription.json", %{subscription: subscription})
+ assert expected == View.render("show.json", %{subscription: subscription})
end
end
diff --git a/test/web/media_proxy/invalidation_test.exs b/test/web/media_proxy/invalidation_test.exs
new file mode 100644
index 000000000..926ae74ca
--- /dev/null
+++ b/test/web/media_proxy/invalidation_test.exs
@@ -0,0 +1,64 @@
+defmodule Pleroma.Web.MediaProxy.InvalidationTest do
+ use ExUnit.Case
+ use Pleroma.Tests.Helpers
+
+ alias Pleroma.Config
+ alias Pleroma.Web.MediaProxy.Invalidation
+
+ import ExUnit.CaptureLog
+ import Mock
+ import Tesla.Mock
+
+ setup do: clear_config([:media_proxy])
+
+ setup do
+ on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
+ end
+
+ describe "Invalidation.Http" do
+ test "perform request to clear cache" do
+ Config.put([:media_proxy, :enabled], false)
+ Config.put([:media_proxy, :invalidation, :enabled], true)
+ Config.put([:media_proxy, :invalidation, :provider], Invalidation.Http)
+
+ Config.put([Invalidation.Http], method: :purge, headers: [{"x-refresh", 1}])
+ image_url = "http://example.com/media/example.jpg"
+ Pleroma.Web.MediaProxy.put_in_banned_urls(image_url)
+
+ mock(fn
+ %{
+ method: :purge,
+ url: "http://example.com/media/example.jpg",
+ headers: [{"x-refresh", 1}]
+ } ->
+ %Tesla.Env{status: 200}
+ end)
+
+ assert capture_log(fn ->
+ assert Pleroma.Web.MediaProxy.in_banned_urls(image_url)
+ assert Invalidation.purge([image_url]) == {:ok, [image_url]}
+ assert Pleroma.Web.MediaProxy.in_banned_urls(image_url)
+ end) =~ "Running cache purge: [\"#{image_url}\"]"
+ end
+ end
+
+ describe "Invalidation.Script" do
+ test "run script to clear cache" do
+ Config.put([:media_proxy, :enabled], false)
+ Config.put([:media_proxy, :invalidation, :enabled], true)
+ Config.put([:media_proxy, :invalidation, :provider], Invalidation.Script)
+ Config.put([Invalidation.Script], script_path: "purge-nginx")
+
+ image_url = "http://example.com/media/example.jpg"
+ Pleroma.Web.MediaProxy.put_in_banned_urls(image_url)
+
+ with_mocks [{System, [], [cmd: fn _, _ -> {"ok", 0} end]}] do
+ assert capture_log(fn ->
+ assert Pleroma.Web.MediaProxy.in_banned_urls(image_url)
+ assert Invalidation.purge([image_url]) == {:ok, [image_url]}
+ assert Pleroma.Web.MediaProxy.in_banned_urls(image_url)
+ end) =~ "Running cache purge: [\"#{image_url}\"]"
+ end
+ end
+ end
+end
diff --git a/test/web/media_proxy/invalidations/http_test.exs b/test/web/media_proxy/invalidations/http_test.exs
new file mode 100644
index 000000000..a1bef5237
--- /dev/null
+++ b/test/web/media_proxy/invalidations/http_test.exs
@@ -0,0 +1,39 @@
+defmodule Pleroma.Web.MediaProxy.Invalidation.HttpTest do
+ use ExUnit.Case
+ alias Pleroma.Web.MediaProxy.Invalidation
+
+ import ExUnit.CaptureLog
+ import Tesla.Mock
+
+ setup do
+ on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
+ end
+
+ test "logs hasn't error message when request is valid" do
+ mock(fn
+ %{method: :purge, url: "http://example.com/media/example.jpg"} ->
+ %Tesla.Env{status: 200}
+ end)
+
+ refute capture_log(fn ->
+ assert Invalidation.Http.purge(
+ ["http://example.com/media/example.jpg"],
+ []
+ ) == {:ok, ["http://example.com/media/example.jpg"]}
+ end) =~ "Error while cache purge"
+ end
+
+ test "it write error message in logs when request invalid" do
+ mock(fn
+ %{method: :purge, url: "http://example.com/media/example1.jpg"} ->
+ %Tesla.Env{status: 404}
+ end)
+
+ assert capture_log(fn ->
+ assert Invalidation.Http.purge(
+ ["http://example.com/media/example1.jpg"],
+ []
+ ) == {:ok, ["http://example.com/media/example1.jpg"]}
+ end) =~ "Error while cache purge: url - http://example.com/media/example1.jpg"
+ end
+end
diff --git a/test/web/media_proxy/invalidations/script_test.exs b/test/web/media_proxy/invalidations/script_test.exs
new file mode 100644
index 000000000..51833ab18
--- /dev/null
+++ b/test/web/media_proxy/invalidations/script_test.exs
@@ -0,0 +1,26 @@
+defmodule Pleroma.Web.MediaProxy.Invalidation.ScriptTest do
+ use ExUnit.Case
+ alias Pleroma.Web.MediaProxy.Invalidation
+
+ import ExUnit.CaptureLog
+
+ setup do
+ on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
+ end
+
+ test "it logger error when script not found" do
+ assert capture_log(fn ->
+ assert Invalidation.Script.purge(
+ ["http://example.com/media/example.jpg"],
+ script_path: "./example"
+ ) == {:error, "%ErlangError{original: :enoent}"}
+ end) =~ "Error while cache purge: %ErlangError{original: :enoent}"
+
+ capture_log(fn ->
+ assert Invalidation.Script.purge(
+ ["http://example.com/media/example.jpg"],
+ []
+ ) == {:error, "\"not found script path\""}
+ end)
+ end
+end
diff --git a/test/web/media_proxy/media_proxy_controller_test.exs b/test/web/media_proxy/media_proxy_controller_test.exs
index da79d38a5..d61cef83b 100644
--- a/test/web/media_proxy/media_proxy_controller_test.exs
+++ b/test/web/media_proxy/media_proxy_controller_test.exs
@@ -10,6 +10,10 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
setup do: clear_config(:media_proxy)
setup do: clear_config([Pleroma.Web.Endpoint, :secret_key_base])
+ 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)
@@ -66,4 +70,16 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
assert %Plug.Conn{status: :success} = get(conn, url)
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")
+
+ 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)
+ end
+ end
end
diff --git a/test/web/media_proxy/media_proxy_test.exs b/test/web/media_proxy/media_proxy_test.exs
index 69c2d5dae..69d2a71a6 100644
--- a/test/web/media_proxy/media_proxy_test.exs
+++ b/test/web/media_proxy/media_proxy_test.exs
@@ -124,15 +124,7 @@ defmodule Pleroma.Web.MediaProxyTest do
end
test "uses the configured base_url" do
- base_url = Pleroma.Config.get([:media_proxy, :base_url])
-
- if base_url do
- on_exit(fn ->
- Pleroma.Config.put([:media_proxy, :base_url], base_url)
- end)
- end
-
- Pleroma.Config.put([:media_proxy, :base_url], "https://cache.pleroma.social")
+ clear_config([:media_proxy, :base_url], "https://cache.pleroma.social")
url = "https://pleroma.soykaf.com/static/logo.png"
encoded = url(url)
@@ -213,8 +205,8 @@ defmodule Pleroma.Web.MediaProxyTest do
end
test "does not change whitelisted urls" do
- Pleroma.Config.put([:media_proxy, :whitelist], ["mycdn.akamai.com"])
- Pleroma.Config.put([:media_proxy, :base_url], "https://cache.pleroma.social")
+ clear_config([:media_proxy, :whitelist], ["mycdn.akamai.com"])
+ clear_config([:media_proxy, :base_url], "https://cache.pleroma.social")
media_url = "https://mycdn.akamai.com"
diff --git a/test/web/metadata/twitter_card_test.exs b/test/web/metadata/twitter_card_test.exs
index 9e9c6853a..10931b5ba 100644
--- a/test/web/metadata/twitter_card_test.exs
+++ b/test/web/metadata/twitter_card_test.exs
@@ -30,7 +30,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
test "it uses summary twittercard if post has no attachment" do
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "HI"})
note =
insert(:note, %{
@@ -56,7 +56,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
test "it renders avatar not attachment if post is nsfw and unfurl_nsfw is disabled" do
Pleroma.Config.put([Pleroma.Web.Metadata, :unfurl_nsfw], false)
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "HI"})
note =
insert(:note, %{
@@ -100,7 +100,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
test "it renders supported types of attachments and skips unknown types" do
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "HI"})
note =
insert(:note, %{
diff --git a/test/web/mongooseim/mongoose_im_controller_test.exs b/test/web/mongooseim/mongoose_im_controller_test.exs
index 291ae54fc..5176cde84 100644
--- a/test/web/mongooseim/mongoose_im_controller_test.exs
+++ b/test/web/mongooseim/mongoose_im_controller_test.exs
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.MongooseIMController do
test "/user_exists", %{conn: conn} do
_user = insert(:user, nickname: "lain")
_remote_user = insert(:user, nickname: "alice", local: false)
+ _deactivated_user = insert(:user, nickname: "konata", deactivated: true)
res =
conn
@@ -30,10 +31,24 @@ defmodule Pleroma.Web.MongooseIMController do
|> json_response(404)
assert res == false
+
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :user_exists), user: "konata")
+ |> json_response(404)
+
+ assert res == false
end
test "/check_password", %{conn: conn} do
- user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("cool"))
+ user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt("cool"))
+
+ _deactivated_user =
+ insert(:user,
+ nickname: "konata",
+ deactivated: true,
+ password_hash: Pbkdf2.hash_pwd_salt("cool")
+ )
res =
conn
@@ -51,6 +66,13 @@ defmodule Pleroma.Web.MongooseIMController do
res =
conn
+ |> get(mongoose_im_path(conn, :check_password), user: "konata", pass: "cool")
+ |> json_response(404)
+
+ assert res == false
+
+ res =
+ conn
|> get(mongoose_im_path(conn, :check_password), user: "nobody", pass: "cool")
|> json_response(404)
diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs
index 9bcc07b37..00925caad 100644
--- a/test/web/node_info_test.exs
+++ b/test/web/node_info_test.exs
@@ -145,7 +145,8 @@ defmodule Pleroma.Web.NodeInfoTest do
"shareable_emoji_packs",
"multifetch",
"pleroma_emoji_reactions",
- "pleroma:api/v1/notifications:include_types_filter"
+ "pleroma:api/v1/notifications:include_types_filter",
+ "pleroma_chat_messages"
]
assert MapSet.subset?(
diff --git a/test/web/oauth/ldap_authorization_test.exs b/test/web/oauth/ldap_authorization_test.exs
index a8fe8a841..011642c08 100644
--- a/test/web/oauth/ldap_authorization_test.exs
+++ b/test/web/oauth/ldap_authorization_test.exs
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
@tag @skip
test "authorizes the existing user using LDAP credentials" do
password = "testpassword"
- user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
+ user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))
app = insert(:oauth_app, scopes: ["read", "write"])
host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
@@ -104,7 +104,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
@tag @skip
test "falls back to the default authorization when LDAP is unavailable" do
password = "testpassword"
- user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
+ user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))
app = insert(:oauth_app, scopes: ["read", "write"])
host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
@@ -148,7 +148,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
@tag @skip
test "disallow authorization for wrong LDAP credentials" do
password = "testpassword"
- user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
+ user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))
app = insert(:oauth_app, scopes: ["read", "write"])
host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
diff --git a/test/web/oauth/mfa_controller_test.exs b/test/web/oauth/mfa_controller_test.exs
new file mode 100644
index 000000000..3c341facd
--- /dev/null
+++ b/test/web/oauth/mfa_controller_test.exs
@@ -0,0 +1,306 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.OAuth.MFAControllerTest do
+ use Pleroma.Web.ConnCase
+ import Pleroma.Factory
+
+ alias Pleroma.MFA
+ alias Pleroma.MFA.BackupCodes
+ alias Pleroma.MFA.TOTP
+ alias Pleroma.Repo
+ alias Pleroma.Web.OAuth.Authorization
+ alias Pleroma.Web.OAuth.OAuthController
+
+ setup %{conn: conn} do
+ otp_secret = TOTP.generate_secret()
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ backup_codes: [Pbkdf2.hash_pwd_salt("test-code")],
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ app = insert(:oauth_app)
+ {:ok, conn: conn, user: user, app: app}
+ end
+
+ describe "show" do
+ setup %{conn: conn, user: user, app: app} do
+ mfa_token =
+ insert(:mfa_token,
+ user: user,
+ authorization: build(:oauth_authorization, app: app, scopes: ["write"])
+ )
+
+ {:ok, conn: conn, mfa_token: mfa_token}
+ end
+
+ test "GET /oauth/mfa renders mfa forms", %{conn: conn, mfa_token: mfa_token} do
+ conn =
+ get(
+ conn,
+ "/oauth/mfa",
+ %{
+ "mfa_token" => mfa_token.token,
+ "state" => "a_state",
+ "redirect_uri" => "http://localhost:8080/callback"
+ }
+ )
+
+ assert response = html_response(conn, 200)
+ assert response =~ "Two-factor authentication"
+ assert response =~ mfa_token.token
+ assert response =~ "http://localhost:8080/callback"
+ end
+
+ test "GET /oauth/mfa renders mfa recovery forms", %{conn: conn, mfa_token: mfa_token} do
+ conn =
+ get(
+ conn,
+ "/oauth/mfa",
+ %{
+ "mfa_token" => mfa_token.token,
+ "state" => "a_state",
+ "redirect_uri" => "http://localhost:8080/callback",
+ "challenge_type" => "recovery"
+ }
+ )
+
+ assert response = html_response(conn, 200)
+ assert response =~ "Two-factor recovery"
+ assert response =~ mfa_token.token
+ assert response =~ "http://localhost:8080/callback"
+ end
+ end
+
+ describe "verify" do
+ setup %{conn: conn, user: user, app: app} do
+ mfa_token =
+ insert(:mfa_token,
+ user: user,
+ authorization: build(:oauth_authorization, app: app, scopes: ["write"])
+ )
+
+ {:ok, conn: conn, user: user, mfa_token: mfa_token, app: app}
+ end
+
+ test "POST /oauth/mfa/verify, verify totp code", %{
+ conn: conn,
+ user: user,
+ mfa_token: mfa_token,
+ app: app
+ } do
+ otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret)
+
+ conn =
+ conn
+ |> post("/oauth/mfa/verify", %{
+ "mfa" => %{
+ "mfa_token" => mfa_token.token,
+ "challenge_type" => "totp",
+ "code" => otp_token,
+ "state" => "a_state",
+ "redirect_uri" => OAuthController.default_redirect_uri(app)
+ }
+ })
+
+ target = redirected_to(conn)
+ target_url = %URI{URI.parse(target) | query: nil} |> URI.to_string()
+ query = URI.parse(target).query |> URI.query_decoder() |> Map.new()
+ assert %{"state" => "a_state", "code" => code} = query
+ assert target_url == OAuthController.default_redirect_uri(app)
+ auth = Repo.get_by(Authorization, token: code)
+ assert auth.scopes == ["write"]
+ end
+
+ test "POST /oauth/mfa/verify, verify recovery code", %{
+ conn: conn,
+ mfa_token: mfa_token,
+ app: app
+ } do
+ conn =
+ conn
+ |> post("/oauth/mfa/verify", %{
+ "mfa" => %{
+ "mfa_token" => mfa_token.token,
+ "challenge_type" => "recovery",
+ "code" => "test-code",
+ "state" => "a_state",
+ "redirect_uri" => OAuthController.default_redirect_uri(app)
+ }
+ })
+
+ target = redirected_to(conn)
+ target_url = %URI{URI.parse(target) | query: nil} |> URI.to_string()
+ query = URI.parse(target).query |> URI.query_decoder() |> Map.new()
+ assert %{"state" => "a_state", "code" => code} = query
+ assert target_url == OAuthController.default_redirect_uri(app)
+ auth = Repo.get_by(Authorization, token: code)
+ assert auth.scopes == ["write"]
+ end
+ end
+
+ describe "challenge/totp" do
+ test "returns access token with valid code", %{conn: conn, user: user, app: app} do
+ otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret)
+
+ mfa_token =
+ insert(:mfa_token,
+ user: user,
+ authorization: build(:oauth_authorization, app: app, scopes: ["write"])
+ )
+
+ response =
+ conn
+ |> post("/oauth/mfa/challenge", %{
+ "mfa_token" => mfa_token.token,
+ "challenge_type" => "totp",
+ "code" => otp_token,
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+ |> json_response(:ok)
+
+ ap_id = user.ap_id
+
+ assert match?(
+ %{
+ "access_token" => _,
+ "expires_in" => 600,
+ "me" => ^ap_id,
+ "refresh_token" => _,
+ "scope" => "write",
+ "token_type" => "Bearer"
+ },
+ response
+ )
+ end
+
+ test "returns errors when mfa token invalid", %{conn: conn, user: user, app: app} do
+ otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret)
+
+ response =
+ conn
+ |> post("/oauth/mfa/challenge", %{
+ "mfa_token" => "XXX",
+ "challenge_type" => "totp",
+ "code" => otp_token,
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+ |> json_response(400)
+
+ assert response == %{"error" => "Invalid code"}
+ end
+
+ test "returns error when otp code is invalid", %{conn: conn, user: user, app: app} do
+ mfa_token = insert(:mfa_token, user: user)
+
+ response =
+ conn
+ |> post("/oauth/mfa/challenge", %{
+ "mfa_token" => mfa_token.token,
+ "challenge_type" => "totp",
+ "code" => "XXX",
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+ |> json_response(400)
+
+ assert response == %{"error" => "Invalid code"}
+ end
+
+ test "returns error when client credentails is wrong ", %{conn: conn, user: user} do
+ otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret)
+ mfa_token = insert(:mfa_token, user: user)
+
+ response =
+ conn
+ |> post("/oauth/mfa/challenge", %{
+ "mfa_token" => mfa_token.token,
+ "challenge_type" => "totp",
+ "code" => otp_token,
+ "client_id" => "xxx",
+ "client_secret" => "xxx"
+ })
+ |> json_response(400)
+
+ assert response == %{"error" => "Invalid code"}
+ end
+ end
+
+ describe "challenge/recovery" do
+ setup %{conn: conn} do
+ app = insert(:oauth_app)
+ {:ok, conn: conn, app: app}
+ end
+
+ test "returns access token with valid code", %{conn: conn, app: app} do
+ otp_secret = TOTP.generate_secret()
+
+ [code | _] = backup_codes = BackupCodes.generate()
+
+ hashed_codes =
+ backup_codes
+ |> Enum.map(&Pbkdf2.hash_pwd_salt(&1))
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ backup_codes: hashed_codes,
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ mfa_token =
+ insert(:mfa_token,
+ user: user,
+ authorization: build(:oauth_authorization, app: app, scopes: ["write"])
+ )
+
+ response =
+ conn
+ |> post("/oauth/mfa/challenge", %{
+ "mfa_token" => mfa_token.token,
+ "challenge_type" => "recovery",
+ "code" => code,
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+ |> json_response(:ok)
+
+ ap_id = user.ap_id
+
+ assert match?(
+ %{
+ "access_token" => _,
+ "expires_in" => 600,
+ "me" => ^ap_id,
+ "refresh_token" => _,
+ "scope" => "write",
+ "token_type" => "Bearer"
+ },
+ response
+ )
+
+ error_response =
+ conn
+ |> post("/oauth/mfa/challenge", %{
+ "mfa_token" => mfa_token.token,
+ "challenge_type" => "recovery",
+ "code" => code,
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+ |> json_response(400)
+
+ assert error_response == %{"error" => "Invalid code"}
+ end
+ end
+end
diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs
index f2f98d768..d389e4ce0 100644
--- a/test/web/oauth/oauth_controller_test.exs
+++ b/test/web/oauth/oauth_controller_test.exs
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
+ alias Pleroma.MFA
+ alias Pleroma.MFA.TOTP
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.OAuth.Authorization
@@ -309,7 +311,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
app: app,
conn: conn
} do
- user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("testpassword"))
+ user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt("testpassword"))
registration = insert(:registration, user: nil)
redirect_uri = OAuthController.default_redirect_uri(app)
@@ -340,7 +342,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
app: app,
conn: conn
} do
- user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("testpassword"))
+ user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt("testpassword"))
registration = insert(:registration, user: nil)
unlisted_redirect_uri = "http://cross-site-request.com"
@@ -604,6 +606,41 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
end
end
+ test "redirect to on two-factor auth page" do
+ otp_secret = TOTP.generate_secret()
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ app = insert(:oauth_app, scopes: ["read", "write", "follow"])
+
+ conn =
+ build_conn()
+ |> post("/oauth/authorize", %{
+ "authorization" => %{
+ "name" => user.nickname,
+ "password" => "test",
+ "client_id" => app.client_id,
+ "redirect_uri" => app.redirect_uris,
+ "scope" => "read write",
+ "state" => "statepassed"
+ }
+ })
+
+ result = html_response(conn, 200)
+
+ mfa_token = Repo.get_by(MFA.Token, user_id: user.id)
+ assert result =~ app.redirect_uris
+ assert result =~ "statepassed"
+ assert result =~ mfa_token.token
+ assert result =~ "Two-factor authentication"
+ end
+
test "returns 401 for wrong credentials", %{conn: conn} do
user = insert(:user)
app = insert(:oauth_app)
@@ -713,7 +750,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
test "issues a token for `password` grant_type with valid credentials, with full permissions by default" do
password = "testpassword"
- user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
+ user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))
app = insert(:oauth_app, scopes: ["read", "write"])
@@ -735,6 +772,46 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
assert token.scopes == app.scopes
end
+ test "issues a mfa token for `password` grant_type, when MFA enabled" do
+ password = "testpassword"
+ otp_secret = TOTP.generate_secret()
+
+ user =
+ insert(:user,
+ password_hash: Pbkdf2.hash_pwd_salt(password),
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ app = insert(:oauth_app, scopes: ["read", "write"])
+
+ response =
+ build_conn()
+ |> post("/oauth/token", %{
+ "grant_type" => "password",
+ "username" => user.nickname,
+ "password" => password,
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+ |> json_response(403)
+
+ assert match?(
+ %{
+ "supported_challenge_types" => "totp",
+ "mfa_token" => _,
+ "error" => "mfa_required"
+ },
+ response
+ )
+
+ token = Repo.get_by(MFA.Token, token: response["mfa_token"])
+ assert token.user_id == user.id
+ assert token.authorization_id
+ end
+
test "issues a token for request with HTTP basic auth client credentials" do
user = insert(:user)
app = insert(:oauth_app, scopes: ["scope1", "scope2", "scope3"])
@@ -810,7 +887,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
password = "testpassword"
{:ok, user} =
- insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
+ insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))
|> User.confirmation_changeset(need_confirmation: true)
|> User.update_and_set_cache()
@@ -838,7 +915,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
user =
insert(:user,
- password_hash: Comeonin.Pbkdf2.hashpwsalt(password),
+ password_hash: Pbkdf2.hash_pwd_salt(password),
deactivated: true
)
@@ -866,7 +943,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
user =
insert(:user,
- password_hash: Comeonin.Pbkdf2.hashpwsalt(password),
+ password_hash: Pbkdf2.hash_pwd_salt(password),
password_reset_pending: true
)
@@ -895,7 +972,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
user =
insert(:user,
- password_hash: Comeonin.Pbkdf2.hashpwsalt(password),
+ password_hash: Pbkdf2.hash_pwd_salt(password),
confirmation_pending: true
)
diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs
index bb349cb19..ee498f4b5 100644
--- a/test/web/ostatus/ostatus_controller_test.exs
+++ b/test/web/ostatus/ostatus_controller_test.exs
@@ -10,7 +10,11 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
alias Pleroma.Config
alias Pleroma.Object
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.Endpoint
+
+ require Pleroma.Constants
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
@@ -19,6 +23,47 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
setup do: clear_config([:instance, :federating], true)
+ describe "Mastodon compatibility routes" do
+ setup %{conn: conn} do
+ conn = put_req_header(conn, "accept", "text/html")
+
+ {:ok, object} =
+ %{
+ "type" => "Note",
+ "content" => "hey",
+ "id" => Endpoint.url() <> "/users/raymoo/statuses/999999999",
+ "actor" => Endpoint.url() <> "/users/raymoo",
+ "to" => [Pleroma.Constants.as_public()]
+ }
+ |> Object.create()
+
+ {:ok, activity, _} =
+ %{
+ "id" => object.data["id"] <> "/activity",
+ "type" => "Create",
+ "object" => object.data["id"],
+ "actor" => object.data["actor"],
+ "to" => object.data["to"]
+ }
+ |> ActivityPub.persist(local: true)
+
+ %{conn: conn, activity: activity}
+ end
+
+ test "redirects to /notice/:id for html format", %{conn: conn, activity: activity} do
+ conn = get(conn, "/users/raymoo/statuses/999999999")
+ assert redirected_to(conn) == "/notice/#{activity.id}"
+ end
+
+ test "redirects to /notice/:id for html format for activity", %{
+ conn: conn,
+ activity: activity
+ } do
+ conn = get(conn, "/users/raymoo/statuses/999999999/activity")
+ assert redirected_to(conn) == "/notice/#{activity.id}"
+ end
+ end
+
# Note: see ActivityPubControllerTest for JSON format tests
describe "GET /objects/:uuid (text/html)" do
setup %{conn: conn} do
diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs
index ae5334015..103997c31 100644
--- a/test/web/pleroma_api/controllers/account_controller_test.exs
+++ b/test/web/pleroma_api/controllers/account_controller_test.exs
@@ -31,8 +31,28 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
test "resend account confirmation email", %{conn: conn, user: user} do
conn
+ |> put_req_header("content-type", "application/json")
|> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
- |> json_response(:no_content)
+ |> json_response_and_validate_schema(:no_content)
+
+ ObanHelpers.perform_all()
+
+ email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
+ notify_email = Config.get([:instance, :notify_email])
+ instance_name = Config.get([:instance, :name])
+
+ assert_email_sent(
+ from: {instance_name, notify_email},
+ to: {user.name, user.email},
+ html_body: email.html_body
+ )
+ end
+
+ test "resend account confirmation email (with nickname)", %{conn: conn, user: user} do
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/accounts/confirmation_resend?nickname=#{user.nickname}")
+ |> json_response_and_validate_schema(:no_content)
ObanHelpers.perform_all()
@@ -54,7 +74,10 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
test "user avatar can be set", %{user: user, conn: conn} do
avatar_image = File.read!("test/fixtures/avatar_data_uri")
- conn = patch(conn, "/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
+ conn =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
user = refresh_record(user)
@@ -70,17 +93,20 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
]
} = user.avatar
- assert %{"url" => _} = json_response(conn, 200)
+ assert %{"url" => _} = json_response_and_validate_schema(conn, 200)
end
test "user avatar can be reset", %{user: user, conn: conn} do
- conn = patch(conn, "/api/v1/pleroma/accounts/update_avatar", %{img: ""})
+ 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(conn, 200)
+ assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)
end
end
@@ -88,21 +114,27 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
setup do: oauth_access(["write:accounts"])
test "can set profile banner", %{user: user, conn: conn} do
- conn = patch(conn, "/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
+ 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(conn, 200)
+ assert %{"url" => _} = json_response_and_validate_schema(conn, 200)
end
test "can reset profile banner", %{user: user, conn: conn} do
- conn = patch(conn, "/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
+ 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(conn, 200)
+ assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)
end
end
@@ -110,19 +142,26 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
setup do: oauth_access(["write:accounts"])
test "background image can be set", %{user: user, conn: conn} do
- conn = patch(conn, "/api/v1/pleroma/accounts/update_background", %{"img" => @image})
+ 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(conn, 200)
+ assert %{"url" => _} = json_response_and_validate_schema(conn, 200)
end
test "background image can be reset", %{user: user, conn: conn} do
- conn = patch(conn, "/api/v1/pleroma/accounts/update_background", %{"img" => ""})
+ 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(conn, 200)
+ assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)
end
end
@@ -143,7 +182,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
response =
conn
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
[like] = response
@@ -151,15 +190,18 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
assert like["id"] == activity.id
end
- test "does not return favorites for specified user_id when user is not logged in", %{
+ test "returns favorites for specified user_id when requester is not logged in", %{
user: user
} do
activity = insert(:note_activity)
CommonAPI.favorite(user, activity.id)
- build_conn()
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(403)
+ response =
+ build_conn()
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response_and_validate_schema(200)
+
+ assert length(response) == 1
end
test "returns favorited DM only when user is logged in and he is one of recipients", %{
@@ -168,8 +210,8 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
} do
{:ok, direct} =
CommonAPI.post(current_user, %{
- "status" => "Hi @#{user.nickname}!",
- "visibility" => "direct"
+ status: "Hi @#{user.nickname}!",
+ visibility: "direct"
})
CommonAPI.favorite(user, direct.id)
@@ -180,14 +222,17 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
|> assign(:user, u)
|> assign(:token, insert(:oauth_token, user: u, scopes: ["read:favourites"]))
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert length(response) == 1
end
- build_conn()
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(403)
+ response =
+ build_conn()
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response_and_validate_schema(200)
+
+ assert length(response) == 0
end
test "does not return others' favorited DM when user is not one of recipients", %{
@@ -198,8 +243,8 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
{:ok, direct} =
CommonAPI.post(user_two, %{
- "status" => "Hi @#{user.nickname}!",
- "visibility" => "direct"
+ status: "Hi @#{user.nickname}!",
+ visibility: "direct"
})
CommonAPI.favorite(user, direct.id)
@@ -207,7 +252,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
response =
conn
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert Enum.empty?(response)
end
@@ -227,11 +272,12 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
response =
conn
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
- since_id: third_activity.id,
- max_id: seventh_activity.id
- })
- |> json_response(:ok)
+ |> get(
+ "/api/v1/pleroma/accounts/#{user.id}/favourites?since_id=#{third_activity.id}&max_id=#{
+ seventh_activity.id
+ }"
+ )
+ |> json_response_and_validate_schema(:ok)
assert length(response) == 3
refute third_activity in response
@@ -250,8 +296,8 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
response =
conn
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
- |> json_response(:ok)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites?limit=3")
+ |> json_response_and_validate_schema(:ok)
assert length(response) == 3
end
@@ -263,7 +309,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
response =
conn
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert Enum.empty?(response)
end
@@ -271,7 +317,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
test "returns 404 error when specified user is not exist", %{conn: conn} do
conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
- assert json_response(conn, 404) == %{"error" => "Record not found"}
+ assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
end
test "returns 403 error when user has hidden own favorites", %{conn: conn} do
@@ -281,7 +327,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites")
- assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
+ assert json_response_and_validate_schema(conn, 403) == %{"error" => "Can't get favorites"}
end
test "hides favorites for new users by default", %{conn: conn} do
@@ -292,7 +338,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
assert user.hide_favorites
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites")
- assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
+ assert json_response_and_validate_schema(conn, 403) == %{"error" => "Can't get favorites"}
end
end
@@ -306,11 +352,12 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
|> assign(:user, user)
|> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
- assert %{"id" => _id, "subscribing" => true} = json_response(ret_conn, 200)
+ assert %{"id" => _id, "subscribing" => true} =
+ json_response_and_validate_schema(ret_conn, 200)
conn = post(conn, "/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
- assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
+ assert %{"id" => _id, "subscribing" => false} = json_response_and_validate_schema(conn, 200)
end
end
@@ -320,7 +367,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
conn = post(conn, "/api/v1/pleroma/accounts/target_id/subscribe")
- assert %{"error" => "Record not found"} = json_response(conn, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn, 404)
end
end
@@ -330,7 +377,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
conn = post(conn, "/api/v1/pleroma/accounts/target_id/unsubscribe")
- assert %{"error" => "Record not found"} = json_response(conn, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn, 404)
end
end
end
diff --git a/test/web/pleroma_api/controllers/chat_controller_test.exs b/test/web/pleroma_api/controllers/chat_controller_test.exs
new file mode 100644
index 000000000..82e16741d
--- /dev/null
+++ b/test/web/pleroma_api/controllers/chat_controller_test.exs
@@ -0,0 +1,336 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
+ use Pleroma.Web.ConnCase, async: true
+
+ alias Pleroma.Chat
+ alias Pleroma.Chat.MessageReference
+ alias Pleroma.Object
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "POST /api/v1/pleroma/chats/:id/messages/:message_id/read" do
+ setup do: oauth_access(["write:chats"])
+
+ test "it marks one message as read", %{conn: conn, user: user} do
+ other_user = insert(:user)
+
+ {:ok, create} = CommonAPI.post_chat_message(other_user, user, "sup")
+ {:ok, _create} = CommonAPI.post_chat_message(other_user, user, "sup part 2")
+ {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
+ object = Object.normalize(create, false)
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ assert cm_ref.unread == true
+
+ result =
+ conn
+ |> post("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}/read")
+ |> json_response_and_validate_schema(200)
+
+ assert result["unread"] == false
+
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ assert cm_ref.unread == false
+ end
+ end
+
+ describe "POST /api/v1/pleroma/chats/:id/read" do
+ setup do: oauth_access(["write:chats"])
+
+ test "given a `last_read_id`, it marks everything until then as read", %{
+ conn: conn,
+ user: user
+ } do
+ other_user = insert(:user)
+
+ {:ok, create} = CommonAPI.post_chat_message(other_user, user, "sup")
+ {:ok, _create} = CommonAPI.post_chat_message(other_user, user, "sup part 2")
+ {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
+ object = Object.normalize(create, false)
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ assert cm_ref.unread == true
+
+ result =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/chats/#{chat.id}/read", %{"last_read_id" => cm_ref.id})
+ |> json_response_and_validate_schema(200)
+
+ assert result["unread"] == 1
+
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ assert cm_ref.unread == false
+ end
+ end
+
+ describe "POST /api/v1/pleroma/chats/:id/messages" do
+ setup do: oauth_access(["write:chats"])
+
+ test "it posts a message to the chat", %{conn: conn, user: user} do
+ other_user = insert(:user)
+
+ {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
+
+ result =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "Hallo!!"})
+ |> json_response_and_validate_schema(200)
+
+ assert result["content"] == "Hallo!!"
+ assert result["chat_id"] == chat.id |> to_string()
+ end
+
+ test "it fails if there is no content", %{conn: conn, user: user} do
+ other_user = insert(:user)
+
+ {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
+
+ result =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/chats/#{chat.id}/messages")
+ |> json_response_and_validate_schema(400)
+
+ assert result
+ end
+
+ test "it works with an attachment", %{conn: conn, user: user} do
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
+
+ other_user = insert(:user)
+
+ {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
+
+ result =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{
+ "media_id" => to_string(upload.id)
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert result["attachment"]
+ end
+ end
+
+ describe "DELETE /api/v1/pleroma/chats/:id/messages/:message_id" do
+ setup do: oauth_access(["write:chats"])
+
+ test "it deletes a message from the chat", %{conn: conn, user: user} do
+ recipient = insert(:user)
+
+ {:ok, message} =
+ CommonAPI.post_chat_message(user, recipient, "Hello darkness my old friend")
+
+ {:ok, other_message} = CommonAPI.post_chat_message(recipient, user, "nico nico ni")
+
+ object = Object.normalize(message, false)
+
+ chat = Chat.get(user.id, recipient.ap_id)
+
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ # Deleting your own message removes the message and the reference
+ result =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> delete("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}")
+ |> json_response_and_validate_schema(200)
+
+ assert result["id"] == cm_ref.id
+ refute MessageReference.get_by_id(cm_ref.id)
+ assert %{data: %{"type" => "Tombstone"}} = Object.get_by_id(object.id)
+
+ # Deleting other people's messages just removes the reference
+ object = Object.normalize(other_message, false)
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ result =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> delete("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}")
+ |> json_response_and_validate_schema(200)
+
+ assert result["id"] == cm_ref.id
+ refute MessageReference.get_by_id(cm_ref.id)
+ assert Object.get_by_id(object.id)
+ end
+ end
+
+ describe "GET /api/v1/pleroma/chats/:id/messages" do
+ setup do: oauth_access(["read:chats"])
+
+ test "it paginates", %{conn: conn, user: user} do
+ recipient = insert(:user)
+
+ Enum.each(1..30, fn _ ->
+ {:ok, _} = CommonAPI.post_chat_message(user, recipient, "hey")
+ end)
+
+ chat = Chat.get(user.id, recipient.ap_id)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats/#{chat.id}/messages")
+ |> json_response_and_validate_schema(200)
+
+ assert length(result) == 20
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}")
+ |> json_response_and_validate_schema(200)
+
+ assert length(result) == 10
+ end
+
+ test "it returns the messages for a given chat", %{conn: conn, user: user} do
+ other_user = insert(:user)
+ third_user = insert(:user)
+
+ {:ok, _} = CommonAPI.post_chat_message(user, other_user, "hey")
+ {:ok, _} = CommonAPI.post_chat_message(user, third_user, "hey")
+ {:ok, _} = CommonAPI.post_chat_message(user, other_user, "how are you?")
+ {:ok, _} = CommonAPI.post_chat_message(other_user, user, "fine, how about you?")
+
+ chat = Chat.get(user.id, other_user.ap_id)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats/#{chat.id}/messages")
+ |> json_response_and_validate_schema(200)
+
+ result
+ |> Enum.each(fn message ->
+ assert message["chat_id"] == chat.id |> to_string()
+ end)
+
+ assert length(result) == 3
+
+ # Trying to get the chat of a different user
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> get("/api/v1/pleroma/chats/#{chat.id}/messages")
+
+ assert result |> json_response(404)
+ end
+ end
+
+ describe "POST /api/v1/pleroma/chats/by-account-id/:id" do
+ setup do: oauth_access(["write:chats"])
+
+ test "it creates or returns a chat", %{conn: conn} do
+ other_user = insert(:user)
+
+ result =
+ conn
+ |> post("/api/v1/pleroma/chats/by-account-id/#{other_user.id}")
+ |> json_response_and_validate_schema(200)
+
+ assert result["id"]
+ end
+ end
+
+ describe "GET /api/v1/pleroma/chats/:id" do
+ setup do: oauth_access(["read:chats"])
+
+ test "it returns a chat", %{conn: conn, user: user} do
+ other_user = insert(:user)
+
+ {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats/#{chat.id}")
+ |> json_response_and_validate_schema(200)
+
+ assert result["id"] == to_string(chat.id)
+ end
+ end
+
+ describe "GET /api/v1/pleroma/chats" do
+ setup do: oauth_access(["read:chats"])
+
+ test "it does not return chats with users you blocked", %{conn: conn, user: user} do
+ recipient = insert(:user)
+
+ {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats")
+ |> json_response_and_validate_schema(200)
+
+ assert length(result) == 1
+
+ User.block(user, recipient)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats")
+ |> json_response_and_validate_schema(200)
+
+ assert length(result) == 0
+ end
+
+ test "it returns all chats", %{conn: conn, user: user} do
+ Enum.each(1..30, fn _ ->
+ recipient = insert(:user)
+ {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
+ end)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats")
+ |> json_response_and_validate_schema(200)
+
+ assert length(result) == 30
+ end
+
+ test "it return a list of chats the current user is participating in, in descending order of updates",
+ %{conn: conn, user: user} do
+ har = insert(:user)
+ jafnhar = insert(:user)
+ tridi = insert(:user)
+
+ {:ok, chat_1} = Chat.get_or_create(user.id, har.ap_id)
+ :timer.sleep(1000)
+ {:ok, _chat_2} = Chat.get_or_create(user.id, jafnhar.ap_id)
+ :timer.sleep(1000)
+ {:ok, chat_3} = Chat.get_or_create(user.id, tridi.ap_id)
+ :timer.sleep(1000)
+
+ # bump the second one
+ {:ok, chat_2} = Chat.bump_or_create(user.id, jafnhar.ap_id)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats")
+ |> json_response_and_validate_schema(200)
+
+ ids = Enum.map(result, & &1["id"])
+
+ assert ids == [
+ chat_2.id |> to_string(),
+ chat_3.id |> to_string(),
+ chat_1.id |> to_string()
+ ]
+ end
+ end
+end
diff --git a/test/web/pleroma_api/controllers/conversation_controller_test.exs b/test/web/pleroma_api/controllers/conversation_controller_test.exs
new file mode 100644
index 000000000..e6d0b3e37
--- /dev/null
+++ b/test/web/pleroma_api/controllers/conversation_controller_test.exs
@@ -0,0 +1,136 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.ConversationControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Conversation.Participation
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "/api/v1/pleroma/conversations/:id" do
+ user = insert(:user)
+ %{user: other_user, conn: conn} = oauth_access(["read:statuses"])
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}!", visibility: "direct"})
+
+ [participation] = Participation.for_user(other_user)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/conversations/#{participation.id}")
+ |> json_response_and_validate_schema(200)
+
+ assert result["id"] == participation.id |> to_string()
+ end
+
+ test "/api/v1/pleroma/conversations/:id/statuses" do
+ user = insert(:user)
+ %{user: other_user, conn: conn} = oauth_access(["read:statuses"])
+ third_user = insert(:user)
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{status: "Hi @#{third_user.nickname}!", visibility: "direct"})
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}!", visibility: "direct"})
+
+ [participation] = Participation.for_user(other_user)
+
+ {:ok, activity_two} =
+ CommonAPI.post(other_user, %{
+ status: "Hi!",
+ in_reply_to_status_id: activity.id,
+ in_reply_to_conversation_id: participation.id
+ })
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses")
+ |> json_response_and_validate_schema(200)
+
+ assert length(result) == 2
+
+ id_one = activity.id
+ id_two = activity_two.id
+ assert [%{"id" => ^id_one}, %{"id" => ^id_two}] = result
+
+ {:ok, %{id: id_three}} =
+ CommonAPI.post(other_user, %{
+ status: "Bye!",
+ in_reply_to_status_id: activity.id,
+ in_reply_to_conversation_id: participation.id
+ })
+
+ assert [%{"id" => ^id_two}, %{"id" => ^id_three}] =
+ conn
+ |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?limit=2")
+ |> json_response_and_validate_schema(:ok)
+
+ assert [%{"id" => ^id_three}] =
+ conn
+ |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?min_id=#{id_two}")
+ |> json_response_and_validate_schema(:ok)
+ end
+
+ test "PATCH /api/v1/pleroma/conversations/:id" do
+ %{user: user, conn: conn} = oauth_access(["write:conversations"])
+ other_user = insert(:user)
+
+ {:ok, _activity} = CommonAPI.post(user, %{status: "Hi", visibility: "direct"})
+
+ [participation] = Participation.for_user(user)
+
+ participation = Repo.preload(participation, :recipients)
+
+ user = User.get_cached_by_id(user.id)
+ assert [user] == participation.recipients
+ assert other_user not in participation.recipients
+
+ query = "recipients[]=#{user.id}&recipients[]=#{other_user.id}"
+
+ result =
+ conn
+ |> patch("/api/v1/pleroma/conversations/#{participation.id}?#{query}")
+ |> json_response_and_validate_schema(200)
+
+ assert result["id"] == participation.id |> to_string
+
+ [participation] = Participation.for_user(user)
+ participation = Repo.preload(participation, :recipients)
+
+ assert user in participation.recipients
+ assert other_user in participation.recipients
+ end
+
+ test "POST /api/v1/pleroma/conversations/read" do
+ user = insert(:user)
+ %{user: other_user, conn: conn} = oauth_access(["write:conversations"])
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}", visibility: "direct"})
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}", visibility: "direct"})
+
+ [participation2, participation1] = Participation.for_user(other_user)
+ assert Participation.get(participation2.id).read == false
+ assert Participation.get(participation1.id).read == false
+ assert User.get_cached_by_id(other_user.id).unread_conversation_count == 2
+
+ [%{"unread" => false}, %{"unread" => false}] =
+ conn
+ |> post("/api/v1/pleroma/conversations/read", %{})
+ |> json_response_and_validate_schema(200)
+
+ [participation2, participation1] = Participation.for_user(other_user)
+ assert Participation.get(participation2.id).read == true
+ assert Participation.get(participation1.id).read == true
+ assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0
+ end
+end
diff --git a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
deleted file mode 100644
index 435fb6592..000000000
--- a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
+++ /dev/null
@@ -1,463 +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.PleromaAPI.EmojiAPIControllerTest do
- use Pleroma.Web.ConnCase
-
- import Tesla.Mock
- import Pleroma.Factory
-
- @emoji_dir_path Path.join(
- Pleroma.Config.get!([:instance, :static_dir]),
- "emoji"
- )
- setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
-
- test "shared & non-shared pack information in list_packs is ok" do
- conn = build_conn()
- resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
-
- assert Map.has_key?(resp, "test_pack")
-
- pack = resp["test_pack"]
-
- assert Map.has_key?(pack["pack"], "download-sha256")
- assert pack["pack"]["can-download"]
-
- assert pack["files"] == %{"blank" => "blank.png"}
-
- # Non-shared pack
-
- assert Map.has_key?(resp, "test_pack_nonshared")
-
- pack = resp["test_pack_nonshared"]
-
- refute pack["pack"]["shared"]
- refute pack["pack"]["can-download"]
- end
-
- test "listing remote packs" do
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
-
- resp =
- build_conn()
- |> get(emoji_api_path(conn, :list_packs))
- |> json_response(200)
-
- mock(fn
- %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
- json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
-
- %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
- json(%{metadata: %{features: ["shareable_emoji_packs"]}})
-
- %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
- json(resp)
- end)
-
- assert conn
- |> post(emoji_api_path(conn, :list_from), %{instance_address: "https://example.com"})
- |> json_response(200) == resp
- end
-
- test "downloading a shared pack from download_shared" do
- conn = build_conn()
-
- resp =
- conn
- |> get(emoji_api_path(conn, :download_shared, "test_pack"))
- |> response(200)
-
- {:ok, arch} = :zip.unzip(resp, [:memory])
-
- assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
- assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
- end
-
- test "downloading shared & unshared packs from another instance via download_from, deleting them" do
- on_exit(fn ->
- File.rm_rf!("#{@emoji_dir_path}/test_pack2")
- File.rm_rf!("#{@emoji_dir_path}/test_pack_nonshared2")
- end)
-
- mock(fn
- %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
- json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
-
- %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
- json(%{metadata: %{features: []}})
-
- %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
- json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
-
- %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
- json(%{metadata: %{features: ["shareable_emoji_packs"]}})
-
- %{
- method: :get,
- url: "https://example.com/api/pleroma/emoji/packs/list"
- } ->
- conn = build_conn()
-
- conn
- |> get(emoji_api_path(conn, :list_packs))
- |> json_response(200)
- |> json()
-
- %{
- method: :get,
- url: "https://example.com/api/pleroma/emoji/packs/download_shared/test_pack"
- } ->
- conn = build_conn()
-
- conn
- |> get(emoji_api_path(conn, :download_shared, "test_pack"))
- |> response(200)
- |> text()
-
- %{
- method: :get,
- url: "https://nonshared-pack"
- } ->
- text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
- end)
-
- admin = insert(:user, is_admin: true)
-
- conn =
- build_conn()
- |> assign(:user, admin)
- |> assign(:token, insert(:oauth_admin_token, user: admin, scopes: ["admin:write"]))
-
- assert (conn
- |> put_req_header("content-type", "application/json")
- |> post(
- emoji_api_path(
- conn,
- :download_from
- ),
- %{
- instance_address: "https://old-instance",
- pack_name: "test_pack",
- as: "test_pack2"
- }
- |> Jason.encode!()
- )
- |> json_response(500))["error"] =~ "does not support"
-
- assert conn
- |> put_req_header("content-type", "application/json")
- |> post(
- emoji_api_path(
- conn,
- :download_from
- ),
- %{
- instance_address: "https://example.com",
- pack_name: "test_pack",
- as: "test_pack2"
- }
- |> Jason.encode!()
- )
- |> json_response(200) == "ok"
-
- assert File.exists?("#{@emoji_dir_path}/test_pack2/pack.json")
- assert File.exists?("#{@emoji_dir_path}/test_pack2/blank.png")
-
- assert conn
- |> delete(emoji_api_path(conn, :delete, "test_pack2"))
- |> json_response(200) == "ok"
-
- refute File.exists?("#{@emoji_dir_path}/test_pack2")
-
- # non-shared, downloaded from the fallback URL
-
- assert conn
- |> put_req_header("content-type", "application/json")
- |> post(
- emoji_api_path(
- conn,
- :download_from
- ),
- %{
- instance_address: "https://example.com",
- pack_name: "test_pack_nonshared",
- as: "test_pack_nonshared2"
- }
- |> Jason.encode!()
- )
- |> json_response(200) == "ok"
-
- assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/pack.json")
- assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/blank.png")
-
- assert conn
- |> delete(emoji_api_path(conn, :delete, "test_pack_nonshared2"))
- |> json_response(200) == "ok"
-
- refute File.exists?("#{@emoji_dir_path}/test_pack_nonshared2")
- end
-
- describe "updating pack metadata" do
- setup do
- pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
- original_content = File.read!(pack_file)
-
- on_exit(fn ->
- File.write!(pack_file, original_content)
- end)
-
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
-
- {:ok,
- admin: admin,
- conn: conn,
- pack_file: pack_file,
- new_data: %{
- "license" => "Test license changed",
- "homepage" => "https://pleroma.social",
- "description" => "Test description",
- "share-files" => false
- }}
- end
-
- test "for a pack without a fallback source", ctx do
- conn = ctx[:conn]
-
- assert conn
- |> post(
- emoji_api_path(conn, :update_metadata, "test_pack"),
- %{
- "new_data" => ctx[:new_data]
- }
- )
- |> json_response(200) == ctx[:new_data]
-
- assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
- end
-
- test "for a pack with a fallback source", ctx do
- mock(fn
- %{
- method: :get,
- url: "https://nonshared-pack"
- } ->
- text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
- end)
-
- new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
-
- new_data_with_sha =
- Map.put(
- new_data,
- "fallback-src-sha256",
- "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"
- )
-
- conn = ctx[:conn]
-
- assert conn
- |> post(
- emoji_api_path(conn, :update_metadata, "test_pack"),
- %{
- "new_data" => new_data
- }
- )
- |> json_response(200) == new_data_with_sha
-
- assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
- end
-
- test "when the fallback source doesn't have all the files", ctx do
- mock(fn
- %{
- method: :get,
- url: "https://nonshared-pack"
- } ->
- {:ok, {'empty.zip', empty_arch}} = :zip.zip('empty.zip', [], [:memory])
- text(empty_arch)
- end)
-
- new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
-
- conn = ctx[:conn]
-
- assert (conn
- |> post(
- emoji_api_path(conn, :update_metadata, "test_pack"),
- %{
- "new_data" => new_data
- }
- )
- |> json_response(:bad_request))["error"] =~ "does not have all"
- end
- end
-
- test "updating pack files" do
- pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
- original_content = File.read!(pack_file)
-
- on_exit(fn ->
- File.write!(pack_file, original_content)
-
- File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png")
- File.rm_rf!("#{@emoji_dir_path}/test_pack/dir")
- File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2")
- end)
-
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
-
- same_name = %{
- "action" => "add",
- "shortcode" => "blank",
- "filename" => "dir/blank.png",
- "file" => %Plug.Upload{
- filename: "blank.png",
- path: "#{@emoji_dir_path}/test_pack/blank.png"
- }
- }
-
- different_name = %{same_name | "shortcode" => "blank_2"}
-
- assert (conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), same_name)
- |> json_response(:conflict))["error"] =~ "already exists"
-
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), different_name)
- |> json_response(200) == %{"blank" => "blank.png", "blank_2" => "dir/blank.png"}
-
- assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png")
-
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
- "action" => "update",
- "shortcode" => "blank_2",
- "new_shortcode" => "blank_3",
- "new_filename" => "dir_2/blank_3.png"
- })
- |> json_response(200) == %{"blank" => "blank.png", "blank_3" => "dir_2/blank_3.png"}
-
- refute File.exists?("#{@emoji_dir_path}/test_pack/dir/")
- assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png")
-
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
- "action" => "remove",
- "shortcode" => "blank_3"
- })
- |> json_response(200) == %{"blank" => "blank.png"}
-
- refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/")
-
- mock(fn
- %{
- method: :get,
- url: "https://test-blank/blank_url.png"
- } ->
- text(File.read!("#{@emoji_dir_path}/test_pack/blank.png"))
- end)
-
- # The name should be inferred from the URL ending
- from_url = %{
- "action" => "add",
- "shortcode" => "blank_url",
- "file" => "https://test-blank/blank_url.png"
- }
-
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), from_url)
- |> json_response(200) == %{
- "blank" => "blank.png",
- "blank_url" => "blank_url.png"
- }
-
- assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
-
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
- "action" => "remove",
- "shortcode" => "blank_url"
- })
- |> json_response(200) == %{"blank" => "blank.png"}
-
- refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
- end
-
- test "creating and deleting a pack" do
- on_exit(fn ->
- File.rm_rf!("#{@emoji_dir_path}/test_created")
- end)
-
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
-
- assert conn
- |> put_req_header("content-type", "application/json")
- |> put(
- emoji_api_path(
- conn,
- :create,
- "test_created"
- )
- )
- |> json_response(200) == "ok"
-
- assert File.exists?("#{@emoji_dir_path}/test_created/pack.json")
-
- assert Jason.decode!(File.read!("#{@emoji_dir_path}/test_created/pack.json")) == %{
- "pack" => %{},
- "files" => %{}
- }
-
- assert conn
- |> delete(emoji_api_path(conn, :delete, "test_created"))
- |> json_response(200) == "ok"
-
- refute File.exists?("#{@emoji_dir_path}/test_created/pack.json")
- end
-
- test "filesystem import" do
- on_exit(fn ->
- File.rm!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt")
- File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
- end)
-
- conn = build_conn()
- resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
-
- refute Map.has_key?(resp, "test_pack_for_import")
-
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
-
- assert conn
- |> post(emoji_api_path(conn, :import_from_fs))
- |> json_response(200) == ["test_pack_for_import"]
-
- resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
- assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
-
- File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
- refute File.exists?("#{@emoji_dir_path}/test_pack_for_import/pack.json")
-
- emoji_txt_content = "blank, blank.png, Fun\n\nblank2, blank.png"
-
- File.write!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
-
- assert conn
- |> post(emoji_api_path(conn, :import_from_fs))
- |> json_response(200) == ["test_pack_for_import"]
-
- resp = build_conn() |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
-
- assert resp["test_pack_for_import"]["files"] == %{
- "blank" => "blank.png",
- "blank2" => "blank.png"
- }
- end
-end
diff --git a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs
new file mode 100644
index 000000000..ee3d281a0
--- /dev/null
+++ b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs
@@ -0,0 +1,780 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Tesla.Mock
+ import Pleroma.Factory
+
+ @emoji_path Path.join(
+ Pleroma.Config.get!([:instance, :static_dir]),
+ "emoji"
+ )
+ setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ admin_conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ Pleroma.Emoji.reload()
+ {:ok, %{admin_conn: admin_conn}}
+ end
+
+ test "GET /api/pleroma/emoji/packs", %{conn: conn} do
+ resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
+
+ shared = resp["test_pack"]
+ assert shared["files"] == %{"blank" => "blank.png"}
+ assert Map.has_key?(shared["pack"], "download-sha256")
+ assert shared["pack"]["can-download"]
+ assert shared["pack"]["share-files"]
+
+ non_shared = resp["test_pack_nonshared"]
+ assert non_shared["pack"]["share-files"] == false
+ assert non_shared["pack"]["can-download"] == false
+ end
+
+ describe "GET /api/pleroma/emoji/packs/remote" do
+ test "shareable instance", %{admin_conn: admin_conn, conn: conn} do
+ resp =
+ conn
+ |> get("/api/pleroma/emoji/packs")
+ |> json_response_and_validate_schema(200)
+
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
+ json(resp)
+ end)
+
+ assert admin_conn
+ |> get("/api/pleroma/emoji/packs/remote?url=https://example.com")
+ |> json_response_and_validate_schema(200) == resp
+ end
+
+ test "non shareable instance", %{admin_conn: admin_conn} do
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: []}})
+ end)
+
+ assert admin_conn
+ |> get("/api/pleroma/emoji/packs/remote?url=https://example.com")
+ |> json_response_and_validate_schema(500) == %{
+ "error" => "The requested instance does not support sharing emoji packs"
+ }
+ end
+ end
+
+ describe "GET /api/pleroma/emoji/packs/:name/archive" do
+ test "download shared pack", %{conn: conn} do
+ resp =
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack/archive")
+ |> response(200)
+
+ {:ok, arch} = :zip.unzip(resp, [:memory])
+
+ assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
+ assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
+ end
+
+ test "non existing pack", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/emoji/packs/test_pack_for_import/archive")
+ |> json_response_and_validate_schema(:not_found) == %{
+ "error" => "Pack test_pack_for_import does not exist"
+ }
+ end
+
+ test "non downloadable pack", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/emoji/packs/test_pack_nonshared/archive")
+ |> json_response_and_validate_schema(:forbidden) == %{
+ "error" =>
+ "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing"
+ }
+ end
+ end
+
+ describe "POST /api/pleroma/emoji/packs/download" do
+ test "shared pack from remote and non shared from fallback-src", %{
+ admin_conn: admin_conn,
+ conn: conn
+ } do
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/test_pack"
+ } ->
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack")
+ |> json_response_and_validate_schema(200)
+ |> json()
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/test_pack/archive"
+ } ->
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack/archive")
+ |> response(200)
+ |> text()
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/test_pack_nonshared"
+ } ->
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack_nonshared")
+ |> json_response_and_validate_schema(200)
+ |> json()
+
+ %{
+ method: :get,
+ url: "https://nonshared-pack"
+ } ->
+ text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
+ end)
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/download", %{
+ url: "https://example.com",
+ name: "test_pack",
+ as: "test_pack2"
+ })
+ |> json_response_and_validate_schema(200) == "ok"
+
+ assert File.exists?("#{@emoji_path}/test_pack2/pack.json")
+ assert File.exists?("#{@emoji_path}/test_pack2/blank.png")
+
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_pack2")
+ |> json_response_and_validate_schema(200) == "ok"
+
+ refute File.exists?("#{@emoji_path}/test_pack2")
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post(
+ "/api/pleroma/emoji/packs/download",
+ %{
+ url: "https://example.com",
+ name: "test_pack_nonshared",
+ as: "test_pack_nonshared2"
+ }
+ )
+ |> json_response_and_validate_schema(200) == "ok"
+
+ assert File.exists?("#{@emoji_path}/test_pack_nonshared2/pack.json")
+ assert File.exists?("#{@emoji_path}/test_pack_nonshared2/blank.png")
+
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_pack_nonshared2")
+ |> json_response_and_validate_schema(200) == "ok"
+
+ refute File.exists?("#{@emoji_path}/test_pack_nonshared2")
+ end
+
+ test "nonshareable instance", %{admin_conn: admin_conn} do
+ mock(fn
+ %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: []}})
+ end)
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post(
+ "/api/pleroma/emoji/packs/download",
+ %{
+ url: "https://old-instance",
+ name: "test_pack",
+ as: "test_pack2"
+ }
+ )
+ |> json_response_and_validate_schema(500) == %{
+ "error" => "The requested instance does not support sharing emoji packs"
+ }
+ end
+
+ test "checksum fail", %{admin_conn: admin_conn} do
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha"
+ } ->
+ {:ok, pack} = Pleroma.Emoji.Pack.load_pack("pack_bad_sha")
+ %Tesla.Env{status: 200, body: Jason.encode!(pack)}
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha/archive"
+ } ->
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip")
+ }
+ end)
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/download", %{
+ url: "https://example.com",
+ name: "pack_bad_sha",
+ as: "pack_bad_sha2"
+ })
+ |> json_response_and_validate_schema(:internal_server_error) == %{
+ "error" => "SHA256 for the pack doesn't match the one sent by the server"
+ }
+ end
+
+ test "other error", %{admin_conn: admin_conn} do
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/test_pack"
+ } ->
+ {:ok, pack} = Pleroma.Emoji.Pack.load_pack("test_pack")
+ %Tesla.Env{status: 200, body: Jason.encode!(pack)}
+ end)
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/download", %{
+ url: "https://example.com",
+ name: "test_pack",
+ as: "test_pack2"
+ })
+ |> json_response_and_validate_schema(:internal_server_error) == %{
+ "error" =>
+ "The pack was not set as shared and there is no fallback src to download from"
+ }
+ end
+ end
+
+ describe "PATCH /api/pleroma/emoji/packs/:name" do
+ setup do
+ pack_file = "#{@emoji_path}/test_pack/pack.json"
+ original_content = File.read!(pack_file)
+
+ on_exit(fn ->
+ File.write!(pack_file, original_content)
+ end)
+
+ {:ok,
+ pack_file: pack_file,
+ new_data: %{
+ "license" => "Test license changed",
+ "homepage" => "https://pleroma.social",
+ "description" => "Test description",
+ "share-files" => false
+ }}
+ end
+
+ test "for a pack without a fallback source", ctx do
+ assert ctx[:admin_conn]
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/test_pack", %{"metadata" => ctx[:new_data]})
+ |> json_response_and_validate_schema(200) == ctx[:new_data]
+
+ assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
+ end
+
+ test "for a pack with a fallback source", ctx do
+ mock(fn
+ %{
+ method: :get,
+ url: "https://nonshared-pack"
+ } ->
+ text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
+ end)
+
+ new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
+
+ new_data_with_sha =
+ Map.put(
+ new_data,
+ "fallback-src-sha256",
+ "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"
+ )
+
+ assert ctx[:admin_conn]
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})
+ |> json_response_and_validate_schema(200) == new_data_with_sha
+
+ assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
+ end
+
+ test "when the fallback source doesn't have all the files", ctx do
+ mock(fn
+ %{
+ method: :get,
+ url: "https://nonshared-pack"
+ } ->
+ {:ok, {'empty.zip', empty_arch}} = :zip.zip('empty.zip', [], [:memory])
+ text(empty_arch)
+ end)
+
+ new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
+
+ assert ctx[:admin_conn]
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "The fallback archive does not have all files specified in pack.json"
+ }
+ end
+ end
+
+ describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/:name/files" do
+ setup do
+ pack_file = "#{@emoji_path}/test_pack/pack.json"
+ original_content = File.read!(pack_file)
+
+ on_exit(fn ->
+ File.write!(pack_file, original_content)
+ end)
+
+ :ok
+ end
+
+ test "create shortcode exists", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response_and_validate_schema(:conflict) == %{
+ "error" => "An emoji with the \"blank\" shortcode already exists"
+ }
+ end
+
+ test "don't rewrite old emoji", %{admin_conn: admin_conn} do
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir/") end)
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "blank" => "blank.png",
+ "blank2" => "dir/blank.png"
+ }
+
+ assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank",
+ new_shortcode: "blank2",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response_and_validate_schema(:conflict) == %{
+ "error" =>
+ "New shortcode \"blank2\" is already used. If you want to override emoji use 'force' option"
+ }
+ end
+
+ test "rewrite old emoji with force option", %{admin_conn: admin_conn} do
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir_2/") end)
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "blank" => "blank.png",
+ "blank2" => "dir/blank.png"
+ }
+
+ assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ new_shortcode: "blank3",
+ new_filename: "dir_2/blank_3.png",
+ force: true
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "blank" => "blank.png",
+ "blank3" => "dir_2/blank_3.png"
+ }
+
+ assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
+ end
+
+ test "with empty filename", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ filename: "",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "pack name, shortcode or filename cannot be empty"
+ }
+ end
+
+ test "add file with not loaded pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/not_loaded/files", %{
+ shortcode: "blank2",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "pack \"not_loaded\" is not found"
+ }
+ end
+
+ test "remove file with not loaded pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/not_loaded/files?shortcode=blank3")
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "pack \"not_loaded\" is not found"
+ }
+ end
+
+ test "remove file with empty shortcode", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/not_loaded/files?shortcode=")
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "pack name or shortcode cannot be empty"
+ }
+ end
+
+ test "update file with not loaded pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/not_loaded/files", %{
+ shortcode: "blank4",
+ new_shortcode: "blank3",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "pack \"not_loaded\" is not found"
+ }
+ end
+
+ test "new with shortcode as file with update", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank4",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "blank" => "blank.png",
+ "blank4" => "dir/blank.png"
+ }
+
+ assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank4",
+ new_shortcode: "blank3",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "blank3" => "dir_2/blank_3.png",
+ "blank" => "blank.png"
+ }
+
+ refute File.exists?("#{@emoji_path}/test_pack/dir/")
+ assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
+
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank3")
+ |> json_response_and_validate_schema(200) == %{"blank" => "blank.png"}
+
+ refute File.exists?("#{@emoji_path}/test_pack/dir_2/")
+
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir") end)
+ end
+
+ test "new with shortcode from url", %{admin_conn: admin_conn} do
+ mock(fn
+ %{
+ method: :get,
+ url: "https://test-blank/blank_url.png"
+ } ->
+ text(File.read!("#{@emoji_path}/test_pack/blank.png"))
+ end)
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank_url",
+ file: "https://test-blank/blank_url.png"
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "blank_url" => "blank_url.png",
+ "blank" => "blank.png"
+ }
+
+ assert File.exists?("#{@emoji_path}/test_pack/blank_url.png")
+
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/blank_url.png") end)
+ end
+
+ test "new without shortcode", %{admin_conn: admin_conn} do
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/shortcode.png") end)
+
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ file: %Plug.Upload{
+ filename: "shortcode.png",
+ path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png"
+ }
+ })
+ |> json_response_and_validate_schema(200) == %{
+ "shortcode" => "shortcode.png",
+ "blank" => "blank.png"
+ }
+ end
+
+ test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank2")
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "Emoji \"blank2\" does not exist"
+ }
+ end
+
+ test "update non existing emoji", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ new_shortcode: "blank3",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "Emoji \"blank2\" does not exist"
+ }
+ end
+
+ test "update with empty shortcode", %{admin_conn: admin_conn} do
+ assert %{
+ "error" => "Missing field: new_shortcode."
+ } =
+ admin_conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response_and_validate_schema(:bad_request)
+ end
+ end
+
+ describe "POST/DELETE /api/pleroma/emoji/packs/:name" do
+ test "creating and deleting a pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_created")
+ |> json_response_and_validate_schema(200) == "ok"
+
+ assert File.exists?("#{@emoji_path}/test_created/pack.json")
+
+ assert Jason.decode!(File.read!("#{@emoji_path}/test_created/pack.json")) == %{
+ "pack" => %{},
+ "files" => %{}
+ }
+
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_created")
+ |> json_response_and_validate_schema(200) == "ok"
+
+ refute File.exists?("#{@emoji_path}/test_created/pack.json")
+ end
+
+ test "if pack exists", %{admin_conn: admin_conn} do
+ path = Path.join(@emoji_path, "test_created")
+ File.mkdir(path)
+ pack_file = Jason.encode!(%{files: %{}, pack: %{}})
+ File.write!(Path.join(path, "pack.json"), pack_file)
+
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_created")
+ |> json_response_and_validate_schema(:conflict) == %{
+ "error" => "A pack named \"test_created\" already exists"
+ }
+
+ on_exit(fn -> File.rm_rf(path) end)
+ end
+
+ test "with empty name", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/ ")
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "pack name cannot be empty"
+ }
+ end
+ end
+
+ test "deleting nonexisting pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/non_existing")
+ |> json_response_and_validate_schema(:not_found) == %{
+ "error" => "Pack non_existing does not exist"
+ }
+ end
+
+ test "deleting with empty name", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/ ")
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "pack name cannot be empty"
+ }
+ end
+
+ test "filesystem import", %{admin_conn: admin_conn, conn: conn} do
+ on_exit(fn ->
+ File.rm!("#{@emoji_path}/test_pack_for_import/emoji.txt")
+ File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
+ end)
+
+ resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
+
+ refute Map.has_key?(resp, "test_pack_for_import")
+
+ assert admin_conn
+ |> get("/api/pleroma/emoji/packs/import")
+ |> json_response_and_validate_schema(200) == ["test_pack_for_import"]
+
+ resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
+ assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
+
+ File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
+ refute File.exists?("#{@emoji_path}/test_pack_for_import/pack.json")
+
+ emoji_txt_content = """
+ blank, blank.png, Fun
+ blank2, blank.png
+ foo, /emoji/test_pack_for_import/blank.png
+ bar
+ """
+
+ File.write!("#{@emoji_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
+
+ assert admin_conn
+ |> get("/api/pleroma/emoji/packs/import")
+ |> json_response_and_validate_schema(200) == ["test_pack_for_import"]
+
+ resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
+
+ assert resp["test_pack_for_import"]["files"] == %{
+ "blank" => "blank.png",
+ "blank2" => "blank.png",
+ "foo" => "blank.png"
+ }
+ end
+
+ describe "GET /api/pleroma/emoji/packs/:name" do
+ test "shows pack.json", %{conn: conn} do
+ assert %{
+ "files" => %{"blank" => "blank.png"},
+ "pack" => %{
+ "can-download" => true,
+ "description" => "Test description",
+ "download-sha256" => _,
+ "homepage" => "https://pleroma.social",
+ "license" => "Test license",
+ "share-files" => true
+ }
+ } =
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack")
+ |> json_response_and_validate_schema(200)
+ end
+
+ test "non existing pack", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/emoji/packs/non_existing")
+ |> json_response_and_validate_schema(:not_found) == %{
+ "error" => "Pack non_existing does not exist"
+ }
+ end
+
+ test "error name", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/emoji/packs/ ")
+ |> json_response_and_validate_schema(:bad_request) == %{
+ "error" => "pack name cannot be empty"
+ }
+ end
+ end
+end
diff --git a/test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs b/test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs
new file mode 100644
index 000000000..e1bb5ebfe
--- /dev/null
+++ b/test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs
@@ -0,0 +1,132 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.EmojiReactionControllerTest do
+ use Oban.Testing, repo: Pleroma.Repo
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Object
+ alias Pleroma.Tests.ObanHelpers
+ alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
+
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"]))
+ |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/☕")
+ |> json_response_and_validate_schema(200)
+
+ # We return the status, but this our implementation detail.
+ assert %{"id" => id} = result
+ assert to_string(activity.id) == id
+
+ assert result["pleroma"]["emoji_reactions"] == [
+ %{"name" => "☕", "count" => 1, "me" => true}
+ ]
+
+ # Reacting with a non-emoji
+ assert conn
+ |> assign(:user, other_user)
+ |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"]))
+ |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/x")
+ |> json_response_and_validate_schema(400)
+ end
+
+ test "DELETE /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
+ {:ok, _reaction_activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
+
+ ObanHelpers.perform_all()
+
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"]))
+ |> delete("/api/v1/pleroma/statuses/#{activity.id}/reactions/☕")
+
+ assert %{"id" => id} = json_response_and_validate_schema(result, 200)
+ assert to_string(activity.id) == id
+
+ ObanHelpers.perform_all()
+
+ object = Object.get_by_ap_id(activity.data["object"])
+
+ assert object.data["reaction_count"] == 0
+ end
+
+ test "GET /api/v1/pleroma/statuses/:id/reactions", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+ doomed_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
+ |> json_response_and_validate_schema(200)
+
+ assert result == []
+
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, doomed_user, "🎅")
+
+ User.perform(:delete, doomed_user)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
+ |> json_response_and_validate_schema(200)
+
+ [%{"name" => "🎅", "count" => 1, "accounts" => [represented_user], "me" => false}] = result
+
+ assert represented_user["id"] == other_user.id
+
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:statuses"]))
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
+ |> json_response_and_validate_schema(200)
+
+ assert [%{"name" => "🎅", "count" => 1, "accounts" => [_represented_user], "me" => true}] =
+ result
+ end
+
+ test "GET /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions/🎅")
+ |> json_response_and_validate_schema(200)
+
+ assert result == []
+
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
+
+ assert [%{"name" => "🎅", "count" => 1, "accounts" => [represented_user], "me" => false}] =
+ conn
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions/🎅")
+ |> json_response_and_validate_schema(200)
+
+ assert represented_user["id"] == other_user.id
+ end
+end
diff --git a/test/web/pleroma_api/controllers/mascot_controller_test.exs b/test/web/pleroma_api/controllers/mascot_controller_test.exs
index 617831b02..e2ead6e15 100644
--- a/test/web/pleroma_api/controllers/mascot_controller_test.exs
+++ b/test/web/pleroma_api/controllers/mascot_controller_test.exs
@@ -16,9 +16,12 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do
filename: "sound.mp3"
}
- ret_conn = put(conn, "/api/v1/pleroma/mascot", %{"file" => non_image_file})
+ ret_conn =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
- assert json_response(ret_conn, 415)
+ assert json_response_and_validate_schema(ret_conn, 415)
file = %Plug.Upload{
content_type: "image/jpg",
@@ -26,9 +29,12 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do
filename: "an_image.jpg"
}
- conn = put(conn, "/api/v1/pleroma/mascot", %{"file" => file})
+ conn =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> put("/api/v1/pleroma/mascot", %{"file" => file})
- assert %{"id" => _, "type" => image} = json_response(conn, 200)
+ assert %{"id" => _, "type" => image} = json_response_and_validate_schema(conn, 200)
end
test "mascot retrieving" do
@@ -37,7 +43,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do
# When user hasn't set a mascot, we should just get pleroma tan back
ret_conn = get(conn, "/api/v1/pleroma/mascot")
- assert %{"url" => url} = json_response(ret_conn, 200)
+ assert %{"url" => url} = json_response_and_validate_schema(ret_conn, 200)
assert url =~ "pleroma-fox-tan-smol"
# When a user sets their mascot, we should get that back
@@ -47,9 +53,12 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do
filename: "an_image.jpg"
}
- ret_conn = put(conn, "/api/v1/pleroma/mascot", %{"file" => file})
+ ret_conn =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> put("/api/v1/pleroma/mascot", %{"file" => file})
- assert json_response(ret_conn, 200)
+ assert json_response_and_validate_schema(ret_conn, 200)
user = User.get_cached_by_id(user.id)
@@ -58,7 +67,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do
|> assign(:user, user)
|> get("/api/v1/pleroma/mascot")
- assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
+ assert %{"url" => url, "type" => "image"} = json_response_and_validate_schema(conn, 200)
assert url =~ "an_image"
end
end
diff --git a/test/web/pleroma_api/controllers/notification_controller_test.exs b/test/web/pleroma_api/controllers/notification_controller_test.exs
new file mode 100644
index 000000000..bb4fe6c49
--- /dev/null
+++ b/test/web/pleroma_api/controllers/notification_controller_test.exs
@@ -0,0 +1,68 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.NotificationControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Notification
+ alias Pleroma.Repo
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "POST /api/v1/pleroma/notifications/read" do
+ setup do: oauth_access(["write:notifications"])
+
+ test "it marks a single notification as read", %{user: user1, conn: conn} do
+ user2 = insert(:user)
+ {:ok, activity1} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"})
+ {:ok, activity2} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"})
+ {:ok, [notification1]} = Notification.create_notifications(activity1)
+ {:ok, [notification2]} = Notification.create_notifications(activity2)
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/notifications/read", %{id: notification1.id})
+ |> json_response_and_validate_schema(:ok)
+
+ assert %{"pleroma" => %{"is_seen" => true}} = response
+ assert Repo.get(Notification, notification1.id).seen
+ refute Repo.get(Notification, notification2.id).seen
+ end
+
+ test "it marks multiple notifications as read", %{user: user1, conn: conn} do
+ user2 = insert(:user)
+ {:ok, _activity1} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"})
+ {:ok, _activity2} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"})
+ {:ok, _activity3} = CommonAPI.post(user2, %{status: "HIE @#{user1.nickname}"})
+
+ [notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3})
+
+ [response1, response2] =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/notifications/read", %{max_id: notification2.id})
+ |> json_response_and_validate_schema(:ok)
+
+ assert %{"pleroma" => %{"is_seen" => true}} = response1
+ assert %{"pleroma" => %{"is_seen" => true}} = response2
+ assert Repo.get(Notification, notification1.id).seen
+ assert Repo.get(Notification, notification2.id).seen
+ refute Repo.get(Notification, notification3.id).seen
+ end
+
+ test "it returns error when notification not found", %{conn: conn} do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/notifications/read", %{
+ id: 22_222_222_222_222
+ })
+ |> json_response_and_validate_schema(:bad_request)
+
+ assert response == %{"error" => "Cannot get notification"}
+ end
+ end
+end
diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
deleted file mode 100644
index 61a1689b9..000000000
--- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
+++ /dev/null
@@ -1,296 +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.PleromaAPI.PleromaAPIControllerTest do
- use Pleroma.Web.ConnCase
-
- alias Pleroma.Conversation.Participation
- alias Pleroma.Notification
- alias Pleroma.Object
- alias Pleroma.Repo
- alias Pleroma.User
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
-
- result =
- conn
- |> assign(:user, other_user)
- |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"]))
- |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/☕")
- |> json_response(200)
-
- # We return the status, but this our implementation detail.
- assert %{"id" => id} = result
- assert to_string(activity.id) == id
-
- assert result["pleroma"]["emoji_reactions"] == [
- %{"name" => "☕", "count" => 1, "me" => true}
- ]
- end
-
- test "DELETE /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
- {:ok, activity, _object} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
-
- result =
- conn
- |> assign(:user, other_user)
- |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"]))
- |> delete("/api/v1/pleroma/statuses/#{activity.id}/reactions/☕")
-
- assert %{"id" => id} = json_response(result, 200)
- assert to_string(activity.id) == id
-
- object = Object.normalize(activity)
-
- assert object.data["reaction_count"] == 0
- end
-
- test "GET /api/v1/pleroma/statuses/:id/reactions", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
- doomed_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
-
- result =
- conn
- |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
- |> json_response(200)
-
- assert result == []
-
- {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
- {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, doomed_user, "🎅")
-
- User.perform(:delete, doomed_user)
-
- result =
- conn
- |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
- |> json_response(200)
-
- [%{"name" => "🎅", "count" => 1, "accounts" => [represented_user], "me" => false}] = result
-
- assert represented_user["id"] == other_user.id
-
- result =
- conn
- |> assign(:user, other_user)
- |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:statuses"]))
- |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
- |> json_response(200)
-
- assert [%{"name" => "🎅", "count" => 1, "accounts" => [_represented_user], "me" => true}] =
- result
- end
-
- test "GET /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
-
- result =
- conn
- |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions/🎅")
- |> json_response(200)
-
- assert result == []
-
- {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
- {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
-
- result =
- conn
- |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions/🎅")
- |> json_response(200)
-
- [%{"name" => "🎅", "count" => 1, "accounts" => [represented_user], "me" => false}] = result
-
- assert represented_user["id"] == other_user.id
- end
-
- test "/api/v1/pleroma/conversations/:id" do
- user = insert(:user)
- %{user: other_user, conn: conn} = oauth_access(["read:statuses"])
-
- {:ok, _activity} =
- CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}!", "visibility" => "direct"})
-
- [participation] = Participation.for_user(other_user)
-
- result =
- conn
- |> get("/api/v1/pleroma/conversations/#{participation.id}")
- |> json_response(200)
-
- assert result["id"] == participation.id |> to_string()
- end
-
- test "/api/v1/pleroma/conversations/:id/statuses" do
- user = insert(:user)
- %{user: other_user, conn: conn} = oauth_access(["read:statuses"])
- third_user = insert(:user)
-
- {:ok, _activity} =
- CommonAPI.post(user, %{"status" => "Hi @#{third_user.nickname}!", "visibility" => "direct"})
-
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}!", "visibility" => "direct"})
-
- [participation] = Participation.for_user(other_user)
-
- {:ok, activity_two} =
- CommonAPI.post(other_user, %{
- "status" => "Hi!",
- "in_reply_to_status_id" => activity.id,
- "in_reply_to_conversation_id" => participation.id
- })
-
- result =
- conn
- |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses")
- |> json_response(200)
-
- assert length(result) == 2
-
- id_one = activity.id
- id_two = activity_two.id
- assert [%{"id" => ^id_one}, %{"id" => ^id_two}] = result
-
- {:ok, %{id: id_three}} =
- CommonAPI.post(other_user, %{
- "status" => "Bye!",
- "in_reply_to_status_id" => activity.id,
- "in_reply_to_conversation_id" => participation.id
- })
-
- assert [%{"id" => ^id_two}, %{"id" => ^id_three}] =
- conn
- |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?limit=2")
- |> json_response(:ok)
-
- assert [%{"id" => ^id_three}] =
- conn
- |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?min_id=#{id_two}")
- |> json_response(:ok)
- end
-
- test "PATCH /api/v1/pleroma/conversations/:id" do
- %{user: user, conn: conn} = oauth_access(["write:conversations"])
- other_user = insert(:user)
-
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "Hi", "visibility" => "direct"})
-
- [participation] = Participation.for_user(user)
-
- participation = Repo.preload(participation, :recipients)
-
- user = User.get_cached_by_id(user.id)
- assert [user] == participation.recipients
- assert other_user not in participation.recipients
-
- result =
- conn
- |> patch("/api/v1/pleroma/conversations/#{participation.id}", %{
- "recipients" => [user.id, other_user.id]
- })
- |> json_response(200)
-
- assert result["id"] == participation.id |> to_string
-
- [participation] = Participation.for_user(user)
- participation = Repo.preload(participation, :recipients)
-
- assert user in participation.recipients
- assert other_user in participation.recipients
- end
-
- test "POST /api/v1/pleroma/conversations/read" do
- user = insert(:user)
- %{user: other_user, conn: conn} = oauth_access(["write:conversations"])
-
- {:ok, _activity} =
- CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}", "visibility" => "direct"})
-
- {:ok, _activity} =
- CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}", "visibility" => "direct"})
-
- [participation2, participation1] = Participation.for_user(other_user)
- assert Participation.get(participation2.id).read == false
- assert Participation.get(participation1.id).read == false
- assert User.get_cached_by_id(other_user.id).unread_conversation_count == 2
-
- [%{"unread" => false}, %{"unread" => false}] =
- conn
- |> post("/api/v1/pleroma/conversations/read", %{})
- |> json_response(200)
-
- [participation2, participation1] = Participation.for_user(other_user)
- assert Participation.get(participation2.id).read == true
- assert Participation.get(participation1.id).read == true
- assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0
- end
-
- describe "POST /api/v1/pleroma/notifications/read" do
- setup do: oauth_access(["write:notifications"])
-
- test "it marks a single notification as read", %{user: user1, conn: conn} do
- user2 = insert(:user)
- {:ok, activity1} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
- {:ok, activity2} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
- {:ok, [notification1]} = Notification.create_notifications(activity1)
- {:ok, [notification2]} = Notification.create_notifications(activity2)
-
- response =
- conn
- |> post("/api/v1/pleroma/notifications/read", %{"id" => "#{notification1.id}"})
- |> json_response(:ok)
-
- assert %{"pleroma" => %{"is_seen" => true}} = response
- assert Repo.get(Notification, notification1.id).seen
- refute Repo.get(Notification, notification2.id).seen
- end
-
- test "it marks multiple notifications as read", %{user: user1, conn: conn} do
- user2 = insert(:user)
- {:ok, _activity1} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
- {:ok, _activity2} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
- {:ok, _activity3} = CommonAPI.post(user2, %{"status" => "HIE @#{user1.nickname}"})
-
- [notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3})
-
- [response1, response2] =
- conn
- |> post("/api/v1/pleroma/notifications/read", %{"max_id" => "#{notification2.id}"})
- |> json_response(:ok)
-
- assert %{"pleroma" => %{"is_seen" => true}} = response1
- assert %{"pleroma" => %{"is_seen" => true}} = response2
- assert Repo.get(Notification, notification1.id).seen
- assert Repo.get(Notification, notification2.id).seen
- refute Repo.get(Notification, notification3.id).seen
- end
-
- test "it returns error when notification not found", %{conn: conn} do
- response =
- conn
- |> post("/api/v1/pleroma/notifications/read", %{"id" => "22222222222222"})
- |> json_response(:bad_request)
-
- assert response == %{"error" => "Cannot get notification"}
- end
- end
-end
diff --git a/test/web/pleroma_api/controllers/scrobble_controller_test.exs b/test/web/pleroma_api/controllers/scrobble_controller_test.exs
index 1b945040c..f39c07ac6 100644
--- a/test/web/pleroma_api/controllers/scrobble_controller_test.exs
+++ b/test/web/pleroma_api/controllers/scrobble_controller_test.exs
@@ -12,14 +12,16 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
%{conn: conn} = oauth_access(["write"])
conn =
- post(conn, "/api/v1/pleroma/scrobble", %{
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/scrobble", %{
"title" => "lain radio episode 1",
"artist" => "lain",
"album" => "lain radio",
"length" => "180000"
})
- assert %{"title" => "lain radio episode 1"} = json_response(conn, 200)
+ assert %{"title" => "lain radio episode 1"} = json_response_and_validate_schema(conn, 200)
end
end
@@ -29,28 +31,28 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
{:ok, _activity} =
CommonAPI.listen(user, %{
- "title" => "lain radio episode 1",
- "artist" => "lain",
- "album" => "lain radio"
+ title: "lain radio episode 1",
+ artist: "lain",
+ album: "lain radio"
})
{:ok, _activity} =
CommonAPI.listen(user, %{
- "title" => "lain radio episode 2",
- "artist" => "lain",
- "album" => "lain radio"
+ title: "lain radio episode 2",
+ artist: "lain",
+ album: "lain radio"
})
{:ok, _activity} =
CommonAPI.listen(user, %{
- "title" => "lain radio episode 3",
- "artist" => "lain",
- "album" => "lain radio"
+ title: "lain radio episode 3",
+ artist: "lain",
+ album: "lain radio"
})
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/scrobbles")
- result = json_response(conn, 200)
+ result = json_response_and_validate_schema(conn, 200)
assert length(result) == 3
end
diff --git a/test/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs b/test/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs
new file mode 100644
index 000000000..d23d08a00
--- /dev/null
+++ b/test/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs
@@ -0,0 +1,260 @@
+defmodule Pleroma.Web.PleromaAPI.TwoFactorAuthenticationControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+ alias Pleroma.MFA.Settings
+ alias Pleroma.MFA.TOTP
+
+ describe "GET /api/pleroma/accounts/mfa/settings" do
+ test "returns user mfa settings for new user", %{conn: conn} do
+ token = insert(:oauth_token, scopes: ["read", "follow"])
+ token2 = insert(:oauth_token, scopes: ["write"])
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> get("/api/pleroma/accounts/mfa")
+ |> json_response(:ok) == %{
+ "settings" => %{"enabled" => false, "totp" => false}
+ }
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token2.token}")
+ |> get("/api/pleroma/accounts/mfa")
+ |> json_response(403) == %{
+ "error" => "Insufficient permissions: read:security."
+ }
+ end
+
+ test "returns user mfa settings with enabled totp", %{conn: conn} do
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %Settings{
+ enabled: true,
+ totp: %Settings.TOTP{secret: "XXX", delivery_type: "app", confirmed: true}
+ }
+ )
+
+ token = insert(:oauth_token, scopes: ["read", "follow"], user: user)
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> get("/api/pleroma/accounts/mfa")
+ |> json_response(:ok) == %{
+ "settings" => %{"enabled" => true, "totp" => true}
+ }
+ end
+ end
+
+ describe "GET /api/pleroma/accounts/mfa/backup_codes" do
+ test "returns backup codes", %{conn: conn} do
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %Settings{
+ backup_codes: ["1", "2", "3"],
+ totp: %Settings.TOTP{secret: "secret"}
+ }
+ )
+
+ token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
+ token2 = insert(:oauth_token, scopes: ["read"])
+
+ response =
+ conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> get("/api/pleroma/accounts/mfa/backup_codes")
+ |> json_response(:ok)
+
+ assert [<<_::bytes-size(6)>>, <<_::bytes-size(6)>>] = response["codes"]
+ user = refresh_record(user)
+ mfa_settings = user.multi_factor_authentication_settings
+ assert mfa_settings.totp.secret == "secret"
+ refute mfa_settings.backup_codes == ["1", "2", "3"]
+ refute mfa_settings.backup_codes == []
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token2.token}")
+ |> get("/api/pleroma/accounts/mfa/backup_codes")
+ |> json_response(403) == %{
+ "error" => "Insufficient permissions: write:security."
+ }
+ end
+ end
+
+ describe "GET /api/pleroma/accounts/mfa/setup/totp" do
+ test "return errors when method is invalid", %{conn: conn} do
+ user = insert(:user)
+ token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
+
+ response =
+ conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> get("/api/pleroma/accounts/mfa/setup/torf")
+ |> json_response(400)
+
+ assert response == %{"error" => "undefined method"}
+ end
+
+ test "returns key and provisioning_uri", %{conn: conn} do
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %Settings{backup_codes: ["1", "2", "3"]}
+ )
+
+ token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
+ token2 = insert(:oauth_token, scopes: ["read"])
+
+ response =
+ conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> get("/api/pleroma/accounts/mfa/setup/totp")
+ |> json_response(:ok)
+
+ user = refresh_record(user)
+ mfa_settings = user.multi_factor_authentication_settings
+ secret = mfa_settings.totp.secret
+ refute mfa_settings.enabled
+ assert mfa_settings.backup_codes == ["1", "2", "3"]
+
+ assert response == %{
+ "key" => secret,
+ "provisioning_uri" => TOTP.provisioning_uri(secret, "#{user.email}")
+ }
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token2.token}")
+ |> get("/api/pleroma/accounts/mfa/setup/totp")
+ |> json_response(403) == %{
+ "error" => "Insufficient permissions: write:security."
+ }
+ end
+ end
+
+ describe "GET /api/pleroma/accounts/mfa/confirm/totp" do
+ test "returns success result", %{conn: conn} do
+ secret = TOTP.generate_secret()
+ code = TOTP.generate_token(secret)
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %Settings{
+ backup_codes: ["1", "2", "3"],
+ totp: %Settings.TOTP{secret: secret}
+ }
+ )
+
+ token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
+ token2 = insert(:oauth_token, scopes: ["read"])
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: code})
+ |> json_response(:ok)
+
+ settings = refresh_record(user).multi_factor_authentication_settings
+ assert settings.enabled
+ assert settings.totp.secret == secret
+ assert settings.totp.confirmed
+ assert settings.backup_codes == ["1", "2", "3"]
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token2.token}")
+ |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: code})
+ |> json_response(403) == %{
+ "error" => "Insufficient permissions: write:security."
+ }
+ end
+
+ test "returns error if password incorrect", %{conn: conn} do
+ secret = TOTP.generate_secret()
+ code = TOTP.generate_token(secret)
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %Settings{
+ backup_codes: ["1", "2", "3"],
+ totp: %Settings.TOTP{secret: secret}
+ }
+ )
+
+ token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
+
+ response =
+ conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "xxx", code: code})
+ |> json_response(422)
+
+ settings = refresh_record(user).multi_factor_authentication_settings
+ refute settings.enabled
+ refute settings.totp.confirmed
+ assert settings.backup_codes == ["1", "2", "3"]
+ assert response == %{"error" => "Invalid password."}
+ end
+
+ test "returns error if code incorrect", %{conn: conn} do
+ secret = TOTP.generate_secret()
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %Settings{
+ backup_codes: ["1", "2", "3"],
+ totp: %Settings.TOTP{secret: secret}
+ }
+ )
+
+ token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
+ token2 = insert(:oauth_token, scopes: ["read"])
+
+ response =
+ conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: "code"})
+ |> json_response(422)
+
+ settings = refresh_record(user).multi_factor_authentication_settings
+ refute settings.enabled
+ refute settings.totp.confirmed
+ assert settings.backup_codes == ["1", "2", "3"]
+ assert response == %{"error" => "invalid_token"}
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token2.token}")
+ |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: "code"})
+ |> json_response(403) == %{
+ "error" => "Insufficient permissions: write:security."
+ }
+ end
+ end
+
+ describe "DELETE /api/pleroma/accounts/mfa/totp" do
+ test "returns success result", %{conn: conn} do
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %Settings{
+ backup_codes: ["1", "2", "3"],
+ totp: %Settings.TOTP{secret: "secret"}
+ }
+ )
+
+ token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
+ token2 = insert(:oauth_token, scopes: ["read"])
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token.token}")
+ |> delete("/api/pleroma/accounts/mfa/totp", %{password: "test"})
+ |> json_response(:ok)
+
+ settings = refresh_record(user).multi_factor_authentication_settings
+ refute settings.enabled
+ assert settings.totp.secret == nil
+ refute settings.totp.confirmed
+
+ assert conn
+ |> put_req_header("authorization", "Bearer #{token2.token}")
+ |> delete("/api/pleroma/accounts/mfa/totp", %{password: "test"})
+ |> json_response(403) == %{
+ "error" => "Insufficient permissions: write:security."
+ }
+ end
+ end
+end
diff --git a/test/web/pleroma_api/views/chat/message_reference_view_test.exs b/test/web/pleroma_api/views/chat/message_reference_view_test.exs
new file mode 100644
index 000000000..e5b165255
--- /dev/null
+++ b/test/web/pleroma_api/views/chat/message_reference_view_test.exs
@@ -0,0 +1,61 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceViewTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Chat
+ alias Pleroma.Chat.MessageReference
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
+
+ import Pleroma.Factory
+
+ test "it displays a chat message" do
+ user = insert(:user)
+ recipient = insert(:user)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
+ {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "kippis :firefox:")
+
+ chat = Chat.get(user.id, recipient.ap_id)
+
+ object = Object.normalize(activity)
+
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ chat_message = MessageReferenceView.render("show.json", chat_message_reference: cm_ref)
+
+ assert chat_message[:id] == cm_ref.id
+ assert chat_message[:content] == "kippis :firefox:"
+ assert chat_message[:account_id] == user.id
+ assert chat_message[:chat_id]
+ assert chat_message[:created_at]
+ assert chat_message[:unread] == false
+ assert match?([%{shortcode: "firefox"}], chat_message[:emojis])
+
+ {:ok, activity} = CommonAPI.post_chat_message(recipient, user, "gkgkgk", media_id: upload.id)
+
+ object = Object.normalize(activity)
+
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+
+ chat_message_two = MessageReferenceView.render("show.json", chat_message_reference: cm_ref)
+
+ assert chat_message_two[:id] == cm_ref.id
+ assert chat_message_two[:content] == "gkgkgk"
+ assert chat_message_two[:account_id] == recipient.id
+ assert chat_message_two[:chat_id] == chat_message[:chat_id]
+ assert chat_message_two[:attachment]
+ assert chat_message_two[:unread] == true
+ end
+end
diff --git a/test/web/pleroma_api/views/chat_view_test.exs b/test/web/pleroma_api/views/chat_view_test.exs
new file mode 100644
index 000000000..14eecb1bd
--- /dev/null
+++ b/test/web/pleroma_api/views/chat_view_test.exs
@@ -0,0 +1,48 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.ChatViewTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Chat
+ alias Pleroma.Chat.MessageReference
+ alias Pleroma.Object
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.CommonAPI.Utils
+ alias Pleroma.Web.MastodonAPI.AccountView
+ alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
+ alias Pleroma.Web.PleromaAPI.ChatView
+
+ import Pleroma.Factory
+
+ test "it represents a chat" do
+ user = insert(:user)
+ recipient = insert(:user)
+
+ {:ok, chat} = Chat.get_or_create(user.id, recipient.ap_id)
+
+ represented_chat = ChatView.render("show.json", chat: chat)
+
+ assert represented_chat == %{
+ id: "#{chat.id}",
+ account: AccountView.render("show.json", user: recipient),
+ unread: 0,
+ last_message: nil,
+ updated_at: Utils.to_masto_date(chat.updated_at)
+ }
+
+ {:ok, chat_message_creation} = CommonAPI.post_chat_message(user, recipient, "hello")
+
+ chat_message = Object.normalize(chat_message_creation, false)
+
+ {:ok, chat} = Chat.get_or_create(user.id, recipient.ap_id)
+
+ represented_chat = ChatView.render("show.json", chat: chat)
+
+ cm_ref = MessageReference.for_chat_and_object(chat, chat_message)
+
+ assert represented_chat[:last_message] ==
+ MessageReferenceView.render("show.json", chat_message_reference: cm_ref)
+ end
+end
diff --git a/test/web/pleroma_api/views/scrobble_view_test.exs b/test/web/pleroma_api/views/scrobble_view_test.exs
new file mode 100644
index 000000000..6bdb56509
--- /dev/null
+++ b/test/web/pleroma_api/views/scrobble_view_test.exs
@@ -0,0 +1,20 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.StatusViewTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.PleromaAPI.ScrobbleView
+
+ import Pleroma.Factory
+
+ test "successfully renders a Listen activity (pleroma extension)" do
+ listen_activity = insert(:listen)
+
+ status = ScrobbleView.render("show.json", activity: listen_activity)
+
+ assert status.length == listen_activity.data["object"]["length"]
+ assert status.title == listen_activity.data["object"]["title"]
+ end
+end
diff --git a/test/web/plugs/plug_test.exs b/test/web/plugs/plug_test.exs
new file mode 100644
index 000000000..943e484e7
--- /dev/null
+++ b/test/web/plugs/plug_test.exs
@@ -0,0 +1,91 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PlugTest do
+ @moduledoc "Tests for the functionality added via `use Pleroma.Web, :plug`"
+
+ alias Pleroma.Plugs.ExpectAuthenticatedCheckPlug
+ alias Pleroma.Plugs.ExpectPublicOrAuthenticatedCheckPlug
+ alias Pleroma.Plugs.PlugHelper
+
+ import Mock
+
+ use Pleroma.Web.ConnCase
+
+ describe "when plug is skipped, " do
+ setup_with_mocks(
+ [
+ {ExpectPublicOrAuthenticatedCheckPlug, [:passthrough], []}
+ ],
+ %{conn: conn}
+ ) do
+ conn = ExpectPublicOrAuthenticatedCheckPlug.skip_plug(conn)
+ %{conn: conn}
+ end
+
+ test "it neither adds plug to called plugs list nor calls `perform/2`, " <>
+ "regardless of :if_func / :unless_func options",
+ %{conn: conn} do
+ for opts <- [%{}, %{if_func: fn _ -> true end}, %{unless_func: fn _ -> false end}] do
+ ret_conn = ExpectPublicOrAuthenticatedCheckPlug.call(conn, opts)
+
+ refute called(ExpectPublicOrAuthenticatedCheckPlug.perform(:_, :_))
+ refute PlugHelper.plug_called?(ret_conn, ExpectPublicOrAuthenticatedCheckPlug)
+ end
+ end
+ end
+
+ describe "when plug is NOT skipped, " do
+ setup_with_mocks([{ExpectAuthenticatedCheckPlug, [:passthrough], []}]) do
+ :ok
+ end
+
+ test "with no pre-run checks, adds plug to called plugs list and calls `perform/2`", %{
+ conn: conn
+ } do
+ ret_conn = ExpectAuthenticatedCheckPlug.call(conn, %{})
+
+ assert called(ExpectAuthenticatedCheckPlug.perform(ret_conn, :_))
+ assert PlugHelper.plug_called?(ret_conn, ExpectAuthenticatedCheckPlug)
+ end
+
+ test "when :if_func option is given, calls the plug only if provided function evals tru-ish",
+ %{conn: conn} do
+ ret_conn = ExpectAuthenticatedCheckPlug.call(conn, %{if_func: fn _ -> false end})
+
+ refute called(ExpectAuthenticatedCheckPlug.perform(:_, :_))
+ refute PlugHelper.plug_called?(ret_conn, ExpectAuthenticatedCheckPlug)
+
+ ret_conn = ExpectAuthenticatedCheckPlug.call(conn, %{if_func: fn _ -> true end})
+
+ assert called(ExpectAuthenticatedCheckPlug.perform(ret_conn, :_))
+ assert PlugHelper.plug_called?(ret_conn, ExpectAuthenticatedCheckPlug)
+ end
+
+ test "if :unless_func option is given, calls the plug only if provided function evals falsy",
+ %{conn: conn} do
+ ret_conn = ExpectAuthenticatedCheckPlug.call(conn, %{unless_func: fn _ -> true end})
+
+ refute called(ExpectAuthenticatedCheckPlug.perform(:_, :_))
+ refute PlugHelper.plug_called?(ret_conn, ExpectAuthenticatedCheckPlug)
+
+ ret_conn = ExpectAuthenticatedCheckPlug.call(conn, %{unless_func: fn _ -> false end})
+
+ assert called(ExpectAuthenticatedCheckPlug.perform(ret_conn, :_))
+ assert PlugHelper.plug_called?(ret_conn, ExpectAuthenticatedCheckPlug)
+ end
+
+ test "allows a plug to be called multiple times (even if it's in called plugs list)", %{
+ conn: conn
+ } do
+ conn = ExpectAuthenticatedCheckPlug.call(conn, %{an_option: :value1})
+ assert called(ExpectAuthenticatedCheckPlug.perform(conn, %{an_option: :value1}))
+
+ assert PlugHelper.plug_called?(conn, ExpectAuthenticatedCheckPlug)
+
+ conn = ExpectAuthenticatedCheckPlug.call(conn, %{an_option: :value2})
+ assert called(ExpectAuthenticatedCheckPlug.perform(conn, %{an_option: :value2}))
+ end
+ end
+end
diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs
index 9121d90e7..b48952b29 100644
--- a/test/web/push/impl_test.exs
+++ b/test/web/push/impl_test.exs
@@ -5,16 +5,18 @@
defmodule Pleroma.Web.Push.ImplTest do
use Pleroma.DataCase
+ alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Push.Impl
alias Pleroma.Web.Push.Subscription
import Pleroma.Factory
- setup_all do
- Tesla.Mock.mock_global(fn
+ setup do
+ Tesla.Mock.mock(fn
%{method: :post, url: "https://example.com/example/1234"} ->
%Tesla.Env{status: 200}
@@ -55,20 +57,21 @@ defmodule Pleroma.Web.Push.ImplTest do
data: %{alerts: %{"follow" => true, "mention" => false}}
)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "<Lorem ipsum dolor sit amet."})
+ {:ok, activity} = CommonAPI.post(user, %{status: "<Lorem ipsum dolor sit amet."})
notif =
insert(:notification,
user: user,
- activity: activity
+ activity: activity,
+ type: "mention"
)
- assert Impl.perform(notif) == [:ok, :ok]
+ assert Impl.perform(notif) == {:ok, [:ok, :ok]}
end
@tag capture_log: true
test "returns error if notif does not match " do
- assert Impl.perform(%{}) == :error
+ assert Impl.perform(%{}) == {:error, :unknown_type}
end
test "successful message sending" do
@@ -111,7 +114,7 @@ defmodule Pleroma.Web.Push.ImplTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
})
@@ -126,7 +129,7 @@ defmodule Pleroma.Web.Push.ImplTest do
) ==
"@Bob: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini..."
- assert Impl.format_title(%{activity: activity}) ==
+ assert Impl.format_title(%{activity: activity, type: "mention"}) ==
"New Mention"
end
@@ -136,9 +139,10 @@ defmodule Pleroma.Web.Push.ImplTest do
{:ok, _, _, activity} = CommonAPI.follow(user, other_user)
object = Object.normalize(activity, false)
- assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has followed you"
+ assert Impl.format_body(%{activity: activity, type: "follow"}, user, object) ==
+ "@Bob has followed you"
- assert Impl.format_title(%{activity: activity}) ==
+ assert Impl.format_title(%{activity: activity, type: "follow"}) ==
"New Follower"
end
@@ -147,17 +151,17 @@ defmodule Pleroma.Web.Push.ImplTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
})
- {:ok, announce_activity, _} = CommonAPI.repeat(activity.id, user)
+ {:ok, announce_activity} = CommonAPI.repeat(activity.id, user)
object = Object.normalize(activity)
assert Impl.format_body(%{activity: announce_activity}, user, object) ==
"@#{user.nickname} repeated: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini..."
- assert Impl.format_title(%{activity: announce_activity}) ==
+ assert Impl.format_title(%{activity: announce_activity, type: "reblog"}) ==
"New Repeat"
end
@@ -166,16 +170,17 @@ defmodule Pleroma.Web.Push.ImplTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" =>
+ status:
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
})
{:ok, activity} = CommonAPI.favorite(user, activity.id)
object = Object.normalize(activity)
- assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post"
+ assert Impl.format_body(%{activity: activity, type: "favourite"}, user, object) ==
+ "@Bob has favorited your post"
- assert Impl.format_title(%{activity: activity}) ==
+ assert Impl.format_title(%{activity: activity, type: "favourite"}) ==
"New Favorite"
end
@@ -184,8 +189,8 @@ defmodule Pleroma.Web.Push.ImplTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "visibility" => "direct",
- "status" => "This is just between you and me, pal"
+ visibility: "direct",
+ status: "This is just between you and me, pal"
})
assert Impl.format_title(%{activity: activity}) ==
@@ -193,14 +198,54 @@ defmodule Pleroma.Web.Push.ImplTest do
end
describe "build_content/3" do
- test "returns info content for direct message with enabled privacy option" do
+ test "builds content for chat messages" do
+ user = insert(:user)
+ recipient = insert(:user)
+
+ {:ok, chat} = CommonAPI.post_chat_message(user, recipient, "hey")
+ object = Object.normalize(chat, false)
+ [notification] = Notification.for_user(recipient)
+
+ res = Impl.build_content(notification, user, object)
+
+ assert res == %{
+ body: "@#{user.nickname}: hey",
+ title: "New Chat Message"
+ }
+ end
+
+ test "builds content for chat messages with no content" do
+ user = insert(:user)
+ recipient = insert(:user)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
+
+ {:ok, chat} = CommonAPI.post_chat_message(user, recipient, nil, media_id: upload.id)
+ object = Object.normalize(chat, false)
+ [notification] = Notification.for_user(recipient)
+
+ res = Impl.build_content(notification, user, object)
+
+ assert res == %{
+ body: "@#{user.nickname}: (Attachment)",
+ title: "New Chat Message"
+ }
+ end
+
+ test "hides details for notifications when privacy option enabled" do
user = insert(:user, nickname: "Bob")
user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: true})
{:ok, activity} =
CommonAPI.post(user, %{
- "visibility" => "direct",
- "status" => "<Lorem ipsum dolor sit amet."
+ visibility: "direct",
+ status: "<Lorem ipsum dolor sit amet."
})
notif = insert(:notification, user: user2, activity: activity)
@@ -209,19 +254,44 @@ defmodule Pleroma.Web.Push.ImplTest do
object = Object.normalize(activity)
assert Impl.build_content(notif, actor, object) == %{
- body: "@Bob",
- title: "New Direct Message"
+ body: "New Direct Message"
+ }
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ visibility: "public",
+ status: "<Lorem ipsum dolor sit amet."
+ })
+
+ notif = insert(:notification, user: user2, activity: activity, type: "mention")
+
+ actor = User.get_cached_by_ap_id(notif.activity.data["actor"])
+ object = Object.normalize(activity)
+
+ assert Impl.build_content(notif, actor, object) == %{
+ body: "New Mention"
+ }
+
+ {:ok, activity} = CommonAPI.favorite(user, activity.id)
+
+ notif = insert(:notification, user: user2, activity: activity, type: "favourite")
+
+ actor = User.get_cached_by_ap_id(notif.activity.data["actor"])
+ object = Object.normalize(activity)
+
+ assert Impl.build_content(notif, actor, object) == %{
+ body: "New Favorite"
}
end
- test "returns regular content for direct message with disabled privacy option" do
+ test "returns regular content for notifications with privacy option disabled" do
user = insert(:user, nickname: "Bob")
user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: false})
{:ok, activity} =
CommonAPI.post(user, %{
- "visibility" => "direct",
- "status" =>
+ visibility: "direct",
+ status:
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
})
@@ -235,6 +305,36 @@ defmodule Pleroma.Web.Push.ImplTest do
"@Bob: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini...",
title: "New Direct Message"
}
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ visibility: "public",
+ status:
+ "<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
+ })
+
+ notif = insert(:notification, user: user2, activity: activity, type: "mention")
+
+ actor = User.get_cached_by_ap_id(notif.activity.data["actor"])
+ object = Object.normalize(activity)
+
+ assert Impl.build_content(notif, actor, object) == %{
+ body:
+ "@Bob: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini...",
+ title: "New Mention"
+ }
+
+ {:ok, activity} = CommonAPI.favorite(user, activity.id)
+
+ notif = insert(:notification, user: user2, activity: activity, type: "favourite")
+
+ actor = User.get_cached_by_ap_id(notif.activity.data["actor"])
+ object = Object.normalize(activity)
+
+ assert Impl.build_content(notif, actor, object) == %{
+ body: "@Bob has favorited your post",
+ title: "New Favorite"
+ }
end
end
end
diff --git a/test/web/rel_me_test.exs b/test/web/rel_me_test.exs
index e05a8863d..65255916d 100644
--- a/test/web/rel_me_test.exs
+++ b/test/web/rel_me_test.exs
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.RelMeTest do
- use ExUnit.Case, async: true
+ use ExUnit.Case
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
diff --git a/test/web/rich_media/helpers_test.exs b/test/web/rich_media/helpers_test.exs
index aa0c5c830..8264a9c41 100644
--- a/test/web/rich_media/helpers_test.exs
+++ b/test/web/rich_media/helpers_test.exs
@@ -26,8 +26,8 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "[test](example.com/ogp)",
- "content_type" => "text/markdown"
+ status: "[test](example.com/ogp)",
+ content_type: "text/markdown"
})
Config.put([:rich_media, :enabled], true)
@@ -40,8 +40,8 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "[test](example.com[]/ogp)",
- "content_type" => "text/markdown"
+ status: "[test](example.com[]/ogp)",
+ content_type: "text/markdown"
})
Config.put([:rich_media, :enabled], true)
@@ -54,8 +54,8 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "[test](https://example.com/ogp)",
- "content_type" => "text/markdown"
+ status: "[test](https://example.com/ogp)",
+ content_type: "text/markdown"
})
Config.put([:rich_media, :enabled], true)
@@ -69,8 +69,8 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "http://example.com/ogp",
- "sensitive" => true
+ status: "http://example.com/ogp",
+ sensitive: true
})
%Object{} = object = Object.normalize(activity)
@@ -87,7 +87,7 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do
{:ok, activity} =
CommonAPI.post(user, %{
- "status" => "http://example.com/ogp #nsfw"
+ status: "http://example.com/ogp #nsfw"
})
%Object{} = object = Object.normalize(activity)
@@ -103,12 +103,12 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do
user = insert(:user)
{:ok, activity} =
- CommonAPI.post(user, %{"status" => "http://127.0.0.1:4000/notice/9kCP7VNyPJXFOXDrgO"})
+ CommonAPI.post(user, %{status: "http://127.0.0.1:4000/notice/9kCP7VNyPJXFOXDrgO"})
- {:ok, activity2} = CommonAPI.post(user, %{"status" => "https://10.111.10.1/notice/9kCP7V"})
- {:ok, activity3} = CommonAPI.post(user, %{"status" => "https://172.16.32.40/notice/9kCP7V"})
- {:ok, activity4} = CommonAPI.post(user, %{"status" => "https://192.168.10.40/notice/9kCP7V"})
- {:ok, activity5} = CommonAPI.post(user, %{"status" => "https://pleroma.local/notice/9kCP7V"})
+ {:ok, activity2} = CommonAPI.post(user, %{status: "https://10.111.10.1/notice/9kCP7V"})
+ {:ok, activity3} = CommonAPI.post(user, %{status: "https://172.16.32.40/notice/9kCP7V"})
+ {:ok, activity4} = CommonAPI.post(user, %{status: "https://192.168.10.40/notice/9kCP7V"})
+ {:ok, activity5} = CommonAPI.post(user, %{status: "https://pleroma.local/notice/9kCP7V"})
Config.put([:rich_media, :enabled], true)
diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs
index e54a13bc8..420a612c6 100644
--- a/test/web/rich_media/parser_test.exs
+++ b/test/web/rich_media/parser_test.exs
@@ -60,19 +60,19 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
test "doesn't just add a title" do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/non-ogp") ==
{:error,
- "Found metadata was invalid or incomplete: %{url: \"http://example.com/non-ogp\"}"}
+ "Found metadata was invalid or incomplete: %{\"url\" => \"http://example.com/non-ogp\"}"}
end
test "parses ogp" do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp") ==
{:ok,
%{
- image: "http://ia.media-imdb.com/images/rock.jpg",
- title: "The Rock",
- description:
+ "image" => "http://ia.media-imdb.com/images/rock.jpg",
+ "title" => "The Rock",
+ "description" =>
"Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.",
- type: "video.movie",
- url: "http://example.com/ogp"
+ "type" => "video.movie",
+ "url" => "http://example.com/ogp"
}}
end
@@ -80,12 +80,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp-missing-title") ==
{:ok,
%{
- image: "http://ia.media-imdb.com/images/rock.jpg",
- title: "The Rock (1996)",
- description:
+ "image" => "http://ia.media-imdb.com/images/rock.jpg",
+ "title" => "The Rock (1996)",
+ "description" =>
"Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.",
- type: "video.movie",
- url: "http://example.com/ogp-missing-title"
+ "type" => "video.movie",
+ "url" => "http://example.com/ogp-missing-title"
}}
end
@@ -93,12 +93,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/twitter-card") ==
{:ok,
%{
- card: "summary",
- site: "@flickr",
- image: "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg",
- title: "Small Island Developing States Photo Submission",
- description: "View the album on Flickr.",
- url: "http://example.com/twitter-card"
+ "card" => "summary",
+ "site" => "@flickr",
+ "image" => "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg",
+ "title" => "Small Island Developing States Photo Submission",
+ "description" => "View the album on Flickr.",
+ "url" => "http://example.com/twitter-card"
}}
end
@@ -106,27 +106,28 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/oembed") ==
{:ok,
%{
- author_name: "‮‭‬bees‬",
- author_url: "https://www.flickr.com/photos/bees/",
- cache_age: 3600,
- flickr_type: "photo",
- height: "768",
- html:
+ "author_name" => "‮‭‬bees‬",
+ "author_url" => "https://www.flickr.com/photos/bees/",
+ "cache_age" => 3600,
+ "flickr_type" => "photo",
+ "height" => "768",
+ "html" =>
"<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/bees/2362225867/\" title=\"Bacon Lollys by ‮‭‬bees‬, on Flickr\"><img src=\"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"></a><script async src=\"https://embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>",
- license: "All Rights Reserved",
- license_id: 0,
- provider_name: "Flickr",
- provider_url: "https://www.flickr.com/",
- thumbnail_height: 150,
- thumbnail_url: "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg",
- thumbnail_width: 150,
- title: "Bacon Lollys",
- type: "photo",
- url: "http://example.com/oembed",
- version: "1.0",
- web_page: "https://www.flickr.com/photos/bees/2362225867/",
- web_page_short_url: "https://flic.kr/p/4AK2sc",
- width: "1024"
+ "license" => "All Rights Reserved",
+ "license_id" => 0,
+ "provider_name" => "Flickr",
+ "provider_url" => "https://www.flickr.com/",
+ "thumbnail_height" => 150,
+ "thumbnail_url" =>
+ "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg",
+ "thumbnail_width" => 150,
+ "title" => "Bacon Lollys",
+ "type" => "photo",
+ "url" => "http://example.com/oembed",
+ "version" => "1.0",
+ "web_page" => "https://www.flickr.com/photos/bees/2362225867/",
+ "web_page_short_url" => "https://flic.kr/p/4AK2sc",
+ "width" => "1024"
}}
end
diff --git a/test/web/rich_media/parsers/twitter_card_test.exs b/test/web/rich_media/parsers/twitter_card_test.exs
index 87c767c15..219f005a2 100644
--- a/test/web/rich_media/parsers/twitter_card_test.exs
+++ b/test/web/rich_media/parsers/twitter_card_test.exs
@@ -7,8 +7,7 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
alias Pleroma.Web.RichMedia.Parsers.TwitterCard
test "returns error when html not contains twitter card" do
- assert TwitterCard.parse([{"html", [], [{"head", [], []}, {"body", [], []}]}], %{}) ==
- {:error, "No twitter card metadata found"}
+ assert TwitterCard.parse([{"html", [], [{"head", [], []}, {"body", [], []}]}], %{}) == %{}
end
test "parses twitter card with only name attributes" do
@@ -17,15 +16,21 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
|> Floki.parse_document!()
assert TwitterCard.parse(html, %{}) ==
- {:ok,
- %{
- "app:id:googleplay": "com.nytimes.android",
- "app:name:googleplay": "NYTimes",
- "app:url:googleplay": "nytimes://reader/id/100000006583622",
- site: nil,
- title:
- "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database. - The New York Times"
- }}
+ %{
+ "app:id:googleplay" => "com.nytimes.android",
+ "app:name:googleplay" => "NYTimes",
+ "app:url:googleplay" => "nytimes://reader/id/100000006583622",
+ "site" => nil,
+ "description" =>
+ "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
+ "image" =>
+ "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-facebookJumbo.jpg",
+ "type" => "article",
+ "url" =>
+ "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html",
+ "title" =>
+ "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database."
+ }
end
test "parses twitter card with only property attributes" do
@@ -34,19 +39,19 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
|> Floki.parse_document!()
assert TwitterCard.parse(html, %{}) ==
- {:ok,
- %{
- card: "summary_large_image",
- description:
- "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
- image:
- "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg",
- "image:alt": "",
- title:
- "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.",
- url:
- "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html"
- }}
+ %{
+ "card" => "summary_large_image",
+ "description" =>
+ "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
+ "image" =>
+ "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg",
+ "image:alt" => "",
+ "title" =>
+ "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.",
+ "url" =>
+ "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html",
+ "type" => "article"
+ }
end
test "parses twitter card with name & property attributes" do
@@ -55,23 +60,23 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
|> Floki.parse_document!()
assert TwitterCard.parse(html, %{}) ==
- {:ok,
- %{
- "app:id:googleplay": "com.nytimes.android",
- "app:name:googleplay": "NYTimes",
- "app:url:googleplay": "nytimes://reader/id/100000006583622",
- card: "summary_large_image",
- description:
- "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
- image:
- "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg",
- "image:alt": "",
- site: nil,
- title:
- "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.",
- url:
- "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html"
- }}
+ %{
+ "app:id:googleplay" => "com.nytimes.android",
+ "app:name:googleplay" => "NYTimes",
+ "app:url:googleplay" => "nytimes://reader/id/100000006583622",
+ "card" => "summary_large_image",
+ "description" =>
+ "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
+ "image" =>
+ "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg",
+ "image:alt" => "",
+ "site" => nil,
+ "title" =>
+ "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.",
+ "url" =>
+ "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html",
+ "type" => "article"
+ }
end
test "respect only first title tag on the page" do
@@ -84,14 +89,17 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
File.read!("test/fixtures/margaret-corbin-grave-west-point.html") |> Floki.parse_document!()
assert TwitterCard.parse(html, %{}) ==
- {:ok,
- %{
- site: "@atlasobscura",
- title:
- "The Missing Grave of Margaret Corbin, Revolutionary War Veteran - Atlas Obscura",
- card: "summary_large_image",
- image: image_path
- }}
+ %{
+ "site" => "@atlasobscura",
+ "title" => "The Missing Grave of Margaret Corbin, Revolutionary War Veteran",
+ "card" => "summary_large_image",
+ "image" => image_path,
+ "description" =>
+ "She's the only woman veteran honored with a monument at West Point. But where was she buried?",
+ "site_name" => "Atlas Obscura",
+ "type" => "article",
+ "url" => "http://www.atlasobscura.com/articles/margaret-corbin-grave-west-point"
+ }
end
test "takes first founded title in html head if there is html markup error" do
@@ -100,14 +108,20 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
|> Floki.parse_document!()
assert TwitterCard.parse(html, %{}) ==
- {:ok,
- %{
- site: nil,
- title:
- "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database. - The New York Times",
- "app:id:googleplay": "com.nytimes.android",
- "app:name:googleplay": "NYTimes",
- "app:url:googleplay": "nytimes://reader/id/100000006583622"
- }}
+ %{
+ "site" => nil,
+ "title" =>
+ "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.",
+ "app:id:googleplay" => "com.nytimes.android",
+ "app:name:googleplay" => "NYTimes",
+ "app:url:googleplay" => "nytimes://reader/id/100000006583622",
+ "description" =>
+ "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.",
+ "image" =>
+ "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-facebookJumbo.jpg",
+ "type" => "article",
+ "url" =>
+ "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html"
+ }
end
end
diff --git a/test/web/static_fe/static_fe_controller_test.exs b/test/web/static_fe/static_fe_controller_test.exs
index 430683ea0..a49ab002f 100644
--- a/test/web/static_fe/static_fe_controller_test.exs
+++ b/test/web/static_fe/static_fe_controller_test.exs
@@ -32,8 +32,8 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
end
test "profile does not include private messages", %{conn: conn, user: user} do
- CommonAPI.post(user, %{"status" => "public"})
- CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
+ CommonAPI.post(user, %{status: "public"})
+ CommonAPI.post(user, %{status: "private", visibility: "private"})
conn = get(conn, "/users/#{user.nickname}")
@@ -44,7 +44,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
end
test "pagination", %{conn: conn, user: user} do
- Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
+ Enum.map(1..30, fn i -> CommonAPI.post(user, %{status: "test#{i}"}) end)
conn = get(conn, "/users/#{user.nickname}")
@@ -57,7 +57,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
end
test "pagination, page 2", %{conn: conn, user: user} do
- activities = Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
+ activities = Enum.map(1..30, fn i -> CommonAPI.post(user, %{status: "test#{i}"}) end)
{:ok, a11} = Enum.at(activities, 11)
conn = get(conn, "/users/#{user.nickname}?max_id=#{a11.id}")
@@ -77,7 +77,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
describe "notice html" do
test "single notice page", %{conn: conn, user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "testing a thing!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"})
conn = get(conn, "/notice/#{activity.id}")
@@ -89,7 +89,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
test "filters HTML tags", %{conn: conn} do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "<script>alert('xss')</script>"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "<script>alert('xss')</script>"})
conn =
conn
@@ -101,11 +101,11 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
end
test "shows the whole thread", %{conn: conn, user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "space: the final frontier"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "space: the final frontier"})
CommonAPI.post(user, %{
- "status" => "these are the voyages or something",
- "in_reply_to_status_id" => activity.id
+ status: "these are the voyages or something",
+ in_reply_to_status_id: activity.id
})
conn = get(conn, "/notice/#{activity.id}")
@@ -117,7 +117,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
test "redirect by AP object ID", %{conn: conn, user: user} do
{:ok, %Activity{data: %{"object" => object_url}}} =
- CommonAPI.post(user, %{"status" => "beam me up"})
+ CommonAPI.post(user, %{status: "beam me up"})
conn = get(conn, URI.parse(object_url).path)
@@ -126,7 +126,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
test "redirect by activity ID", %{conn: conn, user: user} do
{:ok, %Activity{data: %{"id" => id}}} =
- CommonAPI.post(user, %{"status" => "I'm a doctor, not a devops!"})
+ CommonAPI.post(user, %{status: "I'm a doctor, not a devops!"})
conn = get(conn, URI.parse(id).path)
@@ -140,8 +140,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
end
test "404 for private status", %{conn: conn, user: user} do
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "don't show me!", "visibility" => "private"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "don't show me!", visibility: "private"})
conn = get(conn, "/notice/#{activity.id}")
@@ -171,7 +170,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
end
test "it requires authentication if instance is NOT federating", %{conn: conn, user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "testing a thing!"})
+ {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"})
ensure_federating_or_authenticated(conn, "/notice/#{activity.id}", user)
end
diff --git a/test/web/streamer/ping_test.exs b/test/web/streamer/ping_test.exs
deleted file mode 100644
index 5df6c1cc3..000000000
--- a/test/web/streamer/ping_test.exs
+++ /dev/null
@@ -1,36 +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.PingTest do
- use Pleroma.DataCase
-
- import Pleroma.Factory
- alias Pleroma.Web.Streamer
-
- setup do
- start_supervised({Streamer.supervisor(), [ping_interval: 30]})
-
- :ok
- end
-
- describe "sockets" do
- setup do
- user = insert(:user)
- {:ok, %{user: user}}
- end
-
- test "it sends pings", %{user: user} do
- task =
- Task.async(fn ->
- assert_receive {:text, received_event}, 40
- assert_receive {:text, received_event}, 40
- assert_receive {:text, received_event}, 40
- end)
-
- Streamer.add_socket("public", %{transport_pid: task.pid, assigns: %{user: user}})
-
- Task.await(task)
- end
- end
-end
diff --git a/test/web/streamer/state_test.exs b/test/web/streamer/state_test.exs
deleted file mode 100644
index a755e75c0..000000000
--- a/test/web/streamer/state_test.exs
+++ /dev/null
@@ -1,54 +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.StateTest do
- use Pleroma.DataCase
-
- import Pleroma.Factory
- alias Pleroma.Web.Streamer
- alias Pleroma.Web.Streamer.StreamerSocket
-
- @moduletag needs_streamer: true
-
- describe "sockets" do
- setup do
- user = insert(:user)
- user2 = insert(:user)
- {:ok, %{user: user, user2: user2}}
- end
-
- test "it can add a socket", %{user: user} do
- Streamer.add_socket("public", %{transport_pid: 1, assigns: %{user: user}})
-
- assert(%{"public" => [%StreamerSocket{transport_pid: 1}]} = Streamer.get_sockets())
- end
-
- test "it can add multiple sockets per user", %{user: user} do
- Streamer.add_socket("public", %{transport_pid: 1, assigns: %{user: user}})
- Streamer.add_socket("public", %{transport_pid: 2, assigns: %{user: user}})
-
- assert(
- %{
- "public" => [
- %StreamerSocket{transport_pid: 2},
- %StreamerSocket{transport_pid: 1}
- ]
- } = Streamer.get_sockets()
- )
- end
-
- test "it will not add a duplicate socket", %{user: user} do
- Streamer.add_socket("activity", %{transport_pid: 1, assigns: %{user: user}})
- Streamer.add_socket("activity", %{transport_pid: 1, assigns: %{user: user}})
-
- assert(
- %{
- "activity" => [
- %StreamerSocket{transport_pid: 1}
- ]
- } = Streamer.get_sockets()
- )
- end
- end
-end
diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs
index eb082b79f..245f6e63f 100644
--- a/test/web/streamer/streamer_test.exs
+++ b/test/web/streamer/streamer_test.exs
@@ -7,20 +7,90 @@ defmodule Pleroma.Web.StreamerTest do
import Pleroma.Factory
+ alias Pleroma.Chat
+ alias Pleroma.Chat.MessageReference
alias Pleroma.Conversation.Participation
alias Pleroma.List
+ alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Streamer
- alias Pleroma.Web.Streamer.StreamerSocket
- alias Pleroma.Web.Streamer.Worker
+ alias Pleroma.Web.StreamerView
@moduletag needs_streamer: true, capture_log: true
- @streamer_timeout 150
- @streamer_start_wait 10
setup do: clear_config([:instance, :skip_thread_containment])
+ describe "get_topic without an user" do
+ test "allows public" do
+ assert {:ok, "public"} = Streamer.get_topic("public", nil)
+ assert {:ok, "public:local"} = Streamer.get_topic("public:local", nil)
+ assert {:ok, "public:media"} = Streamer.get_topic("public:media", nil)
+ assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil)
+ end
+
+ test "allows hashtag streams" do
+ assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", nil, %{"tag" => "cofe"})
+ end
+
+ test "disallows user streams" do
+ assert {:error, _} = Streamer.get_topic("user", nil)
+ assert {:error, _} = Streamer.get_topic("user:notification", nil)
+ assert {:error, _} = Streamer.get_topic("direct", nil)
+ end
+
+ test "disallows list streams" do
+ assert {:error, _} = Streamer.get_topic("list", nil, %{"list" => 42})
+ end
+ end
+
+ describe "get_topic with an user" do
+ setup do
+ user = insert(:user)
+ {:ok, %{user: user}}
+ end
+
+ test "allows public streams", %{user: user} do
+ assert {:ok, "public"} = Streamer.get_topic("public", user)
+ assert {:ok, "public:local"} = Streamer.get_topic("public:local", user)
+ assert {:ok, "public:media"} = Streamer.get_topic("public:media", user)
+ assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", user)
+ end
+
+ test "allows user streams", %{user: user} do
+ expected_user_topic = "user:#{user.id}"
+ expected_notif_topic = "user:notification:#{user.id}"
+ expected_direct_topic = "direct:#{user.id}"
+ assert {:ok, ^expected_user_topic} = Streamer.get_topic("user", user)
+ assert {:ok, ^expected_notif_topic} = Streamer.get_topic("user:notification", user)
+ assert {:ok, ^expected_direct_topic} = Streamer.get_topic("direct", user)
+ end
+
+ test "allows hashtag streams", %{user: user} do
+ assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", user, %{"tag" => "cofe"})
+ end
+
+ test "disallows registering to an user stream", %{user: user} do
+ another_user = insert(:user)
+ assert {:error, _} = Streamer.get_topic("user:#{another_user.id}", user)
+ assert {:error, _} = Streamer.get_topic("user:notification:#{another_user.id}", user)
+ assert {:error, _} = Streamer.get_topic("direct:#{another_user.id}", user)
+ end
+
+ test "allows list stream that are owned by the user", %{user: user} do
+ {:ok, list} = List.create("Test", user)
+ assert {:error, _} = Streamer.get_topic("list:#{list.id}", user)
+ assert {:ok, _} = Streamer.get_topic("list", user, %{"list" => list.id})
+ end
+
+ test "disallows list stream that are not owned by the user", %{user: user} do
+ another_user = insert(:user)
+ {:ok, list} = List.create("Test", another_user)
+ assert {:error, _} = Streamer.get_topic("list:#{list.id}", user)
+ assert {:error, _} = Streamer.get_topic("list", user, %{"list" => list.id})
+ end
+ end
+
describe "user streams" do
setup do
user = insert(:user)
@@ -28,34 +98,106 @@ defmodule Pleroma.Web.StreamerTest do
{:ok, %{user: user, notify: notify}}
end
- test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do
- task =
- Task.async(fn ->
- assert_receive {:text, _}, @streamer_timeout
- end)
+ test "it streams the user's post in the 'user' stream", %{user: user} do
+ Streamer.get_topic_and_add_socket("user", user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
+ assert_receive {:render_with_user, _, _, ^activity}
+ refute Streamer.filtered_by_user?(user, activity)
+ end
+
+ test "it streams boosts of the user in the 'user' stream", %{user: user} do
+ Streamer.get_topic_and_add_socket("user", user)
+
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
+ {:ok, announce} = CommonAPI.repeat(activity.id, user)
+
+ assert_receive {:render_with_user, Pleroma.Web.StreamerView, "update.json", ^announce}
+ refute Streamer.filtered_by_user?(user, announce)
+ end
+
+ test "it streams boosts of mastodon user in the 'user' stream", %{user: user} do
+ Streamer.get_topic_and_add_socket("user", user)
+
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
- Streamer.add_socket(
- "user",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
+ data =
+ File.read!("test/fixtures/mastodon-announce.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+ |> Map.put("actor", user.ap_id)
+ {:ok, %Pleroma.Activity{data: _data, local: false} = announce} =
+ Pleroma.Web.ActivityPub.Transmogrifier.handle_incoming(data)
+
+ assert_receive {:render_with_user, Pleroma.Web.StreamerView, "update.json", ^announce}
+ refute Streamer.filtered_by_user?(user, announce)
+ end
+
+ test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do
+ Streamer.get_topic_and_add_socket("user", user)
Streamer.stream("user", notify)
- Task.await(task)
+ assert_receive {:render_with_user, _, _, ^notify}
+ refute Streamer.filtered_by_user?(user, notify)
end
test "it sends notify to in the 'user:notification' stream", %{user: user, notify: notify} do
- task =
- Task.async(fn ->
- assert_receive {:text, _}, @streamer_timeout
- end)
+ Streamer.get_topic_and_add_socket("user:notification", user)
+ Streamer.stream("user:notification", notify)
+ assert_receive {:render_with_user, _, _, ^notify}
+ refute Streamer.filtered_by_user?(user, notify)
+ end
+
+ test "it sends chat messages to the 'user:pleroma_chat' stream", %{user: user} do
+ other_user = insert(:user)
+
+ {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno")
+ object = Object.normalize(create_activity, false)
+ chat = Chat.get(user.id, other_user.ap_id)
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+ cm_ref = %{cm_ref | chat: chat, object: object}
+
+ Streamer.get_topic_and_add_socket("user:pleroma_chat", user)
+ Streamer.stream("user:pleroma_chat", {user, cm_ref})
+
+ text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref})
+
+ assert text =~ "hey cirno"
+ assert_receive {:text, ^text}
+ end
+
+ test "it sends chat messages to the 'user' stream", %{user: user} do
+ other_user = insert(:user)
+
+ {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno")
+ object = Object.normalize(create_activity, false)
+ chat = Chat.get(user.id, other_user.ap_id)
+ cm_ref = MessageReference.for_chat_and_object(chat, object)
+ cm_ref = %{cm_ref | chat: chat, object: object}
+
+ Streamer.get_topic_and_add_socket("user", user)
+ Streamer.stream("user", {user, cm_ref})
+
+ text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref})
+
+ assert text =~ "hey cirno"
+ assert_receive {:text, ^text}
+ end
- Streamer.add_socket(
- "user:notification",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
+ test "it sends chat message notifications to the 'user:notification' stream", %{user: user} do
+ other_user = insert(:user)
+ {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey")
+
+ notify =
+ Repo.get_by(Pleroma.Notification, user_id: user.id, activity_id: create_activity.id)
+ |> Repo.preload(:activity)
+
+ Streamer.get_topic_and_add_socket("user:notification", user)
Streamer.stream("user:notification", notify)
- Task.await(task)
+ assert_receive {:render_with_user, _, _, ^notify}
+ refute Streamer.filtered_by_user?(user, notify)
end
test "it doesn't send notify to the 'user:notification' stream when a user is blocked", %{
@@ -64,18 +206,12 @@ defmodule Pleroma.Web.StreamerTest do
blocked = insert(:user)
{:ok, _user_relationship} = User.block(user, blocked)
- task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
-
- Streamer.add_socket(
- "user:notification",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
+ Streamer.get_topic_and_add_socket("user:notification", user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => ":("})
- {:ok, notif} = CommonAPI.favorite(blocked, activity.id)
+ {:ok, activity} = CommonAPI.post(user, %{status: ":("})
+ {:ok, _} = CommonAPI.favorite(blocked, activity.id)
- Streamer.stream("user:notification", notif)
- Task.await(task)
+ refute_receive _
end
test "it doesn't send notify to the 'user:notification' stream when a thread is muted", %{
@@ -83,45 +219,50 @@ defmodule Pleroma.Web.StreamerTest do
} do
user2 = insert(:user)
- task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
+ {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"})
+ {:ok, _} = CommonAPI.add_mute(user, activity)
- Streamer.add_socket(
- "user:notification",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
+ Streamer.get_topic_and_add_socket("user:notification", user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
- {:ok, activity} = CommonAPI.add_mute(user, activity)
- {:ok, notif} = CommonAPI.favorite(user2, activity.id)
+ {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id)
- Streamer.stream("user:notification", notif)
- Task.await(task)
+ refute_receive _
+ assert Streamer.filtered_by_user?(user, favorite_activity)
end
- test "it doesn't send notify to the 'user:notification' stream' when a domain is blocked", %{
+ test "it sends favorite to 'user:notification' stream'", %{
user: user
} do
user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})
- task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
+ {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"})
+ Streamer.get_topic_and_add_socket("user:notification", user)
+ {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id)
- Streamer.add_socket(
- "user:notification",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
+ assert_receive {:render_with_user, _, "notification.json", notif}
+ assert notif.activity.id == favorite_activity.id
+ refute Streamer.filtered_by_user?(user, notif)
+ end
+
+ test "it doesn't send the 'user:notification' stream' when a domain is blocked", %{
+ user: user
+ } do
+ user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})
{:ok, user} = User.block_domain(user, "hecking-lewd-place.com")
- {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
- {:ok, notif} = CommonAPI.favorite(user2, activity.id)
+ {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"})
+ Streamer.get_topic_and_add_socket("user:notification", user)
+ {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id)
- Streamer.stream("user:notification", notif)
- Task.await(task)
+ refute_receive _
+ assert Streamer.filtered_by_user?(user, favorite_activity)
end
test "it sends follow activities to the 'user:notification' stream", %{
user: user
} do
user_url = user.ap_id
+ user2 = insert(:user)
body =
File.read!("test/fixtures/users_mock/localhost.json")
@@ -133,79 +274,57 @@ defmodule Pleroma.Web.StreamerTest do
%Tesla.Env{status: 200, body: body}
end)
- user2 = insert(:user)
- task = Task.async(fn -> assert_receive {:text, _}, @streamer_timeout end)
-
- Process.sleep(@streamer_start_wait)
-
- Streamer.add_socket(
- "user:notification",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
-
- {:ok, _follower, _followed, _activity} = CommonAPI.follow(user2, user)
+ Streamer.get_topic_and_add_socket("user:notification", user)
+ {:ok, _follower, _followed, follow_activity} = CommonAPI.follow(user2, user)
- # We don't directly pipe the notification to the streamer as it's already
- # generated as a side effect of CommonAPI.follow().
- Task.await(task)
+ assert_receive {:render_with_user, _, "notification.json", notif}
+ assert notif.activity.id == follow_activity.id
+ refute Streamer.filtered_by_user?(user, notif)
end
end
- test "it sends to public" do
+ test "it sends to public authenticated" do
user = insert(:user)
other_user = insert(:user)
- task =
- Task.async(fn ->
- assert_receive {:text, _}, @streamer_timeout
- end)
-
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user
- }
-
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "Test"})
+ Streamer.get_topic_and_add_socket("public", other_user)
- topics = %{
- "public" => [fake_socket]
- }
-
- Worker.push_to_socket(topics, "public", activity)
+ {:ok, activity} = CommonAPI.post(user, %{status: "Test"})
+ assert_receive {:render_with_user, _, _, ^activity}
+ refute Streamer.filtered_by_user?(user, activity)
+ end
- Task.await(task)
+ test "works for deletions" do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"})
- task =
- Task.async(fn ->
- expected_event =
- %{
- "event" => "delete",
- "payload" => activity.id
- }
- |> Jason.encode!()
+ Streamer.get_topic_and_add_socket("public", user)
- assert_receive {:text, received_event}, @streamer_timeout
- assert received_event == expected_event
- end)
-
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user
- }
+ {:ok, _} = CommonAPI.delete(activity.id, other_user)
+ activity_id = activity.id
+ assert_receive {:text, event}
+ assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event)
+ end
- {:ok, activity} = CommonAPI.delete(activity.id, other_user)
+ test "it sends to public unauthenticated" do
+ user = insert(:user)
- topics = %{
- "public" => [fake_socket]
- }
+ Streamer.get_topic_and_add_socket("public", nil)
- Worker.push_to_socket(topics, "public", activity)
+ {:ok, activity} = CommonAPI.post(user, %{status: "Test"})
+ activity_id = activity.id
+ assert_receive {:text, event}
+ assert %{"event" => "update", "payload" => payload} = Jason.decode!(event)
+ assert %{"id" => ^activity_id} = Jason.decode!(payload)
- Task.await(task)
+ {:ok, _} = CommonAPI.delete(activity.id, user)
+ assert_receive {:text, event}
+ assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event)
end
describe "thread_containment" do
- test "it doesn't send to user if recipients invalid and thread containment is enabled" do
+ test "it filters to user if recipients invalid and thread containment is enabled" do
Pleroma.Config.put([:instance, :skip_thread_containment], false)
author = insert(:user)
user = insert(:user)
@@ -220,12 +339,10 @@ defmodule Pleroma.Web.StreamerTest do
)
)
- task = Task.async(fn -> refute_receive {:text, _}, 1_000 end)
- fake_socket = %StreamerSocket{transport_pid: task.pid, user: user}
- topics = %{"public" => [fake_socket]}
- Worker.push_to_socket(topics, "public", activity)
-
- Task.await(task)
+ Streamer.get_topic_and_add_socket("public", user)
+ Streamer.stream("public", activity)
+ assert_receive {:render_with_user, _, _, ^activity}
+ assert Streamer.filtered_by_user?(user, activity)
end
test "it sends message if recipients invalid and thread containment is disabled" do
@@ -243,12 +360,11 @@ defmodule Pleroma.Web.StreamerTest do
)
)
- task = Task.async(fn -> assert_receive {:text, _}, 1_000 end)
- fake_socket = %StreamerSocket{transport_pid: task.pid, user: user}
- topics = %{"public" => [fake_socket]}
- Worker.push_to_socket(topics, "public", activity)
+ Streamer.get_topic_and_add_socket("public", user)
+ Streamer.stream("public", activity)
- Task.await(task)
+ assert_receive {:render_with_user, _, _, ^activity}
+ refute Streamer.filtered_by_user?(user, activity)
end
test "it sends message if recipients invalid and thread containment is enabled but user's thread containment is disabled" do
@@ -266,255 +382,168 @@ defmodule Pleroma.Web.StreamerTest do
)
)
- task = Task.async(fn -> assert_receive {:text, _}, 1_000 end)
- fake_socket = %StreamerSocket{transport_pid: task.pid, user: user}
- topics = %{"public" => [fake_socket]}
- Worker.push_to_socket(topics, "public", activity)
+ Streamer.get_topic_and_add_socket("public", user)
+ Streamer.stream("public", activity)
- Task.await(task)
+ assert_receive {:render_with_user, _, _, ^activity}
+ refute Streamer.filtered_by_user?(user, activity)
end
end
describe "blocks" do
- test "it doesn't send messages involving blocked users" do
+ test "it filters messages involving blocked users" do
user = insert(:user)
blocked_user = insert(:user)
{:ok, _user_relationship} = User.block(user, blocked_user)
- {:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"})
-
- task =
- Task.async(fn ->
- refute_receive {:text, _}, 1_000
- end)
-
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user
- }
-
- topics = %{
- "public" => [fake_socket]
- }
-
- Worker.push_to_socket(topics, "public", activity)
-
- Task.await(task)
+ Streamer.get_topic_and_add_socket("public", user)
+ {:ok, activity} = CommonAPI.post(blocked_user, %{status: "Test"})
+ assert_receive {:render_with_user, _, _, ^activity}
+ assert Streamer.filtered_by_user?(user, activity)
end
- test "it doesn't send messages transitively involving blocked users" do
+ test "it filters messages transitively involving blocked users" do
blocker = insert(:user)
blockee = insert(:user)
friend = insert(:user)
- task =
- Task.async(fn ->
- refute_receive {:text, _}, 1_000
- end)
-
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: blocker
- }
-
- topics = %{
- "public" => [fake_socket]
- }
+ Streamer.get_topic_and_add_socket("public", blocker)
{:ok, _user_relationship} = User.block(blocker, blockee)
- {:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey! @#{blockee.nickname}"})
-
- Worker.push_to_socket(topics, "public", activity_one)
+ {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey! @#{blockee.nickname}"})
- {:ok, activity_two} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
+ assert_receive {:render_with_user, _, _, ^activity_one}
+ assert Streamer.filtered_by_user?(blocker, activity_one)
- Worker.push_to_socket(topics, "public", activity_two)
+ {:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
- {:ok, activity_three} = CommonAPI.post(blockee, %{"status" => "hey! @#{blocker.nickname}"})
+ assert_receive {:render_with_user, _, _, ^activity_two}
+ assert Streamer.filtered_by_user?(blocker, activity_two)
- Worker.push_to_socket(topics, "public", activity_three)
+ {:ok, activity_three} = CommonAPI.post(blockee, %{status: "hey! @#{blocker.nickname}"})
- Task.await(task)
+ assert_receive {:render_with_user, _, _, ^activity_three}
+ assert Streamer.filtered_by_user?(blocker, activity_three)
end
end
- test "it doesn't send unwanted DMs to list" do
- user_a = insert(:user)
- user_b = insert(:user)
- user_c = insert(:user)
+ describe "lists" do
+ test "it doesn't send unwanted DMs to list" do
+ user_a = insert(:user)
+ user_b = insert(:user)
+ user_c = insert(:user)
- {:ok, user_a} = User.follow(user_a, user_b)
+ {:ok, user_a} = User.follow(user_a, user_b)
- {:ok, list} = List.create("Test", user_a)
- {:ok, list} = List.follow(list, user_b)
+ {:ok, list} = List.create("Test", user_a)
+ {:ok, list} = List.follow(list, user_b)
- {:ok, activity} =
- CommonAPI.post(user_b, %{
- "status" => "@#{user_c.nickname} Test",
- "visibility" => "direct"
- })
+ Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id})
- task =
- Task.async(fn ->
- refute_receive {:text, _}, 1_000
- end)
-
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user_a
- }
-
- topics = %{
- "list:#{list.id}" => [fake_socket]
- }
-
- Worker.handle_call({:stream, "list", activity}, self(), topics)
-
- Task.await(task)
- end
-
- test "it doesn't send unwanted private posts to list" do
- user_a = insert(:user)
- user_b = insert(:user)
-
- {:ok, list} = List.create("Test", user_a)
- {:ok, list} = List.follow(list, user_b)
-
- {:ok, activity} =
- CommonAPI.post(user_b, %{
- "status" => "Test",
- "visibility" => "private"
- })
-
- task =
- Task.async(fn ->
- refute_receive {:text, _}, 1_000
- end)
-
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user_a
- }
+ {:ok, _activity} =
+ CommonAPI.post(user_b, %{
+ status: "@#{user_c.nickname} Test",
+ visibility: "direct"
+ })
- topics = %{
- "list:#{list.id}" => [fake_socket]
- }
+ refute_receive _
+ end
- Worker.handle_call({:stream, "list", activity}, self(), topics)
+ test "it doesn't send unwanted private posts to list" do
+ user_a = insert(:user)
+ user_b = insert(:user)
- Task.await(task)
- end
+ {:ok, list} = List.create("Test", user_a)
+ {:ok, list} = List.follow(list, user_b)
- test "it sends wanted private posts to list" do
- user_a = insert(:user)
- user_b = insert(:user)
+ Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id})
- {:ok, user_a} = User.follow(user_a, user_b)
+ {:ok, _activity} =
+ CommonAPI.post(user_b, %{
+ status: "Test",
+ visibility: "private"
+ })
- {:ok, list} = List.create("Test", user_a)
- {:ok, list} = List.follow(list, user_b)
+ refute_receive _
+ end
- {:ok, activity} =
- CommonAPI.post(user_b, %{
- "status" => "Test",
- "visibility" => "private"
- })
+ test "it sends wanted private posts to list" do
+ user_a = insert(:user)
+ user_b = insert(:user)
- task =
- Task.async(fn ->
- assert_receive {:text, _}, 1_000
- end)
+ {:ok, user_a} = User.follow(user_a, user_b)
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user_a
- }
+ {:ok, list} = List.create("Test", user_a)
+ {:ok, list} = List.follow(list, user_b)
- Streamer.add_socket(
- "list:#{list.id}",
- fake_socket
- )
+ Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id})
- Worker.handle_call({:stream, "list", activity}, self(), %{})
+ {:ok, activity} =
+ CommonAPI.post(user_b, %{
+ status: "Test",
+ visibility: "private"
+ })
- Task.await(task)
+ assert_receive {:render_with_user, _, _, ^activity}
+ refute Streamer.filtered_by_user?(user_a, activity)
+ end
end
- test "it doesn't send muted reblogs" do
- user1 = insert(:user)
- user2 = insert(:user)
- user3 = insert(:user)
- CommonAPI.hide_reblogs(user1, user2)
-
- {:ok, create_activity} = CommonAPI.post(user3, %{"status" => "I'm kawen"})
- {:ok, announce_activity, _} = CommonAPI.repeat(create_activity.id, user2)
-
- task =
- Task.async(fn ->
- refute_receive {:text, _}, 1_000
- end)
-
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user1
- }
-
- topics = %{
- "public" => [fake_socket]
- }
-
- Worker.push_to_socket(topics, "public", announce_activity)
+ describe "muted reblogs" do
+ test "it filters muted reblogs" do
+ user1 = insert(:user)
+ user2 = insert(:user)
+ user3 = insert(:user)
+ CommonAPI.follow(user1, user2)
+ CommonAPI.hide_reblogs(user1, user2)
- Task.await(task)
- end
+ {:ok, create_activity} = CommonAPI.post(user3, %{status: "I'm kawen"})
- test "it does send non-reblog notification for reblog-muted actors" do
- user1 = insert(:user)
- user2 = insert(:user)
- user3 = insert(:user)
- CommonAPI.hide_reblogs(user1, user2)
+ Streamer.get_topic_and_add_socket("user", user1)
+ {:ok, announce_activity} = CommonAPI.repeat(create_activity.id, user2)
+ assert_receive {:render_with_user, _, _, ^announce_activity}
+ assert Streamer.filtered_by_user?(user1, announce_activity)
+ end
- {:ok, create_activity} = CommonAPI.post(user3, %{"status" => "I'm kawen"})
- {:ok, favorite_activity} = CommonAPI.favorite(user2, create_activity.id)
+ test "it filters reblog notification for reblog-muted actors" do
+ user1 = insert(:user)
+ user2 = insert(:user)
+ CommonAPI.follow(user1, user2)
+ CommonAPI.hide_reblogs(user1, user2)
- task =
- Task.async(fn ->
- assert_receive {:text, _}, 1_000
- end)
+ {:ok, create_activity} = CommonAPI.post(user1, %{status: "I'm kawen"})
+ Streamer.get_topic_and_add_socket("user", user1)
+ {:ok, _announce_activity} = CommonAPI.repeat(create_activity.id, user2)
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user1
- }
+ assert_receive {:render_with_user, _, "notification.json", notif}
+ assert Streamer.filtered_by_user?(user1, notif)
+ end
- topics = %{
- "public" => [fake_socket]
- }
+ test "it send non-reblog notification for reblog-muted actors" do
+ user1 = insert(:user)
+ user2 = insert(:user)
+ CommonAPI.follow(user1, user2)
+ CommonAPI.hide_reblogs(user1, user2)
- Worker.push_to_socket(topics, "public", favorite_activity)
+ {:ok, create_activity} = CommonAPI.post(user1, %{status: "I'm kawen"})
+ Streamer.get_topic_and_add_socket("user", user1)
+ {:ok, _favorite_activity} = CommonAPI.favorite(user2, create_activity.id)
- Task.await(task)
+ assert_receive {:render_with_user, _, "notification.json", notif}
+ refute Streamer.filtered_by_user?(user1, notif)
+ end
end
- test "it doesn't send posts from muted threads" do
+ test "it filters posts from muted threads" do
user = insert(:user)
user2 = insert(:user)
+ Streamer.get_topic_and_add_socket("user", user2)
{:ok, user2, user, _activity} = CommonAPI.follow(user2, user)
-
- {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
-
- {:ok, activity} = CommonAPI.add_mute(user2, activity)
-
- task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
-
- Streamer.add_socket(
- "user",
- %{transport_pid: task.pid, assigns: %{user: user2}}
- )
-
- Streamer.stream("user", activity)
- Task.await(task)
+ {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"})
+ {:ok, _} = CommonAPI.add_mute(user2, activity)
+ assert_receive {:render_with_user, _, _, ^activity}
+ assert Streamer.filtered_by_user?(user2, activity)
end
describe "direct streams" do
@@ -526,103 +555,88 @@ defmodule Pleroma.Web.StreamerTest do
user = insert(:user)
another_user = insert(:user)
- task =
- Task.async(fn ->
- assert_receive {:text, received_event}, @streamer_timeout
-
- assert %{"event" => "conversation", "payload" => received_payload} =
- Jason.decode!(received_event)
-
- assert %{"last_status" => last_status} = Jason.decode!(received_payload)
- [participation] = Participation.for_user(user)
- assert last_status["pleroma"]["direct_conversation_id"] == participation.id
- end)
-
- Streamer.add_socket(
- "direct",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
+ Streamer.get_topic_and_add_socket("direct", user)
{:ok, _create_activity} =
CommonAPI.post(another_user, %{
- "status" => "hey @#{user.nickname}",
- "visibility" => "direct"
+ status: "hey @#{user.nickname}",
+ visibility: "direct"
})
- Task.await(task)
+ assert_receive {:text, received_event}
+
+ assert %{"event" => "conversation", "payload" => received_payload} =
+ Jason.decode!(received_event)
+
+ assert %{"last_status" => last_status} = Jason.decode!(received_payload)
+ [participation] = Participation.for_user(user)
+ assert last_status["pleroma"]["direct_conversation_id"] == participation.id
end
test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted" do
user = insert(:user)
another_user = insert(:user)
+ Streamer.get_topic_and_add_socket("direct", user)
+
{:ok, create_activity} =
CommonAPI.post(another_user, %{
- "status" => "hi @#{user.nickname}",
- "visibility" => "direct"
+ status: "hi @#{user.nickname}",
+ visibility: "direct"
})
- task =
- Task.async(fn ->
- assert_receive {:text, received_event}, @streamer_timeout
- assert %{"event" => "delete", "payload" => _} = Jason.decode!(received_event)
-
- refute_receive {:text, _}, @streamer_timeout
- end)
+ create_activity_id = create_activity.id
+ assert_receive {:render_with_user, _, _, ^create_activity}
+ assert_receive {:text, received_conversation1}
+ assert %{"event" => "conversation", "payload" => _} = Jason.decode!(received_conversation1)
- Process.sleep(@streamer_start_wait)
+ {:ok, _} = CommonAPI.delete(create_activity_id, another_user)
- Streamer.add_socket(
- "direct",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
+ assert_receive {:text, received_event}
- {:ok, _} = CommonAPI.delete(create_activity.id, another_user)
+ assert %{"event" => "delete", "payload" => ^create_activity_id} =
+ Jason.decode!(received_event)
- Task.await(task)
+ refute_receive _
end
test "it sends conversation update to the 'direct' stream when a message is deleted" do
user = insert(:user)
another_user = insert(:user)
+ Streamer.get_topic_and_add_socket("direct", user)
{:ok, create_activity} =
CommonAPI.post(another_user, %{
- "status" => "hi @#{user.nickname}",
- "visibility" => "direct"
+ status: "hi @#{user.nickname}",
+ visibility: "direct"
})
{:ok, create_activity2} =
CommonAPI.post(another_user, %{
- "status" => "hi @#{user.nickname}",
- "in_reply_to_status_id" => create_activity.id,
- "visibility" => "direct"
+ status: "hi @#{user.nickname} 2",
+ in_reply_to_status_id: create_activity.id,
+ visibility: "direct"
})
- task =
- Task.async(fn ->
- assert_receive {:text, received_event}, @streamer_timeout
- assert %{"event" => "delete", "payload" => _} = Jason.decode!(received_event)
+ assert_receive {:render_with_user, _, _, ^create_activity}
+ assert_receive {:render_with_user, _, _, ^create_activity2}
+ assert_receive {:text, received_conversation1}
+ assert %{"event" => "conversation", "payload" => _} = Jason.decode!(received_conversation1)
+ assert_receive {:text, received_conversation1}
+ assert %{"event" => "conversation", "payload" => _} = Jason.decode!(received_conversation1)
- assert_receive {:text, received_event}, @streamer_timeout
-
- assert %{"event" => "conversation", "payload" => received_payload} =
- Jason.decode!(received_event)
-
- assert %{"last_status" => last_status} = Jason.decode!(received_payload)
- assert last_status["id"] == to_string(create_activity.id)
- end)
+ {:ok, _} = CommonAPI.delete(create_activity2.id, another_user)
- Process.sleep(@streamer_start_wait)
+ assert_receive {:text, received_event}
+ assert %{"event" => "delete", "payload" => _} = Jason.decode!(received_event)
- Streamer.add_socket(
- "direct",
- %{transport_pid: task.pid, assigns: %{user: user}}
- )
+ assert_receive {:text, received_event}
- {:ok, _} = CommonAPI.delete(create_activity2.id, another_user)
+ assert %{"event" => "conversation", "payload" => received_payload} =
+ Jason.decode!(received_event)
- Task.await(task)
+ assert %{"last_status" => last_status} = Jason.decode!(received_payload)
+ assert last_status["id"] == to_string(create_activity.id)
end
end
end
diff --git a/test/web/twitter_api/password_controller_test.exs b/test/web/twitter_api/password_controller_test.exs
index 0a24860d3..231a46c67 100644
--- a/test/web/twitter_api/password_controller_test.exs
+++ b/test/web/twitter_api/password_controller_test.exs
@@ -54,7 +54,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do
assert response =~ "<h2>Password changed!</h2>"
user = refresh_record(user)
- assert Comeonin.Pbkdf2.checkpw("test", user.password_hash)
+ assert Pbkdf2.verify_pass("test", user.password_hash)
assert Enum.empty?(Token.get_user_tokens(user))
end
diff --git a/test/web/twitter_api/remote_follow_controller_test.exs b/test/web/twitter_api/remote_follow_controller_test.exs
index 5ff8694a8..f7e54c26a 100644
--- a/test/web/twitter_api/remote_follow_controller_test.exs
+++ b/test/web/twitter_api/remote_follow_controller_test.exs
@@ -6,11 +6,14 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.Config
+ alias Pleroma.MFA
+ alias Pleroma.MFA.TOTP
alias Pleroma.User
alias Pleroma.Web.CommonAPI
import ExUnit.CaptureLog
import Pleroma.Factory
+ import Ecto.Query
setup do
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
@@ -160,6 +163,119 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
end
end
+ describe "POST /ostatus_subscribe - follow/2 with enabled Two-Factor Auth " do
+ test "render the MFA login form", %{conn: conn} do
+ otp_secret = TOTP.generate_secret()
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ user2 = insert(:user)
+
+ response =
+ conn
+ |> post(remote_follow_path(conn, :do_follow), %{
+ "authorization" => %{"name" => user.nickname, "password" => "test", "id" => user2.id}
+ })
+ |> response(200)
+
+ mfa_token = Pleroma.Repo.one(from(q in Pleroma.MFA.Token, where: q.user_id == ^user.id))
+
+ assert response =~ "Two-factor authentication"
+ assert response =~ "Authentication code"
+ assert response =~ mfa_token.token
+ refute user2.follower_address in User.following(user)
+ end
+
+ test "returns error when password is incorrect", %{conn: conn} do
+ otp_secret = TOTP.generate_secret()
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ user2 = insert(:user)
+
+ response =
+ conn
+ |> post(remote_follow_path(conn, :do_follow), %{
+ "authorization" => %{"name" => user.nickname, "password" => "test1", "id" => user2.id}
+ })
+ |> response(200)
+
+ assert response =~ "Wrong username or password"
+ refute user2.follower_address in User.following(user)
+ end
+
+ test "follows", %{conn: conn} do
+ otp_secret = TOTP.generate_secret()
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ {:ok, %{token: token}} = MFA.Token.create_token(user)
+
+ user2 = insert(:user)
+ otp_token = TOTP.generate_token(otp_secret)
+
+ conn =
+ conn
+ |> post(
+ remote_follow_path(conn, :do_follow),
+ %{
+ "mfa" => %{"code" => otp_token, "token" => token, "id" => user2.id}
+ }
+ )
+
+ assert redirected_to(conn) == "/users/#{user2.id}"
+ assert user2.follower_address in User.following(user)
+ end
+
+ test "returns error when auth code is incorrect", %{conn: conn} do
+ otp_secret = TOTP.generate_secret()
+
+ user =
+ insert(:user,
+ multi_factor_authentication_settings: %MFA.Settings{
+ enabled: true,
+ totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
+ }
+ )
+
+ {:ok, %{token: token}} = MFA.Token.create_token(user)
+
+ user2 = insert(:user)
+ otp_token = TOTP.generate_token(TOTP.generate_secret())
+
+ response =
+ conn
+ |> post(
+ remote_follow_path(conn, :do_follow),
+ %{
+ "mfa" => %{"code" => otp_token, "token" => token, "id" => user2.id}
+ }
+ )
+ |> response(200)
+
+ assert response =~ "Wrong authentication code"
+ refute user2.follower_address in User.following(user)
+ end
+ end
+
describe "POST /ostatus_subscribe - follow/2 without assigned user " do
test "follows", %{conn: conn} do
user = insert(:user)
diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs
index ab0a2c3df..464d0ea2e 100644
--- a/test/web/twitter_api/twitter_api_controller_test.exs
+++ b/test/web/twitter_api/twitter_api_controller_test.exs
@@ -19,13 +19,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
end
test "with credentials, without any params" do
- %{user: current_user, conn: conn} =
- oauth_access(["read:notifications", "write:notifications"])
+ %{conn: conn} = oauth_access(["write:notifications"])
- conn =
- conn
- |> assign(:user, current_user)
- |> post("/api/qvitter/statuses/notifications/read")
+ conn = post(conn, "/api/qvitter/statuses/notifications/read")
assert json_response(conn, 400) == %{
"error" => "You need to specify latest_id",
diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs
index f6e13b661..368533292 100644
--- a/test/web/twitter_api/twitter_api_test.exs
+++ b/test/web/twitter_api/twitter_api_test.exs
@@ -18,11 +18,11 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "it registers a new user and returns the user." do
data = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "password" => "bear",
- "confirm" => "bear"
+ :username => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -35,12 +35,12 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "it registers a new user with empty string in bio and returns the user." do
data = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "bio" => "",
- "password" => "bear",
- "confirm" => "bear"
+ :username => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -60,12 +60,12 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
end
data = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "bio" => "",
- "password" => "bear",
- "confirm" => "bear"
+ :username => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -87,23 +87,23 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "it registers a new user and parses mentions in the bio" do
data1 = %{
- "nickname" => "john",
- "email" => "john@gmail.com",
- "fullname" => "John Doe",
- "bio" => "test",
- "password" => "bear",
- "confirm" => "bear"
+ :username => "john",
+ :email => "john@gmail.com",
+ :fullname => "John Doe",
+ :bio => "test",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user1} = TwitterAPI.register_user(data1)
data2 = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "bio" => "@john test",
- "password" => "bear",
- "confirm" => "bear"
+ :username => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "@john test",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user2} = TwitterAPI.register_user(data2)
@@ -123,13 +123,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
{:ok, invite} = UserInviteToken.create_invite()
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees",
- "token" => invite.token
+ :username => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees",
+ :token => invite.token
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -145,13 +145,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "returns error on invalid token" do
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => "DudeLetMeInImAFairy"
+ :username => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => "DudeLetMeInImAFairy"
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -165,13 +165,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
UserInviteToken.update_invite!(invite, used: true)
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :username => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -186,16 +186,16 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
setup do
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees"
+ :username => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees"
}
check_fn = fn invite ->
- data = Map.put(data, "token", invite.token)
+ data = Map.put(data, :token, invite.token)
{:ok, user} = TwitterAPI.register_user(data)
fetched_user = User.get_cached_by_nickname("vinny")
@@ -250,13 +250,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
UserInviteToken.update_invite!(invite, uses: 99)
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees",
- "token" => invite.token
+ :username => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees",
+ :token => invite.token
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -269,13 +269,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
AccountView.render("show.json", %{user: fetched_user})
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :username => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -292,13 +292,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 100})
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees",
- "token" => invite.token
+ :username => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees",
+ :token => invite.token
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -317,13 +317,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
UserInviteToken.update_invite!(invite, uses: 99)
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees",
- "token" => invite.token
+ :username => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees",
+ :token => invite.token
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -335,13 +335,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
AccountView.render("show.json", %{user: fetched_user})
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :username => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -355,13 +355,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), -1), max_use: 100})
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :username => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -377,13 +377,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
UserInviteToken.update_invite!(invite, uses: 100)
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :username => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -395,16 +395,15 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "it returns the error on registration problems" do
data = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "bio" => "close the world.",
- "password" => "bear"
+ :username => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "close the world."
}
- {:error, error_object} = TwitterAPI.register_user(data)
+ {:error, error} = TwitterAPI.register_user(data)
- assert is_binary(error_object[:error])
+ assert is_binary(error)
refute User.get_cached_by_nickname("lain")
end
diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs
index 30e54bebd..ad919d341 100644
--- a/test/web/twitter_api/util_controller_test.exs
+++ b/test/web/twitter_api/util_controller_test.exs
@@ -95,6 +95,30 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
end
end
end
+
+ test "it imports follows with different nickname variations", %{conn: conn} do
+ [user2, user3, user4, user5, user6] = insert_list(5, :user)
+
+ identifiers =
+ [
+ user2.ap_id,
+ user3.nickname,
+ " ",
+ "@" <> user4.nickname,
+ user5.nickname <> "@localhost",
+ "@" <> user6.nickname <> "@localhost"
+ ]
+ |> Enum.join("\n")
+
+ response =
+ conn
+ |> post("/api/pleroma/follow_import", %{"list" => identifiers})
+ |> json_response(:ok)
+
+ assert response == "job started"
+ assert [{:ok, job_result}] = ObanHelpers.perform_all()
+ assert job_result == [user2, user3, user4, user5, user6]
+ end
end
describe "POST /api/pleroma/blocks_import" do
@@ -136,6 +160,29 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
)
end
end
+
+ test "it imports blocks with different nickname variations", %{conn: conn} do
+ [user2, user3, user4, user5, user6] = insert_list(5, :user)
+
+ identifiers =
+ [
+ user2.ap_id,
+ user3.nickname,
+ "@" <> user4.nickname,
+ user5.nickname <> "@localhost",
+ "@" <> user6.nickname <> "@localhost"
+ ]
+ |> Enum.join(" ")
+
+ response =
+ conn
+ |> post("/api/pleroma/blocks_import", %{"list" => identifiers})
+ |> json_response(:ok)
+
+ assert response == "job started"
+ assert [{:ok, job_result}] = ObanHelpers.perform_all()
+ assert job_result == [user2, user3, user4, user5, user6]
+ end
end
describe "PUT /api/pleroma/notification_settings" do
@@ -641,7 +688,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
assert json_response(conn, 200) == %{"status" => "success"}
fetched_user = User.get_cached_by_id(user.id)
- assert Comeonin.Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
+ assert Pbkdf2.verify_pass("newpass", fetched_user.password_hash) == true
end
end
diff --git a/test/web/web_finger/web_finger_test.exs b/test/web/web_finger/web_finger_test.exs
index 4b4282727..f4884e0a2 100644
--- a/test/web/web_finger/web_finger_test.exs
+++ b/test/web/web_finger/web_finger_test.exs
@@ -67,7 +67,7 @@ defmodule Pleroma.Web.WebFingerTest do
assert data["magic_key"] == nil
assert data["salmon"] == nil
- assert data["topic"] == "https://mstdn.jp/users/kPherox.atom"
+ assert data["topic"] == nil
assert data["subject"] == "acct:kPherox@mstdn.jp"
assert data["ap_id"] == "https://mstdn.jp/users/kPherox"
assert data["subscribe_address"] == "https://mstdn.jp/authorize_interaction?acct={uri}"
diff --git a/test/workers/cron/digest_emails_worker_test.exs b/test/workers/cron/digest_emails_worker_test.exs
index 0a63bf4e0..f9bc50db5 100644
--- a/test/workers/cron/digest_emails_worker_test.exs
+++ b/test/workers/cron/digest_emails_worker_test.exs
@@ -29,7 +29,7 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorkerTest do
user2 = insert(:user, last_digest_emailed_at: date)
{:ok, _} = User.switch_email_notifications(user2, "digest", true)
- CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}!"})
+ CommonAPI.post(user, %{status: "hey @#{user2.nickname}!"})
{:ok, user2: user2}
end
diff --git a/test/workers/cron/new_users_digest_worker_test.exs b/test/workers/cron/new_users_digest_worker_test.exs
index e6d050ecc..ee589bb55 100644
--- a/test/workers/cron/new_users_digest_worker_test.exs
+++ b/test/workers/cron/new_users_digest_worker_test.exs
@@ -15,7 +15,7 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorkerTest do
admin = insert(:user, %{is_admin: true})
user = insert(:user, %{inserted_at: yesterday})
user2 = insert(:user, %{inserted_at: yesterday})
- CommonAPI.post(user, %{"status" => "cofe"})
+ CommonAPI.post(user, %{status: "cofe"})
NewUsersDigestWorker.perform(nil, nil)
ObanHelpers.perform_all()
@@ -28,6 +28,7 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorkerTest do
assert email.html_body =~ user.nickname
assert email.html_body =~ user2.nickname
assert email.html_body =~ "cofe"
+ assert email.html_body =~ "#{Pleroma.Web.Endpoint.url()}/static/logo.png"
end
test "it doesn't fail when admin has no email" do
@@ -36,7 +37,7 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorkerTest do
insert(:user, %{inserted_at: yesterday})
user = insert(:user, %{inserted_at: yesterday})
- CommonAPI.post(user, %{"status" => "cofe"})
+ CommonAPI.post(user, %{status: "cofe"})
NewUsersDigestWorker.perform(nil, nil)
ObanHelpers.perform_all()
diff --git a/test/workers/cron/purge_expired_activities_worker_test.exs b/test/workers/cron/purge_expired_activities_worker_test.exs
index 5864f9e5f..6d2991a60 100644
--- a/test/workers/cron/purge_expired_activities_worker_test.exs
+++ b/test/workers/cron/purge_expired_activities_worker_test.exs
@@ -11,7 +11,10 @@ defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do
import Pleroma.Factory
import ExUnit.CaptureLog
- setup do: clear_config([ActivityExpiration, :enabled])
+ setup do
+ clear_config([ActivityExpiration, :enabled])
+ clear_config([:instance, :rewrite_policy])
+ end
test "deletes an expiration activity" do
Pleroma.Config.put([ActivityExpiration, :enabled], true)
@@ -36,6 +39,35 @@ defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do
refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id)
end
+ test "works with ActivityExpirationPolicy" do
+ Pleroma.Config.put([ActivityExpiration, :enabled], true)
+
+ Pleroma.Config.put(
+ [:instance, :rewrite_policy],
+ Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy
+ )
+
+ user = insert(:user)
+
+ days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365)
+
+ {:ok, %{id: id} = activity} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"})
+
+ past_date =
+ NaiveDateTime.utc_now() |> Timex.shift(days: -days) |> NaiveDateTime.truncate(:second)
+
+ activity
+ |> Repo.preload(:expiration)
+ |> Map.get(:expiration)
+ |> Ecto.Changeset.change(%{scheduled_at: past_date})
+ |> Repo.update!()
+
+ Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(:ops, :pid)
+
+ assert [%{data: %{"type" => "Delete", "deleted_activity_id" => ^id}}] =
+ Pleroma.Repo.all(Pleroma.Activity)
+ end
+
describe "delete_activity/1" do
test "adds log message if activity isn't find" do
assert capture_log([level: :error], fn ->