summaryrefslogtreecommitdiff
path: root/test/web
diff options
context:
space:
mode:
Diffstat (limited to 'test/web')
-rw-r--r--test/web/activity_pub/activity_pub_controller_test.exs67
-rw-r--r--test/web/activity_pub/activity_pub_test.exs434
-rw-r--r--test/web/activity_pub/mrf/activity_expiration_policy_test.exs15
-rw-r--r--test/web/activity_pub/mrf/anti_followbot_policy_test.exs4
-rw-r--r--test/web/activity_pub/mrf/anti_link_spam_policy_test.exs16
-rw-r--r--test/web/activity_pub/mrf/ensure_re_prepended_test.exs10
-rw-r--r--test/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs60
-rw-r--r--test/web/activity_pub/mrf/hellthread_policy_test.exs21
-rw-r--r--test/web/activity_pub/mrf/keyword_policy_test.exs12
-rw-r--r--test/web/activity_pub/mrf/mention_policy_test.exs6
-rw-r--r--test/web/activity_pub/mrf/mrf_test.exs4
-rw-r--r--test/web/activity_pub/mrf/object_age_policy_test.exs42
-rw-r--r--test/web/activity_pub/mrf/reject_non_public_test.exs4
-rw-r--r--test/web/activity_pub/mrf/simple_policy_test.exs76
-rw-r--r--test/web/activity_pub/mrf/tag_policy_test.exs6
-rw-r--r--test/web/activity_pub/mrf/user_allowlist_policy_test.exs2
-rw-r--r--test/web/activity_pub/mrf/vocabulary_policy_test.exs8
-rw-r--r--test/web/activity_pub/object_validator_test.exs625
-rw-r--r--test/web/activity_pub/object_validators/accept_validation_test.exs56
-rw-r--r--test/web/activity_pub/object_validators/announce_validation_test.exs106
-rw-r--r--test/web/activity_pub/object_validators/attachment_validator_test.exs74
-rw-r--r--test/web/activity_pub/object_validators/block_validation_test.exs39
-rw-r--r--test/web/activity_pub/object_validators/chat_validation_test.exs212
-rw-r--r--test/web/activity_pub/object_validators/delete_validation_test.exs106
-rw-r--r--test/web/activity_pub/object_validators/emoji_react_validation_test.exs53
-rw-r--r--test/web/activity_pub/object_validators/follow_validation_test.exs26
-rw-r--r--test/web/activity_pub/object_validators/like_validation_test.exs113
-rw-r--r--test/web/activity_pub/object_validators/reject_validation_test.exs56
-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.exs2
-rw-r--r--test/web/activity_pub/object_validators/types/recipients_test.exs2
-rw-r--r--test/web/activity_pub/object_validators/types/safe_text_test.exs2
-rw-r--r--test/web/activity_pub/object_validators/undo_validation_test.exs53
-rw-r--r--test/web/activity_pub/object_validators/update_validation_test.exs44
-rw-r--r--test/web/activity_pub/pipeline_test.exs45
-rw-r--r--test/web/activity_pub/publisher_test.exs34
-rw-r--r--test/web/activity_pub/relay_test.exs6
-rw-r--r--test/web/activity_pub/side_effects_test.exs119
-rw-r--r--test/web/activity_pub/transmogrifier/accept_handling_test.exs91
-rw-r--r--test/web/activity_pub/transmogrifier/answer_handling_test.exs78
-rw-r--r--test/web/activity_pub/transmogrifier/audio_handling_test.exs83
-rw-r--r--test/web/activity_pub/transmogrifier/block_handling_test.exs63
-rw-r--r--test/web/activity_pub/transmogrifier/chat_message_test.exs18
-rw-r--r--test/web/activity_pub/transmogrifier/event_handling_test.exs40
-rw-r--r--test/web/activity_pub/transmogrifier/follow_handling_test.exs21
-rw-r--r--test/web/activity_pub/transmogrifier/question_handling_test.exs176
-rw-r--r--test/web/activity_pub/transmogrifier/reject_handling_test.exs67
-rw-r--r--test/web/activity_pub/transmogrifier/undo_handling_test.exs2
-rw-r--r--test/web/activity_pub/transmogrifier/user_update_handling_test.exs159
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs646
-rw-r--r--test/web/activity_pub/utils_test.exs28
-rw-r--r--test/web/activity_pub/views/user_view_test.exs19
-rw-r--r--test/web/admin_api/controllers/admin_api_controller_test.exs300
-rw-r--r--test/web/admin_api/controllers/config_controller_test.exs333
-rw-r--r--test/web/admin_api/controllers/media_proxy_cache_controller_test.exs167
-rw-r--r--test/web/admin_api/controllers/relay_controller_test.exs15
-rw-r--r--test/web/admin_api/controllers/report_controller_test.exs14
-rw-r--r--test/web/admin_api/search_test.exs11
-rw-r--r--test/web/admin_api/views/report_view_test.exs27
-rw-r--r--test/web/common_api/common_api_test.exs178
-rw-r--r--test/web/fallback_test.exs68
-rw-r--r--test/web/federator_test.exs4
-rw-r--r--test/web/feed/tag_controller_test.exs13
-rw-r--r--test/web/feed/user_controller_test.exs27
-rw-r--r--test/web/instances/instance_test.exs33
-rw-r--r--test/web/masto_fe_controller_test.exs2
-rw-r--r--test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs153
-rw-r--r--test/web/mastodon_api/controllers/account_controller_test.exs308
-rw-r--r--test/web/mastodon_api/controllers/auth_controller_test.exs22
-rw-r--r--test/web/mastodon_api/controllers/domain_block_controller_test.exs32
-rw-r--r--test/web/mastodon_api/controllers/filter_controller_test.exs27
-rw-r--r--test/web/mastodon_api/controllers/follow_request_controller_test.exs8
-rw-r--r--test/web/mastodon_api/controllers/instance_controller_test.exs7
-rw-r--r--test/web/mastodon_api/controllers/list_controller_test.exs20
-rw-r--r--test/web/mastodon_api/controllers/search_controller_test.exs33
-rw-r--r--test/web/mastodon_api/controllers/status_controller_test.exs175
-rw-r--r--test/web/mastodon_api/controllers/timeline_controller_test.exs131
-rw-r--r--test/web/mastodon_api/mastodon_api_test.exs3
-rw-r--r--test/web/mastodon_api/views/account_view_test.exs80
-rw-r--r--test/web/mastodon_api/views/conversation_view_test.exs11
-rw-r--r--test/web/mastodon_api/views/notification_view_test.exs36
-rw-r--r--test/web/mastodon_api/views/poll_view_test.exs29
-rw-r--r--test/web/mastodon_api/views/status_view_test.exs45
-rw-r--r--test/web/media_proxy/invalidation_test.exs64
-rw-r--r--test/web/media_proxy/invalidations/http_test.exs12
-rw-r--r--test/web/media_proxy/invalidations/script_test.exs20
-rw-r--r--test/web/media_proxy/media_proxy_controller_test.exs136
-rw-r--r--test/web/media_proxy/media_proxy_test.exs142
-rw-r--r--test/web/metadata/metadata_test.exs9
-rw-r--r--test/web/metadata/rel_me_test.exs5
-rw-r--r--test/web/node_info_test.exs46
-rw-r--r--test/web/oauth/app_test.exs11
-rw-r--r--test/web/oauth/ldap_authorization_test.exs49
-rw-r--r--test/web/oauth/oauth_controller_test.exs29
-rw-r--r--test/web/oauth/token_test.exs13
-rw-r--r--test/web/pleroma_api/controllers/account_controller_test.exs99
-rw-r--r--test/web/pleroma_api/controllers/chat_controller_test.exs37
-rw-r--r--test/web/pleroma_api/controllers/emoji_pack_controller_test.exs135
-rw-r--r--test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs17
-rw-r--r--test/web/pleroma_api/views/chat/message_reference_view_test.exs15
-rw-r--r--test/web/pleroma_api/views/chat_view_test.exs3
-rw-r--r--test/web/preload/instance_test.exs48
-rw-r--r--test/web/preload/timeline_test.exs56
-rw-r--r--test/web/preload/user_test.exs33
-rw-r--r--test/web/push/impl_test.exs12
-rw-r--r--test/web/rich_media/aws_signed_url_test.exs4
-rw-r--r--test/web/rich_media/parser_test.exs28
-rw-r--r--test/web/static_fe/static_fe_controller_test.exs14
-rw-r--r--test/web/streamer/streamer_test.exs29
-rw-r--r--test/web/twitter_api/password_controller_test.exs4
-rw-r--r--test/web/twitter_api/remote_follow_controller_test.exs4
-rw-r--r--test/web/twitter_api/twitter_api_test.exs81
-rw-r--r--test/web/twitter_api/util_controller_test.exs151
-rw-r--r--test/web/web_finger/web_finger_test.exs5
114 files changed, 5383 insertions, 2293 deletions
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index 8c6ee68b2..b11e2f961 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -533,9 +533,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
end)
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
- assert_receive {:mix_shell, :info, ["relay.mastodon.host"]}
+ assert_receive {:mix_shell, :info, ["https://relay.mastodon.host/actor"]}
end
+ @tag capture_log: true
test "without valid signature, " <>
"it only accepts Create activities and requires enabled federation",
%{conn: conn} do
@@ -648,11 +649,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it accepts announces with to as string instead of array", %{conn: conn} do
user = insert(:user)
+ {:ok, post} = CommonAPI.post(user, %{status: "hey"})
+ announcer = insert(:user, local: false)
+
data = %{
"@context" => "https://www.w3.org/ns/activitystreams",
- "actor" => "http://mastodon.example.org/users/admin",
- "id" => "http://mastodon.example.org/users/admin/statuses/19512778738411822/activity",
- "object" => "https://mastodon.social/users/emelie/statuses/101849165031453009",
+ "actor" => announcer.ap_id,
+ "id" => "#{announcer.ap_id}/statuses/19512778738411822/activity",
+ "object" => post.data["object"],
"to" => "https://www.w3.org/ns/activitystreams#Public",
"cc" => [user.ap_id],
"type" => "Announce"
@@ -901,6 +905,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
end
describe "POST /users/:nickname/outbox (C2S)" do
+ setup do: clear_config([:instance, :limit])
+
setup do
[
activity: %{
@@ -1078,6 +1084,59 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert object = Object.get_by_ap_id(note_object.data["id"])
assert object.data["like_count"] == 1
end
+
+ test "it doesn't spreads faulty attributedTo or actor fields", %{
+ conn: conn,
+ activity: activity
+ } do
+ reimu = insert(:user, nickname: "reimu")
+ cirno = insert(:user, nickname: "cirno")
+
+ assert reimu.ap_id
+ assert cirno.ap_id
+
+ activity =
+ activity
+ |> put_in(["object", "actor"], reimu.ap_id)
+ |> put_in(["object", "attributedTo"], reimu.ap_id)
+ |> put_in(["actor"], reimu.ap_id)
+ |> put_in(["attributedTo"], reimu.ap_id)
+
+ _reimu_outbox =
+ conn
+ |> assign(:user, cirno)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{reimu.nickname}/outbox", activity)
+ |> json_response(403)
+
+ cirno_outbox =
+ conn
+ |> assign(:user, cirno)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{cirno.nickname}/outbox", activity)
+ |> json_response(201)
+
+ assert cirno_outbox["attributedTo"] == nil
+ assert cirno_outbox["actor"] == cirno.ap_id
+
+ assert cirno_object = Object.normalize(cirno_outbox["object"])
+ assert cirno_object.data["actor"] == cirno.ap_id
+ assert cirno_object.data["attributedTo"] == cirno.ap_id
+ end
+
+ test "Character limitation", %{conn: conn, activity: activity} do
+ Pleroma.Config.put([:instance, :limit], 5)
+ user = insert(:user)
+
+ result =
+ conn
+ |> assign(:user, user)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/outbox", activity)
+ |> json_response(400)
+
+ assert result == "Note is over the character limit"
+ end
end
describe "/relay/followers" do
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index 7693f6400..d8caa0b00 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -184,36 +184,43 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert User.invisible?(user)
end
- test "it fetches the appropriate tag-restricted posts" do
- user = insert(:user)
+ test "it returns a user that accepts chat messages" do
+ user_id = "http://mastodon.example.org/users/admin"
+ {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
- {:ok, status_one} = CommonAPI.post(user, %{status: ". #test"})
- {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"})
- {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"})
+ assert user.accepts_chat_messages
+ end
+ end
- fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"})
+ test "it fetches the appropriate tag-restricted posts" do
+ user = insert(:user)
- fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]})
+ {:ok, status_one} = CommonAPI.post(user, %{status: ". #test"})
+ {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"})
+ {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"})
- fetch_three =
- ActivityPub.fetch_activities([], %{
- type: "Create",
- tag: ["test", "essais"],
- tag_reject: ["reject"]
- })
+ fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"})
- fetch_four =
- ActivityPub.fetch_activities([], %{
- type: "Create",
- tag: ["test"],
- tag_all: ["test", "reject"]
- })
+ fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]})
- assert fetch_one == [status_one, status_three]
- assert fetch_two == [status_one, status_two, status_three]
- assert fetch_three == [status_one, status_two]
- assert fetch_four == [status_three]
- end
+ fetch_three =
+ ActivityPub.fetch_activities([], %{
+ type: "Create",
+ tag: ["test", "essais"],
+ tag_reject: ["reject"]
+ })
+
+ fetch_four =
+ ActivityPub.fetch_activities([], %{
+ type: "Create",
+ tag: ["test"],
+ tag_all: ["test", "reject"]
+ })
+
+ assert fetch_one == [status_one, status_three]
+ assert fetch_two == [status_one, status_two, status_three]
+ assert fetch_three == [status_one, status_two]
+ assert fetch_four == [status_three]
end
describe "insertion" do
@@ -232,7 +239,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
}
}
- assert {:error, {:remote_limit_error, _}} = ActivityPub.insert(data)
+ assert {:error, :remote_limit} = ActivityPub.insert(data)
end
test "doesn't drop activities with content being null" do
@@ -379,9 +386,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
describe "create activities" do
- test "it reverts create" do
- user = insert(:user)
+ setup do
+ [user: insert(:user)]
+ end
+ test "it reverts create", %{user: user} do
with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
assert {:error, :reverted} =
ActivityPub.create(%{
@@ -400,9 +409,47 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Repo.aggregate(Object, :count, :id) == 0
end
- test "removes doubled 'to' recipients" do
- user = insert(:user)
+ test "creates activity if expiration is not configured and expires_at is not passed", %{
+ user: user
+ } do
+ clear_config([Pleroma.Workers.PurgeExpiredActivity, :enabled], false)
+
+ assert {:ok, _} =
+ ActivityPub.create(%{
+ to: ["user1", "user2"],
+ actor: user,
+ context: "",
+ object: %{
+ "to" => ["user1", "user2"],
+ "type" => "Note",
+ "content" => "testing"
+ }
+ })
+ end
+
+ test "rejects activity if expires_at present but expiration is not configured", %{user: user} do
+ clear_config([Pleroma.Workers.PurgeExpiredActivity, :enabled], false)
+
+ assert {:error, :expired_activities_disabled} =
+ ActivityPub.create(%{
+ to: ["user1", "user2"],
+ actor: user,
+ context: "",
+ object: %{
+ "to" => ["user1", "user2"],
+ "type" => "Note",
+ "content" => "testing"
+ },
+ additional: %{
+ "expires_at" => DateTime.utc_now()
+ }
+ })
+ assert Repo.aggregate(Activity, :count, :id) == 0
+ assert Repo.aggregate(Object, :count, :id) == 0
+ end
+
+ test "removes doubled 'to' recipients", %{user: user} do
{:ok, activity} =
ActivityPub.create(%{
to: ["user1", "user1", "user2"],
@@ -420,9 +467,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert activity.recipients == ["user1", "user2", user.ap_id]
end
- test "increases user note count only for public activities" do
- user = insert(:user)
-
+ test "increases user note count only for public activities", %{user: user} do
{:ok, _} =
CommonAPI.post(User.get_cached_by_id(user.id), %{
status: "1",
@@ -451,8 +496,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert user.note_count == 2
end
- test "increases replies count" do
- user = insert(:user)
+ test "increases replies count", %{user: user} do
user2 = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"})
@@ -507,6 +551,33 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activities = ActivityPub.fetch_activities_for_context("2hu", %{blocking_user: user})
assert activities == [activity_two, activity]
end
+
+ test "doesn't return activities with filtered words" do
+ user = insert(:user)
+ user_two = insert(:user)
+ insert(:filter, user: user, phrase: "test", hide: true)
+
+ {:ok, %{id: id1, data: %{"context" => context}}} = CommonAPI.post(user, %{status: "1"})
+
+ {:ok, %{id: id2}} = CommonAPI.post(user_two, %{status: "2", in_reply_to_status_id: id1})
+
+ {:ok, %{id: id3} = user_activity} =
+ CommonAPI.post(user, %{status: "3 test?", in_reply_to_status_id: id2})
+
+ {:ok, %{id: id4} = filtered_activity} =
+ CommonAPI.post(user_two, %{status: "4 test!", in_reply_to_status_id: id3})
+
+ {:ok, _} = CommonAPI.post(user, %{status: "5", in_reply_to_status_id: id4})
+
+ activities =
+ context
+ |> ActivityPub.fetch_activities_for_context(%{user: user})
+ |> Enum.map(& &1.id)
+
+ assert length(activities) == 4
+ assert user_activity.id in activities
+ refute filtered_activity.id in activities
+ end
end
test "doesn't return blocked activities" do
@@ -642,7 +713,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
refute activity in activities
followed_user = insert(:user)
- ActivityPub.follow(user, followed_user)
+ CommonAPI.follow(user, followed_user)
{:ok, repeat_activity} = CommonAPI.repeat(activity.id, followed_user)
activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
@@ -785,6 +856,75 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert activity == expected_activity
end
+ describe "irreversible filters" do
+ setup do
+ user = insert(:user)
+ user_two = insert(:user)
+
+ insert(:filter, user: user_two, phrase: "cofe", hide: true)
+ insert(:filter, user: user_two, phrase: "ok boomer", hide: true)
+ insert(:filter, user: user_two, phrase: "test", hide: false)
+
+ params = %{
+ type: ["Create", "Announce"],
+ user: user_two
+ }
+
+ {:ok, %{user: user, user_two: user_two, params: params}}
+ end
+
+ test "it returns statuses if they don't contain exact filter words", %{
+ user: user,
+ params: params
+ } do
+ {:ok, _} = CommonAPI.post(user, %{status: "hey"})
+ {:ok, _} = CommonAPI.post(user, %{status: "got cofefe?"})
+ {:ok, _} = CommonAPI.post(user, %{status: "I am not a boomer"})
+ {:ok, _} = CommonAPI.post(user, %{status: "ok boomers"})
+ {:ok, _} = CommonAPI.post(user, %{status: "ccofee is not a word"})
+ {:ok, _} = CommonAPI.post(user, %{status: "this is a test"})
+
+ activities = ActivityPub.fetch_activities([], params)
+
+ assert Enum.count(activities) == 6
+ end
+
+ test "it does not filter user's own statuses", %{user_two: user_two, params: params} do
+ {:ok, _} = CommonAPI.post(user_two, %{status: "Give me some cofe!"})
+ {:ok, _} = CommonAPI.post(user_two, %{status: "ok boomer"})
+
+ activities = ActivityPub.fetch_activities([], params)
+
+ assert Enum.count(activities) == 2
+ end
+
+ test "it excludes statuses with filter words", %{user: user, params: params} do
+ {:ok, _} = CommonAPI.post(user, %{status: "Give me some cofe!"})
+ {:ok, _} = CommonAPI.post(user, %{status: "ok boomer"})
+ {:ok, _} = CommonAPI.post(user, %{status: "is it a cOfE?"})
+ {:ok, _} = CommonAPI.post(user, %{status: "cofe is all I need"})
+ {:ok, _} = CommonAPI.post(user, %{status: "— ok BOOMER\n"})
+
+ activities = ActivityPub.fetch_activities([], params)
+
+ assert Enum.empty?(activities)
+ end
+
+ test "it returns all statuses if user does not have any filters" do
+ another_user = insert(:user)
+ {:ok, _} = CommonAPI.post(another_user, %{status: "got cofe?"})
+ {:ok, _} = CommonAPI.post(another_user, %{status: "test!"})
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ type: ["Create", "Announce"],
+ user: another_user
+ })
+
+ assert Enum.count(activities) == 2
+ end
+ end
+
describe "public fetch activities" do
test "doesn't retrieve unlisted activities" do
user = insert(:user)
@@ -887,13 +1027,39 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
describe "uploading files" do
- test "copies the file to the configured folder" do
- file = %Plug.Upload{
+ setup do
+ test_file = %Plug.Upload{
content_type: "image/jpg",
path: Path.absname("test/fixtures/image.jpg"),
filename: "an_image.jpg"
}
+ %{test_file: test_file}
+ end
+
+ test "sets a description if given", %{test_file: file} do
+ {:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file")
+ assert object.data["name"] == "a cool file"
+ end
+
+ test "it sets the default description depending on the configuration", %{test_file: file} do
+ clear_config([Pleroma.Upload, :default_description])
+
+ Pleroma.Config.put([Pleroma.Upload, :default_description], nil)
+ {:ok, %Object{} = object} = ActivityPub.upload(file)
+ assert object.data["name"] == ""
+
+ Pleroma.Config.put([Pleroma.Upload, :default_description], :filename)
+ {:ok, %Object{} = object} = ActivityPub.upload(file)
+ assert object.data["name"] == "an_image.jpg"
+
+ Pleroma.Config.put([Pleroma.Upload, :default_description], "unnamed attachment")
+ {:ok, %Object{} = object} = ActivityPub.upload(file)
+ assert object.data["name"] == "unnamed attachment"
+ end
+
+ test "copies the file to the configured folder", %{test_file: file} do
+ clear_config([Pleroma.Upload, :default_description], :filename)
{:ok, %Object{} = object} = ActivityPub.upload(file)
assert object.data["name"] == "an_image.jpg"
end
@@ -917,24 +1083,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
- describe "following / unfollowing" do
- test "it reverts follow activity" do
- follower = insert(:user)
- followed = insert(:user)
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.follow(follower, followed)
- end
-
- assert Repo.aggregate(Activity, :count, :id) == 0
- assert Repo.aggregate(Object, :count, :id) == 0
- end
-
+ describe "unfollowing" do
test "it reverts unfollow activity" do
follower = insert(:user)
followed = insert(:user)
- {:ok, follow_activity} = ActivityPub.follow(follower, followed)
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
assert {:error, :reverted} = ActivityPub.unfollow(follower, followed)
@@ -947,21 +1101,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert activity.data["object"] == followed.ap_id
end
- test "creates a follow activity" do
- follower = insert(:user)
- followed = insert(:user)
-
- {:ok, activity} = ActivityPub.follow(follower, followed)
- assert activity.data["type"] == "Follow"
- assert activity.data["actor"] == follower.ap_id
- assert activity.data["object"] == followed.ap_id
- end
-
test "creates an undo activity for the last follow" do
follower = insert(:user)
followed = insert(:user)
- {:ok, follow_activity} = ActivityPub.follow(follower, followed)
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
{:ok, activity} = ActivityPub.unfollow(follower, followed)
assert activity.data["type"] == "Undo"
@@ -978,7 +1122,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
follower = insert(:user)
followed = insert(:user, %{locked: true})
- {:ok, follow_activity} = ActivityPub.follow(follower, followed)
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
{:ok, activity} = ActivityPub.unfollow(follower, followed)
assert activity.data["type"] == "Undo"
@@ -992,54 +1136,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
- describe "blocking" do
- test "reverts block activity on error" do
- [blocker, blocked] = insert_list(2, :user)
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.block(blocker, blocked)
- end
-
- assert Repo.aggregate(Activity, :count, :id) == 0
- assert Repo.aggregate(Object, :count, :id) == 0
- end
-
- test "creates a block activity" do
- clear_config([:instance, :federating], true)
- blocker = insert(:user)
- blocked = insert(:user)
-
- 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
-
- assert called(Pleroma.Web.Federator.publish(activity))
- end
- end
-
- 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)
-
- 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
-
- refute called(Pleroma.Web.Federator.publish(:_))
- end
- end
- end
-
describe "timeline post-processing" do
test "it filters broken threads" do
user1 = insert(:user)
@@ -1092,52 +1188,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
- describe "update" do
- setup do: clear_config([:instance, :max_pinned_statuses])
-
- test "it creates an update activity with the new user data" do
- user = insert(:user)
- {:ok, user} = User.ensure_keys_present(user)
- user_data = Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user})
-
- {:ok, update} =
- ActivityPub.update(%{
- actor: user_data["id"],
- to: [user.follower_address],
- cc: [],
- object: user_data
- })
-
- assert update.data["actor"] == user.ap_id
- assert update.data["to"] == [user.follower_address]
- assert embedded_object = update.data["object"]
- assert embedded_object["id"] == user_data["id"]
- assert embedded_object["type"] == user_data["type"]
- end
- end
-
- test "returned pinned statuses" 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!!!"})
-
- CommonAPI.pin(activity_one.id, user)
- user = refresh_record(user)
-
- CommonAPI.pin(activity_two.id, user)
- user = refresh_record(user)
-
- CommonAPI.pin(activity_three.id, user)
- user = refresh_record(user)
-
- activities = ActivityPub.fetch_user_activities(user, nil, %{pinned: true})
-
- assert 3 = length(activities)
- end
-
describe "flag/1" do
setup do
reporter = insert(:user)
@@ -1192,7 +1242,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
"id" => activity_ap_id,
"content" => content,
"published" => activity_with_object.object.data["published"],
- "actor" => AccountView.render("show.json", %{user: target_account})
+ "actor" =>
+ AccountView.render("show.json", %{user: target_account, skip_visibility_check: true})
}
assert %Activity{
@@ -1457,7 +1508,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert_enqueued(worker: Pleroma.Workers.BackgroundWorker, args: params)
- Pleroma.Workers.BackgroundWorker.perform(params, nil)
+ Pleroma.Workers.BackgroundWorker.perform(%Oban.Job{args: params})
refute User.following?(follower, old_user)
assert User.following?(follower, new_user)
@@ -2055,18 +2106,67 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
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
+ clear_config([:mrf, :policies], Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy)
+
+ {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
+ {:ok, follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"})
+
+ assert_enqueued(
+ worker: Pleroma.Workers.PurgeExpiredActivity,
+ args: %{activity_id: activity.id},
+ scheduled_at:
+ activity.inserted_at
+ |> DateTime.from_naive!("Etc/UTC")
+ |> Timex.shift(days: 365)
+ )
+
+ refute_enqueued(
+ worker: Pleroma.Workers.PurgeExpiredActivity,
+ args: %{activity_id: follow.id}
)
+ end
+ end
+
+ describe "handling of clashing nicknames" do
+ test "renames an existing user with a clashing nickname and a different ap id" do
+ orig_user =
+ insert(
+ :user,
+ local: false,
+ nickname: "admin@mastodon.example.org",
+ ap_id: "http://mastodon.example.org/users/harinezumigari"
+ )
+
+ %{
+ nickname: orig_user.nickname,
+ ap_id: orig_user.ap_id <> "part_2"
+ }
+ |> ActivityPub.maybe_handle_clashing_nickname()
+
+ user = User.get_by_id(orig_user.id)
+
+ assert user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
+ end
+
+ test "does nothing with a clashing nickname and the same ap id" do
+ orig_user =
+ insert(
+ :user,
+ local: false,
+ nickname: "admin@mastodon.example.org",
+ ap_id: "http://mastodon.example.org/users/harinezumigari"
+ )
+
+ %{
+ nickname: orig_user.nickname,
+ ap_id: orig_user.ap_id
+ }
+ |> ActivityPub.maybe_handle_clashing_nickname()
- {:ok, %{id: id_create}} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
- {:ok, _follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"})
+ user = User.get_by_id(orig_user.id)
- assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all()
+ assert user.nickname == orig_user.nickname
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
index 8babf49e7..e7370d4ef 100644
--- a/test/web/activity_pub/mrf/activity_expiration_policy_test.exs
+++ b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs
@@ -7,24 +7,27 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
alias Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy
@id Pleroma.Web.Endpoint.url() <> "/activities/cofe"
+ @local_actor Pleroma.Web.Endpoint.url() <> "/users/cofe"
test "adds `expires_at` property" do
assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
ActivityExpirationPolicy.filter(%{
"id" => @id,
+ "actor" => @local_actor,
"type" => "Create",
"object" => %{"type" => "Note"}
})
- assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364
+ assert Timex.diff(expires_at, DateTime.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)
+ expires_at = DateTime.utc_now() |> Timex.shift(days: 1)
assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} =
ActivityExpirationPolicy.filter(%{
"id" => @id,
+ "actor" => @local_actor,
"type" => "Create",
"expires_at" => expires_at,
"object" => %{"type" => "Note"}
@@ -32,23 +35,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
end
test "overwrites existing `expires_at` if it greater than the config setting" do
- too_distant_future = NaiveDateTime.utc_now() |> Timex.shift(years: 2)
+ too_distant_future = DateTime.utc_now() |> Timex.shift(years: 2)
assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
ActivityExpirationPolicy.filter(%{
"id" => @id,
+ "actor" => @local_actor,
"type" => "Create",
"expires_at" => too_distant_future,
"object" => %{"type" => "Note"}
})
- assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364
+ assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
end
test "ignores remote activities" do
assert {:ok, activity} =
ActivityExpirationPolicy.filter(%{
"id" => "https://example.com/123",
+ "actor" => "https://example.com/users/cofe",
"type" => "Create",
"object" => %{"type" => "Note"}
})
@@ -60,6 +65,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
assert {:ok, activity} =
ActivityExpirationPolicy.filter(%{
"id" => "https://example.com/123",
+ "actor" => "https://example.com/users/cofe",
"type" => "Follow"
})
@@ -68,6 +74,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
assert {:ok, activity} =
ActivityExpirationPolicy.filter(%{
"id" => "https://example.com/123",
+ "actor" => "https://example.com/users/cofe",
"type" => "Create",
"object" => %{"type" => "Cofe"}
})
diff --git a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs
index fca0de7c6..3c795f5ac 100644
--- a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs
+++ b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs
@@ -21,7 +21,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
"id" => "https://example.com/activities/1234"
}
- {:reject, nil} = AntiFollowbotPolicy.filter(message)
+ assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
end
test "matches followbots by display name" do
@@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
"id" => "https://example.com/activities/1234"
}
- {:reject, nil} = AntiFollowbotPolicy.filter(message)
+ assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
end
end
diff --git a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs
index 1a13699be..6867c9853 100644
--- a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs
+++ b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs
@@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
describe "with new user" do
test "it allows posts without links" do
- user = insert(:user)
+ user = insert(:user, local: false)
assert user.note_count == 0
@@ -45,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
end
test "it disallows posts with links" do
- user = insert(:user)
+ user = insert(:user, local: false)
assert user.note_count == 0
@@ -55,6 +55,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
{:reject, _} = AntiLinkSpamPolicy.filter(message)
end
+
+ test "it allows posts with links for local users" do
+ user = insert(:user)
+
+ assert user.note_count == 0
+
+ message =
+ @linkful_message
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ end
end
describe "with old user" do
diff --git a/test/web/activity_pub/mrf/ensure_re_prepended_test.exs b/test/web/activity_pub/mrf/ensure_re_prepended_test.exs
index 38ddec5bb..9a283f27d 100644
--- a/test/web/activity_pub/mrf/ensure_re_prepended_test.exs
+++ b/test/web/activity_pub/mrf/ensure_re_prepended_test.exs
@@ -78,5 +78,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
assert {:ok, res} = EnsureRePrepended.filter(message)
assert res == message
end
+
+ test "it skips if the object is only a reference" do
+ message = %{
+ "type" => "Create",
+ "object" => "somereference"
+ }
+
+ assert {:ok, res} = EnsureRePrepended.filter(message)
+ assert res == message
+ end
end
end
diff --git a/test/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs b/test/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs
new file mode 100644
index 000000000..86dd9ddae
--- /dev/null
+++ b/test/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs
@@ -0,0 +1,60 @@
+# 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.ForceBotUnlistedPolicyTest do
+ use Pleroma.DataCase
+ import Pleroma.Factory
+
+ alias Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy
+ @public "https://www.w3.org/ns/activitystreams#Public"
+
+ defp generate_messages(actor) do
+ {%{
+ "actor" => actor.ap_id,
+ "type" => "Create",
+ "object" => %{},
+ "to" => [@public, "f"],
+ "cc" => [actor.follower_address, "d"]
+ },
+ %{
+ "actor" => actor.ap_id,
+ "type" => "Create",
+ "object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]},
+ "to" => ["f", actor.follower_address],
+ "cc" => ["d", @public]
+ }}
+ end
+
+ test "removes from the federated timeline by nickname heuristics 1" do
+ actor = insert(:user, %{nickname: "annoying_ebooks@example.com"})
+
+ {message, except_message} = generate_messages(actor)
+
+ assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
+ end
+
+ test "removes from the federated timeline by nickname heuristics 2" do
+ actor = insert(:user, %{nickname: "cirnonewsnetworkbot@meow.cat"})
+
+ {message, except_message} = generate_messages(actor)
+
+ assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
+ end
+
+ test "removes from the federated timeline by actor type Application" do
+ actor = insert(:user, %{actor_type: "Application"})
+
+ {message, except_message} = generate_messages(actor)
+
+ assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
+ end
+
+ test "removes from the federated timeline by actor type Service" do
+ actor = insert(:user, %{actor_type: "Service"})
+
+ {message, except_message} = generate_messages(actor)
+
+ assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
+ end
+end
diff --git a/test/web/activity_pub/mrf/hellthread_policy_test.exs b/test/web/activity_pub/mrf/hellthread_policy_test.exs
index 95ef0b168..26f5bcdaa 100644
--- a/test/web/activity_pub/mrf/hellthread_policy_test.exs
+++ b/test/web/activity_pub/mrf/hellthread_policy_test.exs
@@ -8,6 +8,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do
import Pleroma.Web.ActivityPub.MRF.HellthreadPolicy
+ alias Pleroma.Web.CommonAPI
+
setup do
user = insert(:user)
@@ -20,7 +22,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do
"https://instance.tld/users/user1",
"https://instance.tld/users/user2",
"https://instance.tld/users/user3"
- ]
+ ],
+ "object" => %{
+ "type" => "Note"
+ }
}
[user: user, message: message]
@@ -28,13 +33,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do
setup do: clear_config(:mrf_hellthread)
+ test "doesn't die on chat messages" do
+ Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 2, reject_threshold: 0})
+
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post_chat_message(user, other_user, "moin")
+
+ assert {:ok, _} = filter(activity.data)
+ end
+
describe "reject" do
test "rejects the message if the recipient count is above reject_threshold", %{
message: message
} do
Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 2})
- {:reject, nil} = filter(message)
+ assert {:reject, "[HellthreadPolicy] 3 recipients is over the limit of 2"} ==
+ filter(message)
end
test "does not reject the message if the recipient count is below reject_threshold", %{
diff --git a/test/web/activity_pub/mrf/keyword_policy_test.exs b/test/web/activity_pub/mrf/keyword_policy_test.exs
index fd1f7aec8..b3d0f3d90 100644
--- a/test/web/activity_pub/mrf/keyword_policy_test.exs
+++ b/test/web/activity_pub/mrf/keyword_policy_test.exs
@@ -25,7 +25,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
}
}
- assert {:reject, nil} == KeywordPolicy.filter(message)
+ assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} =
+ KeywordPolicy.filter(message)
end
test "rejects if string matches in summary" do
@@ -39,7 +40,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
}
}
- assert {:reject, nil} == KeywordPolicy.filter(message)
+ assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} =
+ KeywordPolicy.filter(message)
end
test "rejects if regex matches in content" do
@@ -55,7 +57,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
}
}
- {:reject, nil} == KeywordPolicy.filter(message)
+ {:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
+ KeywordPolicy.filter(message)
end)
end
@@ -72,7 +75,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
}
}
- {:reject, nil} == KeywordPolicy.filter(message)
+ {:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
+ KeywordPolicy.filter(message)
end)
end
end
diff --git a/test/web/activity_pub/mrf/mention_policy_test.exs b/test/web/activity_pub/mrf/mention_policy_test.exs
index aa003bef5..220309cc9 100644
--- a/test/web/activity_pub/mrf/mention_policy_test.exs
+++ b/test/web/activity_pub/mrf/mention_policy_test.exs
@@ -76,7 +76,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do
"to" => ["https://example.com/blocked"]
}
- assert MentionPolicy.filter(message) == {:reject, nil}
+ assert MentionPolicy.filter(message) ==
+ {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
end
test "cc" do
@@ -88,7 +89,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do
"cc" => ["https://example.com/blocked"]
}
- assert MentionPolicy.filter(message) == {:reject, nil}
+ assert MentionPolicy.filter(message) ==
+ {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
end
end
end
diff --git a/test/web/activity_pub/mrf/mrf_test.exs b/test/web/activity_pub/mrf/mrf_test.exs
index c941066f2..a63b25423 100644
--- a/test/web/activity_pub/mrf/mrf_test.exs
+++ b/test/web/activity_pub/mrf/mrf_test.exs
@@ -60,8 +60,6 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do
end
describe "describe/0" do
- setup do: clear_config([:instance, :rewrite_policy])
-
test "it works as expected with noop policy" do
expected = %{
mrf_policies: ["NoOpPolicy"],
@@ -72,7 +70,7 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do
end
test "it works as expected with mock policy" do
- Pleroma.Config.put([:instance, :rewrite_policy], [MRFModuleMock])
+ clear_config([:mrf, :policies], [MRFModuleMock])
expected = %{
mrf_policies: ["MRFModuleMock"],
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 b0fb753bd..cf6acc9a2 100644
--- a/test/web/activity_pub/mrf/object_age_policy_test.exs
+++ b/test/web/activity_pub/mrf/object_age_policy_test.exs
@@ -38,6 +38,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
end
describe "with reject action" do
+ test "works with objects with empty to or cc fields" do
+ Config.put([:mrf_object_age, :actions], [:reject])
+
+ data =
+ get_old_message()
+ |> Map.put("cc", nil)
+ |> Map.put("to", nil)
+
+ assert match?({:reject, _}, ObjectAgePolicy.filter(data))
+ end
+
test "it rejects an old post" do
Config.put([:mrf_object_age, :actions], [:reject])
@@ -56,6 +67,21 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
end
describe "with delist action" do
+ test "works with objects with empty to or cc fields" do
+ Config.put([:mrf_object_age, :actions], [:delist])
+
+ data =
+ get_old_message()
+ |> Map.put("cc", nil)
+ |> Map.put("to", nil)
+
+ {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
+
+ {:ok, data} = ObjectAgePolicy.filter(data)
+
+ assert Visibility.get_visibility(%{data: data}) == "unlisted"
+ end
+
test "it delists an old post" do
Config.put([:mrf_object_age, :actions], [:delist])
@@ -80,6 +106,22 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
end
describe "with strip_followers action" do
+ test "works with objects with empty to or cc fields" do
+ Config.put([:mrf_object_age, :actions], [:strip_followers])
+
+ data =
+ get_old_message()
+ |> Map.put("cc", nil)
+ |> Map.put("to", nil)
+
+ {:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
+
+ {:ok, data} = ObjectAgePolicy.filter(data)
+
+ refute user.follower_address in data["to"]
+ refute user.follower_address in data["cc"]
+ end
+
test "it strips followers collections from an old post" do
Config.put([:mrf_object_age, :actions], [:strip_followers])
diff --git a/test/web/activity_pub/mrf/reject_non_public_test.exs b/test/web/activity_pub/mrf/reject_non_public_test.exs
index f36299b86..58b46b9a2 100644
--- a/test/web/activity_pub/mrf/reject_non_public_test.exs
+++ b/test/web/activity_pub/mrf/reject_non_public_test.exs
@@ -64,7 +64,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do
}
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], false)
- assert {:reject, nil} = RejectNonPublic.filter(message)
+ assert {:reject, _} = RejectNonPublic.filter(message)
end
end
@@ -94,7 +94,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do
}
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], false)
- assert {:reject, nil} = RejectNonPublic.filter(message)
+ assert {:reject, _} = RejectNonPublic.filter(message)
end
end
end
diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs
index b7b9bc6a2..d7dde62c4 100644
--- a/test/web/activity_pub/mrf/simple_policy_test.exs
+++ b/test/web/activity_pub/mrf/simple_policy_test.exs
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
import Pleroma.Factory
alias Pleroma.Config
alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
+ alias Pleroma.Web.CommonAPI
setup do:
clear_config(:mrf_simple,
@@ -15,6 +16,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
federated_timeline_removal: [],
report_removal: [],
reject: [],
+ followers_only: [],
accept: [],
avatar_removal: [],
banner_removal: [],
@@ -124,7 +126,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
report_message = build_report_message()
local_message = build_local_message()
- assert SimplePolicy.filter(report_message) == {:reject, nil}
+ assert {:reject, _} = SimplePolicy.filter(report_message)
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
@@ -133,7 +135,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
report_message = build_report_message()
local_message = build_local_message()
- assert SimplePolicy.filter(report_message) == {:reject, nil}
+ assert {:reject, _} = SimplePolicy.filter(report_message)
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
end
@@ -241,7 +243,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
remote_message = build_remote_message()
- assert SimplePolicy.filter(remote_message) == {:reject, nil}
+ assert {:reject, _} = SimplePolicy.filter(remote_message)
end
test "activity matches with wildcard domain" do
@@ -249,7 +251,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
remote_message = build_remote_message()
- assert SimplePolicy.filter(remote_message) == {:reject, nil}
+ assert {:reject, _} = SimplePolicy.filter(remote_message)
end
test "actor has a matching host" do
@@ -257,7 +259,65 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
remote_user = build_remote_user()
- assert SimplePolicy.filter(remote_user) == {:reject, nil}
+ assert {:reject, _} = SimplePolicy.filter(remote_user)
+ end
+ end
+
+ describe "when :followers_only" do
+ test "is empty" do
+ Config.put([:mrf_simple, :followers_only], [])
+ {_, ftl_message} = build_ftl_actor_and_message()
+ local_message = build_local_message()
+
+ assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
+ assert SimplePolicy.filter(local_message) == {:ok, local_message}
+ end
+
+ test "has a matching host" do
+ actor = insert(:user)
+ following_user = insert(:user)
+ non_following_user = insert(:user)
+
+ {:ok, _, _, _} = CommonAPI.follow(following_user, actor)
+
+ activity = %{
+ "actor" => actor.ap_id,
+ "to" => [
+ "https://www.w3.org/ns/activitystreams#Public",
+ following_user.ap_id,
+ non_following_user.ap_id
+ ],
+ "cc" => [actor.follower_address, "http://foo.bar/qux"]
+ }
+
+ dm_activity = %{
+ "actor" => actor.ap_id,
+ "to" => [
+ following_user.ap_id,
+ non_following_user.ap_id
+ ],
+ "cc" => []
+ }
+
+ actor_domain =
+ activity
+ |> Map.fetch!("actor")
+ |> URI.parse()
+ |> Map.fetch!(:host)
+
+ Config.put([:mrf_simple, :followers_only], [actor_domain])
+
+ assert {:ok, new_activity} = SimplePolicy.filter(activity)
+ assert actor.follower_address in new_activity["cc"]
+ assert following_user.ap_id in new_activity["to"]
+ refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["to"]
+ refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["cc"]
+ refute non_following_user.ap_id in new_activity["to"]
+ refute non_following_user.ap_id in new_activity["cc"]
+
+ assert {:ok, new_dm_activity} = SimplePolicy.filter(dm_activity)
+ assert new_dm_activity["to"] == [following_user.ap_id]
+ assert new_dm_activity["cc"] == []
end
end
@@ -279,7 +339,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
remote_message = build_remote_message()
assert SimplePolicy.filter(local_message) == {:ok, local_message}
- assert SimplePolicy.filter(remote_message) == {:reject, nil}
+ assert {:reject, _} = SimplePolicy.filter(remote_message)
end
test "activity has a matching host" do
@@ -429,7 +489,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
test "it rejects the deletion" do
deletion_message = build_remote_deletion_message()
- assert SimplePolicy.filter(deletion_message) == {:reject, nil}
+ assert {:reject, _} = SimplePolicy.filter(deletion_message)
end
end
@@ -439,7 +499,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
test "it rejects the deletion" do
deletion_message = build_remote_deletion_message()
- assert SimplePolicy.filter(deletion_message) == {:reject, nil}
+ assert {:reject, _} = SimplePolicy.filter(deletion_message)
end
end
diff --git a/test/web/activity_pub/mrf/tag_policy_test.exs b/test/web/activity_pub/mrf/tag_policy_test.exs
index e7793641a..6ff71d640 100644
--- a/test/web/activity_pub/mrf/tag_policy_test.exs
+++ b/test/web/activity_pub/mrf/tag_policy_test.exs
@@ -12,8 +12,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
describe "mrf_tag:disable-any-subscription" do
test "rejects message" do
actor = insert(:user, tags: ["mrf_tag:disable-any-subscription"])
- message = %{"object" => actor.ap_id, "type" => "Follow"}
- assert {:reject, nil} = TagPolicy.filter(message)
+ message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => actor.ap_id}
+ assert {:reject, _} = TagPolicy.filter(message)
end
end
@@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: false)
message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
- assert {:reject, nil} = TagPolicy.filter(message)
+ assert {:reject, _} = TagPolicy.filter(message)
end
test "allows non-local follow requests" do
diff --git a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
index ba1b69658..8e1ad5bc8 100644
--- a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
+++ b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
@@ -26,6 +26,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
actor = insert(:user)
Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => ["test-ap-id"]})
message = %{"actor" => actor.ap_id}
- assert UserAllowListPolicy.filter(message) == {:reject, nil}
+ assert {:reject, _} = UserAllowListPolicy.filter(message)
end
end
diff --git a/test/web/activity_pub/mrf/vocabulary_policy_test.exs b/test/web/activity_pub/mrf/vocabulary_policy_test.exs
index 69f22bb77..2bceb67ee 100644
--- a/test/web/activity_pub/mrf/vocabulary_policy_test.exs
+++ b/test/web/activity_pub/mrf/vocabulary_policy_test.exs
@@ -46,7 +46,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do
}
}
- {:reject, nil} = VocabularyPolicy.filter(message)
+ {:reject, _} = VocabularyPolicy.filter(message)
end
test "it does not accept disallowed parent types" do
@@ -60,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do
}
}
- {:reject, nil} = VocabularyPolicy.filter(message)
+ {:reject, _} = VocabularyPolicy.filter(message)
end
end
@@ -75,7 +75,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do
"object" => "whatever"
}
- {:reject, nil} = VocabularyPolicy.filter(message)
+ {:reject, _} = VocabularyPolicy.filter(message)
end
test "it rejects based on child object type" do
@@ -89,7 +89,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do
}
}
- {:reject, nil} = VocabularyPolicy.filter(message)
+ {:reject, _} = VocabularyPolicy.filter(message)
end
test "it passes through objects that aren't disallowed" do
diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs
deleted file mode 100644
index ee1e1bcfe..000000000
--- a/test/web/activity_pub/object_validator_test.exs
+++ /dev/null
@@ -1,625 +0,0 @@
-defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
- use Pleroma.DataCase
-
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.ActivityPub
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
- alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
- alias Pleroma.Web.ActivityPub.Utils
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- describe "attachments" do
- test "works with honkerific attachments" do
- attachment = %{
- "mediaType" => "",
- "name" => "",
- "summary" => "298p3RG7j27tfsZ9RQ.jpg",
- "type" => "Document",
- "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg"
- }
-
- assert {:ok, attachment} =
- AttachmentValidator.cast_and_validate(attachment)
- |> Ecto.Changeset.apply_action(:insert)
-
- assert attachment.mediaType == "application/octet-stream"
- end
-
- test "it turns mastodon attachments into our attachments" do
- attachment = %{
- "url" =>
- "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
- "type" => "Document",
- "name" => nil,
- "mediaType" => "image/jpeg"
- }
-
- {:ok, attachment} =
- AttachmentValidator.cast_and_validate(attachment)
- |> Ecto.Changeset.apply_action(:insert)
-
- assert [
- %{
- href:
- "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
- type: "Link",
- mediaType: "image/jpeg"
- }
- ] = attachment.url
-
- assert attachment.mediaType == "image/jpeg"
- end
-
- test "it handles our own uploads" do
- user = insert(:user)
-
- file = %Plug.Upload{
- content_type: "image/jpeg",
- 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"})
-
- valid_like = %{
- "to" => [user.ap_id],
- "cc" => [],
- "type" => "Like",
- "id" => Utils.generate_activity_id(),
- "object" => post_activity.data["object"],
- "actor" => user.ap_id,
- "context" => "a context"
- }
-
- %{valid_like: valid_like, user: user, post_activity: post_activity}
- end
-
- test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do
- {:ok, object, _meta} = ObjectValidator.validate(valid_like, [])
-
- assert "id" in Map.keys(object)
- end
-
- test "is valid for a valid object", %{valid_like: valid_like} do
- assert LikeValidator.cast_and_validate(valid_like).valid?
- end
-
- test "sets the 'to' field to the object actor if no recipients are given", %{
- valid_like: valid_like,
- user: user
- } do
- without_recipients =
- valid_like
- |> Map.delete("to")
-
- {:ok, object, _meta} = ObjectValidator.validate(without_recipients, [])
-
- assert object["to"] == [user.ap_id]
- end
-
- test "sets the context field to the context of the object if no context is given", %{
- valid_like: valid_like,
- post_activity: post_activity
- } do
- without_context =
- valid_like
- |> Map.delete("context")
-
- {:ok, object, _meta} = ObjectValidator.validate(without_context, [])
-
- assert object["context"] == post_activity.data["context"]
- end
-
- test "it errors when the actor is missing or not known", %{valid_like: valid_like} do
- without_actor = Map.delete(valid_like, "actor")
-
- refute LikeValidator.cast_and_validate(without_actor).valid?
-
- with_invalid_actor = Map.put(valid_like, "actor", "invalidactor")
-
- refute LikeValidator.cast_and_validate(with_invalid_actor).valid?
- end
-
- test "it errors when the object is missing or not known", %{valid_like: valid_like} do
- without_object = Map.delete(valid_like, "object")
-
- refute LikeValidator.cast_and_validate(without_object).valid?
-
- with_invalid_object = Map.put(valid_like, "object", "invalidobject")
-
- refute LikeValidator.cast_and_validate(with_invalid_object).valid?
- end
-
- test "it errors when the actor has already like the object", %{
- valid_like: valid_like,
- user: user,
- post_activity: post_activity
- } do
- _like = CommonAPI.favorite(user, post_activity.id)
-
- refute LikeValidator.cast_and_validate(valid_like).valid?
- end
-
- test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do
- wrapped_like =
- valid_like
- |> Map.put("actor", %{"id" => valid_like["actor"]})
- |> Map.put("object", %{"id" => valid_like["object"]})
-
- validated = LikeValidator.cast_and_validate(wrapped_like)
-
- assert validated.valid?
-
- assert {:actor, valid_like["actor"]} in validated.changes
- assert {:object, valid_like["object"]} in validated.changes
- end
- end
-
- describe "announces" do
- setup do
- user = insert(:user)
- announcer = insert(:user)
- {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
-
- object = Object.normalize(post_activity, false)
- {:ok, valid_announce, []} = Builder.announce(announcer, object)
-
- %{
- valid_announce: valid_announce,
- user: user,
- post_activity: post_activity,
- announcer: announcer
- }
- end
-
- test "returns ok for a valid announce", %{valid_announce: valid_announce} do
- assert {:ok, _object, _meta} = ObjectValidator.validate(valid_announce, [])
- end
-
- test "returns an error if the object can't be found", %{valid_announce: valid_announce} do
- without_object =
- valid_announce
- |> Map.delete("object")
-
- {:error, cng} = ObjectValidator.validate(without_object, [])
-
- assert {:object, {"can't be blank", [validation: :required]}} in cng.errors
-
- nonexisting_object =
- valid_announce
- |> Map.put("object", "https://gensokyo.2hu/objects/99999999")
-
- {:error, cng} = ObjectValidator.validate(nonexisting_object, [])
-
- assert {:object, {"can't find object", []}} in cng.errors
- end
-
- test "returns an error if we don't have the actor", %{valid_announce: valid_announce} do
- nonexisting_actor =
- valid_announce
- |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
-
- {:error, cng} = ObjectValidator.validate(nonexisting_actor, [])
-
- assert {:actor, {"can't find user", []}} in cng.errors
- end
-
- test "returns an error if the actor already announced the object", %{
- valid_announce: valid_announce,
- announcer: announcer,
- post_activity: post_activity
- } do
- _announce = CommonAPI.repeat(post_activity.id, announcer)
-
- {:error, cng} = ObjectValidator.validate(valid_announce, [])
-
- assert {:actor, {"already announced this object", []}} in cng.errors
- assert {:object, {"already announced by this actor", []}} in cng.errors
- end
-
- test "returns an error if the actor can't announce the object", %{
- announcer: announcer,
- user: user
- } do
- {:ok, post_activity} =
- CommonAPI.post(user, %{status: "a secret post", visibility: "private"})
-
- object = Object.normalize(post_activity, false)
-
- # Another user can't announce it
- {:ok, announce, []} = Builder.announce(announcer, object, public: false)
-
- {:error, cng} = ObjectValidator.validate(announce, [])
-
- assert {:actor, {"can not announce this object", []}} in cng.errors
-
- # The actor of the object can announce it
- {:ok, announce, []} = Builder.announce(user, object, public: false)
-
- assert {:ok, _, _} = ObjectValidator.validate(announce, [])
-
- # The actor of the object can not announce it publicly
- {:ok, announce, []} = Builder.announce(user, object, public: true)
-
- {:error, cng} = ObjectValidator.validate(announce, [])
-
- assert {:actor, {"can not announce this object publicly", []}} in cng.errors
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/accept_validation_test.exs b/test/web/activity_pub/object_validators/accept_validation_test.exs
new file mode 100644
index 000000000..d6111ba41
--- /dev/null
+++ b/test/web/activity_pub/object_validators/accept_validation_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.Web.ActivityPub.ObjectValidators.AcceptValidationTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.ActivityPub.Pipeline
+
+ import Pleroma.Factory
+
+ setup do
+ follower = insert(:user)
+ followed = insert(:user, local: false)
+
+ {:ok, follow_data, _} = Builder.follow(follower, followed)
+ {:ok, follow_activity, _} = Pipeline.common_pipeline(follow_data, local: true)
+
+ {:ok, accept_data, _} = Builder.accept(followed, follow_activity)
+
+ %{accept_data: accept_data, followed: followed}
+ end
+
+ test "it validates a basic 'accept'", %{accept_data: accept_data} do
+ assert {:ok, _, _} = ObjectValidator.validate(accept_data, [])
+ end
+
+ test "it fails when the actor doesn't exist", %{accept_data: accept_data} do
+ accept_data =
+ accept_data
+ |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
+
+ assert {:error, _} = ObjectValidator.validate(accept_data, [])
+ end
+
+ test "it fails when the accepted activity doesn't exist", %{accept_data: accept_data} do
+ accept_data =
+ accept_data
+ |> Map.put("object", "https://gensokyo.2hu/users/raymoo/follows/1")
+
+ assert {:error, _} = ObjectValidator.validate(accept_data, [])
+ end
+
+ test "for an accepted follow, it only validates if the actor of the accept is the followed actor",
+ %{accept_data: accept_data} do
+ stranger = insert(:user)
+
+ accept_data =
+ accept_data
+ |> Map.put("actor", stranger.ap_id)
+
+ assert {:error, _} = ObjectValidator.validate(accept_data, [])
+ end
+end
diff --git a/test/web/activity_pub/object_validators/announce_validation_test.exs b/test/web/activity_pub/object_validators/announce_validation_test.exs
new file mode 100644
index 000000000..623342f76
--- /dev/null
+++ b/test/web/activity_pub/object_validators/announce_validation_test.exs
@@ -0,0 +1,106 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnouncValidationTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "announces" do
+ setup do
+ user = insert(:user)
+ announcer = insert(:user)
+ {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
+
+ object = Object.normalize(post_activity, false)
+ {:ok, valid_announce, []} = Builder.announce(announcer, object)
+
+ %{
+ valid_announce: valid_announce,
+ user: user,
+ post_activity: post_activity,
+ announcer: announcer
+ }
+ end
+
+ test "returns ok for a valid announce", %{valid_announce: valid_announce} do
+ assert {:ok, _object, _meta} = ObjectValidator.validate(valid_announce, [])
+ end
+
+ test "returns an error if the object can't be found", %{valid_announce: valid_announce} do
+ without_object =
+ valid_announce
+ |> Map.delete("object")
+
+ {:error, cng} = ObjectValidator.validate(without_object, [])
+
+ assert {:object, {"can't be blank", [validation: :required]}} in cng.errors
+
+ nonexisting_object =
+ valid_announce
+ |> Map.put("object", "https://gensokyo.2hu/objects/99999999")
+
+ {:error, cng} = ObjectValidator.validate(nonexisting_object, [])
+
+ assert {:object, {"can't find object", []}} in cng.errors
+ end
+
+ test "returns an error if we don't have the actor", %{valid_announce: valid_announce} do
+ nonexisting_actor =
+ valid_announce
+ |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
+
+ {:error, cng} = ObjectValidator.validate(nonexisting_actor, [])
+
+ assert {:actor, {"can't find user", []}} in cng.errors
+ end
+
+ test "returns an error if the actor already announced the object", %{
+ valid_announce: valid_announce,
+ announcer: announcer,
+ post_activity: post_activity
+ } do
+ _announce = CommonAPI.repeat(post_activity.id, announcer)
+
+ {:error, cng} = ObjectValidator.validate(valid_announce, [])
+
+ assert {:actor, {"already announced this object", []}} in cng.errors
+ assert {:object, {"already announced by this actor", []}} in cng.errors
+ end
+
+ test "returns an error if the actor can't announce the object", %{
+ announcer: announcer,
+ user: user
+ } do
+ {:ok, post_activity} =
+ CommonAPI.post(user, %{status: "a secret post", visibility: "private"})
+
+ object = Object.normalize(post_activity, false)
+
+ # Another user can't announce it
+ {:ok, announce, []} = Builder.announce(announcer, object, public: false)
+
+ {:error, cng} = ObjectValidator.validate(announce, [])
+
+ assert {:actor, {"can not announce this object", []}} in cng.errors
+
+ # The actor of the object can announce it
+ {:ok, announce, []} = Builder.announce(user, object, public: false)
+
+ assert {:ok, _, _} = ObjectValidator.validate(announce, [])
+
+ # The actor of the object can not announce it publicly
+ {:ok, announce, []} = Builder.announce(user, object, public: true)
+
+ {:error, cng} = ObjectValidator.validate(announce, [])
+
+ assert {:actor, {"can not announce this object publicly", []}} in cng.errors
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/attachment_validator_test.exs b/test/web/activity_pub/object_validators/attachment_validator_test.exs
new file mode 100644
index 000000000..558bb3131
--- /dev/null
+++ b/test/web/activity_pub/object_validators/attachment_validator_test.exs
@@ -0,0 +1,74 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
+
+ import Pleroma.Factory
+
+ describe "attachments" do
+ test "works with honkerific attachments" do
+ attachment = %{
+ "mediaType" => "",
+ "name" => "",
+ "summary" => "298p3RG7j27tfsZ9RQ.jpg",
+ "type" => "Document",
+ "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg"
+ }
+
+ assert {:ok, attachment} =
+ AttachmentValidator.cast_and_validate(attachment)
+ |> Ecto.Changeset.apply_action(:insert)
+
+ assert attachment.mediaType == "application/octet-stream"
+ end
+
+ test "it turns mastodon attachments into our attachments" do
+ attachment = %{
+ "url" =>
+ "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
+ "type" => "Document",
+ "name" => nil,
+ "mediaType" => "image/jpeg"
+ }
+
+ {:ok, attachment} =
+ AttachmentValidator.cast_and_validate(attachment)
+ |> Ecto.Changeset.apply_action(:insert)
+
+ assert [
+ %{
+ href:
+ "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
+ type: "Link",
+ mediaType: "image/jpeg"
+ }
+ ] = attachment.url
+
+ assert attachment.mediaType == "image/jpeg"
+ end
+
+ test "it handles our own uploads" do
+ user = insert(:user)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
+
+ {:ok, attachment} =
+ attachment.data
+ |> AttachmentValidator.cast_and_validate()
+ |> Ecto.Changeset.apply_action(:insert)
+
+ assert attachment.mediaType == "image/jpeg"
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/block_validation_test.exs b/test/web/activity_pub/object_validators/block_validation_test.exs
new file mode 100644
index 000000000..c08d4b2e8
--- /dev/null
+++ b/test/web/activity_pub/object_validators/block_validation_test.exs
@@ -0,0 +1,39 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidationTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+
+ import Pleroma.Factory
+
+ describe "blocks" do
+ setup do
+ user = insert(:user, local: false)
+ blocked = insert(:user)
+
+ {:ok, valid_block, []} = Builder.block(user, blocked)
+
+ %{user: user, valid_block: valid_block}
+ end
+
+ test "validates a basic object", %{
+ valid_block: valid_block
+ } do
+ assert {:ok, _block, []} = ObjectValidator.validate(valid_block, [])
+ end
+
+ test "returns an error if we don't know the blocked user", %{
+ valid_block: valid_block
+ } do
+ block =
+ valid_block
+ |> Map.put("object", "https://gensokyo.2hu/users/raymoo")
+
+ assert {:error, _cng} = ObjectValidator.validate(block, [])
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/chat_validation_test.exs b/test/web/activity_pub/object_validators/chat_validation_test.exs
new file mode 100644
index 000000000..16e4808e5
--- /dev/null
+++ b/test/web/activity_pub/object_validators/chat_validation_test.exs
@@ -0,0 +1,212 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do
+ use Pleroma.DataCase
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "chat message create activities" do
+ test "it is invalid if the object already exists" do
+ user = insert(:user)
+ recipient = insert(:user)
+ {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "hey")
+ object = Object.normalize(activity, false)
+
+ {:ok, create_data, _} = Builder.create(user, object.data, [recipient.ap_id])
+
+ {:error, cng} = ObjectValidator.validate(create_data, [])
+
+ assert {:object, {"The object to create already exists", []}} in cng.errors
+ end
+
+ test "it is invalid if the object data has a different `to` or `actor` field" do
+ user = insert(:user)
+ recipient = insert(:user)
+ {:ok, object_data, _} = Builder.chat_message(recipient, user.ap_id, "Hey")
+
+ {:ok, create_data, _} = Builder.create(user, object_data, [recipient.ap_id])
+
+ {:error, cng} = ObjectValidator.validate(create_data, [])
+
+ assert {:to, {"Recipients don't match with object recipients", []}} in cng.errors
+ assert {:actor, {"Actor doesn't match with object actor", []}} in cng.errors
+ end
+ end
+
+ describe "chat messages" do
+ setup do
+ clear_config([:instance, :remote_limit])
+ user = insert(:user)
+ recipient = insert(:user, local: false)
+
+ {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey :firefox:")
+
+ %{user: user, recipient: recipient, valid_chat_message: valid_chat_message}
+ end
+
+ test "let's through some basic html", %{user: user, recipient: recipient} do
+ {:ok, valid_chat_message, _} =
+ Builder.chat_message(
+ user,
+ recipient.ap_id,
+ "hey <a href='https://example.org'>example</a> <script>alert('uguu')</script>"
+ )
+
+ assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
+
+ assert object["content"] ==
+ "hey <a href=\"https://example.org\">example</a> alert(&#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
+ assert match?(%{"firefox" => _}, object["emoji"])
+ end
+
+ test "validates for a basic object with an attachment", %{
+ valid_chat_message: valid_chat_message,
+ user: user
+ } do
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
+
+ valid_chat_message =
+ valid_chat_message
+ |> Map.put("attachment", attachment.data)
+
+ assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
+
+ assert object["attachment"]
+ end
+
+ test "validates for a basic object with an attachment in an array", %{
+ valid_chat_message: valid_chat_message,
+ user: user
+ } do
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
+
+ valid_chat_message =
+ valid_chat_message
+ |> Map.put("attachment", [attachment.data])
+
+ assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
+
+ assert object["attachment"]
+ end
+
+ test "validates for a basic object with an attachment but without content", %{
+ valid_chat_message: valid_chat_message,
+ user: user
+ } do
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
+
+ valid_chat_message =
+ valid_chat_message
+ |> Map.put("attachment", attachment.data)
+ |> Map.delete("content")
+
+ assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
+
+ assert object["attachment"]
+ end
+
+ test "does not validate if the message has no content", %{
+ valid_chat_message: valid_chat_message
+ } do
+ contentless =
+ valid_chat_message
+ |> Map.delete("content")
+
+ refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, []))
+ end
+
+ test "does not validate if the message is longer than the remote_limit", %{
+ valid_chat_message: valid_chat_message
+ } do
+ Pleroma.Config.put([:instance, :remote_limit], 2)
+ refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
+ end
+
+ test "does not validate if the recipient is blocking the actor", %{
+ valid_chat_message: valid_chat_message,
+ user: user,
+ recipient: recipient
+ } do
+ Pleroma.User.block(recipient, user)
+ refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
+ end
+
+ test "does not validate if the recipient is not accepting chat messages", %{
+ valid_chat_message: valid_chat_message,
+ recipient: recipient
+ } do
+ recipient
+ |> Ecto.Changeset.change(%{accepts_chat_messages: false})
+ |> Pleroma.Repo.update!()
+
+ refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
+ end
+
+ test "does not validate if the actor or the recipient is not in our system", %{
+ valid_chat_message: valid_chat_message
+ } do
+ chat_message =
+ valid_chat_message
+ |> Map.put("actor", "https://raymoo.com/raymoo")
+
+ {:error, _} = ObjectValidator.validate(chat_message, [])
+
+ chat_message =
+ valid_chat_message
+ |> Map.put("to", ["https://raymoo.com/raymoo"])
+
+ {:error, _} = ObjectValidator.validate(chat_message, [])
+ end
+
+ test "does not validate for a message with multiple recipients", %{
+ valid_chat_message: valid_chat_message,
+ user: user,
+ recipient: recipient
+ } do
+ chat_message =
+ valid_chat_message
+ |> Map.put("to", [user.ap_id, recipient.ap_id])
+
+ assert {:error, _} = ObjectValidator.validate(chat_message, [])
+ end
+
+ test "does not validate if it doesn't concern local users" do
+ user = insert(:user, local: false)
+ recipient = insert(:user, local: false)
+
+ {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey")
+ assert {:error, _} = ObjectValidator.validate(valid_chat_message, [])
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/delete_validation_test.exs b/test/web/activity_pub/object_validators/delete_validation_test.exs
new file mode 100644
index 000000000..02683b899
--- /dev/null
+++ b/test/web/activity_pub/object_validators/delete_validation_test.exs
@@ -0,0 +1,106 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidationTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "deletes" do
+ setup do
+ user = insert(:user)
+ {:ok, post_activity} = CommonAPI.post(user, %{status: "cancel me daddy"})
+
+ {:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"])
+ {:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id)
+
+ %{user: user, valid_post_delete: valid_post_delete, valid_user_delete: valid_user_delete}
+ end
+
+ test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do
+ {:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, [])
+
+ assert valid_post_delete["deleted_activity_id"]
+ end
+
+ test "it is invalid if the object isn't in a list of certain types", %{
+ valid_post_delete: valid_post_delete
+ } do
+ object = Object.get_by_ap_id(valid_post_delete["object"])
+
+ data =
+ object.data
+ |> Map.put("type", "Like")
+
+ {:ok, _object} =
+ object
+ |> Ecto.Changeset.change(%{data: data})
+ |> Object.update_and_set_cache()
+
+ {:error, cng} = ObjectValidator.validate(valid_post_delete, [])
+ assert {:object, {"object not in allowed types", []}} in cng.errors
+ end
+
+ test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do
+ assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, []))
+ end
+
+ test "it's invalid if the id is missing", %{valid_post_delete: valid_post_delete} do
+ no_id =
+ valid_post_delete
+ |> Map.delete("id")
+
+ {:error, cng} = ObjectValidator.validate(no_id, [])
+
+ assert {:id, {"can't be blank", [validation: :required]}} in cng.errors
+ end
+
+ test "it's invalid if the object doesn't exist", %{valid_post_delete: valid_post_delete} do
+ missing_object =
+ valid_post_delete
+ |> Map.put("object", "http://does.not/exist")
+
+ {:error, cng} = ObjectValidator.validate(missing_object, [])
+
+ assert {:object, {"can't find object", []}} in cng.errors
+ end
+
+ test "it's invalid if the actor of the object and the actor of delete are from different domains",
+ %{valid_post_delete: valid_post_delete} do
+ valid_user = insert(:user)
+
+ valid_other_actor =
+ valid_post_delete
+ |> Map.put("actor", valid_user.ap_id)
+
+ assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, []))
+
+ invalid_other_actor =
+ valid_post_delete
+ |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
+
+ {:error, cng} = ObjectValidator.validate(invalid_other_actor, [])
+
+ assert {:actor, {"is not allowed to modify object", []}} in cng.errors
+ end
+
+ test "it's valid if the actor of the object is a local superuser",
+ %{valid_post_delete: valid_post_delete} do
+ user =
+ insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo")
+
+ valid_other_actor =
+ valid_post_delete
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, _, meta} = ObjectValidator.validate(valid_other_actor, [])
+ assert meta[:do_not_federate]
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/emoji_react_validation_test.exs b/test/web/activity_pub/object_validators/emoji_react_validation_test.exs
new file mode 100644
index 000000000..582e6d785
--- /dev/null
+++ b/test/web/activity_pub/object_validators/emoji_react_validation_test.exs
@@ -0,0 +1,53 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "EmojiReacts" do
+ setup do
+ user = insert(:user)
+ {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
+
+ object = Pleroma.Object.get_by_ap_id(post_activity.data["object"])
+
+ {:ok, valid_emoji_react, []} = Builder.emoji_react(user, object, "👌")
+
+ %{user: user, post_activity: post_activity, valid_emoji_react: valid_emoji_react}
+ end
+
+ test "it validates a valid EmojiReact", %{valid_emoji_react: valid_emoji_react} do
+ assert {:ok, _, _} = ObjectValidator.validate(valid_emoji_react, [])
+ end
+
+ test "it is not valid without a 'content' field", %{valid_emoji_react: valid_emoji_react} do
+ without_content =
+ valid_emoji_react
+ |> Map.delete("content")
+
+ {:error, cng} = ObjectValidator.validate(without_content, [])
+
+ refute cng.valid?
+ assert {:content, {"can't be blank", [validation: :required]}} in cng.errors
+ end
+
+ test "it is not valid with a non-emoji content field", %{valid_emoji_react: valid_emoji_react} do
+ without_emoji_content =
+ valid_emoji_react
+ |> Map.put("content", "x")
+
+ {:error, cng} = ObjectValidator.validate(without_emoji_content, [])
+
+ refute cng.valid?
+
+ assert {:content, {"must be a single character emoji", []}} in cng.errors
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/follow_validation_test.exs b/test/web/activity_pub/object_validators/follow_validation_test.exs
new file mode 100644
index 000000000..6e1378be2
--- /dev/null
+++ b/test/web/activity_pub/object_validators/follow_validation_test.exs
@@ -0,0 +1,26 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidationTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+
+ import Pleroma.Factory
+
+ describe "Follows" do
+ setup do
+ follower = insert(:user)
+ followed = insert(:user)
+
+ {:ok, valid_follow, []} = Builder.follow(follower, followed)
+ %{follower: follower, followed: followed, valid_follow: valid_follow}
+ end
+
+ test "validates a basic follow object", %{valid_follow: valid_follow} do
+ assert {:ok, _follow, []} = ObjectValidator.validate(valid_follow, [])
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/like_validation_test.exs b/test/web/activity_pub/object_validators/like_validation_test.exs
new file mode 100644
index 000000000..2c033b7e2
--- /dev/null
+++ b/test/web/activity_pub/object_validators/like_validation_test.exs
@@ -0,0 +1,113 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidationTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
+ alias Pleroma.Web.ActivityPub.Utils
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "likes" do
+ setup do
+ user = insert(:user)
+ {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
+
+ valid_like = %{
+ "to" => [user.ap_id],
+ "cc" => [],
+ "type" => "Like",
+ "id" => Utils.generate_activity_id(),
+ "object" => post_activity.data["object"],
+ "actor" => user.ap_id,
+ "context" => "a context"
+ }
+
+ %{valid_like: valid_like, user: user, post_activity: post_activity}
+ end
+
+ test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do
+ {:ok, object, _meta} = ObjectValidator.validate(valid_like, [])
+
+ assert "id" in Map.keys(object)
+ end
+
+ test "is valid for a valid object", %{valid_like: valid_like} do
+ assert LikeValidator.cast_and_validate(valid_like).valid?
+ end
+
+ test "sets the 'to' field to the object actor if no recipients are given", %{
+ valid_like: valid_like,
+ user: user
+ } do
+ without_recipients =
+ valid_like
+ |> Map.delete("to")
+
+ {:ok, object, _meta} = ObjectValidator.validate(without_recipients, [])
+
+ assert object["to"] == [user.ap_id]
+ end
+
+ test "sets the context field to the context of the object if no context is given", %{
+ valid_like: valid_like,
+ post_activity: post_activity
+ } do
+ without_context =
+ valid_like
+ |> Map.delete("context")
+
+ {:ok, object, _meta} = ObjectValidator.validate(without_context, [])
+
+ assert object["context"] == post_activity.data["context"]
+ end
+
+ test "it errors when the actor is missing or not known", %{valid_like: valid_like} do
+ without_actor = Map.delete(valid_like, "actor")
+
+ refute LikeValidator.cast_and_validate(without_actor).valid?
+
+ with_invalid_actor = Map.put(valid_like, "actor", "invalidactor")
+
+ refute LikeValidator.cast_and_validate(with_invalid_actor).valid?
+ end
+
+ test "it errors when the object is missing or not known", %{valid_like: valid_like} do
+ without_object = Map.delete(valid_like, "object")
+
+ refute LikeValidator.cast_and_validate(without_object).valid?
+
+ with_invalid_object = Map.put(valid_like, "object", "invalidobject")
+
+ refute LikeValidator.cast_and_validate(with_invalid_object).valid?
+ end
+
+ test "it errors when the actor has already like the object", %{
+ valid_like: valid_like,
+ user: user,
+ post_activity: post_activity
+ } do
+ _like = CommonAPI.favorite(user, post_activity.id)
+
+ refute LikeValidator.cast_and_validate(valid_like).valid?
+ end
+
+ test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do
+ wrapped_like =
+ valid_like
+ |> Map.put("actor", %{"id" => valid_like["actor"]})
+ |> Map.put("object", %{"id" => valid_like["object"]})
+
+ validated = LikeValidator.cast_and_validate(wrapped_like)
+
+ assert validated.valid?
+
+ assert {:actor, valid_like["actor"]} in validated.changes
+ assert {:object, valid_like["object"]} in validated.changes
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/reject_validation_test.exs b/test/web/activity_pub/object_validators/reject_validation_test.exs
new file mode 100644
index 000000000..370bb6e5c
--- /dev/null
+++ b/test/web/activity_pub/object_validators/reject_validation_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.Web.ActivityPub.ObjectValidators.RejectValidationTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.ActivityPub.Pipeline
+
+ import Pleroma.Factory
+
+ setup do
+ follower = insert(:user)
+ followed = insert(:user, local: false)
+
+ {:ok, follow_data, _} = Builder.follow(follower, followed)
+ {:ok, follow_activity, _} = Pipeline.common_pipeline(follow_data, local: true)
+
+ {:ok, reject_data, _} = Builder.reject(followed, follow_activity)
+
+ %{reject_data: reject_data, followed: followed}
+ end
+
+ test "it validates a basic 'reject'", %{reject_data: reject_data} do
+ assert {:ok, _, _} = ObjectValidator.validate(reject_data, [])
+ end
+
+ test "it fails when the actor doesn't exist", %{reject_data: reject_data} do
+ reject_data =
+ reject_data
+ |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
+
+ assert {:error, _} = ObjectValidator.validate(reject_data, [])
+ end
+
+ test "it fails when the rejected activity doesn't exist", %{reject_data: reject_data} do
+ reject_data =
+ reject_data
+ |> Map.put("object", "https://gensokyo.2hu/users/raymoo/follows/1")
+
+ assert {:error, _} = ObjectValidator.validate(reject_data, [])
+ end
+
+ test "for an rejected follow, it only validates if the actor of the reject is the followed actor",
+ %{reject_data: reject_data} do
+ stranger = insert(:user)
+
+ reject_data =
+ reject_data
+ |> Map.put("actor", stranger.ap_id)
+
+ assert {:error, _} = ObjectValidator.validate(reject_data, [])
+ 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 c8911948e..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
@@ -3,7 +3,7 @@
# 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
index f278f039b..053916bdd 100644
--- a/test/web/activity_pub/object_validators/types/recipients_test.exs
+++ b/test/web/activity_pub/object_validators/types/recipients_test.exs
@@ -1,5 +1,5 @@
defmodule Pleroma.Web.ObjectValidators.Types.RecipientsTest do
- alias Pleroma.Web.ActivityPub.ObjectValidators.Types.Recipients
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.Recipients
use Pleroma.DataCase
test "it asserts that all elements of the list are object ids" do
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
index d4a574554..9c08606f6 100644
--- a/test/web/activity_pub/object_validators/types/safe_text_test.exs
+++ b/test/web/activity_pub/object_validators/types/safe_text_test.exs
@@ -5,7 +5,7 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.SafeTextTest do
use Pleroma.DataCase
- alias Pleroma.Web.ActivityPub.ObjectValidators.Types.SafeText
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.SafeText
test "it lets normal text go through" do
text = "hey how are you"
diff --git a/test/web/activity_pub/object_validators/undo_validation_test.exs b/test/web/activity_pub/object_validators/undo_validation_test.exs
new file mode 100644
index 000000000..75bbcc4b6
--- /dev/null
+++ b/test/web/activity_pub/object_validators/undo_validation_test.exs
@@ -0,0 +1,53 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.UndoHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ describe "Undos" do
+ setup do
+ user = insert(:user)
+ {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
+ {:ok, like} = CommonAPI.favorite(user, post_activity.id)
+ {:ok, valid_like_undo, []} = Builder.undo(user, like)
+
+ %{user: user, like: like, valid_like_undo: valid_like_undo}
+ end
+
+ test "it validates a basic like undo", %{valid_like_undo: valid_like_undo} do
+ assert {:ok, _, _} = ObjectValidator.validate(valid_like_undo, [])
+ end
+
+ test "it does not validate if the actor of the undo is not the actor of the object", %{
+ valid_like_undo: valid_like_undo
+ } do
+ other_user = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo")
+
+ bad_actor =
+ valid_like_undo
+ |> Map.put("actor", other_user.ap_id)
+
+ {:error, cng} = ObjectValidator.validate(bad_actor, [])
+
+ assert {:actor, {"not the same as object actor", []}} in cng.errors
+ end
+
+ test "it does not validate if the object is missing", %{valid_like_undo: valid_like_undo} do
+ missing_object =
+ valid_like_undo
+ |> Map.put("object", "https://gensokyo.2hu/objects/1")
+
+ {:error, cng} = ObjectValidator.validate(missing_object, [])
+
+ assert {:object, {"can't find object", []}} in cng.errors
+ assert length(cng.errors) == 1
+ end
+ end
+end
diff --git a/test/web/activity_pub/object_validators/update_validation_test.exs b/test/web/activity_pub/object_validators/update_validation_test.exs
new file mode 100644
index 000000000..5e80cf731
--- /dev/null
+++ b/test/web/activity_pub/object_validators/update_validation_test.exs
@@ -0,0 +1,44 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.UpdateHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.ObjectValidator
+
+ import Pleroma.Factory
+
+ describe "updates" do
+ setup do
+ user = insert(:user)
+
+ object = %{
+ "id" => user.ap_id,
+ "name" => "A new name",
+ "summary" => "A new bio"
+ }
+
+ {:ok, valid_update, []} = Builder.update(user, object)
+
+ %{user: user, valid_update: valid_update}
+ end
+
+ test "validates a basic object", %{valid_update: valid_update} do
+ assert {:ok, _update, []} = ObjectValidator.validate(valid_update, [])
+ end
+
+ test "returns an error if the object can't be updated by the actor", %{
+ valid_update: valid_update
+ } do
+ other_user = insert(:user)
+
+ update =
+ valid_update
+ |> Map.put("actor", other_user.ap_id)
+
+ assert {:error, _cng} = ObjectValidator.validate(update, [])
+ end
+ end
+end
diff --git a/test/web/activity_pub/pipeline_test.exs b/test/web/activity_pub/pipeline_test.exs
index 8deb64501..f2a231eaf 100644
--- a/test/web/activity_pub/pipeline_test.exs
+++ b/test/web/activity_pub/pipeline_test.exs
@@ -14,6 +14,51 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
:ok
end
+ test "when given an `object_data` in meta, Federation will receive a the original activity with the `object` field set to this embedded object" do
+ activity = insert(:note_activity)
+ object = %{"id" => "1", "type" => "Love"}
+ meta = [local: true, object_data: object]
+
+ activity_with_object = %{activity | data: Map.put(activity.data, "object", object)}
+
+ 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,
+ [],
+ [publish: fn _o -> :ok end]
+ }
+ ]) 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))
+ refute called(Pleroma.Web.Federator.publish(activity))
+ assert_called(Pleroma.Web.Federator.publish(activity_with_object))
+ end
+ end
+
test "it goes through validation, filtering, persisting, side effects and federation for local activities" do
activity = insert(:note_activity)
meta = [local: true]
diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs
index c2bc38d52..b9388b966 100644
--- a/test/web/activity_pub/publisher_test.exs
+++ b/test/web/activity_pub/publisher_test.exs
@@ -123,6 +123,39 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
end
describe "publish_one/1" do
+ test "publish to url with with different ports" do
+ inbox80 = "http://42.site/users/nick1/inbox"
+ inbox42 = "http://42.site:42/users/nick1/inbox"
+
+ mock(fn
+ %{method: :post, url: "http://42.site:42/users/nick1/inbox"} ->
+ {:ok, %Tesla.Env{status: 200, body: "port 42"}}
+
+ %{method: :post, url: "http://42.site/users/nick1/inbox"} ->
+ {:ok, %Tesla.Env{status: 200, body: "port 80"}}
+ end)
+
+ actor = insert(:user)
+
+ assert {:ok, %{body: "port 42"}} =
+ Publisher.publish_one(%{
+ inbox: inbox42,
+ json: "{}",
+ actor: actor,
+ id: 1,
+ unreachable_since: true
+ })
+
+ assert {:ok, %{body: "port 80"}} =
+ Publisher.publish_one(%{
+ inbox: inbox80,
+ json: "{}",
+ actor: actor,
+ id: 1,
+ unreachable_since: true
+ })
+ end
+
test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
Instances,
[:passthrough],
@@ -131,7 +164,6 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
inbox = "http://200.site/users/nick1/inbox"
assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
-
assert called(Instances.set_reachable(inbox))
end
diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs
index b3b573c9b..9d657ac4f 100644
--- a/test/web/activity_pub/relay_test.exs
+++ b/test/web/activity_pub/relay_test.exs
@@ -7,8 +7,8 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
alias Pleroma.Activity
alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Relay
+ alias Pleroma.Web.CommonAPI
import ExUnit.CaptureLog
import Pleroma.Factory
@@ -53,8 +53,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
test "returns activity" do
user = insert(:user)
service_actor = Relay.get_actor()
- ActivityPub.follow(service_actor, user)
- Pleroma.User.follow(service_actor, user)
+ CommonAPI.follow(service_actor, user)
assert "#{user.ap_id}/followers" in User.following(service_actor)
assert {:ok, %Activity{} = activity} = Relay.unfollow(user.ap_id)
assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
@@ -74,6 +73,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
assert Relay.publish(activity) == {:error, "Not implemented"}
end
+ @tag capture_log: true
test "returns error when activity not public" do
activity = insert(:direct_note_activity)
assert Relay.publish(activity) == {:error, false}
diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs
index 6bbbaae87..9efbaad04 100644
--- a/test/web/activity_pub/side_effects_test.exs
+++ b/test/web/activity_pub/side_effects_test.exs
@@ -19,8 +19,9 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
alias Pleroma.Web.ActivityPub.SideEffects
alias Pleroma.Web.CommonAPI
- import Pleroma.Factory
+ import ExUnit.CaptureLog
import Mock
+ import Pleroma.Factory
describe "handle_after_transaction" do
test "it streams out notifications and streams" do
@@ -64,6 +65,72 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
end
end
+ describe "blocking users" do
+ setup do
+ user = insert(:user)
+ blocked = insert(:user)
+ User.follow(blocked, user)
+ User.follow(user, blocked)
+
+ {:ok, block_data, []} = Builder.block(user, blocked)
+ {:ok, block, _meta} = ActivityPub.persist(block_data, local: true)
+
+ %{user: user, blocked: blocked, block: block}
+ end
+
+ test "it unfollows and blocks", %{user: user, blocked: blocked, block: block} do
+ assert User.following?(user, blocked)
+ assert User.following?(blocked, user)
+
+ {:ok, _, _} = SideEffects.handle(block)
+
+ refute User.following?(user, blocked)
+ refute User.following?(blocked, user)
+ assert User.blocks?(user, blocked)
+ end
+
+ test "it blocks but does not unfollow if the relevant setting is set", %{
+ user: user,
+ blocked: blocked,
+ block: block
+ } do
+ clear_config([:activitypub, :unfollow_blocked], false)
+ assert User.following?(user, blocked)
+ assert User.following?(blocked, user)
+
+ {:ok, _, _} = SideEffects.handle(block)
+
+ refute User.following?(user, blocked)
+ assert User.following?(blocked, user)
+ assert User.blocks?(user, blocked)
+ end
+ end
+
+ describe "update users" do
+ setup do
+ user = insert(:user)
+ {:ok, update_data, []} = Builder.update(user, %{"id" => user.ap_id, "name" => "new name!"})
+ {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
+
+ %{user: user, update_data: update_data, update: update}
+ end
+
+ test "it updates the user", %{user: user, update: update} do
+ {:ok, _, _} = SideEffects.handle(update)
+ user = User.get_by_id(user.id)
+ assert user.name == "new name!"
+ end
+
+ test "it uses a given changeset to update", %{user: user, update: update} do
+ changeset = Ecto.Changeset.change(user, %{default_scope: "direct"})
+
+ assert user.default_scope == "public"
+ {:ok, _, _} = SideEffects.handle(update, user_update_changeset: changeset)
+ user = User.get_by_id(user.id)
+ assert user.default_scope == "direct"
+ end
+ end
+
describe "delete objects" do
setup do
user = insert(:user)
@@ -155,6 +222,22 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
assert User.get_cached_by_ap_id(user.ap_id).deactivated
end
+
+ test "it logs issues with objects deletion", %{
+ delete: delete,
+ object: object
+ } do
+ {:ok, object} =
+ object
+ |> Object.change(%{data: Map.delete(object.data, "actor")})
+ |> Repo.update()
+
+ Object.invalid_object_cache(object)
+
+ assert capture_log(fn ->
+ {:error, :no_object_actor} = SideEffects.handle(delete)
+ end) =~ "object doesn't have an actor"
+ end
end
describe "EmojiReact objects" do
@@ -217,8 +300,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
{:ok, like} = CommonAPI.favorite(user, post.id)
{:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
{:ok, announce} = CommonAPI.repeat(post.id, user)
- {:ok, block} = ActivityPub.block(user, poster)
- User.block(user, poster)
+ {:ok, block} = CommonAPI.block(user, poster)
{:ok, undo_data, _meta} = Builder.undo(user, like)
{:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
@@ -247,8 +329,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
}
end
- test "deletes the original block", %{block_undo: block_undo, block: block} do
- {:ok, _block_undo, _} = SideEffects.handle(block_undo)
+ test "deletes the original block", %{
+ block_undo: block_undo,
+ block: block
+ } do
+ {:ok, _block_undo, _meta} = SideEffects.handle(block_undo)
+
refute Activity.get_by_id(block.id)
end
@@ -524,10 +610,29 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
end
test "it streams out the announce", %{announce: announce} do
- with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough], stream_out: fn _ -> nil end do
+ with_mocks([
+ {
+ Pleroma.Web.Streamer,
+ [],
+ [
+ stream: fn _, _ -> nil end
+ ]
+ },
+ {
+ Pleroma.Web.Push,
+ [],
+ [
+ send: fn _ -> nil end
+ ]
+ }
+ ]) do
{:ok, announce, _} = SideEffects.handle(announce)
- assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(announce))
+ assert called(
+ Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], announce)
+ )
+
+ assert called(Pleroma.Web.Push.send(:_))
end
end
end
diff --git a/test/web/activity_pub/transmogrifier/accept_handling_test.exs b/test/web/activity_pub/transmogrifier/accept_handling_test.exs
new file mode 100644
index 000000000..77d468f5c
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/accept_handling_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.ActivityPub.Transmogrifier.AcceptHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "it works for incoming accepts which were pre-accepted" do
+ follower = insert(:user)
+ followed = insert(:user)
+
+ {:ok, follower} = User.follow(follower, followed)
+ assert User.following?(follower, followed) == true
+
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
+
+ accept_data =
+ File.read!("test/fixtures/mastodon-accept-activity.json")
+ |> Poison.decode!()
+ |> Map.put("actor", followed.ap_id)
+
+ object =
+ accept_data["object"]
+ |> Map.put("actor", follower.ap_id)
+ |> Map.put("id", follow_activity.data["id"])
+
+ accept_data = Map.put(accept_data, "object", object)
+
+ {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
+ refute activity.local
+
+ assert activity.data["object"] == follow_activity.data["id"]
+
+ assert activity.data["id"] == accept_data["id"]
+
+ follower = User.get_cached_by_id(follower.id)
+
+ assert User.following?(follower, followed) == true
+ end
+
+ test "it works for incoming accepts which are referenced by IRI only" do
+ follower = insert(:user)
+ followed = insert(:user, locked: true)
+
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
+
+ accept_data =
+ File.read!("test/fixtures/mastodon-accept-activity.json")
+ |> Poison.decode!()
+ |> Map.put("actor", followed.ap_id)
+ |> Map.put("object", follow_activity.data["id"])
+
+ {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
+ assert activity.data["object"] == follow_activity.data["id"]
+
+ 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
+ follower = insert(:user)
+ followed = insert(:user, locked: true)
+
+ accept_data =
+ File.read!("test/fixtures/mastodon-accept-activity.json")
+ |> Poison.decode!()
+ |> Map.put("actor", followed.ap_id)
+
+ accept_data =
+ Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
+
+ {:error, _} = Transmogrifier.handle_incoming(accept_data)
+
+ follower = User.get_cached_by_id(follower.id)
+
+ refute User.following?(follower, followed) == true
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/answer_handling_test.exs b/test/web/activity_pub/transmogrifier/answer_handling_test.exs
new file mode 100644
index 000000000..0f6605c3f
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/answer_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.AnswerHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
+ test "incoming, rewrites Note to Answer and increments vote counters" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ status: "suya...",
+ poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
+ })
+
+ object = Object.normalize(activity)
+
+ data =
+ File.read!("test/fixtures/mastodon-vote.json")
+ |> Poison.decode!()
+ |> Kernel.put_in(["to"], user.ap_id)
+ |> Kernel.put_in(["object", "inReplyTo"], object.data["id"])
+ |> Kernel.put_in(["object", "to"], user.ap_id)
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+ answer_object = Object.normalize(activity)
+ assert answer_object.data["type"] == "Answer"
+ assert answer_object.data["inReplyTo"] == object.data["id"]
+
+ new_object = Object.get_by_ap_id(object.data["id"])
+ assert new_object.data["replies_count"] == object.data["replies_count"]
+
+ assert Enum.any?(
+ new_object.data["oneOf"],
+ fn
+ %{"name" => "suya..", "replies" => %{"totalItems" => 1}} -> true
+ _ -> false
+ end
+ )
+ end
+
+ test "outgoing, rewrites Answer to Note" do
+ user = insert(:user)
+
+ {:ok, poll_activity} =
+ CommonAPI.post(user, %{
+ status: "suya...",
+ poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
+ })
+
+ poll_object = Object.normalize(poll_activity)
+ # TODO: Replace with CommonAPI vote creation when implemented
+ data =
+ File.read!("test/fixtures/mastodon-vote.json")
+ |> Poison.decode!()
+ |> Kernel.put_in(["to"], user.ap_id)
+ |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"])
+ |> Kernel.put_in(["object", "to"], user.ap_id)
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+ {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
+
+ assert data["object"]["type"] == "Note"
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/audio_handling_test.exs b/test/web/activity_pub/transmogrifier/audio_handling_test.exs
new file mode 100644
index 000000000..0636d00c5
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/audio_handling_test.exs
@@ -0,0 +1,83 @@
+# 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.AudioHandlingTest do
+ use Oban.Testing, repo: Pleroma.Repo
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+
+ import Pleroma.Factory
+
+ test "it works for incoming listens" do
+ _user = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
+
+ data = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "type" => "Listen",
+ "id" => "http://mastodon.example.org/users/admin/listens/1234/activity",
+ "actor" => "http://mastodon.example.org/users/admin",
+ "object" => %{
+ "type" => "Audio",
+ "id" => "http://mastodon.example.org/users/admin/listens/1234",
+ "attributedTo" => "http://mastodon.example.org/users/admin",
+ "title" => "lain radio episode 1",
+ "artist" => "lain",
+ "album" => "lain radio",
+ "length" => 180_000
+ }
+ }
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ object = Object.normalize(activity)
+
+ assert object.data["title"] == "lain radio episode 1"
+ assert object.data["artist"] == "lain"
+ assert object.data["album"] == "lain radio"
+ assert object.data["length"] == 180_000
+ end
+
+ test "Funkwhale Audio object" do
+ Tesla.Mock.mock(fn
+ %{url: "https://channels.tests.funkwhale.audio/federation/actors/compositions"} ->
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/funkwhale_channel.json")
+ }
+ end)
+
+ data = File.read!("test/fixtures/tesla_mock/funkwhale_create_audio.json") |> Poison.decode!()
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ assert object = Object.normalize(activity, false)
+
+ assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
+
+ assert object.data["cc"] == []
+
+ assert object.data["url"] == "https://channels.tests.funkwhale.audio/library/tracks/74"
+
+ assert object.data["attachment"] == [
+ %{
+ "mediaType" => "audio/ogg",
+ "type" => "Link",
+ "name" => nil,
+ "url" => [
+ %{
+ "href" =>
+ "https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false",
+ "mediaType" => "audio/ogg",
+ "type" => "Link"
+ }
+ ]
+ }
+ ]
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/block_handling_test.exs b/test/web/activity_pub/transmogrifier/block_handling_test.exs
new file mode 100644
index 000000000..71f1a0ed5
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/block_handling_test.exs
@@ -0,0 +1,63 @@
+# 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.BlockHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+
+ import Pleroma.Factory
+
+ test "it works for incoming blocks" do
+ user = insert(:user)
+
+ data =
+ File.read!("test/fixtures/mastodon-block-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", user.ap_id)
+
+ blocker = insert(:user, ap_id: data["actor"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["type"] == "Block"
+ assert data["object"] == user.ap_id
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+
+ assert User.blocks?(blocker, user)
+ end
+
+ test "incoming blocks successfully tear down any follow relationship" do
+ blocker = insert(:user)
+ blocked = insert(:user)
+
+ data =
+ File.read!("test/fixtures/mastodon-block-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", blocked.ap_id)
+ |> Map.put("actor", blocker.ap_id)
+
+ {:ok, blocker} = User.follow(blocker, blocked)
+ {:ok, blocked} = User.follow(blocked, blocker)
+
+ assert User.following?(blocker, blocked)
+ assert User.following?(blocked, blocker)
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["type"] == "Block"
+ assert data["object"] == blocked.ap_id
+ assert data["actor"] == blocker.ap_id
+
+ blocker = User.get_cached_by_ap_id(data["actor"])
+ blocked = User.get_cached_by_ap_id(data["object"])
+
+ assert User.blocks?(blocker, blocked)
+
+ refute User.following?(blocker, blocked)
+ refute User.following?(blocked, blocker)
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/chat_message_test.exs b/test/web/activity_pub/transmogrifier/chat_message_test.exs
index d6736dc3e..31274c067 100644
--- a/test/web/activity_pub/transmogrifier/chat_message_test.exs
+++ b/test/web/activity_pub/transmogrifier/chat_message_test.exs
@@ -124,6 +124,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do
{:ok, %Activity{} = _activity} = Transmogrifier.handle_incoming(data)
end
+ test "it doesn't work for deactivated 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(),
+ deactivated: true
+ )
+
+ _recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
+
+ assert {:error, _} = Transmogrifier.handle_incoming(data)
+ end
+
test "it inserts it and creates a chat" do
data =
File.read!("test/fixtures/create-chat-message.json")
diff --git a/test/web/activity_pub/transmogrifier/event_handling_test.exs b/test/web/activity_pub/transmogrifier/event_handling_test.exs
new file mode 100644
index 000000000..7f1ef2cbd
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/event_handling_test.exs
@@ -0,0 +1,40 @@
+# 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.EventHandlingTest do
+ use Oban.Testing, repo: Pleroma.Repo
+ use Pleroma.DataCase
+
+ alias Pleroma.Object.Fetcher
+
+ test "Mobilizon Event object" do
+ Tesla.Mock.mock(fn
+ %{url: "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"} ->
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/mobilizon.org-event.json")
+ }
+
+ %{url: "https://mobilizon.org/@tcit"} ->
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/mobilizon.org-user.json")
+ }
+ end)
+
+ assert {:ok, object} =
+ Fetcher.fetch_object_from_id(
+ "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
+ )
+
+ assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
+ assert object.data["cc"] == []
+
+ assert object.data["url"] ==
+ "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
+
+ assert object.data["published"] == "2019-12-17T11:33:56Z"
+ assert object.data["name"] == "Mobilizon Launching Party"
+ 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 06c39eed6..757d90941 100644
--- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs
+++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs
@@ -160,7 +160,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
|> Poison.decode!()
|> Map.put("object", user.ap_id)
- with_mock Pleroma.User, [:passthrough], follow: fn _, _ -> {:error, :testing} end do
+ with_mock Pleroma.User, [:passthrough], follow: fn _, _, _ -> {:error, :testing} end do
{:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
%Activity{} = activity = Activity.get_by_ap_id(id)
@@ -185,5 +185,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end
+
+ test "it works for incoming follows to locked account" do
+ pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
+ user = insert(:user, locked: true)
+
+ data =
+ File.read!("test/fixtures/mastodon-follow-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", user.ap_id)
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["type"] == "Follow"
+ assert data["object"] == user.ap_id
+ assert data["state"] == "pending"
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+
+ assert [^pending_follower] = User.get_follow_requests(user)
+ end
end
end
diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs
new file mode 100644
index 000000000..74ee79543
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/question_handling_test.exs
@@ -0,0 +1,176 @@
+# 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.QuestionHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
+ test "Mastodon Question activity" do
+ data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!()
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ object = Object.normalize(activity, false)
+
+ assert object.data["url"] == "https://mastodon.sdf.org/@rinpatch/102070944809637304"
+
+ assert object.data["closed"] == "2019-05-11T09:03:36Z"
+
+ assert object.data["context"] == activity.data["context"]
+
+ assert object.data["context"] ==
+ "tag:mastodon.sdf.org,2019-05-10:objectId=15095122:objectType=Conversation"
+
+ assert object.data["context_id"]
+
+ assert object.data["anyOf"] == []
+
+ assert Enum.sort(object.data["oneOf"]) ==
+ Enum.sort([
+ %{
+ "name" => "25 char limit is dumb",
+ "replies" => %{"totalItems" => 0, "type" => "Collection"},
+ "type" => "Note"
+ },
+ %{
+ "name" => "Dunno",
+ "replies" => %{"totalItems" => 0, "type" => "Collection"},
+ "type" => "Note"
+ },
+ %{
+ "name" => "Everyone knows that!",
+ "replies" => %{"totalItems" => 1, "type" => "Collection"},
+ "type" => "Note"
+ },
+ %{
+ "name" => "I can't even fit a funny",
+ "replies" => %{"totalItems" => 1, "type" => "Collection"},
+ "type" => "Note"
+ }
+ ])
+
+ user = insert(:user)
+
+ {:ok, reply_activity} = CommonAPI.post(user, %{status: "hewwo", in_reply_to_id: activity.id})
+
+ reply_object = Object.normalize(reply_activity, false)
+
+ assert reply_object.data["context"] == object.data["context"]
+ assert reply_object.data["context_id"] == object.data["context_id"]
+ end
+
+ test "Mastodon Question activity with HTML tags in plaintext" do
+ options = [
+ %{
+ "type" => "Note",
+ "name" => "<input type=\"date\">",
+ "replies" => %{"totalItems" => 0, "type" => "Collection"}
+ },
+ %{
+ "type" => "Note",
+ "name" => "<input type=\"date\"/>",
+ "replies" => %{"totalItems" => 0, "type" => "Collection"}
+ },
+ %{
+ "type" => "Note",
+ "name" => "<input type=\"date\" />",
+ "replies" => %{"totalItems" => 1, "type" => "Collection"}
+ },
+ %{
+ "type" => "Note",
+ "name" => "<input type=\"date\"></input>",
+ "replies" => %{"totalItems" => 1, "type" => "Collection"}
+ }
+ ]
+
+ data =
+ File.read!("test/fixtures/mastodon-question-activity.json")
+ |> Poison.decode!()
+ |> Kernel.put_in(["object", "oneOf"], options)
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+ object = Object.normalize(activity, false)
+
+ assert Enum.sort(object.data["oneOf"]) == Enum.sort(options)
+ end
+
+ test "Mastodon Question activity with custom emojis" do
+ options = [
+ %{
+ "type" => "Note",
+ "name" => ":blobcat:",
+ "replies" => %{"totalItems" => 0, "type" => "Collection"}
+ },
+ %{
+ "type" => "Note",
+ "name" => ":blobfox:",
+ "replies" => %{"totalItems" => 0, "type" => "Collection"}
+ }
+ ]
+
+ tag = [
+ %{
+ "icon" => %{
+ "type" => "Image",
+ "url" => "https://blob.cat/emoji/custom/blobcats/blobcat.png"
+ },
+ "id" => "https://blob.cat/emoji/custom/blobcats/blobcat.png",
+ "name" => ":blobcat:",
+ "type" => "Emoji",
+ "updated" => "1970-01-01T00:00:00Z"
+ },
+ %{
+ "icon" => %{"type" => "Image", "url" => "https://blob.cat/emoji/blobfox/blobfox.png"},
+ "id" => "https://blob.cat/emoji/blobfox/blobfox.png",
+ "name" => ":blobfox:",
+ "type" => "Emoji",
+ "updated" => "1970-01-01T00:00:00Z"
+ }
+ ]
+
+ data =
+ File.read!("test/fixtures/mastodon-question-activity.json")
+ |> Poison.decode!()
+ |> Kernel.put_in(["object", "oneOf"], options)
+ |> Kernel.put_in(["object", "tag"], tag)
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+ object = Object.normalize(activity, false)
+
+ assert object.data["oneOf"] == options
+
+ assert object.data["emoji"] == %{
+ "blobcat" => "https://blob.cat/emoji/custom/blobcats/blobcat.png",
+ "blobfox" => "https://blob.cat/emoji/blobfox/blobfox.png"
+ }
+ end
+
+ test "returns an error if received a second time" do
+ data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!()
+
+ assert {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ assert {:error, {:validate_object, {:error, _}}} = Transmogrifier.handle_incoming(data)
+ end
+
+ test "accepts a Question with no content" do
+ data =
+ File.read!("test/fixtures/mastodon-question-activity.json")
+ |> Poison.decode!()
+ |> Kernel.put_in(["object", "content"], "")
+
+ assert {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/reject_handling_test.exs b/test/web/activity_pub/transmogrifier/reject_handling_test.exs
new file mode 100644
index 000000000..7592fbe1c
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/reject_handling_test.exs
@@ -0,0 +1,67 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.RejectHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "it fails for incoming rejects which cannot be correlated" do
+ follower = insert(:user)
+ followed = insert(:user, locked: true)
+
+ accept_data =
+ File.read!("test/fixtures/mastodon-reject-activity.json")
+ |> Poison.decode!()
+ |> Map.put("actor", followed.ap_id)
+
+ accept_data =
+ Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
+
+ {:error, _} = Transmogrifier.handle_incoming(accept_data)
+
+ follower = User.get_cached_by_id(follower.id)
+
+ refute User.following?(follower, followed) == true
+ end
+
+ test "it works for incoming rejects which are referenced by IRI only" do
+ follower = insert(:user)
+ followed = insert(:user, locked: true)
+
+ {:ok, follower} = User.follow(follower, followed)
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
+
+ assert User.following?(follower, followed) == true
+
+ reject_data =
+ File.read!("test/fixtures/mastodon-reject-activity.json")
+ |> Poison.decode!()
+ |> Map.put("actor", followed.ap_id)
+ |> Map.put("object", follow_activity.data["id"])
+
+ {:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data)
+
+ follower = User.get_cached_by_id(follower.id)
+
+ assert User.following?(follower, followed) == false
+ end
+
+ test "it rejects activities without a valid ID" do
+ user = insert(:user)
+
+ data =
+ File.read!("test/fixtures/mastodon-follow-activity.json")
+ |> Poison.decode!()
+ |> Map.put("object", user.ap_id)
+ |> Map.put("id", "")
+
+ :error = Transmogrifier.handle_incoming(data)
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs
index 01dd6c370..8683f7135 100644
--- a/test/web/activity_pub/transmogrifier/undo_handling_test.exs
+++ b/test/web/activity_pub/transmogrifier/undo_handling_test.exs
@@ -130,7 +130,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
end
- test "it works for incomming unfollows with an existing follow" do
+ test "it works for incoming unfollows with an existing follow" do
user = insert(:user)
follow_data =
diff --git a/test/web/activity_pub/transmogrifier/user_update_handling_test.exs b/test/web/activity_pub/transmogrifier/user_update_handling_test.exs
new file mode 100644
index 000000000..64636656c
--- /dev/null
+++ b/test/web/activity_pub/transmogrifier/user_update_handling_test.exs
@@ -0,0 +1,159 @@
+# 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.UserUpdateHandlingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.Activity
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Transmogrifier
+
+ import Pleroma.Factory
+
+ test "it works for incoming update activities" do
+ user = insert(:user, local: false)
+
+ update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
+
+ object =
+ update_data["object"]
+ |> Map.put("actor", user.ap_id)
+ |> Map.put("id", user.ap_id)
+
+ update_data =
+ update_data
+ |> Map.put("actor", user.ap_id)
+ |> Map.put("object", object)
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
+
+ assert data["id"] == update_data["id"]
+
+ user = User.get_cached_by_ap_id(data["actor"])
+ assert user.name == "gargle"
+
+ assert user.avatar["url"] == [
+ %{
+ "href" =>
+ "https://cd.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
+ }
+ ]
+
+ assert user.banner["url"] == [
+ %{
+ "href" =>
+ "https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
+ }
+ ]
+
+ assert user.bio == "<p>Some bio</p>"
+ end
+
+ test "it works with alsoKnownAs" do
+ %{ap_id: actor} = insert(:user, local: false)
+
+ assert User.get_cached_by_ap_id(actor).also_known_as == []
+
+ {:ok, _activity} =
+ "test/fixtures/mastodon-update.json"
+ |> File.read!()
+ |> Poison.decode!()
+ |> Map.put("actor", actor)
+ |> Map.update!("object", fn object ->
+ object
+ |> Map.put("actor", actor)
+ |> Map.put("id", actor)
+ |> Map.put("alsoKnownAs", [
+ "http://mastodon.example.org/users/foo",
+ "http://example.org/users/bar"
+ ])
+ end)
+ |> Transmogrifier.handle_incoming()
+
+ assert User.get_cached_by_ap_id(actor).also_known_as == [
+ "http://mastodon.example.org/users/foo",
+ "http://example.org/users/bar"
+ ]
+ end
+
+ test "it works with custom profile fields" do
+ user = insert(:user, local: false)
+
+ assert user.fields == []
+
+ update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
+
+ object =
+ update_data["object"]
+ |> Map.put("actor", user.ap_id)
+ |> Map.put("id", user.ap_id)
+
+ update_data =
+ update_data
+ |> Map.put("actor", user.ap_id)
+ |> Map.put("object", object)
+
+ {:ok, _update_activity} = Transmogrifier.handle_incoming(update_data)
+
+ user = User.get_cached_by_ap_id(user.ap_id)
+
+ assert user.fields == [
+ %{"name" => "foo", "value" => "updated"},
+ %{"name" => "foo1", "value" => "updated"}
+ ]
+
+ Pleroma.Config.put([:instance, :max_remote_account_fields], 2)
+
+ update_data =
+ update_data
+ |> put_in(["object", "attachment"], [
+ %{"name" => "foo", "type" => "PropertyValue", "value" => "bar"},
+ %{"name" => "foo11", "type" => "PropertyValue", "value" => "bar11"},
+ %{"name" => "foo22", "type" => "PropertyValue", "value" => "bar22"}
+ ])
+ |> Map.put("id", update_data["id"] <> ".")
+
+ {:ok, _} = Transmogrifier.handle_incoming(update_data)
+
+ user = User.get_cached_by_ap_id(user.ap_id)
+
+ assert user.fields == [
+ %{"name" => "foo", "value" => "updated"},
+ %{"name" => "foo1", "value" => "updated"}
+ ]
+
+ update_data =
+ update_data
+ |> put_in(["object", "attachment"], [])
+ |> Map.put("id", update_data["id"] <> ".")
+
+ {:ok, _} = Transmogrifier.handle_incoming(update_data)
+
+ user = User.get_cached_by_ap_id(user.ap_id)
+
+ assert user.fields == []
+ end
+
+ test "it works for incoming update activities which lock the account" do
+ user = insert(:user, local: false)
+
+ update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
+
+ object =
+ update_data["object"]
+ |> Map.put("actor", user.ap_id)
+ |> Map.put("id", user.ap_id)
+ |> Map.put("manuallyApprovesFollowers", true)
+
+ update_data =
+ update_data
+ |> Map.put("actor", user.ap_id)
+ |> Map.put("object", object)
+
+ {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(update_data)
+
+ user = User.get_cached_by_ap_id(user.ap_id)
+ assert user.locked == true
+ end
+end
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 94d8552e8..cc55a7be7 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -11,7 +11,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
alias Pleroma.Object.Fetcher
alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
@@ -106,7 +105,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
object =
data["object"]
- |> Map.put("inReplyTo", "https://shitposter.club/notice/2827873")
+ |> Map.put("inReplyTo", "https://mstdn.io/users/mayuutann/statuses/99568293732299394")
data = Map.put(data, "object", object)
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
@@ -114,10 +113,11 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert activity =
Activity.get_create_by_object_ap_id(
- "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
+ "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
)
- assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
+ assert returned_object.data["inReplyTo"] ==
+ "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
end
test "it does not fetch reply-to activities beyond max replies depth limit" do
@@ -141,8 +141,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
)
- assert returned_object.data["inReplyToAtomUri"] ==
- "https://shitposter.club/notice/2827873"
+ assert returned_object.data["inReplyTo"] == "https://shitposter.club/notice/2827873"
end
end
@@ -161,7 +160,15 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert capture_log(fn ->
{:ok, _returned_activity} = Transmogrifier.handle_incoming(data)
- end) =~ "[error] Couldn't fetch \"https://404.site/whatever\", error: nil"
+ end) =~ "[warn] Couldn't fetch \"https://404.site/whatever\", error: nil"
+ end
+
+ test "it does not work for deactivated users" do
+ data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
+
+ insert(:user, ap_id: data["actor"], deactivated: true)
+
+ assert {:error, _} = Transmogrifier.handle_incoming(data)
end
test "it works for incoming notices" do
@@ -218,84 +225,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert Enum.at(object.data["tag"], 2) == "moo"
end
- test "it works for incoming questions" do
- data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!()
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- object = Object.normalize(activity)
-
- assert Enum.all?(object.data["oneOf"], fn choice ->
- choice["name"] in [
- "Dunno",
- "Everyone knows that!",
- "25 char limit is dumb",
- "I can't even fit a funny"
- ]
- end)
- end
-
- test "it works for incoming listens" do
- data = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [],
- "type" => "Listen",
- "id" => "http://mastodon.example.org/users/admin/listens/1234/activity",
- "actor" => "http://mastodon.example.org/users/admin",
- "object" => %{
- "type" => "Audio",
- "id" => "http://mastodon.example.org/users/admin/listens/1234",
- "attributedTo" => "http://mastodon.example.org/users/admin",
- "title" => "lain radio episode 1",
- "artist" => "lain",
- "album" => "lain radio",
- "length" => 180_000
- }
- }
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- object = Object.normalize(activity)
-
- assert object.data["title"] == "lain radio episode 1"
- assert object.data["artist"] == "lain"
- assert object.data["album"] == "lain radio"
- assert object.data["length"] == 180_000
- end
-
- test "it rewrites Note votes to Answers and increments vote counters on question activities" do
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- status: "suya...",
- poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
- })
-
- object = Object.normalize(activity)
-
- data =
- File.read!("test/fixtures/mastodon-vote.json")
- |> Poison.decode!()
- |> Kernel.put_in(["to"], user.ap_id)
- |> Kernel.put_in(["object", "inReplyTo"], object.data["id"])
- |> Kernel.put_in(["object", "to"], user.ap_id)
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
- answer_object = Object.normalize(activity)
- assert answer_object.data["type"] == "Answer"
- object = Object.get_by_ap_id(object.data["id"])
-
- assert Enum.any?(
- object.data["oneOf"],
- fn
- %{"name" => "suya..", "replies" => %{"totalItems" => 1}} -> true
- _ -> false
- end
- )
- end
-
test "it works for incoming notices with contentMap" do
data =
File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!()
@@ -401,163 +330,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute Map.has_key?(object_data, "reaction_count")
end
- test "it works for incoming update activities" do
- data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
-
- object =
- update_data["object"]
- |> Map.put("actor", data["actor"])
- |> Map.put("id", data["actor"])
-
- update_data =
- update_data
- |> Map.put("actor", data["actor"])
- |> Map.put("object", object)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
-
- assert data["id"] == update_data["id"]
-
- user = User.get_cached_by_ap_id(data["actor"])
- assert user.name == "gargle"
-
- assert user.avatar["url"] == [
- %{
- "href" =>
- "https://cd.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
- }
- ]
-
- assert user.banner["url"] == [
- %{
- "href" =>
- "https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
- }
- ]
-
- assert user.bio == "<p>Some bio</p>"
- end
-
- test "it works with alsoKnownAs" do
- {:ok, %Activity{data: %{"actor" => actor}}} =
- "test/fixtures/mastodon-post-activity.json"
- |> File.read!()
- |> Poison.decode!()
- |> Transmogrifier.handle_incoming()
-
- assert User.get_cached_by_ap_id(actor).also_known_as == ["http://example.org/users/foo"]
-
- {:ok, _activity} =
- "test/fixtures/mastodon-update.json"
- |> File.read!()
- |> Poison.decode!()
- |> Map.put("actor", actor)
- |> Map.update!("object", fn object ->
- object
- |> Map.put("actor", actor)
- |> Map.put("id", actor)
- |> Map.put("alsoKnownAs", [
- "http://mastodon.example.org/users/foo",
- "http://example.org/users/bar"
- ])
- end)
- |> Transmogrifier.handle_incoming()
-
- assert User.get_cached_by_ap_id(actor).also_known_as == [
- "http://mastodon.example.org/users/foo",
- "http://example.org/users/bar"
- ]
- end
-
- test "it works with custom profile fields" do
- {:ok, activity} =
- "test/fixtures/mastodon-post-activity.json"
- |> File.read!()
- |> Poison.decode!()
- |> Transmogrifier.handle_incoming()
-
- user = User.get_cached_by_ap_id(activity.actor)
-
- assert user.fields == [
- %{"name" => "foo", "value" => "bar"},
- %{"name" => "foo1", "value" => "bar1"}
- ]
-
- update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
-
- object =
- update_data["object"]
- |> Map.put("actor", user.ap_id)
- |> Map.put("id", user.ap_id)
-
- update_data =
- update_data
- |> Map.put("actor", user.ap_id)
- |> Map.put("object", object)
-
- {:ok, _update_activity} = Transmogrifier.handle_incoming(update_data)
-
- user = User.get_cached_by_ap_id(user.ap_id)
-
- assert user.fields == [
- %{"name" => "foo", "value" => "updated"},
- %{"name" => "foo1", "value" => "updated"}
- ]
-
- Pleroma.Config.put([:instance, :max_remote_account_fields], 2)
-
- update_data =
- put_in(update_data, ["object", "attachment"], [
- %{"name" => "foo", "type" => "PropertyValue", "value" => "bar"},
- %{"name" => "foo11", "type" => "PropertyValue", "value" => "bar11"},
- %{"name" => "foo22", "type" => "PropertyValue", "value" => "bar22"}
- ])
-
- {:ok, _} = Transmogrifier.handle_incoming(update_data)
-
- user = User.get_cached_by_ap_id(user.ap_id)
-
- assert user.fields == [
- %{"name" => "foo", "value" => "updated"},
- %{"name" => "foo1", "value" => "updated"}
- ]
-
- update_data = put_in(update_data, ["object", "attachment"], [])
-
- {:ok, _} = Transmogrifier.handle_incoming(update_data)
-
- user = User.get_cached_by_ap_id(user.ap_id)
-
- assert user.fields == []
- end
-
- test "it works for incoming update activities which lock the account" do
- data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
-
- object =
- update_data["object"]
- |> Map.put("actor", data["actor"])
- |> Map.put("id", data["actor"])
- |> Map.put("manuallyApprovesFollowers", true)
-
- update_data =
- update_data
- |> Map.put("actor", data["actor"])
- |> Map.put("object", object)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
-
- user = User.get_cached_by_ap_id(data["actor"])
- assert user.locked == true
- end
-
- test "it works for incomming unfollows with an existing follow" do
+ test "it works for incoming unfollows with an existing follow" do
user = insert(:user)
follow_data =
@@ -582,254 +355,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end
- test "it works for incoming follows to locked account" do
- pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
- user = insert(:user, locked: true)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Follow"
- assert data["object"] == user.ap_id
- assert data["state"] == "pending"
- assert data["actor"] == "http://mastodon.example.org/users/admin"
-
- assert [^pending_follower] = User.get_follow_requests(user)
- end
-
- test "it works for incoming blocks" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-block-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Block"
- assert data["object"] == user.ap_id
- assert data["actor"] == "http://mastodon.example.org/users/admin"
-
- blocker = User.get_cached_by_ap_id(data["actor"])
-
- assert User.blocks?(blocker, user)
- end
-
- test "incoming blocks successfully tear down any follow relationship" do
- blocker = insert(:user)
- blocked = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-block-activity.json")
- |> Poison.decode!()
- |> Map.put("object", blocked.ap_id)
- |> Map.put("actor", blocker.ap_id)
-
- {:ok, blocker} = User.follow(blocker, blocked)
- {:ok, blocked} = User.follow(blocked, blocker)
-
- assert User.following?(blocker, blocked)
- assert User.following?(blocked, blocker)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Block"
- assert data["object"] == blocked.ap_id
- assert data["actor"] == blocker.ap_id
-
- blocker = User.get_cached_by_ap_id(data["actor"])
- blocked = User.get_cached_by_ap_id(data["object"])
-
- assert User.blocks?(blocker, blocked)
-
- refute User.following?(blocker, blocked)
- refute User.following?(blocked, blocker)
- end
-
- test "it works for incoming accepts which were pre-accepted" do
- follower = insert(:user)
- followed = insert(:user)
-
- {:ok, follower} = User.follow(follower, followed)
- assert User.following?(follower, followed) == true
-
- {:ok, follow_activity} = ActivityPub.follow(follower, followed)
-
- accept_data =
- File.read!("test/fixtures/mastodon-accept-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
-
- object =
- accept_data["object"]
- |> Map.put("actor", follower.ap_id)
- |> Map.put("id", follow_activity.data["id"])
-
- accept_data = Map.put(accept_data, "object", object)
-
- {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
- refute activity.local
-
- assert activity.data["object"] == follow_activity.data["id"]
-
- assert activity.data["id"] == accept_data["id"]
-
- follower = User.get_cached_by_id(follower.id)
-
- assert User.following?(follower, followed) == true
- end
-
- test "it works for incoming accepts which were orphaned" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- {:ok, follow_activity} = ActivityPub.follow(follower, followed)
-
- accept_data =
- File.read!("test/fixtures/mastodon-accept-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
-
- accept_data =
- Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
-
- {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
- assert activity.data["object"] == follow_activity.data["id"]
-
- follower = User.get_cached_by_id(follower.id)
-
- assert User.following?(follower, followed) == true
- end
-
- test "it works for incoming accepts which are referenced by IRI only" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- {:ok, follow_activity} = ActivityPub.follow(follower, followed)
-
- accept_data =
- File.read!("test/fixtures/mastodon-accept-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
- |> Map.put("object", follow_activity.data["id"])
-
- {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
- assert activity.data["object"] == follow_activity.data["id"]
-
- 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
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- accept_data =
- File.read!("test/fixtures/mastodon-accept-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
-
- accept_data =
- Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
-
- :error = Transmogrifier.handle_incoming(accept_data)
-
- follower = User.get_cached_by_id(follower.id)
-
- refute User.following?(follower, followed) == true
- end
-
- test "it fails for incoming rejects which cannot be correlated" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- accept_data =
- File.read!("test/fixtures/mastodon-reject-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
-
- accept_data =
- Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
-
- :error = Transmogrifier.handle_incoming(accept_data)
-
- follower = User.get_cached_by_id(follower.id)
-
- refute User.following?(follower, followed) == true
- end
-
- test "it works for incoming rejects which are orphaned" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- {:ok, follower} = User.follow(follower, followed)
- {:ok, _follow_activity} = ActivityPub.follow(follower, followed)
-
- assert User.following?(follower, followed) == true
-
- reject_data =
- File.read!("test/fixtures/mastodon-reject-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
-
- reject_data =
- Map.put(reject_data, "object", Map.put(reject_data["object"], "actor", follower.ap_id))
-
- {:ok, activity} = Transmogrifier.handle_incoming(reject_data)
- refute activity.local
- assert activity.data["id"] == reject_data["id"]
-
- follower = User.get_cached_by_id(follower.id)
-
- assert User.following?(follower, followed) == false
- end
-
- test "it works for incoming rejects which are referenced by IRI only" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- {:ok, follower} = User.follow(follower, followed)
- {:ok, follow_activity} = ActivityPub.follow(follower, followed)
-
- assert User.following?(follower, followed) == true
-
- reject_data =
- File.read!("test/fixtures/mastodon-reject-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
- |> Map.put("object", follow_activity.data["id"])
-
- {:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data)
-
- follower = User.get_cached_by_id(follower.id)
-
- assert User.following?(follower, followed) == false
- end
-
- test "it rejects activities without a valid ID" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
- |> Map.put("id", "")
-
- :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"
@@ -865,22 +390,46 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
)
- attachment = %{
- "type" => "Link",
- "mediaType" => "video/mp4",
- "url" => [
- %{
- "href" =>
- "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
- "mediaType" => "video/mp4"
- }
- ]
- }
-
assert object.data["url"] ==
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
- assert object.data["attachment"] == [attachment]
+ assert object.data["attachment"] == [
+ %{
+ "type" => "Link",
+ "mediaType" => "video/mp4",
+ "url" => [
+ %{
+ "href" =>
+ "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
+ ]
+ }
+ ]
+
+ {:ok, object} =
+ Fetcher.fetch_object_from_id(
+ "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"
+ )
+
+ assert object.data["attachment"] == [
+ %{
+ "type" => "Link",
+ "mediaType" => "video/mp4",
+ "url" => [
+ %{
+ "href" =>
+ "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
+ ]
+ }
+ ]
+
+ assert object.data["url"] ==
+ "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"
end
test "it accepts Flag activities" do
@@ -895,7 +444,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"id" => activity.data["id"],
"content" => "test post",
"published" => object.data["published"],
- "actor" => AccountView.render("show.json", %{user: user})
+ "actor" => AccountView.render("show.json", %{user: user, skip_visibility_check: true})
}
message = %{
@@ -959,6 +508,29 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert [user.follower_address] == activity.data["to"]
end
+ test "it correctly processes messages with weirdness in address fields" do
+ user = insert(:user)
+
+ message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "to" => [nil, user.follower_address],
+ "cc" => ["https://www.w3.org/ns/activitystreams#Public", ["¿"]],
+ "type" => "Create",
+ "object" => %{
+ "content" => "…",
+ "type" => "Note",
+ "attributedTo" => user.ap_id,
+ "inReplyTo" => nil
+ },
+ "actor" => user.ap_id
+ }
+
+ assert {:ok, activity} = Transmogrifier.handle_incoming(message)
+
+ assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"]
+ assert [user.follower_address] == activity.data["to"]
+ end
+
test "it accepts Move activities" do
old_user = insert(:user)
new_user = insert(:user)
@@ -1423,30 +995,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
end
end
- test "Rewrites Answers to Notes" do
- user = insert(:user)
-
- {:ok, poll_activity} =
- CommonAPI.post(user, %{
- status: "suya...",
- poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
- })
-
- poll_object = Object.normalize(poll_activity)
- # TODO: Replace with CommonAPI vote creation when implemented
- data =
- File.read!("test/fixtures/mastodon-vote.json")
- |> Poison.decode!()
- |> Kernel.put_in(["to"], user.ap_id)
- |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"])
- |> Kernel.put_in(["object", "to"], user.ap_id)
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
- {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert data["object"]["type"] == "Note"
- end
-
describe "fix_explicit_addressing" do
setup do
user = insert(:user)
@@ -1524,7 +1072,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert Transmogrifier.fix_in_reply_to(data) == data
end
- test "returns object with inReplyToAtomUri when denied incoming reply", %{data: data} do
+ test "returns object with inReplyTo when denied incoming reply", %{data: data} do
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
object_with_reply =
@@ -1532,26 +1080,22 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873"
- assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
object_with_reply =
Map.put(data["object"], "inReplyTo", %{"id" => "https://shitposter.club/notice/2827873"})
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] == %{"id" => "https://shitposter.club/notice/2827873"}
- assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
object_with_reply =
Map.put(data["object"], "inReplyTo", ["https://shitposter.club/notice/2827873"])
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] == ["https://shitposter.club/notice/2827873"]
- assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
object_with_reply = Map.put(data["object"], "inReplyTo", [])
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] == []
- assert modified_object["inReplyToAtomUri"] == ""
end
@tag capture_log: true
@@ -1560,22 +1104,17 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
Map.put(
data["object"],
"inReplyTo",
- "https://shitposter.club/notice/2827873"
+ "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
)
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 5)
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
assert modified_object["inReplyTo"] ==
- "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
-
- assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
-
- assert modified_object["conversation"] ==
- "tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26"
+ "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
assert modified_object["context"] ==
- "tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26"
+ "tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4"
end
end
@@ -1677,7 +1216,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
@tag capture_log: true
test "returns {:ok, %Object{}} for success case" do
assert {:ok, %Object{}} =
- Transmogrifier.get_obj_helper("https://shitposter.club/notice/2827873")
+ Transmogrifier.get_obj_helper(
+ "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
+ )
end
end
@@ -1697,8 +1238,13 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"attachment" => [
%{
"mediaType" => "video/mp4",
+ "type" => "Document",
"url" => [
- %{"href" => "https://peertube.moe/stat-480.mp4", "mediaType" => "video/mp4"}
+ %{
+ "href" => "https://peertube.moe/stat-480.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
]
}
]
@@ -1715,14 +1261,24 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"attachment" => [
%{
"mediaType" => "video/mp4",
+ "type" => "Document",
"url" => [
- %{"href" => "https://pe.er/stat-480.mp4", "mediaType" => "video/mp4"}
+ %{
+ "href" => "https://pe.er/stat-480.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
]
},
%{
"mediaType" => "video/mp4",
+ "type" => "Document",
"url" => [
- %{"href" => "https://pe.er/stat-480.mp4", "mediaType" => "video/mp4"}
+ %{
+ "href" => "https://pe.er/stat-480.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
]
}
]
diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs
index 15f03f193..d50213545 100644
--- a/test/web/activity_pub/utils_test.exs
+++ b/test/web/activity_pub/utils_test.exs
@@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
@@ -27,16 +26,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
end
end
- describe "fetch the latest Block" do
- test "fetches the latest Block activity" do
- blocker = insert(:user)
- blocked = insert(:user)
- {:ok, activity} = ActivityPub.block(blocker, blocked)
-
- assert activity == Utils.fetch_latest_block(blocker, blocked)
- end
- end
-
describe "determine_explicit_mentions()" do
test "works with an object that has mentions" do
object = %{
@@ -207,8 +196,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
user = insert(:user, locked: true)
follower = insert(:user)
- {:ok, follow_activity} = ActivityPub.follow(follower, user)
- {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
+ {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
data =
follow_activity_two.data
@@ -231,8 +220,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
user = insert(:user, locked: true)
follower = insert(:user)
- {:ok, follow_activity} = ActivityPub.follow(follower, user)
- {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
+ {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
data =
follow_activity_two.data
@@ -344,9 +333,9 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
user1 = insert(:user)
user2 = insert(:user)
- assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2)
- assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2)
- assert {:ok, %Activity{} = activity} = ActivityPub.block(user1, user2)
+ assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
+ assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
+ assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)
assert Utils.fetch_latest_block(user1, user2) == activity
end
@@ -493,7 +482,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
"id" => activity_ap_id,
"content" => content,
"published" => activity.object.data["published"],
- "actor" => AccountView.render("show.json", %{user: target_account})
+ "actor" =>
+ AccountView.render("show.json", %{user: target_account, skip_visibility_check: true})
}
assert %{
diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs
index bec15a996..98c7c9d09 100644
--- a/test/web/activity_pub/views/user_view_test.exs
+++ b/test/web/activity_pub/views/user_view_test.exs
@@ -158,4 +158,23 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
end
end
+
+ describe "acceptsChatMessages" do
+ test "it returns this value if it is set" do
+ true_user = insert(:user, accepts_chat_messages: true)
+ false_user = insert(:user, accepts_chat_messages: false)
+ nil_user = insert(:user, accepts_chat_messages: nil)
+
+ assert %{"capabilities" => %{"acceptsChatMessages" => true}} =
+ UserView.render("user.json", user: true_user)
+
+ assert %{"capabilities" => %{"acceptsChatMessages" => false}} =
+ UserView.render("user.json", user: false_user)
+
+ refute Map.has_key?(
+ UserView.render("user.json", user: nil_user)["capabilities"],
+ "acceptsChatMessages"
+ )
+ end
+ end
end
diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs
index e3d3ccb8d..3bc88c6a9 100644
--- a/test/web/admin_api/controllers/admin_api_controller_test.exs
+++ b/test/web/admin_api/controllers/admin_api_controller_test.exs
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
import ExUnit.CaptureLog
import Mock
import Pleroma.Factory
+ import Swoosh.TestAssertions
alias Pleroma.Activity
alias Pleroma.Config
@@ -41,6 +42,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
{:ok, %{admin: admin, token: token, conn: conn}}
end
+ test "with valid `admin_token` query parameter, skips OAuth scopes check" do
+ clear_config([:admin_token], "password123")
+
+ user = insert(:user)
+
+ conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123")
+
+ assert json_response(conn, 200)
+ end
+
describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
@@ -144,11 +155,30 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
describe "DELETE /api/pleroma/admin/users" do
test "single user", %{admin: admin, conn: conn} do
- user = insert(:user)
clear_config([:instance, :federating], true)
+ user =
+ insert(:user,
+ avatar: %{"url" => [%{"href" => "https://someurl"}]},
+ banner: %{"url" => [%{"href" => "https://somebanner"}]},
+ bio: "Hello world!",
+ name: "A guy"
+ )
+
+ # Create some activities to check they got deleted later
+ follower = insert(:user)
+ {:ok, _} = CommonAPI.post(user, %{status: "test"})
+ {:ok, _, _, _} = CommonAPI.follow(user, follower)
+ {:ok, _, _, _} = CommonAPI.follow(follower, user)
+ user = Repo.get(User, user.id)
+ assert user.note_count == 1
+ assert user.follower_count == 1
+ assert user.following_count == 1
+ refute user.deactivated
+
with_mock Pleroma.Web.Federator,
- publish: fn _ -> nil end do
+ publish: fn _ -> nil end,
+ perform: fn _, _ -> nil end do
conn =
conn
|> put_req_header("accept", "application/json")
@@ -165,6 +195,17 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
assert json_response(conn, 200) == [user.nickname]
+ user = Repo.get(User, user.id)
+ assert user.deactivated
+
+ assert user.avatar == %{}
+ assert user.banner == %{}
+ assert user.note_count == 0
+ assert user.follower_count == 0
+ assert user.following_count == 0
+ assert user.bio == ""
+ assert user.name == nil
+
assert called(Pleroma.Web.Federator.publish(:_))
end
end
@@ -338,7 +379,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
assert expected == json_response(conn, 200)
@@ -426,7 +470,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
user1: user1,
user2: user2
} do
- assert json_response(conn, :no_content)
+ assert empty_json_response(conn)
assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
@@ -444,7 +488,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
- assert json_response(conn, :no_content)
+ assert empty_json_response(conn)
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
end
end
@@ -472,7 +516,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
user1: user1,
user2: user2
} do
- assert json_response(conn, :no_content)
+ assert empty_json_response(conn)
assert User.get_cached_by_id(user1.id).tags == []
assert User.get_cached_by_id(user2.id).tags == ["y"]
@@ -490,7 +534,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
- assert json_response(conn, :no_content)
+ assert empty_json_response(conn)
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
end
end
@@ -602,6 +646,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
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"])
+ user2 = insert(:user, approval_pending: true, registration_reason: "I'm a chill dude")
+
conn = get(conn, "/api/pleroma/admin/users?page=1")
users =
@@ -616,7 +662,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(admin.name || admin.nickname),
"confirmation_pending" => false,
- "url" => admin.ap_id
+ "approval_pending" => false,
+ "url" => admin.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
},
%{
"deactivated" => user.deactivated,
@@ -628,13 +677,31 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
+ },
+ %{
+ "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,
+ "approval_pending" => true,
+ "url" => user2.ap_id,
+ "registration_reason" => "I'm a chill dude",
+ "actor_type" => "Person"
}
]
|> Enum.sort_by(& &1["nickname"])
assert json_response(conn, 200) == %{
- "count" => 2,
+ "count" => 3,
"page_size" => 50,
"users" => users
}
@@ -701,7 +768,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -727,7 +797,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -753,7 +826,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -779,7 +855,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -805,7 +884,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -831,7 +913,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -852,7 +937,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user2) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user2.name || user2.nickname),
"confirmation_pending" => false,
- "url" => user2.ap_id
+ "approval_pending" => false,
+ "url" => user2.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -885,7 +973,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -911,7 +1002,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
},
%{
"deactivated" => admin.deactivated,
@@ -923,7 +1017,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(admin.name || admin.nickname),
"confirmation_pending" => false,
- "url" => admin.ap_id
+ "approval_pending" => false,
+ "url" => admin.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
},
%{
"deactivated" => false,
@@ -935,7 +1032,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"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
+ "approval_pending" => false,
+ "url" => old_admin.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
|> Enum.sort_by(& &1["nickname"])
@@ -947,6 +1047,45 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
}
end
+ test "only unapproved users", %{conn: conn} do
+ user =
+ insert(:user,
+ nickname: "sadboy",
+ approval_pending: true,
+ registration_reason: "Plz let me in!"
+ )
+
+ insert(:user, nickname: "happyboy", approval_pending: false)
+
+ conn = get(conn, "/api/pleroma/admin/users?filters=need_approval")
+
+ 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,
+ "approval_pending" => true,
+ "url" => user.ap_id,
+ "registration_reason" => "Plz let me in!",
+ "actor_type" => "Person"
+ }
+ ]
+ |> Enum.sort_by(& &1["nickname"])
+
+ assert json_response(conn, 200) == %{
+ "count" => 1,
+ "page_size" => 50,
+ "users" => users
+ }
+ end
+
test "load only admins", %{conn: conn, admin: admin} do
second_admin = insert(:user, is_admin: true)
insert(:user)
@@ -966,7 +1105,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(admin.name || admin.nickname),
"confirmation_pending" => false,
- "url" => admin.ap_id
+ "approval_pending" => false,
+ "url" => admin.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
},
%{
"deactivated" => false,
@@ -978,7 +1120,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"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
+ "approval_pending" => false,
+ "url" => second_admin.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
|> Enum.sort_by(& &1["nickname"])
@@ -1011,7 +1156,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
"confirmation_pending" => false,
- "url" => moderator.ap_id
+ "approval_pending" => false,
+ "url" => moderator.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -1037,7 +1185,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user1) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user1.name || user1.nickname),
"confirmation_pending" => false,
- "url" => user1.ap_id
+ "approval_pending" => false,
+ "url" => user1.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
},
%{
"deactivated" => false,
@@ -1049,7 +1200,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user2) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user2.name || user2.nickname),
"confirmation_pending" => false,
- "url" => user2.ap_id
+ "approval_pending" => false,
+ "url" => user2.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
|> Enum.sort_by(& &1["nickname"])
@@ -1061,6 +1215,27 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
}
end
+ test "`active` filters out users pending approval", %{token: token} do
+ insert(:user, approval_pending: true)
+ %{id: user_id} = insert(:user, approval_pending: false)
+ %{id: admin_id} = token.user
+
+ conn =
+ build_conn()
+ |> assign(:user, token.user)
+ |> assign(:token, token)
+ |> get("/api/pleroma/admin/users?filters=active")
+
+ assert %{
+ "count" => 2,
+ "page_size" => 50,
+ "users" => [
+ %{"id" => ^admin_id},
+ %{"id" => ^user_id}
+ ]
+ } = json_response(conn, 200)
+ end
+
test "it works with multiple filters" do
admin = insert(:user, nickname: "john", is_admin: true)
token = insert(:oauth_admin_token, user: admin)
@@ -1089,7 +1264,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -1114,7 +1292,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(admin.name || admin.nickname),
"confirmation_pending" => false,
- "url" => admin.ap_id
+ "approval_pending" => false,
+ "url" => admin.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
]
}
@@ -1161,6 +1342,26 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
end
+ test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do
+ user_one = insert(:user, approval_pending: true)
+ user_two = insert(:user, approval_pending: true)
+
+ conn =
+ patch(
+ conn,
+ "/api/pleroma/admin/users/approve",
+ %{nicknames: [user_one.nickname, user_two.nickname]}
+ )
+
+ response = json_response(conn, 200)
+ assert Enum.map(response["users"], & &1["approval_pending"]) == [false, false]
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} approved 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)
@@ -1177,7 +1378,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"avatar" => User.avatar_url(user) |> MediaProxy.url(),
"display_name" => HTML.strip_tags(user.name || user.nickname),
"confirmation_pending" => false,
- "url" => user.ap_id
+ "approval_pending" => false,
+ "url" => user.ap_id,
+ "registration_reason" => nil,
+ "actor_type" => "Person"
}
log_entry = Repo.one(ModerationLog)
@@ -1514,6 +1718,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
end
+ test "gets a remote users when [:instance, :limit_to_local_content] is set to :unauthenticated",
+ %{conn: conn} do
+ clear_config(Pleroma.Config.get([:instance, :limit_to_local_content]), :unauthenticated)
+ user = insert(:user, %{local: false, nickname: "u@peer1.com"})
+ conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
+
+ assert json_response(conn, 200)
+ end
+
describe "GET /users/:nickname/credentials" do
test "gets the user credentials", %{conn: conn} do
user = insert(:user)
@@ -1599,14 +1812,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
"actor_type" => "Application"
})
- |> json_response(200) == %{"errors" => %{"actor_type" => "is invalid"}}
+ |> json_response(400) == %{"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."}
+ |> json_response(404) == %{"error" => "Not found"}
end
end
@@ -1618,7 +1831,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
conn =
patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
- assert json_response(conn, 204) == ""
+ assert empty_json_response(conn) == ""
ObanHelpers.perform_all()
@@ -1712,6 +1925,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
second_user.nickname
}"
+
+ ObanHelpers.perform_all()
+ assert_email_sent(Pleroma.Emails.UserEmail.account_confirmation_email(first_user))
end
end
@@ -1732,6 +1948,26 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
response["status_visibility"]
end
+
+ test "by instance", %{conn: conn} do
+ admin = insert(:user, is_admin: true)
+ user1 = insert(:user)
+ instance2 = "instance2.tld"
+ user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
+
+ CommonAPI.post(user1, %{visibility: "public", status: "hey"})
+ CommonAPI.post(user2, %{visibility: "unlisted", status: "hey"})
+ CommonAPI.post(user2, %{visibility: "private", status: "hey"})
+
+ response =
+ conn
+ |> assign(:user, admin)
+ |> get("/api/pleroma/admin/stats", instance: instance2)
+ |> json_response(200)
+
+ assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
+ response["status_visibility"]
+ end
end
end
diff --git a/test/web/admin_api/controllers/config_controller_test.exs b/test/web/admin_api/controllers/config_controller_test.exs
index 780de8d18..4e897455f 100644
--- a/test/web/admin_api/controllers/config_controller_test.exs
+++ b/test/web/admin_api/controllers/config_controller_test.exs
@@ -57,12 +57,12 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
]
} = json_response_and_validate_schema(conn, 200)
- assert key1 == config1.key
- assert key2 == config2.key
+ 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: ConfigDB.to_binary(name: "Some name"))
+ _config = insert(:config, key: ":instance", value: [name: "Some name"])
%{"configs" => configs} =
conn
@@ -83,7 +83,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
config3 =
insert(:config,
- value: ConfigDB.to_binary(k1: :v1, k2: :v2)
+ value: [k1: :v1, k2: :v2]
)
%{"configs" => configs} =
@@ -93,42 +93,45 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
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 [config1.key, config2.key, config3.key]
+ group == ":pleroma" and key in keys
end)
assert length(received_configs) == 3
db_keys =
config3.value
- |> ConfigDB.from_binary()
|> Keyword.keys()
- |> ConfigDB.convert()
+ |> 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} ->
- assert db in [[config1.key], [config2.key], db_keys]
+ db = MapSet.new(db)
+ assert MapSet.subset?(db, mapset_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)
- ]
+ assert value in values
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])
- )
+ insert(:config,
+ key: ":emoji",
+ 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])
- )
+ insert(:config,
+ key: ":assets",
+ value: [mascots: [a: 1, b: 2], key: [a: 1]]
+ )
%{"configs" => configs} =
conn
@@ -137,18 +140,26 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
vals =
Enum.filter(configs, fn %{"group" => group, "key" => key} ->
- group == ":pleroma" and key in [config1.key, config2.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.transform_with_out_binary(emoji["value"])
- assets_val = ConfigDB.transform_with_out_binary(assets["value"])
+ 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
+
+ test "with valid `admin_token` query parameter, skips OAuth scopes check" do
+ clear_config([:admin_token], "password123")
+
+ build_conn()
+ |> get("/api/pleroma/admin/config?admin_token=password123")
+ |> json_response_and_validate_schema(200)
+ end
end
test "POST /api/pleroma/admin/config error", %{conn: conn} do
@@ -277,7 +288,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
"value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]},
"db" => [":key5"]
}
- ]
+ ],
+ "need_reboot" => false
}
assert Application.get_env(:pleroma, :key1) == "value1"
@@ -357,7 +369,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
"value" => "https://hooks.slack.com/services/KEY",
"db" => [":webhook_url"]
}
- ]
+ ],
+ "need_reboot" => false
}
assert Application.get_env(:quack, :level) == :info
@@ -366,14 +379,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
end
test "saving config with partial update", %{conn: conn} do
- config = insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2))
+ 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: config.group, key: config.key, value: [%{"tuple" => [":key3", 3]}]}
+ %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]}
]
})
@@ -389,7 +402,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
],
"db" => [":key1", ":key2", ":key3"]
}
- ]
+ ],
+ "need_reboot" => false
}
end
@@ -500,8 +514,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
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]))
+ insert(:config, key: :key1, value: [key1: 1, key2: [k1: 1, k2: 2]])
conn =
conn
@@ -509,8 +522,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|> post("/api/pleroma/admin/config", %{
configs: [
%{
- group: config.group,
- key: config.key,
+ group: ":pleroma",
+ key: ":key1",
value: [
%{"tuple" => [":key3", 3]},
%{
@@ -548,7 +561,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
],
"db" => [":key1", ":key3", ":key2"]
}
- ]
+ ],
+ "need_reboot" => false
}
end
@@ -588,7 +602,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
],
"db" => [":ssl_options"]
}
- ]
+ ],
+ "need_reboot" => false
}
assert Application.get_env(:pleroma, :key1) == [
@@ -600,12 +615,11 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest 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([])
- )
+ insert(:config,
+ group: :logger,
+ key: :backends,
+ value: []
+ )
Pleroma.Config.TransferTask.load_and_update_env([], false)
@@ -617,8 +631,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|> post("/api/pleroma/admin/config", %{
configs: [
%{
- group: config.group,
- key: config.key,
+ group: ":logger",
+ key: ":backends",
value: [":console"]
}
]
@@ -634,7 +648,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
],
"db" => [":backends"]
}
- ]
+ ],
+ "need_reboot" => false
}
assert Application.get_env(:logger, :backends) == [
@@ -643,19 +658,18 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
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)
- )
+ 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: config.group, key: config.key, value: "Tesla.Adapter.Httpc"}
+ %{group: ":tesla", key: ":adapter", value: "Tesla.Adapter.Httpc"}
]
})
@@ -667,7 +681,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
"value" => "Tesla.Adapter.Httpc",
"db" => [":adapter"]
}
- ]
+ ],
+ "need_reboot" => false
}
end
@@ -677,13 +692,13 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
token: token
} do
ueberauth = Application.get_env(:ueberauth, Ueberauth)
- config1 = insert(:config, key: ":keyaa1")
- config2 = insert(:config, key: ":keyaa2")
+ insert(:config, key: :keyaa1)
+ insert(:config, key: :keyaa2)
config3 =
insert(:config,
- group: ":ueberauth",
- key: "Ueberauth"
+ group: :ueberauth,
+ key: Ueberauth
)
conn =
@@ -691,8 +706,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|> put_req_header("content-type", "application/json")
|> post("/api/pleroma/admin/config", %{
configs: [
- %{group: config1.group, key: config1.key, value: "another_value"},
- %{group: config2.group, key: config2.key, value: "another_value"}
+ %{group: ":pleroma", key: ":keyaa1", value: "another_value"},
+ %{group: ":pleroma", key: ":keyaa2", value: "another_value"}
]
})
@@ -700,22 +715,23 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
"configs" => [
%{
"group" => ":pleroma",
- "key" => config1.key,
+ "key" => ":keyaa1",
"value" => "another_value",
"db" => [":keyaa1"]
},
%{
"group" => ":pleroma",
- "key" => config2.key,
+ "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) == ConfigDB.from_binary(config3.value)
+ assert Application.get_env(:ueberauth, Ueberauth) == config3.value
conn =
build_conn()
@@ -724,7 +740,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|> put_req_header("content-type", "application/json")
|> post("/api/pleroma/admin/config", %{
configs: [
- %{group: config2.group, key: config2.key, delete: true},
+ %{group: ":pleroma", key: ":keyaa2", delete: true},
%{
group: ":ueberauth",
key: "Ueberauth",
@@ -734,7 +750,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
})
assert json_response_and_validate_schema(conn, 200) == %{
- "configs" => []
+ "configs" => [],
+ "need_reboot" => false
}
assert Application.get_env(:ueberauth, Ueberauth) == ueberauth
@@ -801,7 +818,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
":name"
]
}
- ]
+ ],
+ "need_reboot" => false
}
end
@@ -935,7 +953,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
],
"db" => [":http"]
}
- ]
+ ],
+ "need_reboot" => false
}
end
@@ -1000,7 +1019,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
],
"db" => [":key2", ":key3"]
}
- ]
+ ],
+ "need_reboot" => false
}
end
@@ -1027,7 +1047,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
"value" => %{"key" => "some_val"},
"db" => [":key1"]
}
- ]
+ ],
+ "need_reboot" => false
}
end
@@ -1077,16 +1098,16 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
":background"
]
}
- ]
+ ],
+ "need_reboot" => false
}
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")
- )
+ insert(:config,
+ key: :keyaa1,
+ value: [subkey1: "val1", subkey2: "val2", subkey3: "val3"]
+ )
conn =
conn
@@ -1094,8 +1115,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|> post("/api/pleroma/admin/config", %{
configs: [
%{
- group: config.group,
- key: config.key,
+ group: ":pleroma",
+ key: ":keyaa1",
subkeys: [":subkey1", ":subkey3"],
delete: true
}
@@ -1110,7 +1131,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
"value" => [%{"tuple" => [":subkey2", "val2"]}],
"db" => [":subkey2"]
}
- ]
+ ],
+ "need_reboot" => false
}
end
@@ -1236,6 +1258,159 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
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
+
+ test "enables the welcome messages", %{conn: conn} do
+ clear_config([:welcome])
+
+ params = %{
+ "group" => ":pleroma",
+ "key" => ":welcome",
+ "value" => [
+ %{
+ "tuple" => [
+ ":direct_message",
+ [
+ %{"tuple" => [":enabled", true]},
+ %{"tuple" => [":message", "Welcome to Pleroma!"]},
+ %{"tuple" => [":sender_nickname", "pleroma"]}
+ ]
+ ]
+ },
+ %{
+ "tuple" => [
+ ":chat_message",
+ [
+ %{"tuple" => [":enabled", true]},
+ %{"tuple" => [":message", "Welcome to Pleroma!"]},
+ %{"tuple" => [":sender_nickname", "pleroma"]}
+ ]
+ ]
+ },
+ %{
+ "tuple" => [
+ ":email",
+ [
+ %{"tuple" => [":enabled", true]},
+ %{"tuple" => [":sender", %{"tuple" => ["pleroma@dev.dev", "Pleroma"]}]},
+ %{"tuple" => [":subject", "Welcome to <%= instance_name %>!"]},
+ %{"tuple" => [":html", "Welcome to <%= instance_name %>!"]},
+ %{"tuple" => [":text", "Welcome to <%= instance_name %>!"]}
+ ]
+ ]
+ }
+ ]
+ }
+
+ refute Pleroma.User.WelcomeEmail.enabled?()
+ refute Pleroma.User.WelcomeMessage.enabled?()
+ refute Pleroma.User.WelcomeChatMessage.enabled?()
+
+ res =
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/config", %{"configs" => [params]})
+ |> json_response_and_validate_schema(200)
+
+ assert Pleroma.User.WelcomeEmail.enabled?()
+ assert Pleroma.User.WelcomeMessage.enabled?()
+ assert Pleroma.User.WelcomeChatMessage.enabled?()
+
+ assert res == %{
+ "configs" => [
+ %{
+ "db" => [":direct_message", ":chat_message", ":email"],
+ "group" => ":pleroma",
+ "key" => ":welcome",
+ "value" => params["value"]
+ }
+ ],
+ "need_reboot" => false
+ }
+ end
end
describe "GET /api/pleroma/admin/config/descriptions" do
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..f243d1fb2
--- /dev/null
+++ b/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs
@@ -0,0 +1,167 @@
+# 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["page_size"] == 2
+ assert response["count"] == 5
+
+ 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"
+ ]
+
+ assert response["page_size"] == 2
+ assert response["count"] == 5
+
+ 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
+
+ test "search banned MediaProxy URLs", %{conn: conn} do
+ MediaProxy.put_in_banned_urls([
+ "http://localhost:4001/media/a688346.jpg",
+ "http://localhost:4001/media/ff44b1f4d.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&query=F44")
+ |> json_response_and_validate_schema(200)
+
+ assert response["urls"] == [
+ "http://localhost:4001/media/gb1f44.jpg",
+ "http://localhost:4001/media/ff44b1f4d.jpg"
+ ]
+
+ assert response["page_size"] == 2
+ assert response["count"] == 2
+ 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"
+ ])
+
+ 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)
+
+ 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
+ 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)
+
+ 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
+ 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 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/relay_controller_test.exs b/test/web/admin_api/controllers/relay_controller_test.exs
index 64086adc5..adadf2b5c 100644
--- a/test/web/admin_api/controllers/relay_controller_test.exs
+++ b/test/web/admin_api/controllers/relay_controller_test.exs
@@ -39,8 +39,10 @@ defmodule Pleroma.Web.AdminAPI.RelayControllerTest do
relay_url: "http://mastodon.example.org/users/admin"
})
- assert json_response_and_validate_schema(conn, 200) ==
- "http://mastodon.example.org/users/admin"
+ assert json_response_and_validate_schema(conn, 200) == %{
+ "actor" => "http://mastodon.example.org/users/admin",
+ "followed_back" => false
+ }
log_entry = Repo.one(ModerationLog)
@@ -59,8 +61,13 @@ defmodule Pleroma.Web.AdminAPI.RelayControllerTest do
conn = get(conn, "/api/pleroma/admin/relay")
- assert json_response_and_validate_schema(conn, 200)["relays"] --
- ["mastodon.example.org", "mstdn.io"] == []
+ assert json_response_and_validate_schema(conn, 200)["relays"] == [
+ %{
+ "actor" => "http://mastodon.example.org/users/admin",
+ "followed_back" => true
+ },
+ %{"actor" => "https://mstdn.io/users/mayuutann", "followed_back" => true}
+ ]
end
test "DELETE /relay", %{conn: conn, admin: admin} do
diff --git a/test/web/admin_api/controllers/report_controller_test.exs b/test/web/admin_api/controllers/report_controller_test.exs
index 940bce340..57946e6bb 100644
--- a/test/web/admin_api/controllers/report_controller_test.exs
+++ b/test/web/admin_api/controllers/report_controller_test.exs
@@ -204,7 +204,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
test "returns empty response when no reports created", %{conn: conn} do
response =
conn
- |> get("/api/pleroma/admin/reports")
+ |> get(report_path(conn, :index))
|> json_response_and_validate_schema(:ok)
assert Enum.empty?(response["reports"])
@@ -224,7 +224,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
response =
conn
- |> get("/api/pleroma/admin/reports")
+ |> get(report_path(conn, :index))
|> json_response_and_validate_schema(:ok)
[report] = response["reports"]
@@ -256,7 +256,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
response =
conn
- |> get("/api/pleroma/admin/reports?state=open")
+ |> get(report_path(conn, :index, %{state: "open"}))
|> json_response_and_validate_schema(:ok)
assert [open_report] = response["reports"]
@@ -268,7 +268,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
response =
conn
- |> get("/api/pleroma/admin/reports?state=closed")
+ |> get(report_path(conn, :index, %{state: "closed"}))
|> json_response_and_validate_schema(:ok)
assert [closed_report] = response["reports"]
@@ -280,9 +280,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
assert %{"total" => 0, "reports" => []} ==
conn
- |> get("/api/pleroma/admin/reports?state=resolved", %{
- "" => ""
- })
+ |> get(report_path(conn, :index, %{state: "resolved"}))
|> json_response_and_validate_schema(:ok)
end
@@ -297,7 +295,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|> get("/api/pleroma/admin/reports")
assert json_response(conn, :forbidden) ==
- %{"error" => "User is not an admin or OAuth admin scope is not granted."}
+ %{"error" => "User is not an admin."}
end
test "returns 403 when requested by anonymous" do
diff --git a/test/web/admin_api/search_test.exs b/test/web/admin_api/search_test.exs
index e0e3d4153..b974cedd5 100644
--- a/test/web/admin_api/search_test.exs
+++ b/test/web/admin_api/search_test.exs
@@ -166,5 +166,16 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do
assert total == 3
assert count == 1
end
+
+ test "it returns unapproved user" do
+ unapproved = insert(:user, approval_pending: true)
+ insert(:user)
+ insert(:user)
+
+ {:ok, _results, total} = Search.user()
+ {:ok, [^unapproved], count} = Search.user(%{need_approval: true})
+ assert total == 3
+ assert count == 1
+ 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 f00b0afb2..5a02292be 100644
--- a/test/web/admin_api/views/report_view_test.exs
+++ b/test/web/admin_api/views/report_view_test.exs
@@ -4,11 +4,14 @@
defmodule Pleroma.Web.AdminAPI.ReportViewTest do
use Pleroma.DataCase
+
import Pleroma.Factory
+
+ alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.Report
alias Pleroma.Web.AdminAPI.ReportView
alias Pleroma.Web.CommonAPI
- alias Pleroma.Web.MastodonAPI.AccountView
+ alias Pleroma.Web.MastodonAPI
alias Pleroma.Web.MastodonAPI.StatusView
test "renders a report" do
@@ -21,13 +24,16 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
content: nil,
actor:
Map.merge(
- AccountView.render("show.json", %{user: user}),
- Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
+ MastodonAPI.AccountView.render("show.json", %{user: user, skip_visibility_check: true}),
+ AdminAPI.AccountView.render("show.json", %{user: user})
),
account:
Map.merge(
- AccountView.render("show.json", %{user: other_user}),
- Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
+ MastodonAPI.AccountView.render("show.json", %{
+ user: other_user,
+ skip_visibility_check: true
+ }),
+ AdminAPI.AccountView.render("show.json", %{user: other_user})
),
statuses: [],
notes: [],
@@ -56,13 +62,16 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
content: nil,
actor:
Map.merge(
- AccountView.render("show.json", %{user: user}),
- Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
+ MastodonAPI.AccountView.render("show.json", %{user: user, skip_visibility_check: true}),
+ AdminAPI.AccountView.render("show.json", %{user: user})
),
account:
Map.merge(
- AccountView.render("show.json", %{user: other_user}),
- Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
+ MastodonAPI.AccountView.render("show.json", %{
+ user: other_user,
+ skip_visibility_check: true
+ }),
+ AdminAPI.AccountView.render("show.json", %{user: other_user})
),
statuses: [StatusView.render("show.json", %{activity: activity})],
state: "open",
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index 6bd26050e..5afb0a6dc 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -4,11 +4,14 @@
defmodule Pleroma.Web.CommonAPITest do
use Pleroma.DataCase
+ use Oban.Testing, repo: Pleroma.Repo
+
alias Pleroma.Activity
alias Pleroma.Chat
alias Pleroma.Conversation.Participation
alias Pleroma.Notification
alias Pleroma.Object
+ alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Transmogrifier
@@ -18,6 +21,7 @@ defmodule Pleroma.Web.CommonAPITest do
import Pleroma.Factory
import Mock
+ import Ecto.Query, only: [from: 2]
require Pleroma.Constants
@@ -25,6 +29,52 @@ defmodule Pleroma.Web.CommonAPITest do
setup do: clear_config([:instance, :limit])
setup do: clear_config([:instance, :max_pinned_statuses])
+ describe "blocking" do
+ setup do
+ blocker = insert(:user)
+ blocked = insert(:user)
+ User.follow(blocker, blocked)
+ User.follow(blocked, blocker)
+ %{blocker: blocker, blocked: blocked}
+ end
+
+ test "it blocks and federates", %{blocker: blocker, blocked: blocked} do
+ clear_config([:instance, :federating], true)
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ assert {:ok, block} = CommonAPI.block(blocker, blocked)
+
+ assert block.local
+ assert User.blocks?(blocker, blocked)
+ refute User.following?(blocker, blocked)
+ refute User.following?(blocked, blocker)
+
+ assert called(Pleroma.Web.Federator.publish(block))
+ end
+ end
+
+ test "it blocks and does not federate if outgoing blocks are disabled", %{
+ blocker: blocker,
+ blocked: blocked
+ } do
+ clear_config([:instance, :federating], true)
+ clear_config([:activitypub, :outgoing_blocks], false)
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ assert {:ok, block} = CommonAPI.block(blocker, blocked)
+
+ assert block.local
+ assert User.blocks?(blocker, blocked)
+ refute User.following?(blocker, blocked)
+ refute User.following?(blocked, blocker)
+
+ refute called(Pleroma.Web.Federator.publish(block))
+ end
+ end
+ end
+
describe "posting chat messages" do
setup do: clear_config([:instance, :chat_limit])
@@ -412,6 +462,11 @@ defmodule Pleroma.Web.CommonAPITest do
end
describe "posting" do
+ test "deactivated users can't post" do
+ user = insert(:user, deactivated: true)
+ assert {:error, _} = CommonAPI.post(user, %{status: "ye"})
+ end
+
test "it supports explicit addressing" do
user = insert(:user)
user_two = insert(:user)
@@ -445,6 +500,7 @@ defmodule Pleroma.Web.CommonAPITest do
object = Object.normalize(activity)
assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
+ assert object.data["source"] == post
end
test "it filters out obviously bad tags when accepting a post as Markdown" do
@@ -461,6 +517,7 @@ defmodule Pleroma.Web.CommonAPITest do
object = Object.normalize(activity)
assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
+ assert object.data["source"] == post
end
test "it does not allow replies to direct messages that are not direct messages themselves" do
@@ -543,15 +600,15 @@ defmodule Pleroma.Web.CommonAPITest do
test "it can handle activities that expire" do
user = insert(:user)
- expires_at =
- NaiveDateTime.utc_now()
- |> NaiveDateTime.truncate(:second)
- |> NaiveDateTime.add(1_000_000, :second)
+ expires_at = DateTime.add(DateTime.utc_now(), 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
+ assert_enqueued(
+ worker: Pleroma.Workers.PurgeExpiredActivity,
+ args: %{activity_id: activity.id},
+ scheduled_at: expires_at
+ )
end
end
@@ -576,14 +633,27 @@ 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, "👍")
+ clear_config([:instance, :federating], true)
- {:ok, unreaction} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ {: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, "👍")
+
+ assert unreaction.data["type"] == "Undo"
+ assert unreaction.data["object"] == reaction.data["id"]
+ assert unreaction.local
- assert unreaction.data["type"] == "Undo"
- assert unreaction.data["object"] == reaction.data["id"]
- assert unreaction.local
+ # On federation, it contains the undone (and deleted) object
+ unreaction_with_object = %{
+ unreaction
+ | data: Map.put(unreaction.data, "object", reaction.data)
+ }
+
+ assert called(Pleroma.Web.Federator.publish(unreaction_with_object))
+ end
end
test "repeating a status" do
@@ -742,6 +812,69 @@ defmodule Pleroma.Web.CommonAPITest do
[user: user, activity: activity]
end
+ test "marks notifications as read after mute" do
+ author = insert(:user)
+ activity = insert(:note_activity, user: author)
+
+ friend1 = insert(:user)
+ friend2 = insert(:user)
+
+ {:ok, reply_activity} =
+ CommonAPI.post(
+ friend2,
+ %{
+ status: "@#{author.nickname} @#{friend1.nickname} test reply",
+ in_reply_to_status_id: activity.id
+ }
+ )
+
+ {:ok, favorite_activity} = CommonAPI.favorite(friend2, activity.id)
+ {:ok, repeat_activity} = CommonAPI.repeat(activity.id, friend1)
+
+ assert Repo.aggregate(
+ from(n in Notification, where: n.seen == false and n.user_id == ^friend1.id),
+ :count
+ ) == 1
+
+ unread_notifications =
+ Repo.all(from(n in Notification, where: n.seen == false, where: n.user_id == ^author.id))
+
+ assert Enum.any?(unread_notifications, fn n ->
+ n.type == "favourite" && n.activity_id == favorite_activity.id
+ end)
+
+ assert Enum.any?(unread_notifications, fn n ->
+ n.type == "reblog" && n.activity_id == repeat_activity.id
+ end)
+
+ assert Enum.any?(unread_notifications, fn n ->
+ n.type == "mention" && n.activity_id == reply_activity.id
+ end)
+
+ {:ok, _} = CommonAPI.add_mute(author, activity)
+ assert CommonAPI.thread_muted?(author, activity)
+
+ assert Repo.aggregate(
+ from(n in Notification, where: n.seen == false and n.user_id == ^friend1.id),
+ :count
+ ) == 1
+
+ read_notifications =
+ Repo.all(from(n in Notification, where: n.seen == true, where: n.user_id == ^author.id))
+
+ assert Enum.any?(read_notifications, fn n ->
+ n.type == "favourite" && n.activity_id == favorite_activity.id
+ end)
+
+ assert Enum.any?(read_notifications, fn n ->
+ n.type == "reblog" && n.activity_id == repeat_activity.id
+ end)
+
+ assert Enum.any?(read_notifications, fn n ->
+ n.type == "mention" && n.activity_id == reply_activity.id
+ end)
+ end
+
test "add mute", %{user: user, activity: activity} do
{:ok, _} = CommonAPI.add_mute(user, activity)
assert CommonAPI.thread_muted?(user, activity)
@@ -886,6 +1019,15 @@ defmodule Pleroma.Web.CommonAPITest do
end
end
+ describe "follow/2" do
+ test "directly follows a non-locked local user" do
+ [follower, followed] = insert_pair(:user)
+ {:ok, follower, followed, _} = CommonAPI.follow(follower, followed)
+
+ assert User.following?(follower, followed)
+ end
+ end
+
describe "unfollow/2" do
test "also unsubscribes a user" do
[follower, followed] = insert_pair(:user)
@@ -950,9 +1092,9 @@ defmodule Pleroma.Web.CommonAPITest do
follower = insert(:user)
follower_two = insert(:user)
- {:ok, follow_activity} = ActivityPub.follow(follower, user)
- {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
- {:ok, follow_activity_three} = ActivityPub.follow(follower_two, user)
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
+ {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
+ {:ok, _, _, follow_activity_three} = CommonAPI.follow(follower_two, user)
assert follow_activity.data["state"] == "pending"
assert follow_activity_two.data["state"] == "pending"
@@ -970,9 +1112,9 @@ defmodule Pleroma.Web.CommonAPITest do
follower = insert(:user)
follower_two = insert(:user)
- {:ok, follow_activity} = ActivityPub.follow(follower, user)
- {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
- {:ok, follow_activity_three} = ActivityPub.follow(follower_two, user)
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
+ {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
+ {:ok, _, _, follow_activity_three} = CommonAPI.follow(follower_two, user)
assert follow_activity.data["state"] == "pending"
assert follow_activity_two.data["state"] == "pending"
diff --git a/test/web/fallback_test.exs b/test/web/fallback_test.exs
index 3919ef93a..a65865860 100644
--- a/test/web/fallback_test.exs
+++ b/test/web/fallback_test.exs
@@ -6,22 +6,56 @@ defmodule Pleroma.Web.FallbackTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
- test "GET /registration/:token", %{conn: conn} do
- assert conn
- |> get("/registration/foo")
- |> html_response(200) =~ "<!--server-generated-meta-->"
+ describe "neither preloaded data nor metadata attached to" do
+ test "GET /registration/:token", %{conn: conn} do
+ response = get(conn, "/registration/foo")
+
+ assert html_response(response, 200) =~ "<!--server-generated-meta-->"
+ end
+
+ test "GET /*path", %{conn: conn} do
+ assert conn
+ |> get("/foo")
+ |> html_response(200) =~ "<!--server-generated-meta-->"
+ end
end
- test "GET /:maybe_nickname_or_id", %{conn: conn} do
- user = insert(:user)
+ describe "preloaded data and metadata attached to" do
+ test "GET /:maybe_nickname_or_id", %{conn: conn} do
+ user = insert(:user)
+ user_missing = get(conn, "/foo")
+ user_present = get(conn, "/#{user.nickname}")
- assert conn
- |> get("/foo")
- |> html_response(200) =~ "<!--server-generated-meta-->"
+ assert(html_response(user_missing, 200) =~ "<!--server-generated-meta-->")
+ refute html_response(user_present, 200) =~ "<!--server-generated-meta-->"
+ assert html_response(user_present, 200) =~ "initial-results"
+ end
- refute conn
- |> get("/" <> user.nickname)
- |> html_response(200) =~ "<!--server-generated-meta-->"
+ test "GET /*path", %{conn: conn} do
+ assert conn
+ |> get("/foo")
+ |> html_response(200) =~ "<!--server-generated-meta-->"
+
+ refute conn
+ |> get("/foo/bar")
+ |> html_response(200) =~ "<!--server-generated-meta-->"
+ end
+ end
+
+ describe "preloaded data is attached to" do
+ test "GET /main/public", %{conn: conn} do
+ public_page = get(conn, "/main/public")
+
+ refute html_response(public_page, 200) =~ "<!--server-generated-meta-->"
+ assert html_response(public_page, 200) =~ "initial-results"
+ end
+
+ test "GET /main/all", %{conn: conn} do
+ public_page = get(conn, "/main/all")
+
+ refute html_response(public_page, 200) =~ "<!--server-generated-meta-->"
+ assert html_response(public_page, 200) =~ "initial-results"
+ end
end
test "GET /api*path", %{conn: conn} do
@@ -34,16 +68,6 @@ defmodule Pleroma.Web.FallbackTest do
assert redirected_to(get(conn, "/pleroma/admin")) =~ "/pleroma/admin/"
end
- test "GET /*path", %{conn: conn} do
- assert conn
- |> get("/foo")
- |> html_response(200) =~ "<!--server-generated-meta-->"
-
- assert conn
- |> get("/foo/bar")
- |> html_response(200) =~ "<!--server-generated-meta-->"
- end
-
test "OPTIONS /*path", %{conn: conn} do
assert conn
|> options("/foo")
diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs
index de90aa6e0..592fdccd1 100644
--- a/test/web/federator_test.exs
+++ b/test/web/federator_test.exs
@@ -23,7 +23,7 @@ defmodule Pleroma.Web.FederatorTest do
setup_all do: clear_config([:instance, :federating], true)
setup do: clear_config([:instance, :allow_relay])
- setup do: clear_config([:instance, :rewrite_policy])
+ setup do: clear_config([:mrf, :policies])
setup do: clear_config([:mrf_keyword])
describe "Publish an activity" do
@@ -158,7 +158,7 @@ defmodule Pleroma.Web.FederatorTest do
Pleroma.Config.put([:mrf_keyword, :reject], ["lain"])
Pleroma.Config.put(
- [:instance, :rewrite_policy],
+ [:mrf, :policies],
Pleroma.Web.ActivityPub.MRF.KeywordPolicy
)
diff --git a/test/web/feed/tag_controller_test.exs b/test/web/feed/tag_controller_test.exs
index 3c29cd94f..868e40965 100644
--- a/test/web/feed/tag_controller_test.exs
+++ b/test/web/feed/tag_controller_test.exs
@@ -181,4 +181,17 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
'yeah #PleromaArt'
]
end
+
+ describe "private instance" do
+ setup do: clear_config([:instance, :public])
+
+ test "returns 404 for tags feed", %{conn: conn} do
+ Config.put([:instance, :public], false)
+
+ conn
+ |> put_req_header("accept", "application/rss+xml")
+ |> get(tag_feed_path(conn, :feed, "pleromaart"))
+ |> response(404)
+ end
+ end
end
diff --git a/test/web/feed/user_controller_test.exs b/test/web/feed/user_controller_test.exs
index fa2ed1ea5..9a5610baa 100644
--- a/test/web/feed/user_controller_test.exs
+++ b/test/web/feed/user_controller_test.exs
@@ -181,6 +181,17 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
assert activity_titles == ['public', 'unlisted']
end
+
+ test "returns 404 when the user is remote", %{conn: conn} do
+ user = insert(:user, local: false)
+
+ {:ok, _} = CommonAPI.post(user, %{status: "test"})
+
+ assert conn
+ |> put_req_header("accept", "application/atom+xml")
+ |> get(user_feed_path(conn, :feed, user.nickname))
+ |> response(404)
+ end
end
# Note: see ActivityPubControllerTest for JSON format tests
@@ -235,4 +246,20 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
assert response == ~S({"error":"Not found"})
end
end
+
+ describe "private instance" do
+ setup do: clear_config([:instance, :public])
+
+ test "returns 404 for user feed", %{conn: conn} do
+ Config.put([:instance, :public], false)
+ user = insert(:user)
+
+ {:ok, _} = CommonAPI.post(user, %{status: "test"})
+
+ assert conn
+ |> put_req_header("accept", "application/atom+xml")
+ |> get(user_feed_path(conn, :feed, user.nickname))
+ |> response(404)
+ end
+ end
end
diff --git a/test/web/instances/instance_test.exs b/test/web/instances/instance_test.exs
index e463200ca..dc6ace843 100644
--- a/test/web/instances/instance_test.exs
+++ b/test/web/instances/instance_test.exs
@@ -8,6 +8,7 @@ defmodule Pleroma.Instances.InstanceTest do
use Pleroma.DataCase
+ import ExUnit.CaptureLog
import Pleroma.Factory
setup_all do: clear_config([:instance, :federation_reachability_timeout_days], 1)
@@ -97,4 +98,36 @@ defmodule Pleroma.Instances.InstanceTest do
assert initial_value == instance.unreachable_since
end
end
+
+ test "Scrapes favicon URLs" do
+ Tesla.Mock.mock(fn %{url: "https://favicon.example.org/"} ->
+ %Tesla.Env{
+ status: 200,
+ body: ~s[<html><head><link rel="icon" href="/favicon.png"></head></html>]
+ }
+ end)
+
+ assert "https://favicon.example.org/favicon.png" ==
+ Instance.get_or_update_favicon(URI.parse("https://favicon.example.org/"))
+ end
+
+ test "Returns nil on too long favicon URLs" do
+ long_favicon_url =
+ "https://Lorem.ipsum.dolor.sit.amet/consecteturadipiscingelit/Praesentpharetrapurusutaliquamtempus/Mauriseulaoreetarcu/atfacilisisorci/Nullamporttitor/nequesedfeugiatmollis/dolormagnaefficiturlorem/nonpretiumsapienorcieurisus/Nullamveleratsem/Maecenassedaccumsanexnam/favicon.png"
+
+ Tesla.Mock.mock(fn %{url: "https://long-favicon.example.org/"} ->
+ %Tesla.Env{
+ status: 200,
+ body: ~s[<html><head><link rel="icon" href="] <> long_favicon_url <> ~s["></head></html>]
+ }
+ end)
+
+ assert capture_log(fn ->
+ assert nil ==
+ Instance.get_or_update_favicon(
+ URI.parse("https://long-favicon.example.org/")
+ )
+ end) =~
+ "Instance.get_or_update_favicon(\"long-favicon.example.org\") error: %Postgrex.Error{"
+ end
end
diff --git a/test/web/masto_fe_controller_test.exs b/test/web/masto_fe_controller_test.exs
index 1d107d56c..f3b54b5f2 100644
--- a/test/web/masto_fe_controller_test.exs
+++ b/test/web/masto_fe_controller_test.exs
@@ -24,7 +24,7 @@ defmodule Pleroma.Web.MastodonAPI.MastoFEController do
assert _result = json_response(conn, 200)
user = User.get_cached_by_ap_id(user.ap_id)
- assert user.settings == %{"programming" => "socks"}
+ assert user.mastofe_settings == %{"programming" => "socks"}
end
describe "index/2 redirections" do
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 7c420985d..2e6704726 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
@@ -83,10 +83,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
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.."
+
+ conn = patch(conn, "/api/v1/accounts/update_credentials", %{"note" => raw_bio})
assert user_data = json_response_and_validate_schema(conn, 200)
@@ -94,6 +93,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
~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
@@ -103,6 +108,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
assert user_data["locked"] == true
end
+ test "updates the user's chat acceptance status", %{conn: conn} do
+ conn = patch(conn, "/api/v1/accounts/update_credentials", %{accepts_chat_messages: "false"})
+
+ assert user_data = json_response_and_validate_schema(conn, 200)
+ assert user_data["pleroma"]["accepts_chat_messages"] == false
+ end
+
test "updates the user's allow_following_move", %{user: user, conn: conn} do
assert user.allow_following_move == true
@@ -202,6 +214,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["display_name"] == "markorepairs"
+
+ update_activity = Repo.one(Pleroma.Activity)
+ assert update_activity.data["type"] == "Update"
+ assert update_activity.data["object"]["name"] == "markorepairs"
end
test "updates the user's avatar", %{user: user, conn: conn} do
@@ -211,10 +227,21 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
filename: "an_image.jpg"
}
- conn = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
+ assert user.avatar == %{}
- assert user_response = json_response_and_validate_schema(conn, 200)
+ res = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
+
+ assert user_response = json_response_and_validate_schema(res, 200)
assert user_response["avatar"] != User.avatar_url(user)
+
+ user = User.get_by_id(user.id)
+ refute user.avatar == %{}
+
+ # Also resets it
+ _res = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => ""})
+
+ user = User.get_by_id(user.id)
+ assert user.avatar == nil
end
test "updates the user's banner", %{user: user, conn: conn} do
@@ -224,26 +251,39 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
filename: "an_image.jpg"
}
- conn = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header})
+ res = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header})
- assert user_response = json_response_and_validate_schema(conn, 200)
+ assert user_response = json_response_and_validate_schema(res, 200)
assert user_response["header"] != User.banner_url(user)
+
+ # Also resets it
+ _res = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => ""})
+
+ user = User.get_by_id(user.id)
+ assert user.banner == nil
end
- test "updates the user's background", %{conn: conn} do
+ test "updates the user's background", %{conn: conn, user: user} do
new_header = %Plug.Upload{
content_type: "image/jpg",
path: Path.absname("test/fixtures/image.jpg"),
filename: "an_image.jpg"
}
- conn =
+ res =
patch(conn, "/api/v1/accounts/update_credentials", %{
"pleroma_background_image" => new_header
})
- assert user_response = json_response_and_validate_schema(conn, 200)
+ assert user_response = json_response_and_validate_schema(res, 200)
assert user_response["pleroma"]["background_image"]
+ #
+ # Also resets it
+ _res =
+ patch(conn, "/api/v1/accounts/update_credentials", %{"pleroma_background_image" => ""})
+
+ user = User.get_by_id(user.id)
+ assert user.background == nil
end
test "requires 'write:accounts' permission" do
@@ -315,6 +355,30 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
]
end
+ test "emojis in fields labels", %{conn: conn} do
+ fields = [
+ %{"name" => ":firefox:", "value" => "is best 2hu"},
+ %{"name" => "they wins", "value" => ":blank:"}
+ ]
+
+ account_data =
+ conn
+ |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
+ |> json_response_and_validate_schema(200)
+
+ assert account_data["fields"] == [
+ %{"name" => ":firefox:", "value" => "is best 2hu"},
+ %{"name" => "they wins", "value" => ":blank:"}
+ ]
+
+ assert account_data["source"]["fields"] == [
+ %{"name" => ":firefox:", "value" => "is best 2hu"},
+ %{"name" => "they wins", "value" => ":blank:"}
+ ]
+
+ assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = account_data["emojis"]
+ end
+
test "update fields via x-www-form-urlencoded", %{conn: conn} do
fields =
[
@@ -395,4 +459,71 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|> 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 1ce97378d..17a1e7d66 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -5,7 +5,6 @@
defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
use Pleroma.Web.ConnCase
- alias Pleroma.Config
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
@@ -16,8 +15,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
import Pleroma.Factory
describe "account fetching" do
- setup do: clear_config([:instance, :limit_to_local_content])
-
test "works by id" do
%User{id: user_id} = insert(:user)
@@ -42,7 +39,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
end
test "works by nickname for remote users" do
- Config.put([:instance, :limit_to_local_content], false)
+ clear_config([:instance, :limit_to_local_content], false)
user = insert(:user, nickname: "user@example.com", local: false)
@@ -53,7 +50,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
end
test "respects limit_to_local_content == :all for remote user nicknames" do
- Config.put([:instance, :limit_to_local_content], :all)
+ clear_config([:instance, :limit_to_local_content], :all)
user = insert(:user, nickname: "user@example.com", local: false)
@@ -63,7 +60,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
end
test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
- Config.put([:instance, :limit_to_local_content], :unauthenticated)
+ clear_config([:instance, :limit_to_local_content], :unauthenticated)
user = insert(:user, nickname: "user@example.com", local: false)
reading_user = insert(:user)
@@ -127,6 +124,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/accounts/internal.fetch")
|> json_response_and_validate_schema(404)
end
+
+ test "returns 404 for deactivated user", %{conn: conn} do
+ user = insert(:user, deactivated: true)
+
+ assert %{"error" => "Can't find user"} =
+ conn
+ |> get("/api/v1/accounts/#{user.id}")
+ |> json_response_and_validate_schema(:not_found)
+ end
end
defp local_and_remote_users do
@@ -143,15 +149,15 @@ 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
- assert %{"error" => "Can't find user"} ==
+ assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{local.id}")
- |> json_response_and_validate_schema(:not_found)
+ |> json_response_and_validate_schema(:unauthorized)
- assert %{"error" => "Can't find user"} ==
+ assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{remote.id}")
- |> json_response_and_validate_schema(:not_found)
+ |> json_response_and_validate_schema(:unauthorized)
end
test "if user is authenticated", %{local: local, remote: remote} do
@@ -173,8 +179,8 @@ 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_and_validate_schema(res_conn, :not_found) == %{
- "error" => "Can't find user"
+ assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
+ "error" => "This API requires an authenticated user"
}
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
@@ -203,8 +209,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert json_response_and_validate_schema(res_conn, :not_found) == %{
- "error" => "Can't find user"
+ assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
+ "error" => "This API requires an authenticated user"
}
end
@@ -249,6 +255,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert id == announce.id
end
+ test "deactivated user", %{conn: conn} do
+ user = insert(:user, deactivated: true)
+
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
+ end
+
+ test "returns 404 when user is invisible", %{conn: conn} do
+ user = insert(:user, %{invisible: true})
+
+ assert %{"error" => "Can't find user"} =
+ conn
+ |> get("/api/v1/accounts/#{user.id}")
+ |> json_response_and_validate_schema(404)
+ end
+
test "respects blocks", %{user: user_one, conn: conn} do
user_two = insert(:user)
user_three = insert(:user)
@@ -350,9 +374,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert json_response_and_validate_schema(conn, 200) == []
end
- test "gets an users media", %{conn: conn} do
+ test "gets an users media, excludes reblogs", %{conn: conn} do
note = insert(:note_activity)
user = User.get_cached_by_ap_id(note.data["actor"])
+ other_user = insert(:user)
file = %Plug.Upload{
content_type: "image/jpg",
@@ -364,6 +389,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
{:ok, %{id: image_post_id}} = CommonAPI.post(user, %{status: "cofe", media_ids: [media_id]})
+ {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: other_user.ap_id)
+
+ {:ok, %{id: other_image_post_id}} =
+ CommonAPI.post(other_user, %{status: "cofe2", media_ids: [media_id]})
+
+ {:ok, _announce} = CommonAPI.repeat(other_image_post_id, user)
+
conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?only_media=true")
assert [%{"id" => ^image_post_id}] = json_response_and_validate_schema(conn, 200)
@@ -422,15 +454,15 @@ 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
- assert %{"error" => "Can't find user"} ==
+ assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{local.id}/statuses")
- |> json_response_and_validate_schema(:not_found)
+ |> json_response_and_validate_schema(:unauthorized)
- assert %{"error" => "Can't find user"} ==
+ assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{remote.id}/statuses")
- |> json_response_and_validate_schema(:not_found)
+ |> json_response_and_validate_schema(:unauthorized)
end
test "if user is authenticated", %{local: local, remote: remote} do
@@ -451,10 +483,10 @@ 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
- assert %{"error" => "Can't find user"} ==
+ assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{local.id}/statuses")
- |> json_response_and_validate_schema(:not_found)
+ |> json_response_and_validate_schema(:unauthorized)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
assert length(json_response_and_validate_schema(res_conn, 200)) == 1
@@ -481,10 +513,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
assert length(json_response_and_validate_schema(res_conn, 200)) == 1
- assert %{"error" => "Can't find user"} ==
+ assert %{"error" => "This API requires an authenticated user"} ==
conn
|> get("/api/v1/accounts/#{remote.id}/statuses")
- |> json_response_and_validate_schema(:not_found)
+ |> json_response_and_validate_schema(:unauthorized)
end
test "if user is authenticated", %{local: local, remote: remote} do
@@ -548,6 +580,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3_id}")
|> json_response_and_validate_schema(200)
+ assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] =
+ conn
+ |> get(
+ "/api/v1/accounts/#{user.id}/followers?id=#{user.id}&limit=20&max_id=#{
+ follower3_id
+ }"
+ )
+ |> json_response_and_validate_schema(200)
+
res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3_id}")
assert [%{"id" => ^follower2_id}] = json_response_and_validate_schema(res_conn, 200)
@@ -620,6 +661,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert id1 == following1.id
res_conn =
+ get(
+ conn,
+ "/api/v1/accounts/#{user.id}/following?id=#{user.id}&limit=20&max_id=#{following3.id}"
+ )
+
+ assert [%{"id" => id2}, %{"id" => id1}] = json_response_and_validate_schema(res_conn, 200)
+ assert id2 == following2.id
+ assert id1 == following1.id
+
+ res_conn =
get(conn, "/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
assert [%{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
@@ -673,7 +724,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
followed = insert(:user)
other_user = insert(:user)
- ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow?reblogs=false")
+ ret_conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})
assert %{"showing_reblogs" => false} = json_response_and_validate_schema(ret_conn, 200)
@@ -687,7 +741,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert %{"showing_reblogs" => true} =
conn
- |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: true})
|> json_response_and_validate_schema(200)
assert [%{"id" => ^reblog_id}] =
@@ -696,6 +751,35 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> json_response(200)
end
+ test "following with reblogs" do
+ %{conn: conn} = oauth_access(["follow", "read:statuses"])
+ followed = insert(:user)
+ other_user = insert(:user)
+
+ ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow")
+
+ assert %{"showing_reblogs" => true} = json_response_and_validate_schema(ret_conn, 200)
+
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
+ {:ok, %{id: reblog_id}} = CommonAPI.repeat(activity.id, followed)
+
+ assert [%{"id" => ^reblog_id}] =
+ conn
+ |> get("/api/v1/timelines/home")
+ |> json_response(200)
+
+ assert %{"showing_reblogs" => false} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})
+ |> json_response_and_validate_schema(200)
+
+ assert [] ==
+ conn
+ |> get("/api/v1/timelines/home")
+ |> json_response(200)
+ end
+
test "following / unfollowing errors", %{user: user, conn: conn} do
# self follow
conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
@@ -745,7 +829,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
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)
@@ -817,9 +900,93 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
[valid_params: valid_params]
end
- setup do: clear_config([:instance, :account_activation_required])
+ test "registers and logs in without :account_activation_required / :account_approval_required",
+ %{conn: conn} do
+ clear_config([:instance, :account_activation_required], false)
+ clear_config([:instance, :account_approval_required], false)
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/apps", %{
+ client_name: "client_name",
+ redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
+ scopes: "read, write, follow"
+ })
+
+ 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", %{
+ grant_type: "client_credentials",
+ client_id: client_id,
+ client_secret: client_secret
+ })
+
+ assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
+ json_response(conn, 200)
+
+ assert token
+ token_from_db = Repo.get_by(Token, token: token)
+ assert token_from_db
+ assert refresh
+ assert scope == "read write follow"
+
+ clear_config([User, :email_blacklist], ["example.org"])
+
+ params = %{
+ username: "lain",
+ email: "lain@example.org",
+ password: "PlzDontHackLain",
+ bio: "Test Bio",
+ agreement: true
+ }
+
+ conn =
+ build_conn()
+ |> put_req_header("content-type", "multipart/form-data")
+ |> put_req_header("authorization", "Bearer " <> token)
+ |> post("/api/v1/accounts", params)
+
+ assert %{"error" => "{\"email\":[\"Invalid email\"]}"} =
+ json_response_and_validate_schema(conn, 400)
+
+ Pleroma.Config.put([User, :email_blacklist], [])
+
+ conn =
+ build_conn()
+ |> put_req_header("content-type", "multipart/form-data")
+ |> put_req_header("authorization", "Bearer " <> token)
+ |> post("/api/v1/accounts", params)
+
+ %{
+ "access_token" => token,
+ "created_at" => _created_at,
+ "scope" => ^scope,
+ "token_type" => "Bearer"
+ } = json_response_and_validate_schema(conn, 200)
+
+ token_from_db = Repo.get_by(Token, token: token)
+ assert token_from_db
+ user = Repo.preload(token_from_db, :user).user
+
+ assert user
+ refute user.confirmation_pending
+ refute user.approval_pending
+ end
+
+ test "registers but does not log in with :account_activation_required", %{conn: conn} do
+ clear_config([:instance, :account_activation_required], true)
+ clear_config([:instance, :account_approval_required], false)
- test "Account registration via Application", %{conn: conn} do
conn =
conn
|> put_req_header("content-type", "application/json")
@@ -867,19 +1034,76 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
agreement: true
})
- %{
- "access_token" => token,
- "created_at" => _created_at,
- "scope" => _scope,
- "token_type" => "Bearer"
- } = json_response_and_validate_schema(conn, 200)
+ response = json_response_and_validate_schema(conn, 200)
+ assert %{"identifier" => "missing_confirmed_email"} = response
+ refute response["access_token"]
+ refute response["token_type"]
+
+ user = Repo.get_by(User, email: "lain@example.org")
+ assert user.confirmation_pending
+ end
+ test "registers but does not log in with :account_approval_required", %{conn: conn} do
+ clear_config([:instance, :account_approval_required], true)
+ clear_config([:instance, :account_activation_required], false)
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/apps", %{
+ client_name: "client_name",
+ redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
+ scopes: "read, write, follow"
+ })
+
+ 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", %{
+ grant_type: "client_credentials",
+ client_id: client_id,
+ client_secret: client_secret
+ })
+
+ assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
+ json_response(conn, 200)
+
+ assert token
token_from_db = Repo.get_by(Token, token: token)
assert token_from_db
- token_from_db = Repo.preload(token_from_db, :user)
- assert token_from_db.user
+ assert refresh
+ assert scope == "read write follow"
- assert token_from_db.user.confirmation_pending
+ conn =
+ build_conn()
+ |> put_req_header("content-type", "multipart/form-data")
+ |> put_req_header("authorization", "Bearer " <> token)
+ |> post("/api/v1/accounts", %{
+ username: "lain",
+ email: "lain@example.org",
+ password: "PlzDontHackLain",
+ bio: "Test Bio",
+ agreement: true,
+ reason: "I'm a cool dude, bro"
+ })
+
+ response = json_response_and_validate_schema(conn, 200)
+ assert %{"identifier" => "awaiting_approval"} = response
+ refute response["access_token"]
+ refute response["token_type"]
+
+ user = Repo.get_by(User, email: "lain@example.org")
+
+ assert user.approval_pending
+ assert user.registration_reason == "I'm a cool dude, bro"
end
test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
@@ -933,11 +1157,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
end)
end
- setup do: clear_config([:instance, :account_activation_required])
-
test "returns bad_request if missing email params when :account_activation_required is enabled",
%{conn: conn, valid_params: valid_params} do
- Pleroma.Config.put([:instance, :account_activation_required], true)
+ clear_config([:instance, :account_activation_required], true)
app_token = insert(:oauth_token, user: nil)
@@ -1032,7 +1254,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert %{
"access_token" => access_token,
"created_at" => _,
- "scope" => ["read", "write", "follow", "push"],
+ "scope" => "read write follow push",
"token_type" => "Bearer"
} = response
@@ -1102,8 +1324,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert token_from_db
token_from_db = Repo.preload(token_from_db, :user)
assert token_from_db.user
-
- assert token_from_db.user.confirmation_pending
end
conn =
@@ -1150,7 +1370,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert %{
"access_token" => access_token,
"created_at" => _,
- "scope" => ["read"],
+ "scope" => "read",
"token_type" => "Bearer"
} =
conn
diff --git a/test/web/mastodon_api/controllers/auth_controller_test.exs b/test/web/mastodon_api/controllers/auth_controller_test.exs
index a485f8e41..4fa95fce1 100644
--- a/test/web/mastodon_api/controllers/auth_controller_test.exs
+++ b/test/web/mastodon_api/controllers/auth_controller_test.exs
@@ -122,17 +122,27 @@ defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do
{:ok, user: user}
end
- test "it returns 404 when user is not found", %{conn: conn, user: user} do
+ test "it returns 204 when user is not found", %{conn: conn, user: user} do
conn = post(conn, "/auth/password?email=nonexisting_#{user.email}")
- assert conn.status == 404
- assert conn.resp_body == ""
+
+ assert conn
+ |> json_response(:no_content)
end
- test "it returns 400 when user is not local", %{conn: conn, user: user} do
+ test "it returns 204 when user is not local", %{conn: conn, user: user} do
{:ok, user} = Repo.update(Ecto.Changeset.change(user, local: false))
conn = post(conn, "/auth/password?email=#{user.email}")
- assert conn.status == 400
- assert conn.resp_body == ""
+
+ assert conn
+ |> json_response(:no_content)
+ end
+
+ test "it returns 204 when user is deactivated", %{conn: conn, user: user} do
+ {:ok, user} = Repo.update(Ecto.Changeset.change(user, deactivated: true, local: true))
+ conn = post(conn, "/auth/password?email=#{user.email}")
+
+ assert conn
+ |> json_response(:no_content)
end
end
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 01a24afcf..664654500 100644
--- a/test/web/mastodon_api/controllers/domain_block_controller_test.exs
+++ b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
@@ -32,6 +32,38 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
refute User.blocks?(user, other_user)
end
+ test "blocking a domain via query params" do
+ %{user: user, conn: conn} = oauth_access(["write:blocks"])
+ other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
+
+ ret_conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/domain_blocks?domain=dogwhistle.zone")
+
+ 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)
+ end
+
+ test "unblocking a domain via query params" do
+ %{user: user, conn: conn} = oauth_access(["write:blocks"])
+ other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
+
+ User.block_domain(user, "dogwhistle.zone")
+ user = refresh_record(user)
+ assert User.blocks?(user, other_user)
+
+ ret_conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> delete("/api/v1/domain_blocks?domain=dogwhistle.zone")
+
+ 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
+
test "getting a list of domain blocks" do
%{user: user, conn: conn} = oauth_access(["read:blocks"])
diff --git a/test/web/mastodon_api/controllers/filter_controller_test.exs b/test/web/mastodon_api/controllers/filter_controller_test.exs
index f29547d13..0d426ec34 100644
--- a/test/web/mastodon_api/controllers/filter_controller_test.exs
+++ b/test/web/mastodon_api/controllers/filter_controller_test.exs
@@ -64,11 +64,31 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
test "get a filter" do
%{user: user, conn: conn} = oauth_access(["read:filters"])
+ # check whole_word false
query = %Pleroma.Filter{
user_id: user.id,
filter_id: 2,
phrase: "knight",
- context: ["home"]
+ context: ["home"],
+ whole_word: false
+ }
+
+ {:ok, filter} = Pleroma.Filter.create(query)
+
+ conn = get(conn, "/api/v1/filters/#{filter.filter_id}")
+
+ assert response = json_response_and_validate_schema(conn, 200)
+ assert response["whole_word"] == false
+
+ # check whole_word true
+ %{user: user, conn: conn} = oauth_access(["read:filters"])
+
+ query = %Pleroma.Filter{
+ user_id: user.id,
+ filter_id: 3,
+ phrase: "knight",
+ context: ["home"],
+ whole_word: true
}
{:ok, filter} = Pleroma.Filter.create(query)
@@ -76,6 +96,7 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
conn = get(conn, "/api/v1/filters/#{filter.filter_id}")
assert response = json_response_and_validate_schema(conn, 200)
+ assert response["whole_word"] == true
end
test "update a filter" do
@@ -86,7 +107,8 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
filter_id: 2,
phrase: "knight",
context: ["home"],
- hide: true
+ hide: true,
+ whole_word: true
}
{:ok, _filter} = Pleroma.Filter.create(query)
@@ -108,6 +130,7 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
assert response["phrase"] == new.phrase
assert response["context"] == new.context
assert response["irreversible"] == true
+ assert response["whole_word"] == true
end
test "delete a filter" do
diff --git a/test/web/mastodon_api/controllers/follow_request_controller_test.exs b/test/web/mastodon_api/controllers/follow_request_controller_test.exs
index 44e12d15a..6749e0e83 100644
--- a/test/web/mastodon_api/controllers/follow_request_controller_test.exs
+++ b/test/web/mastodon_api/controllers/follow_request_controller_test.exs
@@ -6,7 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.CommonAPI
import Pleroma.Factory
@@ -20,7 +20,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
test "/api/v1/follow_requests works", %{user: user, conn: conn} do
other_user = insert(:user)
- {:ok, _activity} = ActivityPub.follow(other_user, user)
+ {:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
{:ok, other_user} = User.follow(other_user, user, :follow_pending)
assert User.following?(other_user, user) == false
@@ -34,7 +34,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
test "/api/v1/follow_requests/:id/authorize works", %{user: user, conn: conn} do
other_user = insert(:user)
- {:ok, _activity} = ActivityPub.follow(other_user, user)
+ {:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
{:ok, other_user} = User.follow(other_user, user, :follow_pending)
user = User.get_cached_by_id(user.id)
@@ -56,7 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
test "/api/v1/follow_requests/:id/reject works", %{user: user, conn: conn} do
other_user = insert(:user)
- {:ok, _activity} = ActivityPub.follow(other_user, user)
+ {:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
user = User.get_cached_by_id(user.id)
diff --git a/test/web/mastodon_api/controllers/instance_controller_test.exs b/test/web/mastodon_api/controllers/instance_controller_test.exs
index 8bdfdddd1..6a9ccd979 100644
--- a/test/web/mastodon_api/controllers/instance_controller_test.exs
+++ b/test/web/mastodon_api/controllers/instance_controller_test.exs
@@ -27,16 +27,21 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
"thumbnail" => _,
"languages" => _,
"registrations" => _,
+ "approval_required" => _,
"poll_limits" => _,
"upload_limit" => _,
"avatar_upload_limit" => _,
"background_upload_limit" => _,
"banner_upload_limit" => _,
- "background_image" => _
+ "background_image" => _,
+ "chat_limit" => _,
+ "description_limit" => _
} = result
+ assert result["pleroma"]["metadata"]["account_activation_required"] != nil
assert result["pleroma"]["metadata"]["features"]
assert result["pleroma"]["metadata"]["federation"]
+ assert result["pleroma"]["metadata"]["fields_limits"]
assert result["pleroma"]["vapid_public_key"]
assert email == from_config_email
diff --git a/test/web/mastodon_api/controllers/list_controller_test.exs b/test/web/mastodon_api/controllers/list_controller_test.exs
index 57a9ef4a4..091ec006c 100644
--- a/test/web/mastodon_api/controllers/list_controller_test.exs
+++ b/test/web/mastodon_api/controllers/list_controller_test.exs
@@ -67,7 +67,7 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
assert following == [other_user.follower_address]
end
- test "removing users from a list" do
+ test "removing users from a list, body params" do
%{user: user, conn: conn} = oauth_access(["write:lists"])
other_user = insert(:user)
third_user = insert(:user)
@@ -85,6 +85,24 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
assert following == [third_user.follower_address]
end
+ test "removing users from a list, query params" do
+ %{user: user, conn: conn} = oauth_access(["write:lists"])
+ other_user = insert(:user)
+ third_user = insert(:user)
+ {:ok, list} = Pleroma.List.create("name", user)
+ {:ok, list} = Pleroma.List.follow(list, other_user)
+ {:ok, list} = Pleroma.List.follow(list, third_user)
+
+ 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)
+
+ %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
+ assert following == [third_user.follower_address]
+ end
+
test "listing users in a list" do
%{user: user, conn: conn} = oauth_access(["read:lists"])
other_user = insert(:user)
diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs
index c605957b1..04dc6f445 100644
--- a/test/web/mastodon_api/controllers/search_controller_test.exs
+++ b/test/web/mastodon_api/controllers/search_controller_test.exs
@@ -79,6 +79,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
assert status["id"] == to_string(activity.id)
end
+ @tag capture_log: true
test "constructs hashtags from search query", %{conn: conn} do
results =
conn
@@ -151,6 +152,22 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
]
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"})
@@ -265,18 +282,18 @@ 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 http://mastodon.example.org/@admin/99541947525187367"
})
results =
conn
- |> get("/api/v1/search?q=https://shitposter.club/notice/2827873")
+ |> get("/api/v1/search?q=http://mastodon.example.org/@admin/99541947525187367")
|> json_response_and_validate_schema(200)
- [status, %{"id" => ^activity_id}] = results["statuses"]
-
- assert status["uri"] ==
- "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
+ assert [
+ %{"url" => "http://mastodon.example.org/@admin/99541947525187367"},
+ %{"id" => ^activity_id}
+ ] = results["statuses"]
end)
end
@@ -302,11 +319,13 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
test "search fetches remote accounts", %{conn: conn} do
user = insert(:user)
+ query = URI.encode_query(%{q: " mike@osada.macgirvin.com ", resolve: true})
+
results =
conn
|> assign(:user, user)
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
- |> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=true")
+ |> get("/api/v1/search?#{query}")
|> json_response_and_validate_schema(200)
[account] = results["accounts"]
diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs
index 648e6f2ce..633a25e50 100644
--- a/test/web/mastodon_api/controllers/status_controller_test.exs
+++ b/test/web/mastodon_api/controllers/status_controller_test.exs
@@ -4,9 +4,9 @@
defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
use Pleroma.Web.ConnCase
+ use Oban.Testing, repo: Pleroma.Repo
alias Pleroma.Activity
- alias Pleroma.ActivityExpiration
alias Pleroma.Config
alias Pleroma.Conversation.Participation
alias Pleroma.Object
@@ -22,13 +22,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: clear_config([:instance, :federating])
setup do: clear_config([:instance, :allow_relay])
setup do: clear_config([:rich_media, :enabled])
+ setup do: clear_config([:mrf, :policies])
+ setup do: clear_config([:mrf_keyword, :reject])
describe "posting statuses" do
setup do: oauth_access(["write:statuses"])
test "posting a status does not increment reblog_count when relaying", %{conn: conn} do
- Pleroma.Config.put([:instance, :federating], true)
- Pleroma.Config.get([:instance, :allow_relay], true)
+ Config.put([:instance, :federating], true)
+ Config.get([:instance, :allow_relay], true)
response =
conn
@@ -101,7 +103,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
# An activity that will expire:
# 2 hours
- expires_in = 120 * 60
+ expires_in = 2 * 60 * 60
+
+ expires_at = DateTime.add(DateTime.utc_now(), expires_in)
conn_four =
conn
@@ -111,29 +115,22 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
"expires_in" => expires_in
})
- 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)
+ assert %{"id" => fourth_id} = json_response_and_validate_schema(conn_four, 200)
- estimated_expires_at =
- NaiveDateTime.utc_now()
- |> NaiveDateTime.add(expires_in)
- |> NaiveDateTime.truncate(:second)
+ assert Activity.get_by_id(fourth_id)
- # This assert will fail if the test takes longer than a minute. I sure hope it never does:
- assert abs(NaiveDateTime.diff(expiration.scheduled_at, estimated_expires_at, :second)) < 60
-
- assert fourth_response["pleroma"]["expires_at"] ==
- NaiveDateTime.to_iso8601(expiration.scheduled_at)
+ assert_enqueued(
+ worker: Pleroma.Workers.PurgeExpiredActivity,
+ args: %{activity_id: fourth_id},
+ scheduled_at: expires_at
+ )
end
test "it fails to create a status if `expires_in` is less or equal than an hour", %{
conn: conn
} do
- # 1 hour
- expires_in = 60 * 60
+ # 1 minute
+ expires_in = 1 * 60
assert %{"error" => "Expiry date is too soon"} =
conn
@@ -144,8 +141,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
})
|> json_response_and_validate_schema(422)
- # 30 minutes
- expires_in = 30 * 60
+ # 5 minutes
+ expires_in = 5 * 60
assert %{"error" => "Expiry date is too soon"} =
conn
@@ -157,6 +154,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> json_response_and_validate_schema(422)
end
+ test "Get MRF reason when posting a status is rejected by one", %{conn: conn} do
+ Config.put([:mrf_keyword, :reject], ["GNO"])
+ Config.put([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])
+
+ assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("api/v1/statuses", %{"status" => "GNO/Linux"})
+ |> json_response_and_validate_schema(422)
+ end
+
test "posting an undefined status with an attachment", %{user: user, conn: conn} do
file = %Plug.Upload{
content_type: "image/jpg",
@@ -283,9 +291,45 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
assert real_status == fake_status
end
+ test "fake statuses' preview card is not cached", %{conn: conn} do
+ clear_config([:rich_media, :enabled], true)
+
+ Tesla.Mock.mock(fn
+ %{
+ method: :get,
+ url: "https://example.com/twitter-card"
+ } ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/twitter_card.html")}
+
+ env ->
+ apply(HttpRequestMock, :request, [env])
+ end)
+
+ conn1 =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
+ "status" => "https://example.com/ogp",
+ "preview" => true
+ })
+
+ conn2 =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses", %{
+ "status" => "https://example.com/twitter-card",
+ "preview" => true
+ })
+
+ assert %{"card" => %{"title" => "The Rock"}} = json_response_and_validate_schema(conn1, 200)
+
+ assert %{"card" => %{"title" => "Small Island Developing States Photo Submission"}} =
+ json_response_and_validate_schema(conn2, 200)
+ end
+
test "posting a status with OGP link preview", %{conn: conn} do
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
- Config.put([:rich_media, :enabled], true)
+ clear_config([:rich_media, :enabled], true)
conn =
conn
@@ -760,13 +804,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "when you created it" do
%{user: author, conn: conn} = oauth_access(["write:statuses"])
activity = insert(:note_activity, user: author)
+ object = Object.normalize(activity)
- conn =
+ content = object.data["content"]
+ source = object.data["source"]
+
+ result =
conn
|> assign(:user, author)
|> delete("/api/v1/statuses/#{activity.id}")
+ |> json_response_and_validate_schema(200)
- assert %{} = json_response_and_validate_schema(conn, 200)
+ assert match?(%{"content" => ^content, "text" => ^source}, result)
refute Activity.get_by_id(activity.id)
end
@@ -789,7 +838,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
conn = delete(conn, "/api/v1/statuses/#{activity.id}")
- assert %{"error" => _} = json_response_and_validate_schema(conn, 403)
+ assert %{"error" => "Record not found"} == json_response_and_validate_schema(conn, 404)
assert Activity.get_by_id(activity.id) == activity
end
@@ -1092,6 +1141,52 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> post("/api/v1/statuses/#{activity_two.id}/pin")
|> json_response_and_validate_schema(400)
end
+
+ test "on pin removes deletion job, on unpin reschedule deletion" do
+ %{conn: conn} = oauth_access(["write:accounts", "write:statuses"])
+ expires_in = 2 * 60 * 60
+
+ expires_at = DateTime.add(DateTime.utc_now(), expires_in)
+
+ assert %{"id" => id} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("api/v1/statuses", %{
+ "status" => "oolong",
+ "expires_in" => expires_in
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert_enqueued(
+ worker: Pleroma.Workers.PurgeExpiredActivity,
+ args: %{activity_id: id},
+ scheduled_at: expires_at
+ )
+
+ assert %{"id" => ^id, "pinned" => true} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{id}/pin")
+ |> json_response_and_validate_schema(200)
+
+ refute_enqueued(
+ worker: Pleroma.Workers.PurgeExpiredActivity,
+ args: %{activity_id: id},
+ scheduled_at: expires_at
+ )
+
+ assert %{"id" => ^id, "pinned" => false} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/statuses/#{id}/unpin")
+ |> json_response_and_validate_schema(200)
+
+ assert_enqueued(
+ worker: Pleroma.Workers.PurgeExpiredActivity,
+ args: %{activity_id: id},
+ scheduled_at: expires_at
+ )
+ end
end
describe "cards" do
@@ -1414,6 +1509,20 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
[%{"id" => id}] = response
assert id == other_user.id
end
+
+ test "returns empty array when :show_reactions is disabled", %{conn: conn, activity: activity} do
+ clear_config([:instance, :show_reactions], false)
+
+ other_user = insert(:user)
+ {:ok, _} = CommonAPI.favorite(other_user, activity.id)
+
+ response =
+ conn
+ |> get("/api/v1/statuses/#{activity.id}/favourited_by")
+ |> json_response_and_validate_schema(:ok)
+
+ assert Enum.empty?(response)
+ end
end
describe "GET /api/v1/statuses/:id/reblogged_by" do
@@ -1561,7 +1670,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
# Using the header for pagination works correctly
[next, _] = get_resp_header(result, "link") |> hd() |> String.split(", ")
- [_, max_id] = Regex.run(~r/max_id=(.*)>;/, next)
+ [_, max_id] = Regex.run(~r/max_id=([^&]+)/, next)
assert max_id == third_favorite.id
@@ -1613,19 +1722,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
test "expires_at is nil for another user" do
%{conn: conn, user: user} = oauth_access(["read:statuses"])
+ expires_at = DateTime.add(DateTime.utc_now(), 1_000_000)
{:ok, activity} = CommonAPI.post(user, %{status: "foobar", expires_in: 1_000_000})
- expires_at =
- activity.id
- |> ActivityExpiration.get_by_activity_id()
- |> Map.get(:scheduled_at)
- |> NaiveDateTime.to_iso8601()
-
- assert %{"pleroma" => %{"expires_at" => ^expires_at}} =
+ assert %{"pleroma" => %{"expires_at" => a_expires_at}} =
conn
|> get("/api/v1/statuses/#{activity.id}")
|> json_response_and_validate_schema(:ok)
+ {:ok, a_expires_at, 0} = DateTime.from_iso8601(a_expires_at)
+ assert DateTime.diff(expires_at, a_expires_at) == 0
+
%{conn: conn} = oauth_access(["read:statuses"])
assert %{"pleroma" => %{"expires_at" => nil}} =
diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs
index f069390c1..517cabcff 100644
--- a/test/web/mastodon_api/controllers/timeline_controller_test.exs
+++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs
@@ -333,6 +333,46 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
describe "list" do
setup do: oauth_access(["read:lists"])
+ test "does not contain retoots", %{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 stupid."})
+ {:ok, _} = CommonAPI.repeat(activity_one.id, other_user)
+
+ {: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_and_validate_schema(conn, :ok)
+
+ assert id == to_string(activity_two.id)
+ end
+
+ test "works with pagination", %{user: user, conn: conn} do
+ other_user = insert(:user)
+ {:ok, list} = Pleroma.List.create("name", user)
+ {:ok, list} = Pleroma.List.follow(list, other_user)
+
+ Enum.each(1..30, fn i ->
+ CommonAPI.post(other_user, %{status: "post number #{i}"})
+ end)
+
+ res =
+ get(conn, "/api/v1/timelines/list/#{list.id}?limit=1")
+ |> json_response_and_validate_schema(:ok)
+
+ assert length(res) == 1
+
+ [first] = res
+
+ res =
+ get(conn, "/api/v1/timelines/list/#{list.id}?max_id=#{first["id"]}&limit=30")
+ |> json_response_and_validate_schema(:ok)
+
+ assert length(res) == 29
+ end
+
test "list timeline", %{user: user, conn: conn} do
other_user = insert(:user)
{:ok, _activity_one} = CommonAPI.post(user, %{status: "Marisa is cute."})
@@ -418,4 +458,95 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
assert [status_none] == json_response_and_validate_schema(all_test, :ok)
end
end
+
+ describe "hashtag timeline handling of :restrict_unauthenticated setting" do
+ setup do
+ user = insert(:user)
+ {:ok, activity1} = CommonAPI.post(user, %{status: "test #tag1"})
+ {:ok, _activity2} = CommonAPI.post(user, %{status: "test #tag1"})
+
+ activity1
+ |> Ecto.Changeset.change(%{local: false})
+ |> Pleroma.Repo.update()
+
+ base_uri = "/api/v1/timelines/tag/tag1"
+ error_response = %{"error" => "authorization required for timeline view"}
+
+ %{base_uri: base_uri, error_response: error_response}
+ end
+
+ defp ensure_authenticated_access(base_uri) do
+ %{conn: auth_conn} = oauth_access(["read:statuses"])
+
+ res_conn = get(auth_conn, "#{base_uri}?local=true")
+ assert length(json_response(res_conn, 200)) == 1
+
+ res_conn = get(auth_conn, "#{base_uri}?local=false")
+ assert length(json_response(res_conn, 200)) == 2
+ end
+
+ test "with default settings on private instances, returns 403 for unauthenticated users", %{
+ conn: conn,
+ base_uri: base_uri,
+ error_response: error_response
+ } do
+ clear_config([:instance, :public], false)
+ clear_config([:restrict_unauthenticated, :timelines])
+
+ for local <- [true, false] do
+ res_conn = get(conn, "#{base_uri}?local=#{local}")
+
+ assert json_response(res_conn, :unauthorized) == error_response
+ end
+
+ ensure_authenticated_access(base_uri)
+ end
+
+ test "with `%{local: true, federated: true}`, returns 403 for unauthenticated users", %{
+ conn: conn,
+ base_uri: base_uri,
+ error_response: error_response
+ } do
+ clear_config([:restrict_unauthenticated, :timelines, :local], true)
+ clear_config([:restrict_unauthenticated, :timelines, :federated], true)
+
+ for local <- [true, false] do
+ res_conn = get(conn, "#{base_uri}?local=#{local}")
+
+ assert json_response(res_conn, :unauthorized) == error_response
+ end
+
+ ensure_authenticated_access(base_uri)
+ end
+
+ test "with `%{local: false, federated: true}`, forbids unauthenticated access to federated timeline",
+ %{conn: conn, base_uri: base_uri, error_response: error_response} do
+ clear_config([:restrict_unauthenticated, :timelines, :local], false)
+ clear_config([:restrict_unauthenticated, :timelines, :federated], true)
+
+ res_conn = get(conn, "#{base_uri}?local=true")
+ assert length(json_response(res_conn, 200)) == 1
+
+ res_conn = get(conn, "#{base_uri}?local=false")
+ assert json_response(res_conn, :unauthorized) == error_response
+
+ ensure_authenticated_access(base_uri)
+ end
+
+ test "with `%{local: true, federated: false}`, forbids unauthenticated access to public timeline" <>
+ "(but not to local public activities which are delivered as part of federated timeline)",
+ %{conn: conn, base_uri: base_uri, error_response: error_response} do
+ clear_config([:restrict_unauthenticated, :timelines, :local], true)
+ clear_config([:restrict_unauthenticated, :timelines, :federated], false)
+
+ res_conn = get(conn, "#{base_uri}?local=true")
+ assert json_response(res_conn, :unauthorized) == error_response
+
+ # Note: local activities get delivered as part of federated timeline
+ res_conn = get(conn, "#{base_uri}?local=false")
+ assert length(json_response(res_conn, 200)) == 2
+
+ ensure_authenticated_access(base_uri)
+ end
+ end
end
diff --git a/test/web/mastodon_api/mastodon_api_test.exs b/test/web/mastodon_api/mastodon_api_test.exs
index a7f9c5205..0c5a38bf6 100644
--- a/test/web/mastodon_api/mastodon_api_test.exs
+++ b/test/web/mastodon_api/mastodon_api_test.exs
@@ -17,8 +17,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do
test "returns error when followed user is deactivated" do
follower = insert(:user)
user = insert(:user, local: true, deactivated: true)
- {:error, error} = MastodonAPI.follow(follower, user)
- assert error == "Could not follow user: #{user.nickname} is deactivated."
+ assert {:error, _error} = MastodonAPI.follow(follower, user)
end
test "following for user" do
diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs
index 044f088a4..9f22f9dcf 100644
--- a/test/web/mastodon_api/views/account_view_test.exs
+++ b/test/web/mastodon_api/views/account_view_test.exs
@@ -33,7 +33,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
bio:
"<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 = %{
@@ -74,6 +75,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
pleroma: %{
ap_id: user.ap_id,
background_image: "https://example.com/images/asuka_hospital.png",
+ favicon: nil,
confirmation_pending: false,
tags: [],
is_admin: false,
@@ -84,22 +86,42 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
hide_followers_count: false,
hide_follows_count: false,
relationship: %{},
- skip_thread_containment: false
+ skip_thread_containment: false,
+ accepts_chat_messages: nil
}
}
- assert expected == AccountView.render("show.json", %{user: user})
+ assert expected == AccountView.render("show.json", %{user: user, skip_visibility_check: true})
+ end
+
+ describe "favicon" do
+ setup do
+ [user: insert(:user)]
+ end
+
+ test "is parsed when :instance_favicons is enabled", %{user: user} do
+ clear_config([:instances_favicons, :enabled], true)
+
+ assert %{
+ pleroma: %{
+ favicon:
+ "https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png"
+ }
+ } = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
+ end
+
+ test "is nil when :instances_favicons is disabled", %{user: user} do
+ assert %{pleroma: %{favicon: nil}} =
+ AccountView.render("show.json", %{user: user, skip_visibility_check: true})
+ end
end
test "Represent the user account for the account owner" do
user = insert(:user)
notification_settings = %{
- followers: true,
- follows: true,
- non_followers: true,
- non_follows: true,
- privacy_option: false
+ block_from_strangers: false,
+ hide_notification_contents: false
}
privacy = user.default_scope
@@ -151,6 +173,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
pleroma: %{
ap_id: user.ap_id,
background_image: nil,
+ favicon: nil,
confirmation_pending: false,
tags: [],
is_admin: false,
@@ -161,11 +184,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
hide_followers_count: false,
hide_follows_count: false,
relationship: %{},
- skip_thread_containment: false
+ skip_thread_containment: false,
+ accepts_chat_messages: nil
}
}
- assert expected == AccountView.render("show.json", %{user: user})
+ assert expected == AccountView.render("show.json", %{user: user, skip_visibility_check: true})
end
test "Represent a Funkwhale channel" do
@@ -174,7 +198,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
"https://channels.tests.funkwhale.audio/federation/actors/compositions"
)
- assert represented = AccountView.render("show.json", %{user: user})
+ assert represented =
+ AccountView.render("show.json", %{user: user, skip_visibility_check: true})
+
assert represented.acct == "compositions@channels.tests.funkwhale.audio"
assert represented.url == "https://channels.tests.funkwhale.audio/channels/compositions"
end
@@ -199,6 +225,23 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
assert expected == AccountView.render("mention.json", %{user: user})
end
+ test "demands :for or :skip_visibility_check option for account rendering" do
+ clear_config([:restrict_unauthenticated, :profiles, :local], false)
+
+ user = insert(:user)
+ user_id = user.id
+
+ assert %{id: ^user_id} = AccountView.render("show.json", %{user: user, for: nil})
+ assert %{id: ^user_id} = AccountView.render("show.json", %{user: user, for: user})
+
+ assert %{id: ^user_id} =
+ AccountView.render("show.json", %{user: user, skip_visibility_check: true})
+
+ assert_raise RuntimeError, ~r/:skip_visibility_check or :for option is required/, fn ->
+ AccountView.render("show.json", %{user: user})
+ end
+ end
+
describe "relationship" do
defp test_relationship_rendering(user, other_user, expected_result) do
opts = %{user: user, target: other_user, relationships: nil}
@@ -312,7 +355,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
assert result.pleroma.settings_store == %{:fe => "test"}
- result = AccountView.render("show.json", %{user: user, with_pleroma_settings: true})
+ result = AccountView.render("show.json", %{user: user, for: nil, with_pleroma_settings: true})
assert result.pleroma[:settings_store] == nil
result = AccountView.render("show.json", %{user: user, for: user})
@@ -321,13 +364,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
test "doesn't sanitize display names" do
user = insert(:user, name: "<marquee> username </marquee>")
- result = AccountView.render("show.json", %{user: user})
+ result = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
assert result.display_name == "<marquee> username </marquee>"
end
test "never display nil user follow counts" do
user = insert(:user, following_count: 0, follower_count: 0)
- result = AccountView.render("show.json", %{user: user})
+ result = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
assert result.following_count == 0
assert result.followers_count == 0
@@ -351,7 +394,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
followers_count: 0,
following_count: 0,
pleroma: %{hide_follows_count: true, hide_followers_count: true}
- } = AccountView.render("show.json", %{user: user})
+ } = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
end
test "shows when follows/followers are hidden" do
@@ -364,13 +407,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
followers_count: 1,
following_count: 1,
pleroma: %{hide_follows: true, hide_followers: true}
- } = AccountView.render("show.json", %{user: user})
+ } = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
end
test "shows actual follower/following count to the account owner" do
user = insert(:user, hide_followers: true, hide_follows: true)
other_user = insert(:user)
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
+
+ assert User.following?(user, other_user)
+ assert Pleroma.FollowingRelationship.follower_count(other_user) == 1
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
assert %{
@@ -504,7 +550,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
emoji: %{"joker_smile" => "https://evil.website/society.png"}
)
- AccountView.render("show.json", %{user: user})
+ AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|> Enum.all?(fn
{key, url} when key in [:avatar, :avatar_static, :header, :header_static] ->
String.starts_with?(url, Pleroma.Web.base_url())
diff --git a/test/web/mastodon_api/views/conversation_view_test.exs b/test/web/mastodon_api/views/conversation_view_test.exs
index 6f84366f8..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/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs
index 9c399b2df..2f6a808f1 100644
--- a/test/web/mastodon_api/views/notification_view_test.exs
+++ b/test/web/mastodon_api/views/notification_view_test.exs
@@ -49,7 +49,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
expected = %{
id: to_string(notification.id),
- pleroma: %{is_seen: false},
+ pleroma: %{is_seen: false, is_muted: 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}),
@@ -68,7 +68,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
expected = %{
id: to_string(notification.id),
- pleroma: %{is_seen: false},
+ pleroma: %{is_seen: false, is_muted: false},
type: "mention",
account:
AccountView.render("show.json", %{
@@ -92,7 +92,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
expected = %{
id: to_string(notification.id),
- pleroma: %{is_seen: false},
+ pleroma: %{is_seen: false, is_muted: false},
type: "favourite",
account: AccountView.render("show.json", %{user: another_user, for: user}),
status: StatusView.render("show.json", %{activity: create_activity, for: user}),
@@ -112,7 +112,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
expected = %{
id: to_string(notification.id),
- pleroma: %{is_seen: false},
+ pleroma: %{is_seen: false, is_muted: false},
type: "reblog",
account: AccountView.render("show.json", %{user: another_user, for: user}),
status: StatusView.render("show.json", %{activity: reblog_activity, for: user}),
@@ -130,7 +130,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
expected = %{
id: to_string(notification.id),
- pleroma: %{is_seen: false},
+ pleroma: %{is_seen: false, is_muted: false},
type: "follow",
account: AccountView.render("show.json", %{user: follower, for: followed}),
created_at: Utils.to_masto_date(notification.inserted_at)
@@ -171,7 +171,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
expected = %{
id: to_string(notification.id),
- pleroma: %{is_seen: false},
+ pleroma: %{is_seen: false, is_muted: false},
type: "move",
account: AccountView.render("show.json", %{user: old_user, for: follower}),
target: AccountView.render("show.json", %{user: new_user, for: follower}),
@@ -196,7 +196,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
expected = %{
id: to_string(notification.id),
- pleroma: %{is_seen: false},
+ pleroma: %{is_seen: false, is_muted: false},
type: "pleroma:emoji_reaction",
emoji: "☕",
account: AccountView.render("show.json", %{user: other_user, for: user}),
@@ -206,4 +206,26 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
test_notifications_rendering([notification], user, [expected])
end
+
+ test "muted notification" do
+ user = insert(:user)
+ another_user = insert(:user)
+
+ {:ok, _} = Pleroma.UserRelationship.create_mute(user, another_user)
+ {: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)
+
+ expected = %{
+ id: to_string(notification.id),
+ pleroma: %{is_seen: true, is_muted: true},
+ type: "favourite",
+ account: AccountView.render("show.json", %{user: another_user, for: user}),
+ status: StatusView.render("show.json", %{activity: create_activity, for: user}),
+ created_at: Utils.to_masto_date(notification.inserted_at)
+ }
+
+ test_notifications_rendering([notification], user, [expected])
+ end
end
diff --git a/test/web/mastodon_api/views/poll_view_test.exs b/test/web/mastodon_api/views/poll_view_test.exs
index 76672f36c..b7e2f17ef 100644
--- a/test/web/mastodon_api/views/poll_view_test.exs
+++ b/test/web/mastodon_api/views/poll_view_test.exs
@@ -135,4 +135,33 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
assert result[:expires_at] == nil
assert result[:expired] == false
end
+
+ test "doesn't strips HTML tags" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ status: "What's with the smug face?",
+ poll: %{
+ options: [
+ "<input type=\"date\">",
+ "<input type=\"date\" >",
+ "<input type=\"date\"/>",
+ "<input type=\"date\"></input>"
+ ],
+ expires_in: 20
+ }
+ })
+
+ object = Object.normalize(activity)
+
+ assert %{
+ options: [
+ %{title: "<input type=\"date\">", votes_count: 0},
+ %{title: "<input type=\"date\" >", votes_count: 0},
+ %{title: "<input type=\"date\"/>", votes_count: 0},
+ %{title: "<input type=\"date\"></input>", votes_count: 0}
+ ]
+ } = PollView.render("show.json", %{object: object})
+ end
end
diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs
index 5cbadf0fc..70d829979 100644
--- a/test/web/mastodon_api/views/status_view_test.exs
+++ b/test/web/mastodon_api/views/status_view_test.exs
@@ -56,6 +56,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
]
end
+ test "works correctly with badly formatted emojis" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "yo"})
+
+ activity
+ |> Object.normalize(false)
+ |> Object.update_data(%{"reactions" => %{"☕" => [user.ap_id], "x" => 1}})
+
+ activity = Activity.get_by_id(activity.id)
+
+ status = StatusView.render("show.json", activity: activity, for: user)
+
+ assert status[:pleroma][:emoji_reactions] == [
+ %{name: "☕", count: 1, me: true}
+ ]
+ end
+
test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
user = insert(:user)
@@ -177,12 +194,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
id: to_string(note.id),
uri: object_data["id"],
url: Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, note),
- account: AccountView.render("show.json", %{user: user}),
+ account: AccountView.render("show.json", %{user: user, skip_visibility_check: true}),
in_reply_to_id: nil,
in_reply_to_account_id: nil,
card: nil,
reblog: nil,
content: HTML.filter_tags(object_data["content"]),
+ text: nil,
created_at: created_at,
reblogs_count: 0,
replies_count: 0,
@@ -226,7 +244,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
expires_at: nil,
direct_conversation_id: nil,
thread_muted: false,
- emoji_reactions: []
+ emoji_reactions: [],
+ parent_visible: false
}
}
@@ -498,6 +517,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
represented = StatusView.render("show.json", %{for: user, activity: activity})
assert represented[:id] == to_string(activity.id)
+
+ assert represented[:url] ==
+ "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
+
+ assert represented[:content] ==
+ "<p><a href=\"https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39\">Mobilizon Launching Party</a></p><p>Mobilizon is now federated! 🎉</p><p></p><p>You can view this event from other instances if they are subscribed to mobilizon.org, and soon directly from Mastodon and Pleroma. It is possible that you may see some comments from other instances, including Mastodon ones, just below.</p><p></p><p>With a Mobilizon account on an instance, you may <strong>participate</strong> at events from other instances and <strong>add comments</strong> on events.</p><p></p><p>Of course, it&#39;s still <u>a work in progress</u>: if reports made from an instance on events and comments can be federated, you can&#39;t block people right now, and moderators actions are rather limited, but this <strong>will definitely get fixed over time</strong> until first stable version next year.</p><p></p><p>Anyway, if you want to come up with some feedback, head over to our forum or - if you feel you have technical skills and are familiar with it - on our Gitlab repository.</p><p></p><p>Also, to people that want to set Mobilizon themselves even though we really don&#39;t advise to do that for now, we have a little documentation but it&#39;s quite the early days and you&#39;ll probably need some help. No worries, you can chat with us on our Forum or though our Matrix channel.</p><p></p><p>Check our website for more informations and follow us on Twitter or Mastodon.</p>"
end
describe "build_tags/1" do
@@ -620,4 +645,20 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
assert status.visibility == "list"
end
+
+ test "has a field for parent visibility" do
+ user = insert(:user)
+ poster = insert(:user)
+
+ {:ok, invisible} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
+
+ {:ok, visible} =
+ CommonAPI.post(poster, %{status: "hey", visibility: "private", in_reply_to_id: invisible.id})
+
+ status = StatusView.render("show.json", activity: visible, for: user)
+ refute status.pleroma.parent_visible
+
+ status = StatusView.render("show.json", activity: visible, for: poster)
+ assert status.pleroma.parent_visible
+ 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
index 8a3b4141c..a1bef5237 100644
--- a/test/web/media_proxy/invalidations/http_test.exs
+++ b/test/web/media_proxy/invalidations/http_test.exs
@@ -5,6 +5,10 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.HttpTest do
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"} ->
@@ -14,8 +18,8 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.HttpTest do
refute capture_log(fn ->
assert Invalidation.Http.purge(
["http://example.com/media/example.jpg"],
- %{}
- ) == {:ok, "success"}
+ []
+ ) == {:ok, ["http://example.com/media/example.jpg"]}
end) =~ "Error while cache purge"
end
@@ -28,8 +32,8 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.HttpTest do
assert capture_log(fn ->
assert Invalidation.Http.purge(
["http://example.com/media/example1.jpg"],
- %{}
- ) == {:ok, "success"}
+ []
+ ) == {: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
index 1358963ab..51833ab18 100644
--- a/test/web/media_proxy/invalidations/script_test.exs
+++ b/test/web/media_proxy/invalidations/script_test.exs
@@ -4,17 +4,23 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.ScriptTest do
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}\""
+ script_path: "./example"
+ ) == {:error, "%ErlangError{original: :enoent}"}
+ end) =~ "Error while cache purge: %ErlangError{original: :enoent}"
- assert Invalidation.Script.purge(
- ["http://example.com/media/example.jpg"],
- %{}
- ) == {:error, "not found script path"}
+ 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..d4db44c63 100644
--- a/test/web/media_proxy/media_proxy_controller_test.exs
+++ b/test/web/media_proxy/media_proxy_controller_test.exs
@@ -4,66 +4,118 @@
defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
use Pleroma.Web.ConnCase
+
import Mock
- alias Pleroma.Config
- setup do: clear_config(:media_proxy)
- setup do: clear_config([Pleroma.Web.Endpoint, :secret_key_base])
+ alias Pleroma.Web.MediaProxy
+ alias Pleroma.Web.MediaProxy.MediaProxyController
+ alias Plug.Conn
+
+ setup do
+ on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
+ end
test "it returns 404 when MediaProxy disabled", %{conn: conn} do
- Config.put([:media_proxy, :enabled], false)
+ clear_config([:media_proxy, :enabled], false)
- assert %Plug.Conn{
+ assert %Conn{
status: 404,
resp_body: "Not Found"
} = get(conn, "/proxy/hhgfh/eeeee")
- assert %Plug.Conn{
+ assert %Conn{
status: 404,
resp_body: "Not Found"
} = get(conn, "/proxy/hhgfh/eeee/fff")
end
- test "it returns 403 when signature invalidated", %{conn: conn} do
- Config.put([:media_proxy, :enabled], true)
- Config.put([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
- path = URI.parse(Pleroma.Web.MediaProxy.encode_url("https://google.fn")).path
- Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")
-
- assert %Plug.Conn{
- status: 403,
- resp_body: "Forbidden"
- } = get(conn, path)
-
- assert %Plug.Conn{
- status: 403,
- resp_body: "Forbidden"
- } = get(conn, "/proxy/hhgfh/eeee")
-
- assert %Plug.Conn{
- status: 403,
- resp_body: "Forbidden"
- } = get(conn, "/proxy/hhgfh/eeee/fff")
- end
+ describe "" do
+ setup do
+ clear_config([:media_proxy, :enabled], true)
+ clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
+ [url: MediaProxy.encode_url("https://google.fn/test.png")]
+ end
+
+ test "it returns 403 for invalid signature", %{conn: conn, url: url} do
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")
+ %{path: path} = URI.parse(url)
+
+ assert %Conn{
+ status: 403,
+ resp_body: "Forbidden"
+ } = get(conn, path)
+
+ assert %Conn{
+ status: 403,
+ resp_body: "Forbidden"
+ } = get(conn, "/proxy/hhgfh/eeee")
+
+ assert %Conn{
+ status: 403,
+ resp_body: "Forbidden"
+ } = get(conn, "/proxy/hhgfh/eeee/fff")
+ end
- test "redirects on valid url when filename invalidated", %{conn: conn} do
- Config.put([:media_proxy, :enabled], true)
- Config.put([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
- url = Pleroma.Web.MediaProxy.encode_url("https://google.fn/test.png")
- invalid_url = String.replace(url, "test.png", "test-file.png")
- response = get(conn, invalid_url)
- assert response.status == 302
- assert redirected_to(response) == url
+ test "redirects on valid url when filename is invalidated", %{conn: conn, url: url} do
+ invalid_url = String.replace(url, "test.png", "test-file.png")
+ response = get(conn, invalid_url)
+ assert response.status == 302
+ assert redirected_to(response) == url
+ end
+
+ test "it performs ReverseProxy.call with valid signature", %{conn: conn, url: url} do
+ with_mock Pleroma.ReverseProxy,
+ call: fn _conn, _url, _opts -> %Conn{status: :success} end do
+ assert %Conn{status: :success} = get(conn, url)
+ end
+ end
+
+ test "it returns 404 when url is in banned_urls cache", %{conn: conn, url: url} do
+ MediaProxy.put_in_banned_urls("https://google.fn/test.png")
+
+ with_mock Pleroma.ReverseProxy,
+ call: fn _conn, _url, _opts -> %Conn{status: :success} end do
+ assert %Conn{status: 404, resp_body: "Not Found"} = get(conn, url)
+ end
+ end
end
- test "it performs ReverseProxy.call when signature valid", %{conn: conn} do
- Config.put([:media_proxy, :enabled], true)
- Config.put([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
- url = Pleroma.Web.MediaProxy.encode_url("https://google.fn/test.png")
+ describe "filename_matches/3" do
+ test "preserves the encoded or decoded path" do
+ assert MediaProxyController.filename_matches(
+ %{"filename" => "/Hello world.jpg"},
+ "/Hello world.jpg",
+ "http://pleroma.social/Hello world.jpg"
+ ) == :ok
+
+ assert MediaProxyController.filename_matches(
+ %{"filename" => "/Hello%20world.jpg"},
+ "/Hello%20world.jpg",
+ "http://pleroma.social/Hello%20world.jpg"
+ ) == :ok
+
+ assert MediaProxyController.filename_matches(
+ %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"},
+ "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg",
+ "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"
+ ) == :ok
+
+ assert MediaProxyController.filename_matches(
+ %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jp"},
+ "/my%2Flong%2Furl%2F2019%2F07%2FS.jp",
+ "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"
+ ) == {:wrong_filename, "my%2Flong%2Furl%2F2019%2F07%2FS.jpg"}
+ end
+
+ test "encoded url are tried to match for proxy as `conn.request_path` encodes the url" do
+ # conn.request_path will return encoded url
+ request_path = "/ANALYSE-DAI-_-LE-STABLECOIN-100-D%C3%89CENTRALIS%C3%89-BQ.jpg"
- with_mock Pleroma.ReverseProxy,
- call: fn _conn, _url, _opts -> %Plug.Conn{status: :success} end do
- assert %Plug.Conn{status: :success} = get(conn, url)
+ assert MediaProxyController.filename_matches(
+ true,
+ request_path,
+ "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg"
+ ) == :ok
end
end
end
diff --git a/test/web/media_proxy/media_proxy_test.exs b/test/web/media_proxy/media_proxy_test.exs
index 69d2a71a6..72885cfdd 100644
--- a/test/web/media_proxy/media_proxy_test.exs
+++ b/test/web/media_proxy/media_proxy_test.exs
@@ -5,38 +5,33 @@
defmodule Pleroma.Web.MediaProxyTest do
use ExUnit.Case
use Pleroma.Tests.Helpers
- import Pleroma.Web.MediaProxy
- alias Pleroma.Web.MediaProxy.MediaProxyController
- setup do: clear_config([:media_proxy, :enabled])
- setup do: clear_config(Pleroma.Upload)
+ alias Pleroma.Web.Endpoint
+ alias Pleroma.Web.MediaProxy
describe "when enabled" do
- setup do
- Pleroma.Config.put([:media_proxy, :enabled], true)
- :ok
- end
+ setup do: clear_config([:media_proxy, :enabled], true)
test "ignores invalid url" do
- assert url(nil) == nil
- assert url("") == nil
+ assert MediaProxy.url(nil) == nil
+ assert MediaProxy.url("") == nil
end
test "ignores relative url" do
- assert url("/local") == "/local"
- assert url("/") == "/"
+ assert MediaProxy.url("/local") == "/local"
+ assert MediaProxy.url("/") == "/"
end
test "ignores local url" do
- local_url = Pleroma.Web.Endpoint.url() <> "/hello"
- local_root = Pleroma.Web.Endpoint.url()
- assert url(local_url) == local_url
- assert url(local_root) == local_root
+ local_url = Endpoint.url() <> "/hello"
+ local_root = Endpoint.url()
+ assert MediaProxy.url(local_url) == local_url
+ assert MediaProxy.url(local_root) == local_root
end
test "encodes and decodes URL" do
url = "https://pleroma.soykaf.com/static/logo.png"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert String.starts_with?(
encoded,
@@ -50,86 +45,44 @@ defmodule Pleroma.Web.MediaProxyTest do
test "encodes and decodes URL without a path" do
url = "https://pleroma.soykaf.com"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert decode_result(encoded) == url
end
test "encodes and decodes URL without an extension" do
url = "https://pleroma.soykaf.com/path/"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert String.ends_with?(encoded, "/path")
assert decode_result(encoded) == url
end
test "encodes and decodes URL and ignores query params for the path" do
url = "https://pleroma.soykaf.com/static/logo.png?93939393939&bunny=true"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert String.ends_with?(encoded, "/logo.png")
assert decode_result(encoded) == url
end
test "validates signature" do
- secret_key_base = Pleroma.Config.get([Pleroma.Web.Endpoint, :secret_key_base])
-
- on_exit(fn ->
- Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], secret_key_base)
- end)
-
- encoded = url("https://pleroma.social")
+ encoded = MediaProxy.url("https://pleroma.social")
- Pleroma.Config.put(
- [Pleroma.Web.Endpoint, :secret_key_base],
+ clear_config(
+ [Endpoint, :secret_key_base],
"00000000000000000000000000000000000000000000000"
)
[_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/")
- assert decode_url(sig, base64) == {:error, :invalid_signature}
- end
-
- test "filename_matches preserves the encoded or decoded path" do
- assert MediaProxyController.filename_matches(
- %{"filename" => "/Hello world.jpg"},
- "/Hello world.jpg",
- "http://pleroma.social/Hello world.jpg"
- ) == :ok
-
- assert MediaProxyController.filename_matches(
- %{"filename" => "/Hello%20world.jpg"},
- "/Hello%20world.jpg",
- "http://pleroma.social/Hello%20world.jpg"
- ) == :ok
-
- assert MediaProxyController.filename_matches(
- %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"},
- "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg",
- "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"
- ) == :ok
-
- assert MediaProxyController.filename_matches(
- %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jp"},
- "/my%2Flong%2Furl%2F2019%2F07%2FS.jp",
- "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"
- ) == {:wrong_filename, "my%2Flong%2Furl%2F2019%2F07%2FS.jpg"}
- end
-
- test "encoded url are tried to match for proxy as `conn.request_path` encodes the url" do
- # conn.request_path will return encoded url
- request_path = "/ANALYSE-DAI-_-LE-STABLECOIN-100-D%C3%89CENTRALIS%C3%89-BQ.jpg"
-
- assert MediaProxyController.filename_matches(
- true,
- request_path,
- "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg"
- ) == :ok
+ assert MediaProxy.decode_url(sig, base64) == {:error, :invalid_signature}
end
test "uses the configured base_url" do
- clear_config([:media_proxy, :base_url], "https://cache.pleroma.social")
+ base_url = "https://cache.pleroma.social"
+ clear_config([:media_proxy, :base_url], base_url)
url = "https://pleroma.soykaf.com/static/logo.png"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
- assert String.starts_with?(encoded, Pleroma.Config.get([:media_proxy, :base_url]))
+ assert String.starts_with?(encoded, base_url)
end
# Some sites expect ASCII encoded characters in the URL to be preserved even if
@@ -140,7 +93,7 @@ defmodule Pleroma.Web.MediaProxyTest do
url =
"https://pleroma.com/%20/%21/%22/%23/%24/%25/%26/%27/%28/%29/%2A/%2B/%2C/%2D/%2E/%2F/%30/%31/%32/%33/%34/%35/%36/%37/%38/%39/%3A/%3B/%3C/%3D/%3E/%3F/%40/%41/%42/%43/%44/%45/%46/%47/%48/%49/%4A/%4B/%4C/%4D/%4E/%4F/%50/%51/%52/%53/%54/%55/%56/%57/%58/%59/%5A/%5B/%5C/%5D/%5E/%5F/%60/%61/%62/%63/%64/%65/%66/%67/%68/%69/%6A/%6B/%6C/%6D/%6E/%6F/%70/%71/%72/%73/%74/%75/%76/%77/%78/%79/%7A/%7B/%7C/%7D/%7E/%7F/%80/%81/%82/%83/%84/%85/%86/%87/%88/%89/%8A/%8B/%8C/%8D/%8E/%8F/%90/%91/%92/%93/%94/%95/%96/%97/%98/%99/%9A/%9B/%9C/%9D/%9E/%9F/%C2%A0/%A1/%A2/%A3/%A4/%A5/%A6/%A7/%A8/%A9/%AA/%AB/%AC/%C2%AD/%AE/%AF/%B0/%B1/%B2/%B3/%B4/%B5/%B6/%B7/%B8/%B9/%BA/%BB/%BC/%BD/%BE/%BF/%C0/%C1/%C2/%C3/%C4/%C5/%C6/%C7/%C8/%C9/%CA/%CB/%CC/%CD/%CE/%CF/%D0/%D1/%D2/%D3/%D4/%D5/%D6/%D7/%D8/%D9/%DA/%DB/%DC/%DD/%DE/%DF/%E0/%E1/%E2/%E3/%E4/%E5/%E6/%E7/%E8/%E9/%EA/%EB/%EC/%ED/%EE/%EF/%F0/%F1/%F2/%F3/%F4/%F5/%F6/%F7/%F8/%F9/%FA/%FB/%FC/%FD/%FE/%FF"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert decode_result(encoded) == url
end
@@ -151,56 +104,49 @@ defmodule Pleroma.Web.MediaProxyTest do
url =
"https://pleroma.com/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-._~:/?#[]@!$&'()*+,;=|^`{}"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert decode_result(encoded) == url
end
test "preserve unicode characters" do
url = "https://ko.wikipedia.org/wiki/위키백과:대문"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert decode_result(encoded) == url
end
end
describe "when disabled" do
- setup do
- enabled = Pleroma.Config.get([:media_proxy, :enabled])
-
- if enabled do
- Pleroma.Config.put([:media_proxy, :enabled], false)
-
- on_exit(fn ->
- Pleroma.Config.put([:media_proxy, :enabled], enabled)
- :ok
- end)
- end
-
- :ok
- end
+ setup do: clear_config([:media_proxy, :enabled], false)
test "does not encode remote urls" do
- assert url("https://google.fr") == "https://google.fr"
+ assert MediaProxy.url("https://google.fr") == "https://google.fr"
end
end
defp decode_result(encoded) do
[_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/")
- {:ok, decoded} = decode_url(sig, base64)
+ {:ok, decoded} = MediaProxy.decode_url(sig, base64)
decoded
end
describe "whitelist" do
- setup do
- Pleroma.Config.put([:media_proxy, :enabled], true)
- :ok
- end
+ setup do: clear_config([:media_proxy, :enabled], true)
test "mediaproxy whitelist" do
- Pleroma.Config.put([:media_proxy, :whitelist], ["google.com", "feld.me"])
+ clear_config([:media_proxy, :whitelist], ["https://google.com", "https://feld.me"])
+ url = "https://feld.me/foo.png"
+
+ unencoded = MediaProxy.url(url)
+ assert unencoded == url
+ end
+
+ # TODO: delete after removing support bare domains for media proxy whitelist
+ test "mediaproxy whitelist bare domains whitelist (deprecated)" do
+ clear_config([:media_proxy, :whitelist], ["google.com", "feld.me"])
url = "https://feld.me/foo.png"
- unencoded = url(url)
+ unencoded = MediaProxy.url(url)
assert unencoded == url
end
@@ -211,17 +157,17 @@ defmodule Pleroma.Web.MediaProxyTest do
media_url = "https://mycdn.akamai.com"
url = "#{media_url}/static/logo.png"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert String.starts_with?(encoded, media_url)
end
test "ensure Pleroma.Upload base_url is always whitelisted" do
media_url = "https://media.pleroma.social"
- Pleroma.Config.put([Pleroma.Upload, :base_url], media_url)
+ clear_config([Pleroma.Upload, :base_url], media_url)
url = "#{media_url}/static/logo.png"
- encoded = url(url)
+ encoded = MediaProxy.url(url)
assert String.starts_with?(encoded, media_url)
end
diff --git a/test/web/metadata/metadata_test.exs b/test/web/metadata/metadata_test.exs
index 3f8b29e58..9d3121b7b 100644
--- a/test/web/metadata/metadata_test.exs
+++ b/test/web/metadata/metadata_test.exs
@@ -22,4 +22,13 @@ defmodule Pleroma.Web.MetadataTest do
"<meta content=\"noindex, noarchive\" name=\"robots\">"
end
end
+
+ describe "no metadata for private instances" do
+ test "for local user" do
+ clear_config([:instance, :public], false)
+ user = insert(:user, bio: "This is my secret fedi account bio")
+
+ assert "" = Pleroma.Web.Metadata.build_tags(%{user: user})
+ end
+ end
end
diff --git a/test/web/metadata/rel_me_test.exs b/test/web/metadata/rel_me_test.exs
index 4107a8459..2293d6e13 100644
--- a/test/web/metadata/rel_me_test.exs
+++ b/test/web/metadata/rel_me_test.exs
@@ -9,13 +9,12 @@ defmodule Pleroma.Web.Metadata.Providers.RelMeTest do
test "it renders all links with rel='me' from user bio" do
bio =
- ~s(<a href="https://some-link.com">https://some-link.com</a> <a rel="me" href="https://another-link.com">https://another-link.com</a>
- <link href="http://some.com"> <link rel="me" href="http://some3.com>")
+ ~s(<a href="https://some-link.com">https://some-link.com</a> <a rel="me" href="https://another-link.com">https://another-link.com</a> <link href="http://some.com"> <link rel="me" href="http://some3.com">)
user = insert(:user, %{bio: bio})
assert RelMe.build_tags(%{user: user}) == [
- {:link, [rel: "me", href: "http://some3.com>"], []},
+ {:link, [rel: "me", href: "http://some3.com"], []},
{:link, [rel: "me", href: "https://another-link.com"], []}
]
end
diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs
index 00925caad..06b33607f 100644
--- a/test/web/node_info_test.exs
+++ b/test/web/node_info_test.exs
@@ -67,10 +67,10 @@ defmodule Pleroma.Web.NodeInfoTest do
end
test "returns fieldsLimits field", %{conn: conn} do
- Config.put([:instance, :max_account_fields], 10)
- Config.put([:instance, :max_remote_account_fields], 15)
- Config.put([:instance, :account_field_name_length], 255)
- Config.put([:instance, :account_field_value_length], 2048)
+ clear_config([:instance, :max_account_fields], 10)
+ clear_config([:instance, :max_remote_account_fields], 15)
+ clear_config([:instance, :account_field_name_length], 255)
+ clear_config([:instance, :account_field_value_length], 2048)
response =
conn
@@ -84,8 +84,7 @@ defmodule Pleroma.Web.NodeInfoTest do
end
test "it returns the safe_dm_mentions feature if enabled", %{conn: conn} do
- option = Config.get([:instance, :safe_dm_mentions])
- Config.put([:instance, :safe_dm_mentions], true)
+ clear_config([:instance, :safe_dm_mentions], true)
response =
conn
@@ -102,8 +101,6 @@ defmodule Pleroma.Web.NodeInfoTest do
|> json_response(:ok)
refute "safe_dm_mentions" in response["metadata"]["features"]
-
- Config.put([:instance, :safe_dm_mentions], option)
end
describe "`metadata/federation/enabled`" do
@@ -156,14 +153,11 @@ defmodule Pleroma.Web.NodeInfoTest do
end
test "it shows MRF transparency data if enabled", %{conn: conn} do
- config = Config.get([:instance, :rewrite_policy])
- Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy])
-
- option = Config.get([:instance, :mrf_transparency])
- Config.put([:instance, :mrf_transparency], true)
+ clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.SimplePolicy])
+ clear_config([:mrf, :transparency], true)
simple_config = %{"reject" => ["example.com"]}
- Config.put(:mrf_simple, simple_config)
+ clear_config(:mrf_simple, simple_config)
response =
conn
@@ -171,26 +165,17 @@ defmodule Pleroma.Web.NodeInfoTest do
|> json_response(:ok)
assert response["metadata"]["federation"]["mrf_simple"] == simple_config
-
- Config.put([:instance, :rewrite_policy], config)
- Config.put([:instance, :mrf_transparency], option)
- Config.put(:mrf_simple, %{})
end
test "it performs exclusions from MRF transparency data if configured", %{conn: conn} do
- config = Config.get([:instance, :rewrite_policy])
- Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy])
-
- option = Config.get([:instance, :mrf_transparency])
- Config.put([:instance, :mrf_transparency], true)
-
- exclusions = Config.get([:instance, :mrf_transparency_exclusions])
- Config.put([:instance, :mrf_transparency_exclusions], ["other.site"])
+ clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.SimplePolicy])
+ clear_config([:mrf, :transparency], true)
+ clear_config([:mrf, :transparency_exclusions], ["other.site"])
simple_config = %{"reject" => ["example.com", "other.site"]}
- expected_config = %{"reject" => ["example.com"]}
+ clear_config(:mrf_simple, simple_config)
- Config.put(:mrf_simple, simple_config)
+ expected_config = %{"reject" => ["example.com"]}
response =
conn
@@ -199,10 +184,5 @@ defmodule Pleroma.Web.NodeInfoTest do
assert response["metadata"]["federation"]["mrf_simple"] == expected_config
assert response["metadata"]["federation"]["exclusions"] == true
-
- Config.put([:instance, :rewrite_policy], config)
- Config.put([:instance, :mrf_transparency], option)
- Config.put([:instance, :mrf_transparency_exclusions], exclusions)
- Config.put(:mrf_simple, %{})
end
end
diff --git a/test/web/oauth/app_test.exs b/test/web/oauth/app_test.exs
index 899af648e..993a490e0 100644
--- a/test/web/oauth/app_test.exs
+++ b/test/web/oauth/app_test.exs
@@ -29,5 +29,16 @@ defmodule Pleroma.Web.OAuth.AppTest do
assert exist_app.id == app.id
assert exist_app.scopes == ["read", "write", "follow", "push"]
end
+
+ test "has unique client_id" do
+ insert(:oauth_app, client_name: "", redirect_uris: "", client_id: "boop")
+
+ error =
+ catch_error(insert(:oauth_app, client_name: "", redirect_uris: "", client_id: "boop"))
+
+ assert %Ecto.ConstraintError{} = error
+ assert error.constraint == "apps_client_id_index"
+ assert error.type == :unique
+ end
end
end
diff --git a/test/web/oauth/ldap_authorization_test.exs b/test/web/oauth/ldap_authorization_test.exs
index 011642c08..63b1c0eb8 100644
--- a/test/web/oauth/ldap_authorization_test.exs
+++ b/test/web/oauth/ldap_authorization_test.exs
@@ -7,7 +7,6 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
alias Pleroma.Repo
alias Pleroma.Web.OAuth.Token
import Pleroma.Factory
- import ExUnit.CaptureLog
import Mock
@skip if !Code.ensure_loaded?(:eldap), do: :skip
@@ -72,9 +71,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
equalityMatch: fn _type, _value -> :ok end,
wholeSubtree: fn -> :ok end,
search: fn _connection, _options ->
- {:ok,
- {:eldap_search_result, [{:eldap_entry, '', [{'mail', [to_charlist(user.email)]}]}],
- []}}
+ {:ok, {:eldap_search_result, [{:eldap_entry, '', []}], []}}
end,
close: fn _connection ->
send(self(), :close_connection)
@@ -102,50 +99,6 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
end
@tag @skip
- test "falls back to the default authorization when LDAP is unavailable" do
- password = "testpassword"
- 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
- port = Pleroma.Config.get([:ldap, :port])
-
- with_mocks [
- {:eldap, [],
- [
- open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:error, 'connect failed'} end,
- simple_bind: fn _connection, _dn, ^password -> :ok end,
- close: fn _connection ->
- send(self(), :close_connection)
- :ok
- end
- ]}
- ] do
- log =
- capture_log(fn ->
- conn =
- build_conn()
- |> post("/oauth/token", %{
- "grant_type" => "password",
- "username" => user.nickname,
- "password" => password,
- "client_id" => app.client_id,
- "client_secret" => app.client_secret
- })
-
- assert %{"access_token" => token} = json_response(conn, 200)
-
- token = Repo.get_by(Token, token: token)
-
- assert token.user_id == user.id
- end)
-
- assert log =~ "Could not open LDAP connection: 'connect failed'"
- refute_received :close_connection
- end
- end
-
- @tag @skip
test "disallow authorization for wrong LDAP credentials" do
password = "testpassword"
user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))
diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs
index d389e4ce0..1200126b8 100644
--- a/test/web/oauth/oauth_controller_test.exs
+++ b/test/web/oauth/oauth_controller_test.exs
@@ -19,7 +19,10 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
key: "_test",
signing_salt: "cooldude"
]
- setup do: clear_config([:instance, :account_activation_required])
+ setup do
+ clear_config([:instance, :account_activation_required])
+ clear_config([:instance, :account_approval_required])
+ end
describe "in OAuth consumer mode, " do
setup do
@@ -995,6 +998,30 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
}
end
+ test "rejects token exchange for valid credentials belonging to an unapproved user" do
+ password = "testpassword"
+
+ user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password), approval_pending: true)
+
+ refute Pleroma.User.account_status(user) == :active
+
+ app = insert(:oauth_app)
+
+ conn =
+ build_conn()
+ |> post("/oauth/token", %{
+ "grant_type" => "password",
+ "username" => user.nickname,
+ "password" => password,
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+
+ assert resp = json_response(conn, 403)
+ assert %{"error" => _} = resp
+ refute Map.has_key?(resp, "access_token")
+ end
+
test "rejects an invalid authorization code" do
app = insert(:oauth_app)
diff --git a/test/web/oauth/token_test.exs b/test/web/oauth/token_test.exs
index 40d71eb59..c88b9cc98 100644
--- a/test/web/oauth/token_test.exs
+++ b/test/web/oauth/token_test.exs
@@ -69,17 +69,4 @@ defmodule Pleroma.Web.OAuth.TokenTest do
assert tokens == 2
end
-
- test "deletes expired tokens" do
- insert(:oauth_token, valid_until: Timex.shift(Timex.now(), days: -3))
- insert(:oauth_token, valid_until: Timex.shift(Timex.now(), days: -3))
- t3 = insert(:oauth_token)
- t4 = insert(:oauth_token, valid_until: Timex.shift(Timex.now(), minutes: 10))
- {tokens, _} = Token.delete_expired_tokens()
- assert tokens == 2
- available_tokens = Pleroma.Repo.all(Token)
-
- token_ids = available_tokens |> Enum.map(& &1.id)
- assert token_ids == [t3.id, t4.id]
- end
end
diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs
index 103997c31..07909d48b 100644
--- a/test/web/pleroma_api/controllers/account_controller_test.exs
+++ b/test/web/pleroma_api/controllers/account_controller_test.exs
@@ -13,8 +13,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
import Pleroma.Factory
import Swoosh.TestAssertions
- @image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
-
describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
setup do
{:ok, user} =
@@ -68,103 +66,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
end
end
- describe "PATCH /api/v1/pleroma/accounts/update_avatar" do
- setup do: oauth_access(["write:accounts"])
-
- test "user avatar can be set", %{user: user, conn: conn} do
- avatar_image = File.read!("test/fixtures/avatar_data_uri")
-
- conn =
- conn
- |> put_req_header("content-type", "multipart/form-data")
- |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
-
- user = refresh_record(user)
-
- assert %{
- "name" => _,
- "type" => _,
- "url" => [
- %{
- "href" => _,
- "mediaType" => _,
- "type" => _
- }
- ]
- } = user.avatar
-
- assert %{"url" => _} = json_response_and_validate_schema(conn, 200)
- end
-
- test "user avatar can be reset", %{user: user, conn: conn} do
- conn =
- conn
- |> put_req_header("content-type", "multipart/form-data")
- |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
-
- user = User.get_cached_by_id(user.id)
-
- assert user.avatar == nil
-
- assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)
- end
- end
-
- describe "PATCH /api/v1/pleroma/accounts/update_banner" do
- setup do: oauth_access(["write:accounts"])
-
- test "can set profile banner", %{user: user, conn: conn} do
- conn =
- conn
- |> put_req_header("content-type", "multipart/form-data")
- |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
-
- user = refresh_record(user)
- assert user.banner["type"] == "Image"
-
- assert %{"url" => _} = json_response_and_validate_schema(conn, 200)
- end
-
- test "can reset profile banner", %{user: user, conn: conn} do
- conn =
- conn
- |> put_req_header("content-type", "multipart/form-data")
- |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
-
- user = refresh_record(user)
- assert user.banner == %{}
-
- assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)
- end
- end
-
- describe "PATCH /api/v1/pleroma/accounts/update_background" do
- setup do: oauth_access(["write:accounts"])
-
- test "background image can be set", %{user: user, conn: conn} do
- conn =
- conn
- |> put_req_header("content-type", "multipart/form-data")
- |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
-
- user = refresh_record(user)
- assert user.background["type"] == "Image"
- # assert %{"url" => _} = json_response(conn, 200)
- assert %{"url" => _} = json_response_and_validate_schema(conn, 200)
- end
-
- test "background image can be reset", %{user: user, conn: conn} do
- conn =
- conn
- |> put_req_header("content-type", "multipart/form-data")
- |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
-
- user = refresh_record(user)
- assert user.background == %{}
- assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)
- end
- end
-
describe "getting favorites timeline of specified user" do
setup do
[current_user, user] = insert_pair(:user, hide_favorites: false)
diff --git a/test/web/pleroma_api/controllers/chat_controller_test.exs b/test/web/pleroma_api/controllers/chat_controller_test.exs
index 82e16741d..7be5fe09c 100644
--- a/test/web/pleroma_api/controllers/chat_controller_test.exs
+++ b/test/web/pleroma_api/controllers/chat_controller_test.exs
@@ -267,6 +267,21 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
describe "GET /api/v1/pleroma/chats" do
setup do: oauth_access(["read:chats"])
+ test "it does not return chats with deleted users", %{conn: conn, user: user} do
+ recipient = insert(:user)
+ {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
+
+ Pleroma.Repo.delete(recipient)
+ User.invalidate_cache(recipient)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats")
+ |> json_response_and_validate_schema(200)
+
+ assert length(result) == 0
+ end
+
test "it does not return chats with users you blocked", %{conn: conn, user: user} do
recipient = insert(:user)
@@ -332,5 +347,27 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
chat_1.id |> to_string()
]
end
+
+ test "it is not affected by :restrict_unauthenticated setting (issue #1973)", %{
+ conn: conn,
+ user: user
+ } do
+ clear_config([:restrict_unauthenticated, :profiles, :local], true)
+ clear_config([:restrict_unauthenticated, :profiles, :remote], true)
+
+ user2 = insert(:user)
+ user3 = insert(:user, local: false)
+
+ {:ok, _chat_12} = Chat.get_or_create(user.id, user2.ap_id)
+ {:ok, _chat_13} = Chat.get_or_create(user.id, user3.ap_id)
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/chats")
+ |> json_response_and_validate_schema(200)
+
+ account_ids = Enum.map(result, &get_in(&1, ["account", "id"]))
+ assert Enum.sort(account_ids) == Enum.sort([user2.id, user3.id])
+ end
end
end
diff --git a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs
index ee3d281a0..e113bb15f 100644
--- a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs
+++ b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs
@@ -14,6 +14,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
)
setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
+ setup do: clear_config([:instance, :public], true)
+
setup do
admin = insert(:user, is_admin: true)
token = insert(:oauth_admin_token, user: admin)
@@ -27,18 +29,63 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
{:ok, %{admin_conn: admin_conn}}
end
+ test "GET /api/pleroma/emoji/packs when :public: false", %{conn: conn} do
+ Config.put([:instance, :public], false)
+ conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
+ 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 resp["count"] == 3
+
+ assert resp["packs"]
+ |> Map.keys()
+ |> length() == 3
+
+ shared = resp["packs"]["test_pack"]
+ assert shared["files"] == %{"blank" => "blank.png", "blank2" => "blank2.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"]
+ non_shared = resp["packs"]["test_pack_nonshared"]
assert non_shared["pack"]["share-files"] == false
assert non_shared["pack"]["can-download"] == false
+
+ resp =
+ conn
+ |> get("/api/pleroma/emoji/packs?page_size=1")
+ |> json_response_and_validate_schema(200)
+
+ assert resp["count"] == 3
+
+ packs = Map.keys(resp["packs"])
+
+ assert length(packs) == 1
+
+ [pack1] = packs
+
+ resp =
+ conn
+ |> get("/api/pleroma/emoji/packs?page_size=1&page=2")
+ |> json_response_and_validate_schema(200)
+
+ assert resp["count"] == 3
+ packs = Map.keys(resp["packs"])
+ assert length(packs) == 1
+ [pack2] = packs
+
+ resp =
+ conn
+ |> get("/api/pleroma/emoji/packs?page_size=1&page=3")
+ |> json_response_and_validate_schema(200)
+
+ assert resp["count"] == 3
+ packs = Map.keys(resp["packs"])
+ assert length(packs) == 1
+ [pack3] = packs
+ assert [pack1, pack2, pack3] |> Enum.uniq() |> length() == 3
end
describe "GET /api/pleroma/emoji/packs/remote" do
@@ -332,7 +379,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
Map.put(
new_data,
"fallback-src-sha256",
- "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"
+ "1967BB4E42BCC34BCC12D57BE7811D3B7BE52F965BCE45C87BD377B9499CE11D"
)
assert ctx[:admin_conn]
@@ -398,7 +445,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/test_pack/files", %{
- shortcode: "blank2",
+ shortcode: "blank3",
filename: "dir/blank.png",
file: %Plug.Upload{
filename: "blank.png",
@@ -407,7 +454,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
})
|> json_response_and_validate_schema(200) == %{
"blank" => "blank.png",
- "blank2" => "dir/blank.png"
+ "blank2" => "blank2.png",
+ "blank3" => "dir/blank.png"
}
assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
@@ -431,7 +479,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/test_pack/files", %{
- shortcode: "blank2",
+ shortcode: "blank3",
filename: "dir/blank.png",
file: %Plug.Upload{
filename: "blank.png",
@@ -440,7 +488,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
})
|> json_response_and_validate_schema(200) == %{
"blank" => "blank.png",
- "blank2" => "dir/blank.png"
+ "blank2" => "blank2.png",
+ "blank3" => "dir/blank.png"
}
assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
@@ -448,14 +497,15 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest 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",
+ shortcode: "blank3",
+ new_shortcode: "blank4",
new_filename: "dir_2/blank_3.png",
force: true
})
|> json_response_and_validate_schema(200) == %{
"blank" => "blank.png",
- "blank3" => "dir_2/blank_3.png"
+ "blank2" => "blank2.png",
+ "blank4" => "dir_2/blank_3.png"
}
assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
@@ -481,7 +531,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/not_loaded/files", %{
- shortcode: "blank2",
+ shortcode: "blank3",
filename: "dir/blank.png",
file: %Plug.Upload{
filename: "blank.png",
@@ -535,7 +585,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
})
|> json_response_and_validate_schema(200) == %{
"blank" => "blank.png",
- "blank4" => "dir/blank.png"
+ "blank4" => "dir/blank.png",
+ "blank2" => "blank2.png"
}
assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
@@ -549,7 +600,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
})
|> json_response_and_validate_schema(200) == %{
"blank3" => "dir_2/blank_3.png",
- "blank" => "blank.png"
+ "blank" => "blank.png",
+ "blank2" => "blank2.png"
}
refute File.exists?("#{@emoji_path}/test_pack/dir/")
@@ -557,7 +609,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
assert admin_conn
|> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank3")
- |> json_response_and_validate_schema(200) == %{"blank" => "blank.png"}
+ |> json_response_and_validate_schema(200) == %{
+ "blank" => "blank.png",
+ "blank2" => "blank2.png"
+ }
refute File.exists?("#{@emoji_path}/test_pack/dir_2/")
@@ -581,7 +636,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
})
|> json_response_and_validate_schema(200) == %{
"blank_url" => "blank_url.png",
- "blank" => "blank.png"
+ "blank" => "blank.png",
+ "blank2" => "blank2.png"
}
assert File.exists?("#{@emoji_path}/test_pack/blank_url.png")
@@ -602,15 +658,16 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
})
|> json_response_and_validate_schema(200) == %{
"shortcode" => "shortcode.png",
- "blank" => "blank.png"
+ "blank" => "blank.png",
+ "blank2" => "blank2.png"
}
end
test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do
assert admin_conn
- |> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank2")
+ |> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank3")
|> json_response_and_validate_schema(:bad_request) == %{
- "error" => "Emoji \"blank2\" does not exist"
+ "error" => "Emoji \"blank3\" does not exist"
}
end
@@ -618,12 +675,12 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest 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",
+ shortcode: "blank3",
+ new_shortcode: "blank4",
new_filename: "dir_2/blank_3.png"
})
|> json_response_and_validate_schema(:bad_request) == %{
- "error" => "Emoji \"blank2\" does not exist"
+ "error" => "Emoji \"blank3\" does not exist"
}
end
@@ -651,7 +708,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
assert Jason.decode!(File.read!("#{@emoji_path}/test_created/pack.json")) == %{
"pack" => %{},
- "files" => %{}
+ "files" => %{},
+ "files_count" => 0
}
assert admin_conn
@@ -709,14 +767,14 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
- refute Map.has_key?(resp, "test_pack_for_import")
+ refute Map.has_key?(resp["packs"], "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"}
+ assert resp["packs"]["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")
@@ -736,7 +794,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
- assert resp["test_pack_for_import"]["files"] == %{
+ assert resp["packs"]["test_pack_for_import"]["files"] == %{
"blank" => "blank.png",
"blank2" => "blank.png",
"foo" => "blank.png"
@@ -746,7 +804,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
describe "GET /api/pleroma/emoji/packs/:name" do
test "shows pack.json", %{conn: conn} do
assert %{
- "files" => %{"blank" => "blank.png"},
+ "files" => files,
+ "files_count" => 2,
"pack" => %{
"can-download" => true,
"description" => "Test description",
@@ -759,6 +818,28 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
conn
|> get("/api/pleroma/emoji/packs/test_pack")
|> json_response_and_validate_schema(200)
+
+ assert files == %{"blank" => "blank.png", "blank2" => "blank2.png"}
+
+ assert %{
+ "files" => files,
+ "files_count" => 2
+ } =
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack?page_size=1")
+ |> json_response_and_validate_schema(200)
+
+ assert files |> Map.keys() |> length() == 1
+
+ assert %{
+ "files" => files,
+ "files_count" => 2
+ } =
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack?page_size=1&page=2")
+ |> json_response_and_validate_schema(200)
+
+ assert files |> Map.keys() |> length() == 1
end
test "non existing pack", %{conn: conn} do
diff --git a/test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs b/test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs
index e1bb5ebfe..3deab30d1 100644
--- a/test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs
+++ b/test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs
@@ -106,6 +106,23 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionControllerTest do
result
end
+ test "GET /api/v1/pleroma/statuses/:id/reactions with :show_reactions disabled", %{conn: conn} do
+ clear_config([:instance, :show_reactions], false)
+
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
+ {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
+
+ result =
+ conn
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
+ |> json_response_and_validate_schema(200)
+
+ assert result == []
+ end
+
test "GET /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
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
index e5b165255..40dbae3cd 100644
--- a/test/web/pleroma_api/views/chat/message_reference_view_test.exs
+++ b/test/web/pleroma_api/views/chat/message_reference_view_test.exs
@@ -43,7 +43,17 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceViewTest do
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)
+ clear_config([:rich_media, :enabled], true)
+
+ Tesla.Mock.mock(fn
+ %{url: "https://example.com/ogp"} ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/ogp.html")}
+ end)
+
+ {:ok, activity} =
+ CommonAPI.post_chat_message(recipient, user, "gkgkgk https://example.com/ogp",
+ media_id: upload.id
+ )
object = Object.normalize(activity)
@@ -52,10 +62,11 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceViewTest do
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[:content] == object.data["content"]
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
+ assert chat_message_two[:card]
end
end
diff --git a/test/web/pleroma_api/views/chat_view_test.exs b/test/web/pleroma_api/views/chat_view_test.exs
index 14eecb1bd..02484b705 100644
--- a/test/web/pleroma_api/views/chat_view_test.exs
+++ b/test/web/pleroma_api/views/chat_view_test.exs
@@ -26,7 +26,8 @@ defmodule Pleroma.Web.PleromaAPI.ChatViewTest do
assert represented_chat == %{
id: "#{chat.id}",
- account: AccountView.render("show.json", user: recipient),
+ account:
+ AccountView.render("show.json", user: recipient, skip_visibility_check: true),
unread: 0,
last_message: nil,
updated_at: Utils.to_masto_date(chat.updated_at)
diff --git a/test/web/preload/instance_test.exs b/test/web/preload/instance_test.exs
new file mode 100644
index 000000000..a46f28312
--- /dev/null
+++ b/test/web/preload/instance_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.Preload.Providers.InstanceTest do
+ use Pleroma.DataCase
+ alias Pleroma.Web.Preload.Providers.Instance
+
+ setup do: {:ok, Instance.generate_terms(nil)}
+
+ test "it renders the info", %{"/api/v1/instance" => info} do
+ assert %{
+ description: description,
+ email: "admin@example.com",
+ registrations: true
+ } = info
+
+ assert String.equivalent?(description, "Pleroma: An efficient and flexible fediverse server")
+ end
+
+ test "it renders the panel", %{"/instance/panel.html" => panel} do
+ assert String.contains?(
+ panel,
+ "<p>Welcome to <a href=\"https://pleroma.social\" target=\"_blank\">Pleroma!</a></p>"
+ )
+ end
+
+ test "it works with overrides" do
+ clear_config([:instance, :static_dir], "test/fixtures/preload_static")
+
+ %{"/instance/panel.html" => panel} = Instance.generate_terms(nil)
+
+ assert String.contains?(
+ panel,
+ "HEY!"
+ )
+ end
+
+ test "it renders the node_info", %{"/nodeinfo/2.0.json" => nodeinfo} do
+ %{
+ metadata: metadata,
+ version: "2.0"
+ } = nodeinfo
+
+ assert metadata.private == false
+ assert metadata.suggestions == %{enabled: false}
+ end
+end
diff --git a/test/web/preload/timeline_test.exs b/test/web/preload/timeline_test.exs
new file mode 100644
index 000000000..3b1f2f1aa
--- /dev/null
+++ b/test/web/preload/timeline_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.Web.Preload.Providers.TimelineTest do
+ use Pleroma.DataCase
+ import Pleroma.Factory
+
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.Preload.Providers.Timelines
+
+ @public_url "/api/v1/timelines/public"
+
+ describe "unauthenticated timeliness when restricted" do
+ setup do: clear_config([:restrict_unauthenticated, :timelines, :local], true)
+ setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], true)
+
+ test "return nothing" do
+ tl_data = Timelines.generate_terms(%{})
+
+ refute Map.has_key?(tl_data, "/api/v1/timelines/public")
+ end
+ end
+
+ describe "unauthenticated timeliness when unrestricted" do
+ setup do: clear_config([:restrict_unauthenticated, :timelines, :local], false)
+ setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], false)
+
+ setup do: {:ok, user: insert(:user)}
+
+ test "returns the timeline when not restricted" do
+ assert Timelines.generate_terms(%{})
+ |> Map.has_key?(@public_url)
+ end
+
+ test "returns public items", %{user: user} do
+ {:ok, _} = CommonAPI.post(user, %{status: "it's post 1!"})
+ {:ok, _} = CommonAPI.post(user, %{status: "it's post 2!"})
+ {:ok, _} = CommonAPI.post(user, %{status: "it's post 3!"})
+
+ assert Timelines.generate_terms(%{})
+ |> Map.fetch!(@public_url)
+ |> Enum.count() == 3
+ end
+
+ test "does not return non-public items", %{user: user} do
+ {:ok, _} = CommonAPI.post(user, %{status: "it's post 1!", visibility: "unlisted"})
+ {:ok, _} = CommonAPI.post(user, %{status: "it's post 2!", visibility: "direct"})
+ {:ok, _} = CommonAPI.post(user, %{status: "it's post 3!"})
+
+ assert Timelines.generate_terms(%{})
+ |> Map.fetch!(@public_url)
+ |> Enum.count() == 1
+ end
+ end
+end
diff --git a/test/web/preload/user_test.exs b/test/web/preload/user_test.exs
new file mode 100644
index 000000000..83f065e27
--- /dev/null
+++ b/test/web/preload/user_test.exs
@@ -0,0 +1,33 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Preload.Providers.UserTest do
+ use Pleroma.DataCase
+ import Pleroma.Factory
+ alias Pleroma.Web.Preload.Providers.User
+
+ describe "returns empty when user doesn't exist" do
+ test "nil user specified" do
+ assert User.generate_terms(%{user: nil}) == %{}
+ end
+
+ test "missing user specified" do
+ assert User.generate_terms(%{user: :not_a_user}) == %{}
+ end
+ end
+
+ describe "specified user exists" do
+ setup do
+ user = insert(:user)
+
+ terms = User.generate_terms(%{user: user})
+ %{terms: terms, user: user}
+ end
+
+ test "account is rendered", %{terms: terms, user: user} do
+ account = terms["/api/v1/accounts/#{user.id}"]
+ assert %{acct: user, username: user} = account
+ end
+ end
+end
diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs
index b48952b29..aeb5c1fbd 100644
--- a/test/web/push/impl_test.exs
+++ b/test/web/push/impl_test.exs
@@ -238,9 +238,11 @@ defmodule Pleroma.Web.Push.ImplTest do
}
end
- test "hides details for notifications when privacy option enabled" do
+ test "hides contents of notifications when option enabled" do
user = insert(:user, nickname: "Bob")
- user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: true})
+
+ user2 =
+ insert(:user, nickname: "Rob", notification_settings: %{hide_notification_contents: true})
{:ok, activity} =
CommonAPI.post(user, %{
@@ -284,9 +286,11 @@ defmodule Pleroma.Web.Push.ImplTest do
}
end
- test "returns regular content for notifications with privacy option disabled" do
+ test "returns regular content when hiding contents option disabled" do
user = insert(:user, nickname: "Bob")
- user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: false})
+
+ user2 =
+ insert(:user, nickname: "Rob", notification_settings: %{hide_notification_contents: false})
{:ok, activity} =
CommonAPI.post(user, %{
diff --git a/test/web/rich_media/aws_signed_url_test.exs b/test/web/rich_media/aws_signed_url_test.exs
index b30f4400e..1ceae1a31 100644
--- a/test/web/rich_media/aws_signed_url_test.exs
+++ b/test/web/rich_media/aws_signed_url_test.exs
@@ -21,7 +21,7 @@ defmodule Pleroma.Web.RichMedia.TTL.AwsSignedUrlTest do
expire_time =
Timex.parse!(timestamp, "{ISO:Basic:Z}") |> Timex.to_unix() |> Kernel.+(valid_till)
- assert expire_time == Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl.ttl(metadata, url)
+ assert {:ok, expire_time} == Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl.ttl(metadata, url)
end
test "s3 signed url is parsed and correct ttl is set for rich media" do
@@ -55,7 +55,7 @@ defmodule Pleroma.Web.RichMedia.TTL.AwsSignedUrlTest do
Cachex.put(:rich_media_cache, url, metadata)
- Pleroma.Web.RichMedia.Parser.set_ttl_based_on_image({:ok, metadata}, url)
+ Pleroma.Web.RichMedia.Parser.set_ttl_based_on_image(metadata, url)
{:ok, cache_ttl} = Cachex.ttl(:rich_media_cache, url)
diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs
index 420a612c6..21ae35f8b 100644
--- a/test/web/rich_media/parser_test.exs
+++ b/test/web/rich_media/parser_test.exs
@@ -5,6 +5,8 @@
defmodule Pleroma.Web.RichMedia.ParserTest do
use ExUnit.Case, async: true
+ alias Pleroma.Web.RichMedia.Parser
+
setup do
Tesla.Mock.mock(fn
%{
@@ -48,23 +50,27 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
%{method: :get, url: "http://example.com/empty"} ->
%Tesla.Env{status: 200, body: "hello"}
+
+ %{method: :get, url: "http://example.com/malformed"} ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/malformed-data.html")}
+
+ %{method: :get, url: "http://example.com/error"} ->
+ {:error, :overload}
end)
:ok
end
test "returns error when no metadata present" do
- assert {:error, _} = Pleroma.Web.RichMedia.Parser.parse("http://example.com/empty")
+ assert {:error, _} = Parser.parse("http://example.com/empty")
end
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\"}"}
+ assert {:error, {:invalid_metadata, _}} = Parser.parse("http://example.com/non-ogp")
end
test "parses ogp" do
- assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp") ==
+ assert Parser.parse("http://example.com/ogp") ==
{:ok,
%{
"image" => "http://ia.media-imdb.com/images/rock.jpg",
@@ -77,7 +83,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
end
test "falls back to <title> when ogp:title is missing" do
- assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp-missing-title") ==
+ assert Parser.parse("http://example.com/ogp-missing-title") ==
{:ok,
%{
"image" => "http://ia.media-imdb.com/images/rock.jpg",
@@ -90,7 +96,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
end
test "parses twitter card" do
- assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/twitter-card") ==
+ assert Parser.parse("http://example.com/twitter-card") ==
{:ok,
%{
"card" => "summary",
@@ -103,7 +109,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
end
test "parses OEmbed" do
- assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/oembed") ==
+ assert Parser.parse("http://example.com/oembed") ==
{:ok,
%{
"author_name" => "‮‭‬bees‬",
@@ -132,6 +138,10 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
end
test "rejects invalid OGP data" do
- assert {:error, _} = Pleroma.Web.RichMedia.Parser.parse("http://example.com/malformed")
+ assert {:error, _} = Parser.parse("http://example.com/malformed")
+ end
+
+ test "returns error if getting page was not successful" do
+ assert {:error, :overload} = Parser.parse("http://example.com/error")
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 a49ab002f..1598bf675 100644
--- a/test/web/static_fe/static_fe_controller_test.exs
+++ b/test/web/static_fe/static_fe_controller_test.exs
@@ -87,6 +87,20 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
assert html =~ "testing a thing!"
end
+ test "redirects to json if requested", %{conn: conn, user: user} do
+ {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"})
+
+ conn =
+ conn
+ |> put_req_header(
+ "accept",
+ "Accept: application/activity+json, application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", text/html"
+ )
+ |> get("/notice/#{activity.id}")
+
+ assert redirected_to(conn, 302) =~ activity.data["object"]
+ end
+
test "filters HTML tags", %{conn: conn} do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{status: "<script>alert('xss')</script>"})
diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs
index 245f6e63f..d56d74464 100644
--- a/test/web/streamer/streamer_test.exs
+++ b/test/web/streamer/streamer_test.exs
@@ -116,6 +116,35 @@ defmodule Pleroma.Web.StreamerTest do
refute Streamer.filtered_by_user?(user, announce)
end
+ test "it does not stream announces of the user's own posts in the 'user' stream", %{
+ user: user
+ } do
+ Streamer.get_topic_and_add_socket("user", user)
+
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
+ {:ok, announce} = CommonAPI.repeat(activity.id, other_user)
+
+ assert Streamer.filtered_by_user?(user, announce)
+ end
+
+ test "it does stream notifications announces of the user's own posts in the 'user' stream", %{
+ user: user
+ } do
+ Streamer.get_topic_and_add_socket("user", user)
+
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
+ {:ok, announce} = CommonAPI.repeat(activity.id, other_user)
+
+ notification =
+ Pleroma.Notification
+ |> Repo.get_by(%{user_id: user.id, activity_id: announce.id})
+ |> Repo.preload(:activity)
+
+ refute Streamer.filtered_by_user?(user, notification)
+ end
+
test "it streams boosts of mastodon user in the 'user' stream", %{user: user} do
Streamer.get_topic_and_add_socket("user", user)
diff --git a/test/web/twitter_api/password_controller_test.exs b/test/web/twitter_api/password_controller_test.exs
index 231a46c67..a5e9e2178 100644
--- a/test/web/twitter_api/password_controller_test.exs
+++ b/test/web/twitter_api/password_controller_test.exs
@@ -37,7 +37,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do
test "it returns HTTP 200", %{conn: conn} do
user = insert(:user)
{:ok, token} = PasswordResetToken.create_token(user)
- {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{})
+ {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{})
params = %{
"password" => "test",
@@ -62,7 +62,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do
user = insert(:user, password_reset_pending: true)
{:ok, token} = PasswordResetToken.create_token(user)
- {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{})
+ {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{})
params = %{
"password" => "test",
diff --git a/test/web/twitter_api/remote_follow_controller_test.exs b/test/web/twitter_api/remote_follow_controller_test.exs
index f7e54c26a..3852c7ce9 100644
--- a/test/web/twitter_api/remote_follow_controller_test.exs
+++ b/test/web/twitter_api/remote_follow_controller_test.exs
@@ -227,7 +227,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
}
)
- {:ok, %{token: token}} = MFA.Token.create_token(user)
+ {:ok, %{token: token}} = MFA.Token.create(user)
user2 = insert(:user)
otp_token = TOTP.generate_token(otp_secret)
@@ -256,7 +256,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
}
)
- {:ok, %{token: token}} = MFA.Token.create_token(user)
+ {:ok, %{token: token}} = MFA.Token.create(user)
user2 = insert(:user)
otp_token = TOTP.generate_token(TOTP.generate_secret())
diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs
index 368533292..20a45cb6f 100644
--- a/test/web/twitter_api/twitter_api_test.exs
+++ b/test/web/twitter_api/twitter_api_test.exs
@@ -4,11 +4,11 @@
defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
use Pleroma.DataCase
+ import Pleroma.Factory
alias Pleroma.Repo
alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
alias Pleroma.UserInviteToken
- alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.TwitterAPI.TwitterAPI
setup_all do
@@ -27,13 +27,10 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
{:ok, user} = TwitterAPI.register_user(data)
- fetched_user = User.get_cached_by_nickname("lain")
-
- assert AccountView.render("show.json", %{user: user}) ==
- AccountView.render("show.json", %{user: fetched_user})
+ assert user == User.get_cached_by_nickname("lain")
end
- test "it registers a new user with empty string in bio and returns the user." do
+ test "it registers a new user with empty string in bio and returns the user" do
data = %{
:username => "lain",
:email => "lain@wired.jp",
@@ -45,10 +42,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
{:ok, user} = TwitterAPI.register_user(data)
- fetched_user = User.get_cached_by_nickname("lain")
-
- assert AccountView.render("show.json", %{user: user}) ==
- AccountView.render("show.json", %{user: fetched_user})
+ assert user == User.get_cached_by_nickname("lain")
end
test "it sends confirmation email if :account_activation_required is specified in instance config" do
@@ -85,6 +79,42 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
)
end
+ test "it sends an admin email if :account_approval_required is specified in instance config" do
+ admin = insert(:user, is_admin: true)
+ setting = Pleroma.Config.get([:instance, :account_approval_required])
+
+ unless setting do
+ Pleroma.Config.put([:instance, :account_approval_required], true)
+ on_exit(fn -> Pleroma.Config.put([:instance, :account_approval_required], setting) end)
+ end
+
+ data = %{
+ :username => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "",
+ :password => "bear",
+ :confirm => "bear",
+ :reason => "I love anime"
+ }
+
+ {:ok, user} = TwitterAPI.register_user(data)
+ ObanHelpers.perform_all()
+
+ assert user.approval_pending
+
+ email = Pleroma.Emails.AdminEmail.new_unapproved_registration(admin, user)
+
+ notify_email = Pleroma.Config.get([:instance, :notify_email])
+ instance_name = Pleroma.Config.get([:instance, :name])
+
+ Swoosh.TestAssertions.assert_email_sent(
+ from: {instance_name, notify_email},
+ to: {admin.name, admin.email},
+ html_body: email.html_body
+ )
+ end
+
test "it registers a new user and parses mentions in the bio" do
data1 = %{
:username => "john",
@@ -134,13 +164,10 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
{:ok, user} = TwitterAPI.register_user(data)
- fetched_user = User.get_cached_by_nickname("vinny")
- invite = Repo.get_by(UserInviteToken, token: invite.token)
+ assert user == User.get_cached_by_nickname("vinny")
+ invite = Repo.get_by(UserInviteToken, token: invite.token)
assert invite.used == true
-
- assert AccountView.render("show.json", %{user: user}) ==
- AccountView.render("show.json", %{user: fetched_user})
end
test "returns error on invalid token" do
@@ -197,10 +224,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
check_fn = fn invite ->
data = Map.put(data, :token, invite.token)
{:ok, user} = TwitterAPI.register_user(data)
- fetched_user = User.get_cached_by_nickname("vinny")
- assert AccountView.render("show.json", %{user: user}) ==
- AccountView.render("show.json", %{user: fetched_user})
+ assert user == User.get_cached_by_nickname("vinny")
end
{:ok, data: data, check_fn: check_fn}
@@ -260,14 +285,11 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
}
{:ok, user} = TwitterAPI.register_user(data)
- fetched_user = User.get_cached_by_nickname("vinny")
- invite = Repo.get_by(UserInviteToken, token: invite.token)
+ assert user == User.get_cached_by_nickname("vinny")
+ invite = Repo.get_by(UserInviteToken, token: invite.token)
assert invite.used == true
- assert AccountView.render("show.json", %{user: user}) ==
- AccountView.render("show.json", %{user: fetched_user})
-
data = %{
:username => "GrimReaper",
:email => "death@reapers.afterlife",
@@ -302,13 +324,10 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
}
{:ok, user} = TwitterAPI.register_user(data)
- fetched_user = User.get_cached_by_nickname("vinny")
- invite = Repo.get_by(UserInviteToken, token: invite.token)
+ assert user == User.get_cached_by_nickname("vinny")
+ invite = Repo.get_by(UserInviteToken, token: invite.token)
refute invite.used
-
- assert AccountView.render("show.json", %{user: user}) ==
- AccountView.render("show.json", %{user: fetched_user})
end
test "error after max uses" do
@@ -327,13 +346,11 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
}
{:ok, user} = TwitterAPI.register_user(data)
- fetched_user = User.get_cached_by_nickname("vinny")
+ assert user == User.get_cached_by_nickname("vinny")
+
invite = Repo.get_by(UserInviteToken, token: invite.token)
assert invite.used == true
- assert AccountView.render("show.json", %{user: user}) ==
- AccountView.render("show.json", %{user: fetched_user})
-
data = %{
:username => "GrimReaper",
:email => "death@reapers.afterlife",
diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs
index ad919d341..d164127ee 100644
--- a/test/web/twitter_api/util_controller_test.exs
+++ b/test/web/twitter_api/util_controller_test.exs
@@ -191,7 +191,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
test "it updates notification settings", %{user: user, conn: conn} do
conn
|> put("/api/pleroma/notification_settings", %{
- "followers" => false,
+ "block_from_strangers" => true,
"bar" => 1
})
|> json_response(:ok)
@@ -199,130 +199,25 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
user = refresh_record(user)
assert %Pleroma.User.NotificationSetting{
- followers: false,
- follows: true,
- non_follows: true,
- non_followers: true,
- privacy_option: false
+ block_from_strangers: true,
+ hide_notification_contents: false
} == user.notification_settings
end
- test "it updates notification privacy option", %{user: user, conn: conn} do
+ test "it updates notification settings to enable hiding contents", %{user: user, conn: conn} do
conn
- |> put("/api/pleroma/notification_settings", %{"privacy_option" => "1"})
+ |> put("/api/pleroma/notification_settings", %{"hide_notification_contents" => "1"})
|> json_response(:ok)
user = refresh_record(user)
assert %Pleroma.User.NotificationSetting{
- followers: true,
- follows: true,
- non_follows: true,
- non_followers: true,
- privacy_option: true
+ block_from_strangers: false,
+ hide_notification_contents: true
} == user.notification_settings
end
end
- describe "GET /api/statusnet/config" do
- test "it returns config in xml format", %{conn: conn} do
- instance = Config.get(:instance)
-
- response =
- conn
- |> put_req_header("accept", "application/xml")
- |> get("/api/statusnet/config")
- |> response(:ok)
-
- assert response ==
- "<config>\n<site>\n<name>#{Keyword.get(instance, :name)}</name>\n<site>#{
- Pleroma.Web.base_url()
- }</site>\n<textlimit>#{Keyword.get(instance, :limit)}</textlimit>\n<closed>#{
- !Keyword.get(instance, :registrations_open)
- }</closed>\n</site>\n</config>\n"
- end
-
- test "it returns config in json format", %{conn: conn} do
- instance = Config.get(:instance)
- Config.put([:instance, :managed_config], true)
- Config.put([:instance, :registrations_open], false)
- Config.put([:instance, :invites_enabled], true)
- Config.put([:instance, :public], false)
- Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
-
- response =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/api/statusnet/config")
- |> json_response(:ok)
-
- expected_data = %{
- "site" => %{
- "accountActivationRequired" => "0",
- "closed" => "1",
- "description" => Keyword.get(instance, :description),
- "invitesEnabled" => "1",
- "name" => Keyword.get(instance, :name),
- "pleromafe" => %{"theme" => "asuka-hospital"},
- "private" => "1",
- "safeDMMentionsEnabled" => "0",
- "server" => Pleroma.Web.base_url(),
- "textlimit" => to_string(Keyword.get(instance, :limit)),
- "uploadlimit" => %{
- "avatarlimit" => to_string(Keyword.get(instance, :avatar_upload_limit)),
- "backgroundlimit" => to_string(Keyword.get(instance, :background_upload_limit)),
- "bannerlimit" => to_string(Keyword.get(instance, :banner_upload_limit)),
- "uploadlimit" => to_string(Keyword.get(instance, :upload_limit))
- },
- "vapidPublicKey" => Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
- }
- }
-
- assert response == expected_data
- end
-
- test "returns the state of safe_dm_mentions flag", %{conn: conn} do
- Config.put([:instance, :safe_dm_mentions], true)
-
- response =
- conn
- |> get("/api/statusnet/config.json")
- |> json_response(:ok)
-
- assert response["site"]["safeDMMentionsEnabled"] == "1"
-
- Config.put([:instance, :safe_dm_mentions], false)
-
- response =
- conn
- |> get("/api/statusnet/config.json")
- |> json_response(:ok)
-
- assert response["site"]["safeDMMentionsEnabled"] == "0"
- end
-
- test "it returns the managed config", %{conn: conn} do
- Config.put([:instance, :managed_config], false)
- Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
-
- response =
- conn
- |> get("/api/statusnet/config.json")
- |> json_response(:ok)
-
- refute response["site"]["pleromafe"]
-
- Config.put([:instance, :managed_config], true)
-
- response =
- conn
- |> get("/api/statusnet/config.json")
- |> json_response(:ok)
-
- assert response["site"]["pleromafe"] == %{"theme" => "asuka-hospital"}
- end
- end
-
describe "GET /api/pleroma/frontend_configurations" do
test "returns everything in :pleroma, :frontend_configurations", %{conn: conn} do
config = [
@@ -451,28 +346,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
end
end
- describe "GET /api/statusnet/version" do
- test "it returns version in xml format", %{conn: conn} do
- response =
- conn
- |> put_req_header("accept", "application/xml")
- |> get("/api/statusnet/version")
- |> response(:ok)
-
- assert response == "<version>#{Pleroma.Application.named_version()}</version>"
- end
-
- test "it returns version in json format", %{conn: conn} do
- response =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/api/statusnet/version")
- |> json_response(:ok)
-
- assert response == "#{Pleroma.Application.named_version()}"
- end
- end
-
describe "POST /main/ostatus - remote_subscribe/2" do
setup do: clear_config([:instance, :federating], true)
@@ -713,10 +586,16 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
end
end
- test "with proper permissions and valid password", %{conn: conn} do
+ test "with proper permissions and valid password", %{conn: conn, user: user} do
conn = post(conn, "/api/pleroma/delete_account", %{"password" => "test"})
-
+ ObanHelpers.perform_all()
assert json_response(conn, 200) == %{"status" => "success"}
+
+ user = User.get_by_id(user.id)
+ assert user.deactivated == true
+ assert user.name == nil
+ assert user.bio == ""
+ assert user.password_hash == nil
end
end
end
diff --git a/test/web/web_finger/web_finger_test.exs b/test/web/web_finger/web_finger_test.exs
index f4884e0a2..96fc0bbaa 100644
--- a/test/web/web_finger/web_finger_test.exs
+++ b/test/web/web_finger/web_finger_test.exs
@@ -40,6 +40,11 @@ defmodule Pleroma.Web.WebFingerTest do
end
describe "fingering" do
+ test "returns error for nonsensical input" do
+ assert {:error, _} = WebFinger.finger("bliblablu")
+ assert {:error, _} = WebFinger.finger("pleroma.social")
+ end
+
test "returns error when fails parse xml or json" do
user = "invalid_content@social.heldscal.la"
assert {:error, %Jason.DecodeError{}} = WebFinger.finger(user)