summaryrefslogtreecommitdiff
path: root/test/web/activity_pub
diff options
context:
space:
mode:
Diffstat (limited to 'test/web/activity_pub')
-rw-r--r--test/web/activity_pub/activity_pub_controller_test.exs247
-rw-r--r--test/web/activity_pub/activity_pub_test.exs885
-rw-r--r--test/web/activity_pub/mrf/anti_link_spam_policy_test.exs22
-rw-r--r--test/web/activity_pub/mrf/hellthread_policy_test.exs4
-rw-r--r--test/web/activity_pub/mrf/keyword_policy_test.exs4
-rw-r--r--test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs8
-rw-r--r--test/web/activity_pub/mrf/mention_policy_test.exs4
-rw-r--r--test/web/activity_pub/mrf/normalize_markup_test.exs10
-rw-r--r--test/web/activity_pub/mrf/object_age_policy_test.exs105
-rw-r--r--test/web/activity_pub/mrf/simple_policy_test.exs26
-rw-r--r--test/web/activity_pub/mrf/subchain_policy_test.exs4
-rw-r--r--test/web/activity_pub/mrf/tag_policy_test.exs2
-rw-r--r--test/web/activity_pub/mrf/user_allowlist_policy_test.exs2
-rw-r--r--test/web/activity_pub/mrf/vocabulary_policy_test.exs2
-rw-r--r--test/web/activity_pub/publisher_test.exs151
-rw-r--r--test/web/activity_pub/relay_test.exs29
-rw-r--r--test/web/activity_pub/transmogrifier/follow_handling_test.exs10
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs866
-rw-r--r--test/web/activity_pub/utils_test.exs260
-rw-r--r--test/web/activity_pub/views/object_view_test.exs22
-rw-r--r--test/web/activity_pub/views/user_view_test.exs102
-rw-r--r--test/web/activity_pub/visibilty_test.exs5
22 files changed, 2481 insertions, 289 deletions
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index fa2364bd2..9151034da 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -1,19 +1,24 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
use Pleroma.Web.ConnCase
+ use Oban.Testing, repo: Pleroma.Repo
+
import Pleroma.Factory
alias Pleroma.Activity
+ alias Pleroma.Delivery
alias Pleroma.Instances
alias Pleroma.Object
+ alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.UserView
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI
+ alias Pleroma.Workers.ReceiverWorker
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
@@ -105,6 +110,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
end
+
+ test "it returns 404 for remote users", %{
+ conn: conn
+ } do
+ user = insert(:user, local: false, nickname: "remoteuser@example.com")
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/users/#{user.nickname}.json")
+
+ assert json_response(conn, 404)
+ end
end
describe "/object/:uuid" do
@@ -280,7 +298,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert json_response(conn1, :ok)
assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
- Activity.delete_by_ap_id(activity.object.data["id"])
+ Activity.delete_all_by_object_ap_id(activity.object.data["id"])
conn2 =
conn
@@ -302,7 +320,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> post("/inbox", data)
assert "ok" == json_response(conn, 200)
- :timer.sleep(500)
+
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
assert Activity.get_by_ap_id(data["id"])
end
@@ -344,10 +363,91 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> post("/users/#{user.nickname}/inbox", data)
assert "ok" == json_response(conn, 200)
- :timer.sleep(500)
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
assert Activity.get_by_ap_id(data["id"])
end
+ test "it accepts messages with to as string instead of array", %{conn: conn, data: data} do
+ user = insert(:user)
+
+ data =
+ Map.put(data, "to", user.ap_id)
+ |> Map.delete("cc")
+
+ conn =
+ conn
+ |> assign(:valid_signature, true)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/inbox", data)
+
+ assert "ok" == json_response(conn, 200)
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
+ assert Activity.get_by_ap_id(data["id"])
+ end
+
+ test "it accepts messages with cc as string instead of array", %{conn: conn, data: data} do
+ user = insert(:user)
+
+ data =
+ Map.put(data, "cc", user.ap_id)
+ |> Map.delete("to")
+
+ conn =
+ conn
+ |> assign(:valid_signature, true)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/inbox", data)
+
+ assert "ok" == json_response(conn, 200)
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
+ %Activity{} = activity = Activity.get_by_ap_id(data["id"])
+ assert user.ap_id in activity.recipients
+ end
+
+ test "it accepts messages with bcc as string instead of array", %{conn: conn, data: data} do
+ user = insert(:user)
+
+ data =
+ Map.put(data, "bcc", user.ap_id)
+ |> Map.delete("to")
+ |> Map.delete("cc")
+
+ conn =
+ conn
+ |> assign(:valid_signature, true)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/inbox", data)
+
+ assert "ok" == json_response(conn, 200)
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
+ assert Activity.get_by_ap_id(data["id"])
+ end
+
+ test "it accepts announces with to as string instead of array", %{conn: conn} do
+ user = insert(:user)
+
+ 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",
+ "to" => "https://www.w3.org/ns/activitystreams#Public",
+ "cc" => [user.ap_id],
+ "type" => "Announce"
+ }
+
+ conn =
+ conn
+ |> assign(:valid_signature, true)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/inbox", data)
+
+ assert "ok" == json_response(conn, 200)
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
+ %Activity{} = activity = Activity.get_by_ap_id(data["id"])
+ assert "https://www.w3.org/ns/activitystreams#Public" in activity.recipients
+ end
+
test "it accepts messages from actors that are followed by the user", %{
conn: conn,
data: data
@@ -373,7 +473,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> post("/users/#{recipient.nickname}/inbox", data)
assert "ok" == json_response(conn, 200)
- :timer.sleep(500)
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
assert Activity.get_by_ap_id(data["id"])
end
@@ -463,6 +563,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> post("/users/#{recipient.nickname}/inbox", data)
|> json_response(200)
+ ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
+
activity = Activity.get_by_ap_id(data["id"])
assert activity.id
@@ -538,6 +640,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> post("/users/#{user.nickname}/outbox", data)
result = json_response(conn, 201)
+
assert Activity.get_by_ap_id(result["id"])
end
@@ -674,7 +777,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it returns returns a uri if the user has 'hide_followers' set", %{conn: conn} do
user = insert(:user)
- user_two = insert(:user, %{info: %{hide_followers: true}})
+ user_two = insert(:user, hide_followers: true)
User.follow(user, user_two)
result =
@@ -687,7 +790,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is not authenticated",
%{conn: conn} do
- user = insert(:user, %{info: %{hide_followers: true}})
+ user = insert(:user, hide_followers: true)
result =
conn
@@ -699,7 +802,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it renders the page, if the user has 'hide_followers' set and the request is authenticated with the same user",
%{conn: conn} do
- user = insert(:user, %{info: %{hide_followers: true}})
+ user = insert(:user, hide_followers: true)
other_user = insert(:user)
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
@@ -755,7 +858,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
end
test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do
- user = insert(:user, %{info: %{hide_follows: true}})
+ user = insert(:user, hide_follows: true)
user_two = insert(:user)
User.follow(user, user_two)
@@ -769,7 +872,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is not authenticated",
%{conn: conn} do
- user = insert(:user, %{info: %{hide_follows: true}})
+ user = insert(:user, hide_follows: true)
result =
conn
@@ -781,7 +884,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it renders the page, if the user has 'hide_follows' set and the request is authenticated with the same user",
%{conn: conn} do
- user = insert(:user, %{info: %{hide_follows: true}})
+ user = insert(:user, hide_follows: true)
other_user = insert(:user)
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
@@ -822,4 +925,126 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert result["totalItems"] == 15
end
end
+
+ describe "delivery tracking" do
+ test "it tracks a signed object fetch", %{conn: conn} do
+ user = insert(:user, local: false)
+ activity = insert(:note_activity)
+ object = Object.normalize(activity)
+
+ object_path = String.trim_leading(object.data["id"], Pleroma.Web.Endpoint.url())
+
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> assign(:user, user)
+ |> get(object_path)
+ |> json_response(200)
+
+ assert Delivery.get(object.id, user.id)
+ end
+
+ test "it tracks a signed activity fetch", %{conn: conn} do
+ user = insert(:user, local: false)
+ activity = insert(:note_activity)
+ object = Object.normalize(activity)
+
+ activity_path = String.trim_leading(activity.data["id"], Pleroma.Web.Endpoint.url())
+
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> assign(:user, user)
+ |> get(activity_path)
+ |> json_response(200)
+
+ assert Delivery.get(object.id, user.id)
+ end
+
+ test "it tracks a signed object fetch when the json is cached", %{conn: conn} do
+ user = insert(:user, local: false)
+ other_user = insert(:user, local: false)
+ activity = insert(:note_activity)
+ object = Object.normalize(activity)
+
+ object_path = String.trim_leading(object.data["id"], Pleroma.Web.Endpoint.url())
+
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> assign(:user, user)
+ |> get(object_path)
+ |> json_response(200)
+
+ build_conn()
+ |> put_req_header("accept", "application/activity+json")
+ |> assign(:user, other_user)
+ |> get(object_path)
+ |> json_response(200)
+
+ assert Delivery.get(object.id, user.id)
+ assert Delivery.get(object.id, other_user.id)
+ end
+
+ test "it tracks a signed activity fetch when the json is cached", %{conn: conn} do
+ user = insert(:user, local: false)
+ other_user = insert(:user, local: false)
+ activity = insert(:note_activity)
+ object = Object.normalize(activity)
+
+ activity_path = String.trim_leading(activity.data["id"], Pleroma.Web.Endpoint.url())
+
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> assign(:user, user)
+ |> get(activity_path)
+ |> json_response(200)
+
+ build_conn()
+ |> put_req_header("accept", "application/activity+json")
+ |> assign(:user, other_user)
+ |> get(activity_path)
+ |> json_response(200)
+
+ assert Delivery.get(object.id, user.id)
+ assert Delivery.get(object.id, other_user.id)
+ end
+ end
+
+ describe "Additionnal ActivityPub C2S endpoints" do
+ test "/api/ap/whoami", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/ap/whoami")
+
+ user = User.get_cached_by_id(user.id)
+
+ assert UserView.render("user.json", %{user: user}) == json_response(conn, 200)
+ end
+
+ clear_config([:media_proxy])
+ clear_config([Pleroma.Upload])
+
+ test "uploadMedia", %{conn: conn} do
+ user = insert(:user)
+
+ desc = "Description of the image"
+
+ image = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/ap/upload_media", %{"file" => image, "description" => desc})
+
+ assert object = json_response(conn, :created)
+ assert object["name"] == desc
+ assert object["type"] == "Document"
+ assert object["actor"] == user.ap_id
+ end
+ end
end
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index fecbf5353..3dd3dd04d 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -1,16 +1,22 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
use Pleroma.DataCase
+ use Oban.Testing, repo: Pleroma.Repo
+
alias Pleroma.Activity
alias Pleroma.Builders.ActivityBuilder
+ alias Pleroma.Config
+ alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
+ alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.Federator
import Pleroma.Factory
import Tesla.Mock
@@ -41,6 +47,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert called(Pleroma.Web.Streamer.stream("participation", participations))
end
end
+
+ test "streams them out on activity creation" do
+ user_one = insert(:user)
+ user_two = insert(:user)
+
+ with_mock Pleroma.Web.Streamer,
+ stream: fn _, _ -> nil end do
+ {:ok, activity} =
+ CommonAPI.post(user_one, %{
+ "status" => "@#{user_two.nickname}",
+ "visibility" => "direct"
+ })
+
+ conversation =
+ activity.data["context"]
+ |> Pleroma.Conversation.get_for_ap_id()
+ |> Repo.preload(participations: :user)
+
+ assert called(Pleroma.Web.Streamer.stream("participation", conversation.participations))
+ end
+ end
end
describe "fetching restricted by visibility" do
@@ -87,17 +114,83 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
+ describe "fetching excluded by visibility" do
+ test "it excludes by the appropriate visibility" do
+ user = insert(:user)
+
+ {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+
+ {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+
+ {:ok, unlisted_activity} =
+ CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
+
+ {:ok, private_activity} =
+ CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ "exclude_visibilities" => "direct",
+ "actor_id" => user.ap_id
+ })
+
+ assert public_activity in activities
+ assert unlisted_activity in activities
+ assert private_activity in activities
+ refute direct_activity in activities
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ "exclude_visibilities" => "unlisted",
+ "actor_id" => user.ap_id
+ })
+
+ assert public_activity in activities
+ refute unlisted_activity in activities
+ assert private_activity in activities
+ assert direct_activity in activities
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ "exclude_visibilities" => "private",
+ "actor_id" => user.ap_id
+ })
+
+ assert public_activity in activities
+ assert unlisted_activity in activities
+ refute private_activity in activities
+ assert direct_activity in activities
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ "exclude_visibilities" => "public",
+ "actor_id" => user.ap_id
+ })
+
+ refute public_activity in activities
+ assert unlisted_activity in activities
+ assert private_activity in activities
+ assert direct_activity in activities
+ end
+ end
+
describe "building a user from his ap id" do
test "it returns a user" do
user_id = "http://mastodon.example.org/users/admin"
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
assert user.ap_id == user_id
assert user.nickname == "admin@mastodon.example.org"
- assert user.info.source_data
- assert user.info.ap_enabled
+ assert user.source_data
+ assert user.ap_enabled
assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
end
+ test "it returns a user that is invisible" do
+ user_id = "http://mastodon.example.org/users/relay"
+ {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
+ assert User.invisible?(user)
+ end
+
test "it fetches the appropriate tag-restricted posts" do
user = insert(:user)
@@ -133,7 +226,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
describe "insertion" do
test "drops activities beyond a certain limit" do
- limit = Pleroma.Config.get([:instance, :remote_limit])
+ limit = Config.get([:instance, :remote_limit])
random_text =
:crypto.strong_rand_bytes(limit + 1)
@@ -257,7 +350,64 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
+ describe "listen activities" do
+ test "does not increase user note count" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ ActivityPub.listen(%{
+ to: ["https://www.w3.org/ns/activitystreams#Public"],
+ actor: user,
+ context: "",
+ object: %{
+ "actor" => user.ap_id,
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "artist" => "lain",
+ "title" => "lain radio episode 1",
+ "length" => 180_000,
+ "type" => "Audio"
+ }
+ })
+
+ assert activity.actor == user.ap_id
+
+ user = User.get_cached_by_id(user.id)
+ assert user.note_count == 0
+ end
+
+ test "can be fetched into a timeline" do
+ _listen_activity_1 = insert(:listen)
+ _listen_activity_2 = insert(:listen)
+ _listen_activity_3 = insert(:listen)
+
+ timeline = ActivityPub.fetch_activities([], %{"type" => ["Listen"]})
+
+ assert length(timeline) == 3
+ end
+ end
+
describe "create activities" do
+ test "it reverts create" do
+ user = insert(:user)
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} =
+ ActivityPub.create(%{
+ to: ["user1", "user2"],
+ actor: user,
+ context: "",
+ object: %{
+ "to" => ["user1", "user2"],
+ "type" => "Note",
+ "content" => "testing"
+ }
+ })
+ end
+
+ assert Repo.aggregate(Activity, :count, :id) == 0
+ assert Repo.aggregate(Object, :count, :id) == 0
+ end
+
test "removes doubled 'to' recipients" do
user = insert(:user)
@@ -306,7 +456,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
})
user = User.get_cached_by_id(user.id)
- assert user.info.note_count == 2
+ assert user.note_count == 2
end
test "increases replies count" do
@@ -360,7 +510,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activity_five = insert(:note_activity)
user = insert(:user)
- {:ok, user} = User.block(user, %{ap_id: activity_five.data["actor"]})
+ {:ok, _user_relationship} = User.block(user, %{ap_id: activity_five.data["actor"]})
activities = ActivityPub.fetch_activities_for_context("2hu", %{"blocking_user" => user})
assert activities == [activity_two, activity]
@@ -373,7 +523,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activity_three = insert(:note_activity)
user = insert(:user)
booster = insert(:user)
- {:ok, user} = User.block(user, %{ap_id: activity_one.data["actor"]})
+ {:ok, _user_relationship} = User.block(user, %{ap_id: activity_one.data["actor"]})
activities =
ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true})
@@ -382,7 +532,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Enum.member?(activities, activity_three)
refute Enum.member?(activities, activity_one)
- {:ok, user} = User.unblock(user, %{ap_id: activity_one.data["actor"]})
+ {:ok, _user_block} = User.unblock(user, %{ap_id: activity_one.data["actor"]})
activities =
ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true})
@@ -391,7 +541,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Enum.member?(activities, activity_three)
assert Enum.member?(activities, activity_one)
- {:ok, user} = User.block(user, %{ap_id: activity_three.data["actor"]})
+ {:ok, _user_relationship} = User.block(user, %{ap_id: activity_three.data["actor"]})
{:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
%Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
activity_three = Activity.get_by_id(activity_three.id)
@@ -418,7 +568,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
blockee = insert(:user)
friend = insert(:user)
- {:ok, blocker} = User.block(blocker, blockee)
+ {:ok, _user_relationship} = User.block(blocker, blockee)
{:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
@@ -441,7 +591,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
blockee = insert(:user)
friend = insert(:user)
- {:ok, blocker} = User.block(blocker, blockee)
+ {:ok, _user_relationship} = User.block(blocker, blockee)
{:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
@@ -481,13 +631,48 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
refute repeat_activity in activities
end
+ test "does return activities from followed users on blocked domains" do
+ domain = "meanies.social"
+ domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"})
+ blocker = insert(:user)
+
+ {:ok, blocker} = User.follow(blocker, domain_user)
+ {:ok, blocker} = User.block_domain(blocker, domain)
+
+ assert User.following?(blocker, domain_user)
+ assert User.blocks_domain?(blocker, domain_user)
+ refute User.blocks?(blocker, domain_user)
+
+ note = insert(:note, %{data: %{"actor" => domain_user.ap_id}})
+ activity = insert(:note_activity, %{note: note})
+
+ activities =
+ ActivityPub.fetch_activities([], %{"blocking_user" => blocker, "skip_preload" => true})
+
+ assert activity in activities
+
+ # And check that if the guy we DO follow boosts someone else from their domain,
+ # that should be hidden
+ another_user = insert(:user, %{ap_id: "https://#{domain}/@meanie2"})
+ bad_note = insert(:note, %{data: %{"actor" => another_user.ap_id}})
+ bad_activity = insert(:note_activity, %{note: bad_note})
+ {:ok, repeat_activity, _} = CommonAPI.repeat(bad_activity.id, domain_user)
+
+ activities =
+ ActivityPub.fetch_activities([], %{"blocking_user" => blocker, "skip_preload" => true})
+
+ refute repeat_activity in activities
+ end
+
test "doesn't return muted activities" do
activity_one = insert(:note_activity)
activity_two = insert(:note_activity)
activity_three = insert(:note_activity)
user = insert(:user)
booster = insert(:user)
- {:ok, user} = User.mute(user, %User{ap_id: activity_one.data["actor"]})
+
+ activity_one_actor = User.get_by_ap_id(activity_one.data["actor"])
+ {:ok, _user_relationships} = User.mute(user, activity_one_actor)
activities =
ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true})
@@ -508,7 +693,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Enum.member?(activities, activity_three)
assert Enum.member?(activities, activity_one)
- {:ok, user} = User.unmute(user, %User{ap_id: activity_one.data["actor"]})
+ {:ok, _user_mute} = User.unmute(user, activity_one_actor)
activities =
ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true})
@@ -517,7 +702,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Enum.member?(activities, activity_three)
assert Enum.member?(activities, activity_one)
- {:ok, user} = User.mute(user, %User{ap_id: activity_three.data["actor"]})
+ activity_three_actor = User.get_by_ap_id(activity_three.data["actor"])
+ {:ok, _user_relationships} = User.mute(user, activity_three_actor)
{:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
%Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
activity_three = Activity.get_by_id(activity_three.id)
@@ -570,7 +756,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, announce, _object} = CommonAPI.repeat(activity_three.id, booster)
- [announce_activity] = ActivityPub.fetch_activities([user.ap_id | user.following])
+ [announce_activity] = ActivityPub.fetch_activities([user.ap_id | User.following(user)])
assert announce_activity.id == announce.id
end
@@ -610,48 +796,61 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
test "retrieves a maximum of 20 activities" do
- activities = ActivityBuilder.insert_list(30)
- last_expected = List.last(activities)
+ ActivityBuilder.insert_list(10)
+ expected_activities = ActivityBuilder.insert_list(20)
activities = ActivityPub.fetch_public_activities()
- last = List.last(activities)
+ assert collect_ids(activities) == collect_ids(expected_activities)
assert length(activities) == 20
- assert last == last_expected
end
test "retrieves ids starting from a since_id" do
activities = ActivityBuilder.insert_list(30)
- later_activities = ActivityBuilder.insert_list(10)
+ expected_activities = ActivityBuilder.insert_list(10)
since_id = List.last(activities).id
- last_expected = List.last(later_activities)
activities = ActivityPub.fetch_public_activities(%{"since_id" => since_id})
- last = List.last(activities)
+ assert collect_ids(activities) == collect_ids(expected_activities)
assert length(activities) == 10
- assert last == last_expected
end
test "retrieves ids up to max_id" do
- _first_activities = ActivityBuilder.insert_list(10)
- activities = ActivityBuilder.insert_list(20)
- later_activities = ActivityBuilder.insert_list(10)
- max_id = List.first(later_activities).id
- last_expected = List.last(activities)
+ ActivityBuilder.insert_list(10)
+ expected_activities = ActivityBuilder.insert_list(20)
+
+ %{id: max_id} =
+ 10
+ |> ActivityBuilder.insert_list()
+ |> List.first()
activities = ActivityPub.fetch_public_activities(%{"max_id" => max_id})
- last = List.last(activities)
assert length(activities) == 20
- assert last == last_expected
+ assert collect_ids(activities) == collect_ids(expected_activities)
+ end
+
+ test "paginates via offset/limit" do
+ _first_part_activities = ActivityBuilder.insert_list(10)
+ second_part_activities = ActivityBuilder.insert_list(10)
+
+ later_activities = ActivityBuilder.insert_list(10)
+
+ activities =
+ ActivityPub.fetch_public_activities(%{"page" => "2", "page_size" => "20"}, :offset)
+
+ assert length(activities) == 20
+
+ assert collect_ids(activities) ==
+ collect_ids(second_part_activities) ++ collect_ids(later_activities)
end
test "doesn't return reblogs for users for whom reblogs have been muted" do
activity = insert(:note_activity)
user = insert(:user)
booster = insert(:user)
- {:ok, user} = CommonAPI.hide_reblogs(user, booster)
+ {:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
{:ok, activity, _} = CommonAPI.repeat(activity.id, booster)
@@ -664,8 +863,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
activity = insert(:note_activity)
user = insert(:user)
booster = insert(:user)
- {:ok, user} = CommonAPI.hide_reblogs(user, booster)
- {:ok, user} = CommonAPI.show_reblogs(user, booster)
+ {:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
+ {:ok, _reblog_mute} = CommonAPI.show_reblogs(user, booster)
{:ok, activity, _} = CommonAPI.repeat(activity.id, booster)
@@ -675,16 +874,137 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
+ describe "react to an object" do
+ test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
+ Config.put([:instance, :federating], true)
+ user = insert(:user)
+ reactor = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+ assert object = Object.normalize(activity)
+
+ {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+ assert called(Federator.publish(reaction_activity))
+ end
+
+ test "adds an emoji reaction activity to the db" do
+ user = insert(:user)
+ reactor = insert(:user)
+ third_user = insert(:user)
+ fourth_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+ assert object = Object.normalize(activity)
+
+ {:ok, reaction_activity, object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+ assert reaction_activity
+
+ assert reaction_activity.data["actor"] == reactor.ap_id
+ assert reaction_activity.data["type"] == "EmojiReact"
+ assert reaction_activity.data["content"] == "🔥"
+ assert reaction_activity.data["object"] == object.data["id"]
+ assert reaction_activity.data["to"] == [User.ap_followers(reactor), activity.data["actor"]]
+ assert reaction_activity.data["context"] == object.data["context"]
+ assert object.data["reaction_count"] == 1
+ assert object.data["reactions"] == [["🔥", [reactor.ap_id]]]
+
+ {:ok, _reaction_activity, object} = ActivityPub.react_with_emoji(third_user, object, "☕")
+
+ assert object.data["reaction_count"] == 2
+ assert object.data["reactions"] == [["🔥", [reactor.ap_id]], ["☕", [third_user.ap_id]]]
+
+ {:ok, _reaction_activity, object} = ActivityPub.react_with_emoji(fourth_user, object, "🔥")
+
+ assert object.data["reaction_count"] == 3
+
+ assert object.data["reactions"] == [
+ ["🔥", [fourth_user.ap_id, reactor.ap_id]],
+ ["☕", [third_user.ap_id]]
+ ]
+ end
+
+ test "reverts emoji reaction on error" do
+ [user, reactor] = insert_list(2, :user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "Status"})
+ object = Object.normalize(activity)
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} = ActivityPub.react_with_emoji(reactor, object, "😀")
+ end
+
+ object = Object.get_by_ap_id(object.data["id"])
+ refute object.data["reaction_count"]
+ refute object.data["reactions"]
+ end
+ end
+
+ describe "unreacting to an object" do
+ test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
+ Config.put([:instance, :federating], true)
+ user = insert(:user)
+ reactor = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+ assert object = Object.normalize(activity)
+
+ {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+ assert called(Federator.publish(reaction_activity))
+
+ {:ok, unreaction_activity, _object} =
+ ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
+
+ assert called(Federator.publish(unreaction_activity))
+ end
+
+ test "adds an undo activity to the db" do
+ user = insert(:user)
+ reactor = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
+ assert object = Object.normalize(activity)
+
+ {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
+
+ {:ok, unreaction_activity, _object} =
+ ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
+
+ assert unreaction_activity.actor == reactor.ap_id
+ assert unreaction_activity.data["object"] == reaction_activity.data["id"]
+
+ object = Object.get_by_ap_id(object.data["id"])
+ assert object.data["reaction_count"] == 0
+ assert object.data["reactions"] == []
+ end
+
+ test "reverts emoji unreact on error" do
+ [user, reactor] = insert_list(2, :user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "Status"})
+ object = Object.normalize(activity)
+
+ {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "😀")
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} =
+ ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
+ end
+
+ object = Object.get_by_ap_id(object.data["id"])
+
+ assert object.data["reaction_count"] == 1
+ assert object.data["reactions"] == [["😀", [reactor.ap_id]]]
+ end
+ end
+
describe "like an object" do
- test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
- Pleroma.Config.put([:instance, :federating], true)
+ test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
+ Config.put([:instance, :federating], true)
note_activity = insert(:note_activity)
assert object_activity = Object.normalize(note_activity)
user = insert(:user)
{:ok, like_activity, _object} = ActivityPub.like(user, object_activity)
- assert called(Pleroma.Web.Federator.publish(like_activity, 5))
+ assert called(Federator.publish(like_activity))
end
test "returns exist activity if object already liked" do
@@ -699,6 +1019,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert like_activity == like_activity_exist
end
+ test "reverts like activity on error" do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ user = insert(:user)
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} = ActivityPub.like(user, object)
+ end
+
+ assert Repo.aggregate(Activity, :count, :id) == 1
+ assert Repo.get(Object, object.id) == object
+ end
+
test "adds a like activity to the db" do
note_activity = insert(:note_activity)
assert object = Object.normalize(note_activity)
@@ -729,15 +1062,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
describe "unliking" do
- test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
- Pleroma.Config.put([:instance, :federating], true)
+ test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
+ Config.put([:instance, :federating], true)
note_activity = insert(:note_activity)
object = Object.normalize(note_activity)
user = insert(:user)
{:ok, object} = ActivityPub.unlike(user, object)
- refute called(Pleroma.Web.Federator.publish())
+ refute called(Federator.publish())
{:ok, _like_activity, object} = ActivityPub.like(user, object)
assert object.data["like_count"] == 1
@@ -745,7 +1078,24 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)
assert object.data["like_count"] == 0
- assert called(Pleroma.Web.Federator.publish(unlike_activity, 5))
+ assert called(Federator.publish(unlike_activity))
+ end
+
+ test "reverts unliking on error" do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ user = insert(:user)
+
+ {:ok, like_activity, object} = ActivityPub.like(user, object)
+ assert object.data["like_count"] == 1
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} = ActivityPub.unlike(user, object)
+ end
+
+ assert Object.get_by_ap_id(object.data["id"]) == object
+ assert object.data["like_count"] == 1
+ assert Activity.get_by_id(like_activity.id)
end
test "unliking a previously liked object" do
@@ -787,6 +1137,54 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert announce_activity.data["actor"] == user.ap_id
assert announce_activity.data["context"] == object.data["context"]
end
+
+ test "reverts annouce from object on error" do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ user = insert(:user)
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} = ActivityPub.announce(user, object)
+ end
+
+ reloaded_object = Object.get_by_ap_id(object.data["id"])
+ assert reloaded_object == object
+ refute reloaded_object.data["announcement_count"]
+ refute reloaded_object.data["announcements"]
+ end
+ end
+
+ describe "announcing a private object" do
+ test "adds an announce activity to the db if the audience is not widened" do
+ user = insert(:user)
+ {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ object = Object.normalize(note_activity)
+
+ {:ok, announce_activity, object} = ActivityPub.announce(user, object, nil, true, false)
+
+ assert announce_activity.data["to"] == [User.ap_followers(user)]
+
+ assert announce_activity.data["object"] == object.data["id"]
+ assert announce_activity.data["actor"] == user.ap_id
+ assert announce_activity.data["context"] == object.data["context"]
+ end
+
+ test "does not add an announce activity to the db if the audience is widened" do
+ user = insert(:user)
+ {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ object = Object.normalize(note_activity)
+
+ assert {:error, _} = ActivityPub.announce(user, object, nil, true, true)
+ end
+
+ test "does not add an announce activity to the db if the announcer is not the author" do
+ user = insert(:user)
+ announcer = insert(:user)
+ {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+ object = Object.normalize(note_activity)
+
+ assert {:error, _} = ActivityPub.announce(announcer, object, nil, true, false)
+ end
end
describe "unannouncing an object" do
@@ -796,8 +1194,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
user = insert(:user)
# Unannouncing an object that is not announced does nothing
- # {:ok, object} = ActivityPub.unannounce(user, object)
- # assert object.data["announcement_count"] == 0
+ {:ok, object} = ActivityPub.unannounce(user, object)
+ refute object.data["announcement_count"]
{:ok, announce_activity, object} = ActivityPub.announce(user, object)
assert object.data["announcement_count"] == 1
@@ -817,6 +1215,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert Activity.get_by_id(announce_activity.id) == nil
end
+
+ test "reverts unannouncing on error" do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ user = insert(:user)
+
+ {:ok, _announce_activity, object} = ActivityPub.announce(user, object)
+ assert object.data["announcement_count"] == 1
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} = ActivityPub.unannounce(user, object)
+ end
+
+ object = Object.get_by_ap_id(object.data["id"])
+ assert object.data["announcement_count"] == 1
+ end
end
describe "uploading files" do
@@ -851,6 +1265,35 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
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
+
+ test "it reverts unfollow activity" do
+ follower = insert(:user)
+ followed = insert(:user)
+
+ {:ok, follow_activity} = ActivityPub.follow(follower, followed)
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} = ActivityPub.unfollow(follower, followed)
+ end
+
+ activity = Activity.get_by_id(follow_activity.id)
+ assert activity.data["type"] == "Follow"
+ assert activity.data["actor"] == follower.ap_id
+
+ assert activity.data["object"] == followed.ap_id
+ end
+
test "creates a follow activity" do
follower = insert(:user)
followed = insert(:user)
@@ -877,9 +1320,37 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert embedded_object["object"] == followed.ap_id
assert embedded_object["id"] == follow_activity.data["id"]
end
+
+ test "creates an undo activity for a pending follow request" do
+ follower = insert(:user)
+ followed = insert(:user, %{locked: true})
+
+ {:ok, follow_activity} = ActivityPub.follow(follower, followed)
+ {:ok, activity} = ActivityPub.unfollow(follower, followed)
+
+ assert activity.data["type"] == "Undo"
+ assert activity.data["actor"] == follower.ap_id
+
+ embedded_object = activity.data["object"]
+ assert is_map(embedded_object)
+ assert embedded_object["type"] == "Follow"
+ assert embedded_object["object"] == followed.ap_id
+ assert embedded_object["id"] == follow_activity.data["id"]
+ end
end
describe "blocking / unblocking" 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
blocker = insert(:user)
blocked = insert(:user)
@@ -891,6 +1362,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert activity.data["object"] == blocked.ap_id
end
+ test "reverts unblock activity on error" do
+ [blocker, blocked] = insert_list(2, :user)
+ {:ok, block_activity} = ActivityPub.block(blocker, blocked)
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} = ActivityPub.unblock(blocker, blocked)
+ end
+
+ assert block_activity.data["type"] == "Block"
+ assert block_activity.data["actor"] == blocker.ap_id
+
+ assert Repo.aggregate(Activity, :count, :id) == 1
+ assert Repo.aggregate(Object, :count, :id) == 1
+ end
+
test "creates an undo activity for the last block" do
blocker = insert(:user)
blocked = insert(:user)
@@ -910,6 +1396,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
describe "deletion" do
+ clear_config([:instance, :rewrite_policy])
+
+ test "it reverts deletion on error" do
+ note = insert(:note_activity)
+ object = Object.normalize(note)
+
+ with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
+ assert {:error, :reverted} = ActivityPub.delete(object)
+ end
+
+ assert Repo.aggregate(Activity, :count, :id) == 1
+ assert Repo.get(Object, object.id) == object
+ assert Activity.get_by_id(note.id) == note
+ end
+
test "it creates a delete activity and deletes the original object" do
note = insert(:note_activity)
object = Object.normalize(note)
@@ -925,7 +1426,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
test "decrements user note count only for public activities" do
- user = insert(:user, info: %{note_count: 10})
+ user = insert(:user, note_count: 10)
{:ok, a1} =
CommonAPI.post(User.get_cached_by_id(user.id), %{
@@ -957,7 +1458,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
{:ok, _} = Object.normalize(a4) |> ActivityPub.delete()
user = User.get_cached_by_id(user.id)
- assert user.info.note_count == 10
+ assert user.note_count == 10
end
test "it creates a delete activity and checks that it is also sent to users mentioned by the deleted object" do
@@ -1011,6 +1512,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
assert object.data["repliesCount"] == 0
end
+
+ test "it passes delete activity through MRF before deleting the object" do
+ Pleroma.Config.put([:instance, :rewrite_policy], Pleroma.Web.ActivityPub.MRF.DropPolicy)
+
+ note = insert(:note_activity)
+ object = Object.normalize(note)
+
+ {:error, {:reject, _}} = ActivityPub.delete(object)
+
+ assert Activity.get_by_id(note.id)
+ assert Repo.get(Object, object.id).data["type"] == object.data["type"]
+ end
end
describe "timeline post-processing" do
@@ -1048,7 +1561,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
})
activities =
- ActivityPub.fetch_activities([user1.ap_id | user1.following])
+ ActivityPub.fetch_activities([user1.ap_id | User.following(user1)])
|> Enum.map(fn a -> a.id end)
private_activity_1 = Activity.get_by_ap_id_with_object(private_activity_1.data["id"])
@@ -1058,7 +1571,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert length(activities) == 3
activities =
- ActivityPub.fetch_activities([user1.ap_id | user1.following], %{"user" => user1})
+ ActivityPub.fetch_activities([user1.ap_id | User.following(user1)], %{"user" => user1})
|> Enum.map(fn a -> a.id end)
assert [public_activity.id, private_activity_1.id] == activities
@@ -1067,6 +1580,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
describe "update" 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)
@@ -1089,7 +1604,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
test "returned pinned statuses" do
- Pleroma.Config.put([:instance, :max_pinned_statuses], 3)
+ Config.put([:instance, :max_pinned_statuses], 3)
user = insert(:user)
{:ok, activity_one} = CommonAPI.post(user, %{"status" => "HI!!!"})
@@ -1110,35 +1625,99 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert 3 = length(activities)
end
- test "it can create a Flag activity" do
- reporter = insert(:user)
- target_account = insert(:user)
- {:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
- context = Utils.generate_context_id()
- content = "foobar"
-
- reporter_ap_id = reporter.ap_id
- target_ap_id = target_account.ap_id
- activity_ap_id = activity.data["id"]
-
- assert {:ok, activity} =
- ActivityPub.flag(%{
- actor: reporter,
- context: context,
- account: target_account,
- statuses: [activity],
- content: content
- })
-
- assert %Activity{
- actor: ^reporter_ap_id,
- data: %{
- "type" => "Flag",
- "content" => ^content,
- "context" => ^context,
- "object" => [^target_ap_id, ^activity_ap_id]
- }
- } = activity
+ describe "flag/1" do
+ setup do
+ reporter = insert(:user)
+ target_account = insert(:user)
+ content = "foobar"
+ {:ok, activity} = CommonAPI.post(target_account, %{"status" => content})
+ context = Utils.generate_context_id()
+
+ reporter_ap_id = reporter.ap_id
+ target_ap_id = target_account.ap_id
+ activity_ap_id = activity.data["id"]
+
+ activity_with_object = Activity.get_by_ap_id_with_object(activity_ap_id)
+
+ {:ok,
+ %{
+ reporter: reporter,
+ context: context,
+ target_account: target_account,
+ reported_activity: activity,
+ content: content,
+ activity_ap_id: activity_ap_id,
+ activity_with_object: activity_with_object,
+ reporter_ap_id: reporter_ap_id,
+ target_ap_id: target_ap_id
+ }}
+ end
+
+ test "it can create a Flag activity",
+ %{
+ reporter: reporter,
+ context: context,
+ target_account: target_account,
+ reported_activity: reported_activity,
+ content: content,
+ activity_ap_id: activity_ap_id,
+ activity_with_object: activity_with_object,
+ reporter_ap_id: reporter_ap_id,
+ target_ap_id: target_ap_id
+ } do
+ assert {:ok, activity} =
+ ActivityPub.flag(%{
+ actor: reporter,
+ context: context,
+ account: target_account,
+ statuses: [reported_activity],
+ content: content
+ })
+
+ note_obj = %{
+ "type" => "Note",
+ "id" => activity_ap_id,
+ "content" => content,
+ "published" => activity_with_object.object.data["published"],
+ "actor" => AccountView.render("show.json", %{user: target_account})
+ }
+
+ assert %Activity{
+ actor: ^reporter_ap_id,
+ data: %{
+ "type" => "Flag",
+ "content" => ^content,
+ "context" => ^context,
+ "object" => [^target_ap_id, ^note_obj]
+ }
+ } = activity
+ end
+
+ test_with_mock "strips status data from Flag, before federating it",
+ %{
+ reporter: reporter,
+ context: context,
+ target_account: target_account,
+ reported_activity: reported_activity,
+ content: content
+ },
+ Utils,
+ [:passthrough],
+ [] do
+ {:ok, activity} =
+ ActivityPub.flag(%{
+ actor: reporter,
+ context: context,
+ account: target_account,
+ statuses: [reported_activity],
+ content: content
+ })
+
+ new_data =
+ put_in(activity.data, ["object"], [target_account.ap_id, reported_activity.data["id"]])
+
+ assert_called(Utils.maybe_federate(%{activity | data: new_data}))
+ end
end
test "fetch_activities/2 returns activities addressed to a list " do
@@ -1221,9 +1800,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
following_address: "http://localhost:4001/users/masto_closed/following"
)
- {:ok, info} = ActivityPub.fetch_follow_information_for_user(user)
- assert info.hide_followers == true
- assert info.hide_follows == false
+ {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
+ assert follow_info.hide_followers == true
+ assert follow_info.hide_follows == false
end
test "detects hidden follows" do
@@ -1244,9 +1823,151 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
following_address: "http://localhost:4001/users/masto_closed/following"
)
- {:ok, info} = ActivityPub.fetch_follow_information_for_user(user)
- assert info.hide_followers == false
- assert info.hide_follows == true
+ {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
+ assert follow_info.hide_followers == false
+ assert follow_info.hide_follows == true
+ end
+
+ test "detects hidden follows/followers for friendica" do
+ user =
+ insert(:user,
+ local: false,
+ follower_address: "http://localhost:8080/followers/fuser3",
+ following_address: "http://localhost:8080/following/fuser3"
+ )
+
+ {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
+ assert follow_info.hide_followers == true
+ assert follow_info.follower_count == 296
+ assert follow_info.following_count == 32
+ assert follow_info.hide_follows == true
+ end
+
+ test "doesn't crash when follower and following counters are hidden" do
+ mock(fn env ->
+ case env.url do
+ "http://localhost:4001/users/masto_hidden_counters/following" ->
+ json(%{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "id" => "http://localhost:4001/users/masto_hidden_counters/followers"
+ })
+
+ "http://localhost:4001/users/masto_hidden_counters/following?page=1" ->
+ %Tesla.Env{status: 403, body: ""}
+
+ "http://localhost:4001/users/masto_hidden_counters/followers" ->
+ json(%{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "id" => "http://localhost:4001/users/masto_hidden_counters/following"
+ })
+
+ "http://localhost:4001/users/masto_hidden_counters/followers?page=1" ->
+ %Tesla.Env{status: 403, body: ""}
+ end
+ end)
+
+ user =
+ insert(:user,
+ local: false,
+ follower_address: "http://localhost:4001/users/masto_hidden_counters/followers",
+ following_address: "http://localhost:4001/users/masto_hidden_counters/following"
+ )
+
+ {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
+
+ assert follow_info.hide_followers == true
+ assert follow_info.follower_count == 0
+ assert follow_info.hide_follows == true
+ assert follow_info.following_count == 0
+ end
+ end
+
+ describe "fetch_favourites/3" do
+ test "returns a favourite activities sorted by adds to favorite" do
+ user = insert(:user)
+ other_user = insert(:user)
+ user1 = insert(:user)
+ user2 = insert(:user)
+ {:ok, a1} = CommonAPI.post(user1, %{"status" => "bla"})
+ {:ok, _a2} = CommonAPI.post(user2, %{"status" => "traps are happy"})
+ {:ok, a3} = CommonAPI.post(user2, %{"status" => "Trees Are "})
+ {:ok, a4} = CommonAPI.post(user2, %{"status" => "Agent Smith "})
+ {:ok, a5} = CommonAPI.post(user1, %{"status" => "Red or Blue "})
+
+ {:ok, _, _} = CommonAPI.favorite(a4.id, user)
+ {:ok, _, _} = CommonAPI.favorite(a3.id, other_user)
+ {:ok, _, _} = CommonAPI.favorite(a3.id, user)
+ {:ok, _, _} = CommonAPI.favorite(a5.id, other_user)
+ {:ok, _, _} = CommonAPI.favorite(a5.id, user)
+ {:ok, _, _} = CommonAPI.favorite(a4.id, other_user)
+ {:ok, _, _} = CommonAPI.favorite(a1.id, user)
+ {:ok, _, _} = CommonAPI.favorite(a1.id, other_user)
+ result = ActivityPub.fetch_favourites(user)
+
+ assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id]
+
+ result = ActivityPub.fetch_favourites(user, %{"limit" => 2})
+ assert Enum.map(result, & &1.id) == [a1.id, a5.id]
+ end
+ end
+
+ describe "Move activity" do
+ test "create" do
+ %{ap_id: old_ap_id} = old_user = insert(:user)
+ %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
+ follower = insert(:user)
+ follower_move_opted_out = insert(:user, allow_following_move: false)
+
+ User.follow(follower, old_user)
+ User.follow(follower_move_opted_out, old_user)
+
+ assert User.following?(follower, old_user)
+ assert User.following?(follower_move_opted_out, old_user)
+
+ assert {:ok, activity} = ActivityPub.move(old_user, new_user)
+
+ assert %Activity{
+ actor: ^old_ap_id,
+ data: %{
+ "actor" => ^old_ap_id,
+ "object" => ^old_ap_id,
+ "target" => ^new_ap_id,
+ "type" => "Move"
+ },
+ local: true
+ } = activity
+
+ params = %{
+ "op" => "move_following",
+ "origin_id" => old_user.id,
+ "target_id" => new_user.id
+ }
+
+ assert_enqueued(worker: Pleroma.Workers.BackgroundWorker, args: params)
+
+ Pleroma.Workers.BackgroundWorker.perform(params, nil)
+
+ refute User.following?(follower, old_user)
+ assert User.following?(follower, new_user)
+
+ assert User.following?(follower_move_opted_out, old_user)
+ refute User.following?(follower_move_opted_out, new_user)
+
+ activity = %Activity{activity | object: nil}
+
+ assert [%Notification{activity: ^activity}] =
+ Notification.for_user(follower, %{with_move: true})
+
+ assert [%Notification{activity: ^activity}] =
+ Notification.for_user(follower_move_opted_out, %{with_move: true})
+ end
+
+ test "old user must be in the new user's `also_known_as` list" do
+ old_user = insert(:user)
+ new_user = insert(:user)
+
+ assert {:error, "Target account must have the origin in `alsoKnownAs`"} =
+ ActivityPub.move(old_user, new_user)
end
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 03dc299ec..b524fdd23 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
@@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
test "it allows posts without links" do
user = insert(:user)
- assert user.info.note_count == 0
+ assert user.note_count == 0
message =
@linkless_message
@@ -47,7 +47,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
test "it disallows posts with links" do
user = insert(:user)
- assert user.info.note_count == 0
+ assert user.note_count == 0
message =
@linkful_message
@@ -59,9 +59,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
describe "with old user" do
test "it allows posts without links" do
- user = insert(:user, info: %{note_count: 1})
+ user = insert(:user, note_count: 1)
- assert user.info.note_count == 1
+ assert user.note_count == 1
message =
@linkless_message
@@ -71,9 +71,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
end
test "it allows posts with links" do
- user = insert(:user, info: %{note_count: 1})
+ user = insert(:user, note_count: 1)
- assert user.info.note_count == 1
+ assert user.note_count == 1
message =
@linkful_message
@@ -85,9 +85,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
describe "with followed new user" do
test "it allows posts without links" do
- user = insert(:user, info: %{follower_count: 1})
+ user = insert(:user, follower_count: 1)
- assert user.info.follower_count == 1
+ assert user.follower_count == 1
message =
@linkless_message
@@ -97,9 +97,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
end
test "it allows posts with links" do
- user = insert(:user, info: %{follower_count: 1})
+ user = insert(:user, follower_count: 1)
- assert user.info.follower_count == 1
+ assert user.follower_count == 1
message =
@linkful_message
@@ -133,7 +133,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
describe "with contentless-objects" do
test "it does not reject them or error out" do
- user = insert(:user, info: %{note_count: 1})
+ user = insert(:user, note_count: 1)
message =
@response_message
diff --git a/test/web/activity_pub/mrf/hellthread_policy_test.exs b/test/web/activity_pub/mrf/hellthread_policy_test.exs
index eb6ee4d04..916b95692 100644
--- a/test/web/activity_pub/mrf/hellthread_policy_test.exs
+++ b/test/web/activity_pub/mrf/hellthread_policy_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do
@@ -26,6 +26,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do
[user: user, message: message]
end
+ clear_config(:mrf_hellthread)
+
describe "reject" do
test "rejects the message if the recipient count is above reject_threshold", %{
message: message
diff --git a/test/web/activity_pub/mrf/keyword_policy_test.exs b/test/web/activity_pub/mrf/keyword_policy_test.exs
index 602892a37..18242a889 100644
--- a/test/web/activity_pub/mrf/keyword_policy_test.exs
+++ b/test/web/activity_pub/mrf/keyword_policy_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
@@ -7,6 +7,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
alias Pleroma.Web.ActivityPub.MRF.KeywordPolicy
+ clear_config(:mrf_keyword)
+
setup do
Pleroma.Config.put([:mrf_keyword], %{reject: [], federated_timeline_removal: [], replace: []})
end
diff --git a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs b/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs
index 372e789be..313d59a66 100644
--- a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs
+++ b/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs
@@ -1,11 +1,12 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
use Pleroma.DataCase
alias Pleroma.HTTP
+ alias Pleroma.Tests.ObanHelpers
alias Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy
import Mock
@@ -24,6 +25,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
test "it prefetches media proxy URIs" do
with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do
MediaProxyWarmingPolicy.filter(@message)
+
+ ObanHelpers.perform_all()
+ # Performing jobs which has been just enqueued
+ ObanHelpers.perform_all()
+
assert called(HTTP.get(:_, :_, :_))
end
end
diff --git a/test/web/activity_pub/mrf/mention_policy_test.exs b/test/web/activity_pub/mrf/mention_policy_test.exs
index 9fd9c31df..08f7be542 100644
--- a/test/web/activity_pub/mrf/mention_policy_test.exs
+++ b/test/web/activity_pub/mrf/mention_policy_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do
@@ -7,6 +7,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do
alias Pleroma.Web.ActivityPub.MRF.MentionPolicy
+ clear_config(:mrf_mention)
+
test "pass filter if allow list is empty" do
Pleroma.Config.delete([:mrf_mention])
diff --git a/test/web/activity_pub/mrf/normalize_markup_test.exs b/test/web/activity_pub/mrf/normalize_markup_test.exs
index 3916a1f35..0207be56b 100644
--- a/test/web/activity_pub/mrf/normalize_markup_test.exs
+++ b/test/web/activity_pub/mrf/normalize_markup_test.exs
@@ -20,11 +20,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
expected = """
<b>this is in bold</b>
<p>this is a paragraph</p>
- this is a linebreak<br />
- this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
- this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
- this is an image: <img src="http://example.com/image.jpg" /><br />
- alert('hacked')
+ this is a linebreak<br/>
+ this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a>
+ this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a>
+ this is an image: <img src="http://example.com/image.jpg"/><br/>
+ alert(&#39;hacked&#39;)
"""
message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
diff --git a/test/web/activity_pub/mrf/object_age_policy_test.exs b/test/web/activity_pub/mrf/object_age_policy_test.exs
new file mode 100644
index 000000000..643609da4
--- /dev/null
+++ b/test/web/activity_pub/mrf/object_age_policy_test.exs
@@ -0,0 +1,105 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
+ use Pleroma.DataCase
+ alias Pleroma.Config
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy
+ alias Pleroma.Web.ActivityPub.Visibility
+
+ clear_config([:mrf_object_age]) do
+ Config.put(:mrf_object_age,
+ threshold: 172_800,
+ actions: [:delist, :strip_followers]
+ )
+ end
+
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
+ describe "with reject action" do
+ test "it rejects an old post" do
+ Config.put([:mrf_object_age, :actions], [:reject])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+
+ {:reject, _} = ObjectAgePolicy.filter(data)
+ end
+
+ test "it allows a new post" do
+ Config.put([:mrf_object_age, :actions], [:reject])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+
+ {:ok, _} = ObjectAgePolicy.filter(data)
+ end
+ end
+
+ describe "with delist action" do
+ test "it delists an old post" do
+ Config.put([:mrf_object_age, :actions], [:delist])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+
+ {: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 allows a new post" do
+ Config.put([:mrf_object_age, :actions], [:delist])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+
+ {:ok, _user} = User.get_or_fetch_by_ap_id(data["actor"])
+
+ {:ok, ^data} = ObjectAgePolicy.filter(data)
+ end
+ end
+
+ describe "with strip_followers action" do
+ test "it strips followers collections from an old post" do
+ Config.put([:mrf_object_age, :actions], [:strip_followers])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+
+ {: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 allows a new post" do
+ Config.put([:mrf_object_age, :actions], [:strip_followers])
+
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+
+ {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
+
+ {:ok, ^data} = ObjectAgePolicy.filter(data)
+ end
+ end
+end
diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs
index 7203b27da..df0f223f8 100644
--- a/test/web/activity_pub/mrf/simple_policy_test.exs
+++ b/test/web/activity_pub/mrf/simple_policy_test.exs
@@ -236,7 +236,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
end
- test "has a matching host" do
+ test "activity has a matching host" do
Config.put([:mrf_simple, :reject], ["remote.instance"])
remote_message = build_remote_message()
@@ -244,13 +244,21 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
assert SimplePolicy.filter(remote_message) == {:reject, nil}
end
- test "match with wildcard domain" do
+ test "activity matches with wildcard domain" do
Config.put([:mrf_simple, :reject], ["*.remote.instance"])
remote_message = build_remote_message()
assert SimplePolicy.filter(remote_message) == {:reject, nil}
end
+
+ test "actor has a matching host" do
+ Config.put([:mrf_simple, :reject], ["remote.instance"])
+
+ remote_user = build_remote_user()
+
+ assert SimplePolicy.filter(remote_user) == {:reject, nil}
+ end
end
describe "when :accept" do
@@ -264,7 +272,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
end
- test "is not empty but it doesn't have a matching host" do
+ test "is not empty but activity doesn't have a matching host" do
Config.put([:mrf_simple, :accept], ["non.matching.remote"])
local_message = build_local_message()
@@ -274,7 +282,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
assert SimplePolicy.filter(remote_message) == {:reject, nil}
end
- test "has a matching host" do
+ test "activity has a matching host" do
Config.put([:mrf_simple, :accept], ["remote.instance"])
local_message = build_local_message()
@@ -284,7 +292,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
end
- test "match with wildcard domain" do
+ test "activity matches with wildcard domain" do
Config.put([:mrf_simple, :accept], ["*.remote.instance"])
local_message = build_local_message()
@@ -293,6 +301,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
assert SimplePolicy.filter(local_message) == {:ok, local_message}
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
end
+
+ test "actor has a matching host" do
+ Config.put([:mrf_simple, :accept], ["remote.instance"])
+
+ remote_user = build_remote_user()
+
+ assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
+ end
end
describe "when :avatar_removal" do
diff --git a/test/web/activity_pub/mrf/subchain_policy_test.exs b/test/web/activity_pub/mrf/subchain_policy_test.exs
index f7cbcad48..221b8958e 100644
--- a/test/web/activity_pub/mrf/subchain_policy_test.exs
+++ b/test/web/activity_pub/mrf/subchain_policy_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicyTest do
@@ -14,6 +14,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicyTest do
"object" => %{"content" => "hi"}
}
+ clear_config([:mrf_subchain, :match_actor])
+
test "it matches and processes subchains when the actor matches a configured target" do
Pleroma.Config.put([:mrf_subchain, :match_actor], %{
~r/^https:\/\/banned.com/s => [DropPolicy]
diff --git a/test/web/activity_pub/mrf/tag_policy_test.exs b/test/web/activity_pub/mrf/tag_policy_test.exs
index 4aa35311e..e7793641a 100644
--- a/test/web/activity_pub/mrf/tag_policy_test.exs
+++ b/test/web/activity_pub/mrf/tag_policy_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest 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 72084c0fd..87c9e1b29 100644
--- a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
+++ b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
use Pleroma.DataCase
diff --git a/test/web/activity_pub/mrf/vocabulary_policy_test.exs b/test/web/activity_pub/mrf/vocabulary_policy_test.exs
index 38309f9f1..d9207b095 100644
--- a/test/web/activity_pub/mrf/vocabulary_policy_test.exs
+++ b/test/web/activity_pub/mrf/vocabulary_policy_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do
diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs
index 36a39c84c..3404848d4 100644
--- a/test/web/activity_pub/publisher_test.exs
+++ b/test/web/activity_pub/publisher_test.exs
@@ -1,17 +1,20 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.PublisherTest do
- use Pleroma.DataCase
+ use Pleroma.Web.ConnCase
+ import ExUnit.CaptureLog
import Pleroma.Factory
import Tesla.Mock
import Mock
alias Pleroma.Activity
alias Pleroma.Instances
+ alias Pleroma.Object
alias Pleroma.Web.ActivityPub.Publisher
+ alias Pleroma.Web.CommonAPI
@as_public "https://www.w3.org/ns/activitystreams#Public"
@@ -20,11 +23,32 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
:ok
end
+ describe "gather_webfinger_links/1" do
+ test "it returns links" do
+ user = insert(:user)
+
+ expected_links = [
+ %{"href" => user.ap_id, "rel" => "self", "type" => "application/activity+json"},
+ %{
+ "href" => user.ap_id,
+ "rel" => "self",
+ "type" => "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
+ },
+ %{
+ "rel" => "http://ostatus.org/schema/1.0/subscribe",
+ "template" => "#{Pleroma.Web.base_url()}/ostatus_subscribe?acct={uri}"
+ }
+ ]
+
+ assert expected_links == Publisher.gather_webfinger_links(user)
+ end
+ end
+
describe "determine_inbox/2" do
test "it returns sharedInbox for messages involving as:Public in to" do
user =
insert(:user, %{
- info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}}
+ source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
})
activity = %Activity{
@@ -37,7 +61,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
test "it returns sharedInbox for messages involving as:Public in cc" do
user =
insert(:user, %{
- info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}}
+ source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
})
activity = %Activity{
@@ -50,7 +74,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
test "it returns sharedInbox for messages involving multiple recipients in to" do
user =
insert(:user, %{
- info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}}
+ source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
})
user_two = insert(:user)
@@ -66,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
test "it returns sharedInbox for messages involving multiple recipients in cc" do
user =
insert(:user, %{
- info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}}
+ source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
})
user_two = insert(:user)
@@ -81,14 +105,12 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
test "it returns sharedInbox for messages involving multiple recipients in total" do
user =
- insert(:user, %{
- info: %{
- source_data: %{
- "inbox" => "http://example.com/personal-inbox",
- "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
- }
+ insert(:user,
+ source_data: %{
+ "inbox" => "http://example.com/personal-inbox",
+ "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
}
- })
+ )
user_two = insert(:user)
@@ -101,14 +123,12 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
test "it returns inbox for messages involving single recipients in total" do
user =
- insert(:user, %{
- info: %{
- source_data: %{
- "inbox" => "http://example.com/personal-inbox",
- "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
- }
+ insert(:user,
+ source_data: %{
+ "inbox" => "http://example.com/personal-inbox",
+ "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
}
- })
+ )
activity = %Activity{
data: %{"to" => [user.ap_id], "cc" => []}
@@ -188,7 +208,10 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
actor = insert(:user)
inbox = "http://connrefused.site/users/nick1/inbox"
- assert {:error, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
+ assert capture_log(fn ->
+ assert {:error, _} =
+ Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
+ end) =~ "connrefused"
assert called(Instances.set_unreachable(inbox))
end
@@ -212,14 +235,16 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
actor = insert(:user)
inbox = "http://connrefused.site/users/nick1/inbox"
- assert {:error, _} =
- Publisher.publish_one(%{
- inbox: inbox,
- json: "{}",
- actor: actor,
- id: 1,
- unreachable_since: NaiveDateTime.utc_now()
- })
+ assert capture_log(fn ->
+ assert {:error, _} =
+ Publisher.publish_one(%{
+ inbox: inbox,
+ json: "{}",
+ actor: actor,
+ id: 1,
+ unreachable_since: NaiveDateTime.utc_now()
+ })
+ end) =~ "connrefused"
refute called(Instances.set_unreachable(inbox))
end
@@ -233,10 +258,8 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
follower =
insert(:user,
local: false,
- info: %{
- ap_enabled: true,
- source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}
- }
+ source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"},
+ ap_enabled: true
)
actor = insert(:user, follower_address: follower.ap_id)
@@ -257,10 +280,70 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
assert called(
Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
inbox: "https://domain.com/users/nick1/inbox",
- actor: actor,
+ actor_id: actor.id,
id: note_activity.data["id"]
})
)
end
+
+ test_with_mock "publishes a delete activity to peers who signed fetch requests to the create acitvity/object.",
+ Pleroma.Web.Federator.Publisher,
+ [:passthrough],
+ [] do
+ fetcher =
+ insert(:user,
+ local: false,
+ source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"},
+ ap_enabled: true
+ )
+
+ another_fetcher =
+ insert(:user,
+ local: false,
+ source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"},
+ ap_enabled: true
+ )
+
+ actor = insert(:user)
+
+ note_activity = insert(:note_activity, user: actor)
+ object = Object.normalize(note_activity)
+
+ activity_path = String.trim_leading(note_activity.data["id"], Pleroma.Web.Endpoint.url())
+ object_path = String.trim_leading(object.data["id"], Pleroma.Web.Endpoint.url())
+
+ build_conn()
+ |> put_req_header("accept", "application/activity+json")
+ |> assign(:user, fetcher)
+ |> get(object_path)
+ |> json_response(200)
+
+ build_conn()
+ |> put_req_header("accept", "application/activity+json")
+ |> assign(:user, another_fetcher)
+ |> get(activity_path)
+ |> json_response(200)
+
+ {:ok, delete} = CommonAPI.delete(note_activity.id, actor)
+
+ res = Publisher.publish(actor, delete)
+ assert res == :ok
+
+ assert called(
+ Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
+ inbox: "https://domain.com/users/nick1/inbox",
+ actor_id: actor.id,
+ id: delete.data["id"]
+ })
+ )
+
+ assert called(
+ Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
+ inbox: "https://domain2.com/users/nick1/inbox",
+ actor_id: actor.id,
+ id: delete.data["id"]
+ })
+ )
+ end
end
end
diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs
index 4f7d592a6..e3115dcd8 100644
--- a/test/web/activity_pub/relay_test.exs
+++ b/test/web/activity_pub/relay_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.RelayTest do
@@ -7,9 +7,11 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
alias Pleroma.Activity
alias Pleroma.Object
+ alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Relay
+ import ExUnit.CaptureLog
import Pleroma.Factory
import Mock
@@ -18,9 +20,16 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
assert user.ap_id == "#{Pleroma.Web.Endpoint.url()}/relay"
end
+ test "relay actor is invisible" do
+ user = Relay.get_actor()
+ assert User.invisible?(user)
+ end
+
describe "follow/1" do
test "returns errors when user not found" do
- assert Relay.follow("test-ap-id") == {:error, "Could not fetch by AP id"}
+ assert capture_log(fn ->
+ {:error, _} = Relay.follow("test-ap-id")
+ end) =~ "Could not decode user at fetch"
end
test "returns activity" do
@@ -37,7 +46,9 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
describe "unfollow/1" do
test "returns errors when user not found" do
- assert Relay.unfollow("test-ap-id") == {:error, "Could not fetch by AP id"}
+ assert capture_log(fn ->
+ {:error, _} = Relay.unfollow("test-ap-id")
+ end) =~ "Could not decode user at fetch"
end
test "returns activity" do
@@ -45,14 +56,14 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
service_actor = Relay.get_actor()
ActivityPub.follow(service_actor, user)
Pleroma.User.follow(service_actor, user)
- assert "#{user.ap_id}/followers" in refresh_record(service_actor).following
+ 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"
assert user.ap_id in activity.recipients
assert activity.data["type"] == "Undo"
assert activity.data["actor"] == service_actor.ap_id
assert activity.data["to"] == [user.ap_id]
- refute "#{user.ap_id}/followers" in refresh_record(service_actor).following
+ refute "#{user.ap_id}/followers" in User.following(service_actor)
end
end
@@ -78,7 +89,9 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
}
)
- assert Relay.publish(activity) == {:error, nil}
+ assert capture_log(fn ->
+ assert Relay.publish(activity) == {:error, nil}
+ end) =~ "[error] error: nil"
end
test_with_mock "returns announce activity and publish to federate",
@@ -92,7 +105,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
assert activity.data["type"] == "Announce"
assert activity.data["actor"] == service_actor.ap_id
assert activity.data["object"] == obj.data["id"]
- assert called(Pleroma.Web.Federator.publish(activity, 5))
+ assert called(Pleroma.Web.Federator.publish(activity))
end
test_with_mock "returns announce activity and not publish to federate",
@@ -106,7 +119,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
assert activity.data["type"] == "Announce"
assert activity.data["actor"] == service_actor.ap_id
assert activity.data["object"] == obj.data["id"]
- refute called(Pleroma.Web.Federator.publish(activity, 5))
+ refute called(Pleroma.Web.Federator.publish(activity))
end
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 fe89f7cb0..c3d3f9830 100644
--- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs
+++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
@@ -19,6 +19,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
end
describe "handle_incoming" do
+ clear_config([:user, :deny_follow_blocked])
+
test "it works for osada follow request" do
user = insert(:user)
@@ -58,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
end
test "with locked accounts, it does not create a follow or an accept" do
- user = insert(:user, info: %{locked: true})
+ user = insert(:user, locked: true)
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
@@ -78,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
)
|> Repo.all()
- assert length(accepts) == 0
+ assert Enum.empty?(accepts)
end
test "it works for follow requests when you are already followed, creating a new accept activity" do
@@ -128,7 +130,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
user = insert(:user)
{:ok, target} = User.get_or_fetch("http://mastodon.example.org/users/admin")
- {:ok, user} = User.block(user, target)
+ {:ok, _user_relationship} = User.block(user, target)
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 300264ea9..efbca82f6 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -1,19 +1,20 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
+ use Oban.Testing, repo: Pleroma.Repo
use Pleroma.DataCase
+
alias Pleroma.Activity
alias Pleroma.Object
alias Pleroma.Object.Fetcher
- alias Pleroma.Repo
+ 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
- alias Pleroma.Web.OStatus
- alias Pleroma.Web.Websub.WebsubClientSubscription
import Mock
import Pleroma.Factory
@@ -40,7 +41,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert activity == returned_activity
end
- test "it fetches replied-to activities if we don't have them" do
+ @tag capture_log: true
+ test "it fetches reply-to activities if we don't have them" do
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
@@ -61,7 +63,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
end
- test "it does not fetch replied-to activities beyond max_replies_depth" do
+ test "it does not fetch reply-to activities beyond max replies depth limit" do
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
@@ -73,7 +75,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
data = Map.put(data, "object", object)
with_mock Pleroma.Web.Federator,
- allowed_incoming_reply_depth?: fn _ -> false end do
+ allowed_thread_distance?: fn _ -> false end do
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
returned_object = Object.normalize(returned_activity, false)
@@ -147,7 +149,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user = User.get_cached_by_ap_id(object_data["actor"])
- assert user.info.note_count == 1
+ assert user.note_count == 1
end
test "it works for incoming notices with hashtags" do
@@ -176,6 +178,35 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
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)
@@ -311,6 +342,99 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert data["object"] == activity.data["object"]
end
+ test "it works for incoming misskey likes, turning them into EmojiReacts" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+ data =
+ File.read!("test/fixtures/misskey-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == data["actor"]
+ assert data["type"] == "EmojiReact"
+ assert data["id"] == data["id"]
+ assert data["object"] == activity.data["object"]
+ assert data["content"] == "🍮"
+ end
+
+ test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReacts" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+ data =
+ File.read!("test/fixtures/misskey-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+ |> Map.put("_misskey_reaction", "⭐")
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == data["actor"]
+ assert data["type"] == "EmojiReact"
+ assert data["id"] == data["id"]
+ assert data["object"] == activity.data["object"]
+ assert data["content"] == "⭐"
+ end
+
+ test "it works for incoming emoji reactions" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+ data =
+ File.read!("test/fixtures/emoji-reaction.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "EmojiReact"
+ assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
+ assert data["object"] == activity.data["object"]
+ assert data["content"] == "👌"
+ end
+
+ test "it reject invalid emoji reactions" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+ data =
+ File.read!("test/fixtures/emoji-reaction-too-long.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ assert :error = Transmogrifier.handle_incoming(data)
+
+ data =
+ File.read!("test/fixtures/emoji-reaction-no-emoji.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ assert :error = Transmogrifier.handle_incoming(data)
+ end
+
+ test "it works for incoming emoji reaction undos" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+ {:ok, reaction_activity, _object} = CommonAPI.react_with_emoji(activity.id, user, "👌")
+
+ data =
+ File.read!("test/fixtures/mastodon-undo-like.json")
+ |> Poison.decode!()
+ |> Map.put("object", reaction_activity.data["id"])
+ |> Map.put("actor", user.ap_id)
+
+ {:ok, activity} = Transmogrifier.handle_incoming(data)
+
+ assert activity.actor == user.ap_id
+ assert activity.data["id"] == data["id"]
+ assert activity.data["type"] == "Undo"
+ end
+
test "it returns an error for incoming unlikes wihout a like activity" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
@@ -412,6 +536,34 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id
end
+ test "it works for incoming announces with an inlined activity" do
+ data =
+ File.read!("test/fixtures/mastodon-announce-private.json")
+ |> Poison.decode!()
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "http://mastodon.example.org/users/admin"
+ assert data["type"] == "Announce"
+
+ assert data["id"] ==
+ "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
+
+ object = Object.normalize(data["object"])
+
+ assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368"
+ assert object.data["content"] == "this is a private toot"
+ end
+
+ @tag capture_log: true
+ test "it rejects incoming announces with an inlined activity from another origin" do
+ data =
+ File.read!("test/fixtures/bogus-mastodon-announce.json")
+ |> Poison.decode!()
+
+ assert :error = Transmogrifier.handle_incoming(data)
+ end
+
test "it does not clobber the addressing on announce activities" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
@@ -498,6 +650,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute Map.has_key?(object.data, "likes")
end
+ test "it strips internal reactions" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
+ {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, user, "📢")
+
+ %{object: object} = Activity.get_by_id_with_object(activity.id)
+ assert Map.has_key?(object.data, "reactions")
+ assert Map.has_key?(object.data, "reaction_count")
+
+ object_data = Transmogrifier.strip_internal_fields(object.data)
+ refute Map.has_key?(object_data, "reactions")
+ refute Map.has_key?(object_data, "reaction_count")
+ end
+
test "it works for incoming update activities" do
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
@@ -528,7 +694,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
}
]
- assert user.info.banner["url"] == [
+ assert user.banner["url"] == [
%{
"href" =>
"https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
@@ -538,6 +704,37 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
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"
@@ -547,7 +744,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user = User.get_cached_by_ap_id(activity.actor)
- assert User.Info.fields(user.info) == [
+ assert User.fields(user) == [
%{"name" => "foo", "value" => "bar"},
%{"name" => "foo1", "value" => "bar1"}
]
@@ -568,7 +765,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user = User.get_cached_by_ap_id(user.ap_id)
- assert User.Info.fields(user.info) == [
+ assert User.fields(user) == [
%{"name" => "foo", "value" => "updated"},
%{"name" => "foo1", "value" => "updated"}
]
@@ -586,7 +783,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user = User.get_cached_by_ap_id(user.ap_id)
- assert User.Info.fields(user.info) == [
+ assert User.fields(user) == [
%{"name" => "foo", "value" => "updated"},
%{"name" => "foo1", "value" => "updated"}
]
@@ -597,7 +794,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
user = User.get_cached_by_ap_id(user.ap_id)
- assert User.Info.fields(user.info) == []
+ assert User.fields(user) == []
end
test "it works for incoming update activities which lock the account" do
@@ -620,11 +817,12 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
user = User.get_cached_by_ap_id(data["actor"])
- assert user.info.locked == true
+ assert user.locked == true
end
test "it works for incoming deletes" do
activity = insert(:note_activity)
+ deleting_user = insert(:user)
data =
File.read!("test/fixtures/mastodon-delete.json")
@@ -637,11 +835,14 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
data =
data
|> Map.put("object", object)
- |> Map.put("actor", activity.data["actor"])
+ |> Map.put("actor", deleting_user.ap_id)
- {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
+ {:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
+ Transmogrifier.handle_incoming(data)
+ assert id == data["id"]
refute Activity.get_by_id(activity.id)
+ assert actor == deleting_user.ap_id
end
test "it fails for incoming deletes with spoofed origin" do
@@ -662,11 +863,12 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert capture_log(fn ->
:error = Transmogrifier.handle_incoming(data)
end) =~
- "[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, {:error, :nxdomain}}"
+ "[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, :nxdomain}"
assert Activity.get_by_id(activity.id)
end
+ @tag capture_log: true
test "it works for incoming user deletes" do
%{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
@@ -675,6 +877,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|> Poison.decode!()
{:ok, _} = Transmogrifier.handle_incoming(data)
+ ObanHelpers.perform_all()
refute User.get_cached_by_ap_id(ap_id)
end
@@ -687,7 +890,10 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|> Poison.decode!()
|> Map.put("actor", ap_id)
- assert :error == Transmogrifier.handle_incoming(data)
+ assert capture_log(fn ->
+ assert :error == Transmogrifier.handle_incoming(data)
+ end) =~ "Object containment failed"
+
assert User.get_cached_by_ap_id(ap_id)
end
@@ -745,6 +951,25 @@ 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)
@@ -847,6 +1072,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
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
@@ -854,7 +1081,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it works for incoming accepts which were orphaned" do
follower = insert(:user)
- followed = insert(:user, %{info: %User.Info{locked: true}})
+ followed = insert(:user, locked: true)
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
@@ -876,7 +1103,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it works for incoming accepts which are referenced by IRI only" do
follower = insert(:user)
- followed = insert(:user, %{info: %User.Info{locked: true}})
+ followed = insert(:user, locked: true)
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
@@ -896,7 +1123,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it fails for incoming accepts which cannot be correlated" do
follower = insert(:user)
- followed = insert(:user, %{info: %User.Info{locked: true}})
+ followed = insert(:user, locked: true)
accept_data =
File.read!("test/fixtures/mastodon-accept-activity.json")
@@ -915,7 +1142,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it fails for incoming rejects which cannot be correlated" do
follower = insert(:user)
- followed = insert(:user, %{info: %User.Info{locked: true}})
+ followed = insert(:user, locked: true)
accept_data =
File.read!("test/fixtures/mastodon-reject-activity.json")
@@ -934,7 +1161,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it works for incoming rejects which are orphaned" do
follower = insert(:user)
- followed = insert(:user, %{info: %User.Info{locked: true}})
+ followed = insert(:user, locked: true)
{:ok, follower} = User.follow(follower, followed)
{:ok, _follow_activity} = ActivityPub.follow(follower, followed)
@@ -951,6 +1178,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{: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)
@@ -959,7 +1187,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it works for incoming rejects which are referenced by IRI only" do
follower = insert(:user)
- followed = insert(:user, %{info: %User.Info{locked: true}})
+ followed = insert(:user, locked: true)
{:ok, follower} = User.follow(follower, followed)
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
@@ -1028,10 +1256,18 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
object = Object.normalize(activity)
+ note_obj = %{
+ "type" => "Note",
+ "id" => activity.data["id"],
+ "content" => "test post",
+ "published" => object.data["published"],
+ "actor" => AccountView.render("show.json", %{user: user})
+ }
+
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"cc" => [user.ap_id],
- "object" => [user.ap_id, object.data["id"]],
+ "object" => [user.ap_id, activity.data["id"]],
"type" => "Flag",
"content" => "blocked AND reported!!!",
"actor" => other_user.ap_id
@@ -1039,14 +1275,190 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
- assert activity.data["object"] == [user.ap_id, object.data["id"]]
+ assert activity.data["object"] == [user.ap_id, note_obj]
assert activity.data["content"] == "blocked AND reported!!!"
assert activity.data["actor"] == other_user.ap_id
assert activity.data["cc"] == [user.ap_id]
end
+
+ test "it correctly processes messages with non-array to field" do
+ user = insert(:user)
+
+ message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "to" => "https://www.w3.org/ns/activitystreams#Public",
+ "type" => "Create",
+ "object" => %{
+ "content" => "blah blah blah",
+ "type" => "Note",
+ "attributedTo" => user.ap_id,
+ "inReplyTo" => nil
+ },
+ "actor" => user.ap_id
+ }
+
+ assert {:ok, activity} = Transmogrifier.handle_incoming(message)
+
+ assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["to"]
+ end
+
+ test "it correctly processes messages with non-array cc field" do
+ user = insert(:user)
+
+ message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "to" => user.follower_address,
+ "cc" => "https://www.w3.org/ns/activitystreams#Public",
+ "type" => "Create",
+ "object" => %{
+ "content" => "blah blah blah",
+ "type" => "Note",
+ "attributedTo" => user.ap_id,
+ "inReplyTo" => nil
+ },
+ "actor" => user.ap_id
+ }
+
+ assert {:ok, activity} = Transmogrifier.handle_incoming(message)
+
+ assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"]
+ assert [user.follower_address] == activity.data["to"]
+ end
+
+ test "it accepts Move activities" do
+ old_user = insert(:user)
+ new_user = insert(:user)
+
+ message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "type" => "Move",
+ "actor" => old_user.ap_id,
+ "object" => old_user.ap_id,
+ "target" => new_user.ap_id
+ }
+
+ assert :error = Transmogrifier.handle_incoming(message)
+
+ {:ok, _new_user} = User.update_and_set_cache(new_user, %{also_known_as: [old_user.ap_id]})
+
+ assert {:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(message)
+ assert activity.actor == old_user.ap_id
+ assert activity.data["actor"] == old_user.ap_id
+ assert activity.data["object"] == old_user.ap_id
+ assert activity.data["target"] == new_user.ap_id
+ assert activity.data["type"] == "Move"
+ end
+ end
+
+ describe "`handle_incoming/2`, Mastodon format `replies` handling" do
+ clear_config([:activitypub, :note_replies_output_limit]) do
+ Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5)
+ end
+
+ clear_config([:instance, :federation_incoming_replies_max_depth])
+
+ setup do
+ data =
+ "test/fixtures/mastodon-post-activity.json"
+ |> File.read!()
+ |> Poison.decode!()
+
+ items = get_in(data, ["object", "replies", "first", "items"])
+ assert length(items) > 0
+
+ %{data: data, items: items}
+ end
+
+ test "schedules background fetching of `replies` items if max thread depth limit allows", %{
+ data: data,
+ items: items
+ } do
+ Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10)
+
+ {:ok, _activity} = Transmogrifier.handle_incoming(data)
+
+ for id <- items do
+ job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1}
+ assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args)
+ end
+ end
+
+ test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows",
+ %{data: data} do
+ Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
+
+ {:ok, _activity} = Transmogrifier.handle_incoming(data)
+
+ assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == []
+ end
+ end
+
+ describe "`handle_incoming/2`, Pleroma format `replies` handling" do
+ clear_config([:activitypub, :note_replies_output_limit]) do
+ Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5)
+ end
+
+ clear_config([:instance, :federation_incoming_replies_max_depth])
+
+ setup do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "post1"})
+
+ {:ok, reply1} =
+ CommonAPI.post(user, %{"status" => "reply1", "in_reply_to_status_id" => activity.id})
+
+ {:ok, reply2} =
+ CommonAPI.post(user, %{"status" => "reply2", "in_reply_to_status_id" => activity.id})
+
+ replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end)
+
+ {:ok, federation_output} = Transmogrifier.prepare_outgoing(activity.data)
+
+ Repo.delete(activity.object)
+ Repo.delete(activity)
+
+ %{federation_output: federation_output, replies_uris: replies_uris}
+ end
+
+ test "schedules background fetching of `replies` items if max thread depth limit allows", %{
+ federation_output: federation_output,
+ replies_uris: replies_uris
+ } do
+ Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 1)
+
+ {:ok, _activity} = Transmogrifier.handle_incoming(federation_output)
+
+ for id <- replies_uris do
+ job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1}
+ assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args)
+ end
+ end
+
+ test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows",
+ %{federation_output: federation_output} do
+ Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
+
+ {:ok, _activity} = Transmogrifier.handle_incoming(federation_output)
+
+ assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == []
+ end
end
describe "prepare outgoing" do
+ test "it inlines private announced objects" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hey", "visibility" => "private"})
+
+ {:ok, announce_activity, _} = CommonAPI.repeat(activity.id, user)
+
+ {:ok, modified} = Transmogrifier.prepare_outgoing(announce_activity.data)
+
+ assert modified["object"]["content"] == "hey"
+ assert modified["object"]["actor"] == modified["object"]["attributedTo"]
+ end
+
test "it turns mentions into tags" do
user = insert(:user)
other_user = insert(:user)
@@ -1103,32 +1515,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert modified["object"]["actor"] == modified["object"]["attributedTo"]
end
- test "it translates ostatus IDs to external URLs" do
- incoming = File.read!("test/fixtures/incoming_note_activity.xml")
- {:ok, [referent_activity]} = OStatus.handle_incoming(incoming)
-
- user = insert(:user)
-
- {:ok, activity, _} = CommonAPI.favorite(referent_activity.id, user)
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["object"] == "http://gs.example.org:4040/index.php/notice/29"
- end
-
- test "it translates ostatus reply_to IDs to external URLs" do
- incoming = File.read!("test/fixtures/incoming_note_activity.xml")
- {:ok, [referred_activity]} = OStatus.handle_incoming(incoming)
-
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "HI!", "in_reply_to_status_id" => referred_activity.id})
-
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["object"]["inReplyTo"] == "http://gs.example.org:4040/index.php/notice/29"
- end
-
test "it strips internal hashtag data" do
user = insert(:user)
@@ -1215,6 +1601,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert is_nil(modified["bcc"])
end
+
+ test "it can handle Listen activities" do
+ listen_activity = insert(:listen)
+
+ {:ok, modified} = Transmogrifier.prepare_outgoing(listen_activity.data)
+
+ assert modified["type"] == "Listen"
+
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.listen(user, %{"title" => "lain radio episode 1"})
+
+ {:ok, _modified} = Transmogrifier.prepare_outgoing(activity.data)
+ end
end
describe "user upgrade" do
@@ -1227,23 +1627,26 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
})
- user_two = insert(:user, %{following: [user.follower_address]})
+ user_two = insert(:user)
+ Pleroma.FollowingRelationship.follow(user_two, user, "accept")
{:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
{:ok, unrelated_activity} = CommonAPI.post(user_two, %{"status" => "test"})
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
user = User.get_cached_by_id(user.id)
- assert user.info.note_count == 1
+ assert user.note_count == 1
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
- assert user.info.ap_enabled
- assert user.info.note_count == 1
+ ObanHelpers.perform_all()
+
+ assert user.ap_enabled
+ assert user.note_count == 1
assert user.follower_address == "https://niu.moe/users/rye/followers"
assert user.following_address == "https://niu.moe/users/rye/following"
user = User.get_cached_by_id(user.id)
- assert user.info.note_count == 1
+ assert user.note_count == 1
activity = Activity.get_by_id(activity.id)
assert user.follower_address in activity.recipients
@@ -1264,7 +1667,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
}
]
- } = user.info.banner
+ } = user.banner
refute "..." in activity.recipients
@@ -1272,23 +1675,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute user.follower_address in unrelated_activity.recipients
user_two = User.get_cached_by_id(user_two.id)
- assert user.follower_address in user_two.following
- refute "..." in user_two.following
- end
- end
-
- describe "maybe_retire_websub" do
- test "it deletes all websub client subscripitions with the user as topic" do
- subscription = %WebsubClientSubscription{topic: "https://niu.moe/users/rye.atom"}
- {:ok, ws} = Repo.insert(subscription)
-
- subscription = %WebsubClientSubscription{topic: "https://niu.moe/users/pasty.atom"}
- {:ok, ws2} = Repo.insert(subscription)
-
- Transmogrifier.maybe_retire_websub("https://niu.moe/users/rye")
-
- refute Repo.get(WebsubClientSubscription, ws.id)
- assert Repo.get(WebsubClientSubscription, ws2.id)
+ assert User.following?(user_two, user)
+ refute "..." in User.following(user_two)
end
end
@@ -1314,7 +1702,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"type" => "Announce"
}
- :error = Transmogrifier.handle_incoming(data)
+ assert capture_log(fn ->
+ :error = Transmogrifier.handle_incoming(data)
+ end) =~ "Object containment failed"
end
test "it rejects activities which reference objects that have an incorrect attribution (variant 1)" do
@@ -1327,7 +1717,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"type" => "Announce"
}
- :error = Transmogrifier.handle_incoming(data)
+ assert capture_log(fn ->
+ :error = Transmogrifier.handle_incoming(data)
+ end) =~ "Object containment failed"
end
test "it rejects activities which reference objects that have an incorrect attribution (variant 2)" do
@@ -1340,7 +1732,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"type" => "Announce"
}
- :error = Transmogrifier.handle_incoming(data)
+ assert capture_log(fn ->
+ :error = Transmogrifier.handle_incoming(data)
+ end) =~ "Object containment failed"
end
end
@@ -1478,4 +1872,320 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
refute recipient.follower_address in fixed_object["to"]
end
end
+
+ describe "fix_summary/1" do
+ test "returns fixed object" do
+ assert Transmogrifier.fix_summary(%{"summary" => nil}) == %{"summary" => ""}
+ assert Transmogrifier.fix_summary(%{"summary" => "ok"}) == %{"summary" => "ok"}
+ assert Transmogrifier.fix_summary(%{}) == %{"summary" => ""}
+ end
+ end
+
+ describe "fix_in_reply_to/2" do
+ clear_config([:instance, :federation_incoming_replies_max_depth])
+
+ setup do
+ data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
+ [data: data]
+ end
+
+ test "returns not modified object when hasn't containts inReplyTo field", %{data: data} do
+ assert Transmogrifier.fix_in_reply_to(data) == data
+ end
+
+ test "returns object with inReplyToAtomUri when denied incoming reply", %{data: data} do
+ Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
+
+ object_with_reply =
+ Map.put(data["object"], "inReplyTo", "https://shitposter.club/notice/2827873")
+
+ modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
+ assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873"
+ 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
+ test "returns modified object when allowed incoming reply", %{data: data} do
+ object_with_reply =
+ Map.put(
+ data["object"],
+ "inReplyTo",
+ "https://shitposter.club/notice/2827873"
+ )
+
+ 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"
+
+ assert modified_object["context"] ==
+ "tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26"
+ end
+ end
+
+ describe "fix_url/1" do
+ test "fixes data for object when url is map" do
+ object = %{
+ "url" => %{
+ "type" => "Link",
+ "mimeType" => "video/mp4",
+ "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4"
+ }
+ }
+
+ assert Transmogrifier.fix_url(object) == %{
+ "url" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4"
+ }
+ end
+
+ test "fixes data for video object" do
+ object = %{
+ "type" => "Video",
+ "url" => [
+ %{
+ "type" => "Link",
+ "mimeType" => "video/mp4",
+ "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4"
+ },
+ %{
+ "type" => "Link",
+ "mimeType" => "video/mp4",
+ "href" => "https://peertube46fb-ad81-2d4c2d1630e3-240.mp4"
+ },
+ %{
+ "type" => "Link",
+ "mimeType" => "text/html",
+ "href" => "https://peertube.-2d4c2d1630e3"
+ },
+ %{
+ "type" => "Link",
+ "mimeType" => "text/html",
+ "href" => "https://peertube.-2d4c2d16377-42"
+ }
+ ]
+ }
+
+ assert Transmogrifier.fix_url(object) == %{
+ "attachment" => [
+ %{
+ "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4",
+ "mimeType" => "video/mp4",
+ "type" => "Link"
+ }
+ ],
+ "type" => "Video",
+ "url" => "https://peertube.-2d4c2d1630e3"
+ }
+ end
+
+ test "fixes url for not Video object" do
+ object = %{
+ "type" => "Text",
+ "url" => [
+ %{
+ "type" => "Link",
+ "mimeType" => "text/html",
+ "href" => "https://peertube.-2d4c2d1630e3"
+ },
+ %{
+ "type" => "Link",
+ "mimeType" => "text/html",
+ "href" => "https://peertube.-2d4c2d16377-42"
+ }
+ ]
+ }
+
+ assert Transmogrifier.fix_url(object) == %{
+ "type" => "Text",
+ "url" => "https://peertube.-2d4c2d1630e3"
+ }
+
+ assert Transmogrifier.fix_url(%{"type" => "Text", "url" => []}) == %{
+ "type" => "Text",
+ "url" => ""
+ }
+ end
+
+ test "retunrs not modified object" do
+ assert Transmogrifier.fix_url(%{"type" => "Text"}) == %{"type" => "Text"}
+ end
+ end
+
+ describe "get_obj_helper/2" do
+ test "returns nil when cannot normalize object" do
+ assert capture_log(fn ->
+ refute Transmogrifier.get_obj_helper("test-obj-id")
+ end) =~ "Unsupported URI scheme"
+ end
+
+ @tag capture_log: true
+ test "returns {:ok, %Object{}} for success case" do
+ assert {:ok, %Object{}} =
+ Transmogrifier.get_obj_helper("https://shitposter.club/notice/2827873")
+ end
+ end
+
+ describe "fix_attachments/1" do
+ test "returns not modified object" do
+ data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
+ assert Transmogrifier.fix_attachments(data) == data
+ end
+
+ test "returns modified object when attachment is map" do
+ assert Transmogrifier.fix_attachments(%{
+ "attachment" => %{
+ "mediaType" => "video/mp4",
+ "url" => "https://peertube.moe/stat-480.mp4"
+ }
+ }) == %{
+ "attachment" => [
+ %{
+ "mediaType" => "video/mp4",
+ "url" => [
+ %{
+ "href" => "https://peertube.moe/stat-480.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
+ ]
+ }
+ ]
+ }
+ end
+
+ test "returns modified object when attachment is list" do
+ assert Transmogrifier.fix_attachments(%{
+ "attachment" => [
+ %{"mediaType" => "video/mp4", "url" => "https://pe.er/stat-480.mp4"},
+ %{"mimeType" => "video/mp4", "href" => "https://pe.er/stat-480.mp4"}
+ ]
+ }) == %{
+ "attachment" => [
+ %{
+ "mediaType" => "video/mp4",
+ "url" => [
+ %{
+ "href" => "https://pe.er/stat-480.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
+ ]
+ },
+ %{
+ "href" => "https://pe.er/stat-480.mp4",
+ "mediaType" => "video/mp4",
+ "mimeType" => "video/mp4",
+ "url" => [
+ %{
+ "href" => "https://pe.er/stat-480.mp4",
+ "mediaType" => "video/mp4",
+ "type" => "Link"
+ }
+ ]
+ }
+ ]
+ }
+ end
+ end
+
+ describe "fix_emoji/1" do
+ test "returns not modified object when object not contains tags" do
+ data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
+ assert Transmogrifier.fix_emoji(data) == data
+ end
+
+ test "returns object with emoji when object contains list tags" do
+ assert Transmogrifier.fix_emoji(%{
+ "tag" => [
+ %{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}},
+ %{"type" => "Hashtag"}
+ ]
+ }) == %{
+ "emoji" => %{"bib" => "/test"},
+ "tag" => [
+ %{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"},
+ %{"type" => "Hashtag"}
+ ]
+ }
+ end
+
+ test "returns object with emoji when object contains map tag" do
+ assert Transmogrifier.fix_emoji(%{
+ "tag" => %{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}}
+ }) == %{
+ "emoji" => %{"bib" => "/test"},
+ "tag" => %{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"}
+ }
+ end
+ end
+
+ describe "set_replies/1" do
+ clear_config([:activitypub, :note_replies_output_limit]) do
+ Pleroma.Config.put([:activitypub, :note_replies_output_limit], 2)
+ end
+
+ test "returns unmodified object if activity doesn't have self-replies" do
+ data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
+ assert Transmogrifier.set_replies(data) == data
+ end
+
+ test "sets `replies` collection with a limited number of self-replies" do
+ [user, another_user] = insert_list(2, :user)
+
+ {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{"status" => "1"})
+
+ {:ok, %{id: id2} = self_reply1} =
+ CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => id1})
+
+ {:ok, self_reply2} =
+ CommonAPI.post(user, %{"status" => "self-reply 2", "in_reply_to_status_id" => id1})
+
+ # Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2
+ {:ok, _} =
+ CommonAPI.post(user, %{"status" => "self-reply 3", "in_reply_to_status_id" => id1})
+
+ {:ok, _} =
+ CommonAPI.post(user, %{
+ "status" => "self-reply to self-reply",
+ "in_reply_to_status_id" => id2
+ })
+
+ {:ok, _} =
+ CommonAPI.post(another_user, %{
+ "status" => "another user's reply",
+ "in_reply_to_status_id" => id1
+ })
+
+ object = Object.normalize(activity)
+ replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end)
+
+ assert %{"type" => "Collection", "items" => ^replies_uris} =
+ Transmogrifier.set_replies(object.data)["replies"]
+ end
+ end
end
diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs
index db6c68c44..e5ab54dd4 100644
--- a/test/web/activity_pub/utils_test.exs
+++ b/test/web/activity_pub/utils_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.UtilsTest do
@@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
+ alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
@@ -87,6 +88,18 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
assert Utils.determine_explicit_mentions(object) == []
end
+
+ test "works with an object has tags as map" do
+ object = %{
+ "tag" => %{
+ "type" => "Mention",
+ "href" => "https://example.com/~alyssa",
+ "name" => "Alyssa P. Hacker"
+ }
+ }
+
+ assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
+ end
end
describe "make_unlike_data/3" do
@@ -285,7 +298,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
describe "update_follow_state_for_all/2" do
test "updates the state of all Follow activities with the same actor and object" do
- user = insert(:user, info: %{locked: true})
+ user = insert(:user, locked: true)
follower = insert(:user)
{:ok, follow_activity} = ActivityPub.follow(follower, user)
@@ -302,14 +315,14 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
{:ok, follow_activity_two} =
Utils.update_follow_state_for_all(follow_activity_two, "accept")
- assert Repo.get(Activity, follow_activity.id).data["state"] == "accept"
- assert Repo.get(Activity, follow_activity_two.id).data["state"] == "accept"
+ assert refresh_record(follow_activity).data["state"] == "accept"
+ assert refresh_record(follow_activity_two).data["state"] == "accept"
end
end
describe "update_follow_state/2" do
test "updates the state of the given follow activity" do
- user = insert(:user, info: %{locked: true})
+ user = insert(:user, locked: true)
follower = insert(:user)
{:ok, follow_activity} = ActivityPub.follow(follower, user)
@@ -325,8 +338,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
{:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
- assert Repo.get(Activity, follow_activity.id).data["state"] == "pending"
- assert Repo.get(Activity, follow_activity_two.id).data["state"] == "reject"
+ assert refresh_record(follow_activity).data["state"] == "pending"
+ assert refresh_record(follow_activity_two).data["state"] == "reject"
end
end
@@ -403,4 +416,237 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
end
end
+
+ describe "get_get_existing_announce/2" do
+ test "returns nil if announce not found" do
+ actor = insert(:user)
+ refute Utils.get_existing_announce(actor.ap_id, %{data: %{"id" => "test"}})
+ end
+
+ test "fetches existing announce" do
+ note_activity = insert(:note_activity)
+ assert object = Object.normalize(note_activity)
+ actor = insert(:user)
+
+ {:ok, announce, _object} = ActivityPub.announce(actor, object)
+ assert Utils.get_existing_announce(actor.ap_id, object) == announce
+ end
+ end
+
+ describe "fetch_latest_block/2" do
+ test "fetches last block activities" 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 Utils.fetch_latest_block(user1, user2) == activity
+ end
+ end
+
+ describe "recipient_in_message/3" do
+ test "returns true when recipient in `to`" do
+ recipient = insert(:user)
+ actor = insert(:user)
+ assert Utils.recipient_in_message(recipient, actor, %{"to" => recipient.ap_id})
+
+ assert Utils.recipient_in_message(
+ recipient,
+ actor,
+ %{"to" => [recipient.ap_id], "cc" => ""}
+ )
+ end
+
+ test "returns true when recipient in `cc`" do
+ recipient = insert(:user)
+ actor = insert(:user)
+ assert Utils.recipient_in_message(recipient, actor, %{"cc" => recipient.ap_id})
+
+ assert Utils.recipient_in_message(
+ recipient,
+ actor,
+ %{"cc" => [recipient.ap_id], "to" => ""}
+ )
+ end
+
+ test "returns true when recipient in `bto`" do
+ recipient = insert(:user)
+ actor = insert(:user)
+ assert Utils.recipient_in_message(recipient, actor, %{"bto" => recipient.ap_id})
+
+ assert Utils.recipient_in_message(
+ recipient,
+ actor,
+ %{"bcc" => "", "bto" => [recipient.ap_id]}
+ )
+ end
+
+ test "returns true when recipient in `bcc`" do
+ recipient = insert(:user)
+ actor = insert(:user)
+ assert Utils.recipient_in_message(recipient, actor, %{"bcc" => recipient.ap_id})
+
+ assert Utils.recipient_in_message(
+ recipient,
+ actor,
+ %{"bto" => "", "bcc" => [recipient.ap_id]}
+ )
+ end
+
+ test "returns true when message without addresses fields" do
+ recipient = insert(:user)
+ actor = insert(:user)
+ assert Utils.recipient_in_message(recipient, actor, %{"bccc" => recipient.ap_id})
+
+ assert Utils.recipient_in_message(
+ recipient,
+ actor,
+ %{"btod" => "", "bccc" => [recipient.ap_id]}
+ )
+ end
+
+ test "returns false" do
+ recipient = insert(:user)
+ actor = insert(:user)
+ refute Utils.recipient_in_message(recipient, actor, %{"to" => "ap_id"})
+ end
+ end
+
+ describe "lazy_put_activity_defaults/2" do
+ test "returns map with id and published data" do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+ res = Utils.lazy_put_activity_defaults(%{"context" => object.data["id"]})
+ assert res["context"] == object.data["id"]
+ assert res["context_id"] == object.id
+ assert res["id"]
+ assert res["published"]
+ end
+
+ test "returns map with fake id and published data" do
+ assert %{
+ "context" => "pleroma:fakecontext",
+ "context_id" => -1,
+ "id" => "pleroma:fakeid",
+ "published" => _
+ } = Utils.lazy_put_activity_defaults(%{}, true)
+ end
+
+ test "returns activity data with object" do
+ note_activity = insert(:note_activity)
+ object = Object.normalize(note_activity)
+
+ res =
+ Utils.lazy_put_activity_defaults(%{
+ "context" => object.data["id"],
+ "object" => %{}
+ })
+
+ assert res["context"] == object.data["id"]
+ assert res["context_id"] == object.id
+ assert res["id"]
+ assert res["published"]
+ assert res["object"]["id"]
+ assert res["object"]["published"]
+ assert res["object"]["context"] == object.data["id"]
+ assert res["object"]["context_id"] == object.id
+ end
+ end
+
+ describe "make_flag_data" do
+ test "returns empty map when params is invalid" do
+ assert Utils.make_flag_data(%{}, %{}) == %{}
+ end
+
+ test "returns map with Flag object" do
+ reporter = insert(:user)
+ target_account = insert(:user)
+ {:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
+ context = Utils.generate_context_id()
+ content = "foobar"
+
+ target_ap_id = target_account.ap_id
+ activity_ap_id = activity.data["id"]
+
+ res =
+ Utils.make_flag_data(
+ %{
+ actor: reporter,
+ context: context,
+ account: target_account,
+ statuses: [%{"id" => activity.data["id"]}],
+ content: content
+ },
+ %{}
+ )
+
+ note_obj = %{
+ "type" => "Note",
+ "id" => activity_ap_id,
+ "content" => content,
+ "published" => activity.object.data["published"],
+ "actor" => AccountView.render("show.json", %{user: target_account})
+ }
+
+ assert %{
+ "type" => "Flag",
+ "content" => ^content,
+ "context" => ^context,
+ "object" => [^target_ap_id, ^note_obj],
+ "state" => "open"
+ } = res
+ end
+ end
+
+ describe "add_announce_to_object/2" do
+ test "adds actor to announcement" do
+ user = insert(:user)
+ object = insert(:note)
+
+ activity =
+ insert(:note_activity,
+ data: %{
+ "actor" => user.ap_id,
+ "cc" => [Pleroma.Constants.as_public()]
+ }
+ )
+
+ assert {:ok, updated_object} = Utils.add_announce_to_object(activity, object)
+ assert updated_object.data["announcements"] == [user.ap_id]
+ assert updated_object.data["announcement_count"] == 1
+ end
+ end
+
+ describe "remove_announce_from_object/2" do
+ test "removes actor from announcements" do
+ user = insert(:user)
+ user2 = insert(:user)
+
+ object =
+ insert(:note,
+ data: %{"announcements" => [user.ap_id, user2.ap_id], "announcement_count" => 2}
+ )
+
+ activity = insert(:note_activity, data: %{"actor" => user.ap_id})
+
+ assert {:ok, updated_object} = Utils.remove_announce_from_object(activity, object)
+ assert updated_object.data["announcements"] == [user2.ap_id]
+ assert updated_object.data["announcement_count"] == 1
+ end
+ end
+
+ describe "get_cached_emoji_reactions/1" do
+ test "returns the data or an emtpy list" do
+ object = insert(:note)
+ assert Utils.get_cached_emoji_reactions(object) == []
+
+ object = insert(:note, data: %{"reactions" => [["x", ["lain"]]]})
+ assert Utils.get_cached_emoji_reactions(object) == [["x", ["lain"]]]
+
+ object = insert(:note, data: %{"reactions" => %{}})
+ assert Utils.get_cached_emoji_reactions(object) == []
+ end
+ end
end
diff --git a/test/web/activity_pub/views/object_view_test.exs b/test/web/activity_pub/views/object_view_test.exs
index 13447dc29..09866e99b 100644
--- a/test/web/activity_pub/views/object_view_test.exs
+++ b/test/web/activity_pub/views/object_view_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
@@ -36,6 +36,26 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
assert result["@context"]
end
+ describe "note activity's `replies` collection rendering" do
+ clear_config([:activitypub, :note_replies_output_limit]) do
+ Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5)
+ end
+
+ test "renders `replies` collection for a note activity" do
+ user = insert(:user)
+ activity = insert(:note_activity, user: user)
+
+ {:ok, self_reply1} =
+ CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => activity.id})
+
+ replies_uris = [self_reply1.object.data["id"]]
+ result = ObjectView.render("object.json", %{object: refresh_record(activity)})
+
+ assert %{"type" => "Collection", "items" => ^replies_uris} =
+ get_in(result, ["object", "replies"])
+ end
+ end
+
test "renders a like activity" do
note = insert(:note_activity)
object = Object.normalize(note)
diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs
index dbb44a8a2..ecb2dc386 100644
--- a/test/web/activity_pub/views/user_view_test.exs
+++ b/test/web/activity_pub/views/user_view_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.UserViewTest do
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
{:ok, user} =
insert(:user)
- |> User.upgrade_changeset(%{info: %{fields: fields}})
+ |> User.upgrade_changeset(%{fields: fields})
|> User.update_and_set_cache()
assert %{
@@ -37,6 +37,22 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
} = UserView.render("user.json", %{user: user})
end
+ test "Renders with emoji tags" do
+ user = insert(:user, emoji: [%{"bib" => "/test"}])
+
+ assert %{
+ "tag" => [
+ %{
+ "icon" => %{"type" => "Image", "url" => "/test"},
+ "id" => "/test",
+ "name" => ":bib:",
+ "type" => "Emoji",
+ "updated" => "1970-01-01T00:00:00Z"
+ }
+ ]
+ } = UserView.render("user.json", %{user: user})
+ end
+
test "Does not add an avatar image if the user hasn't set one" do
user = insert(:user)
{:ok, user} = User.ensure_keys_present(user)
@@ -48,9 +64,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
user =
insert(:user,
avatar: %{"url" => [%{"href" => "https://someurl"}]},
- info: %{
- banner: %{"url" => [%{"href" => "https://somebanner"}]}
- }
+ banner: %{"url" => [%{"href" => "https://somebanner"}]}
)
{:ok, user} = User.ensure_keys_present(user)
@@ -60,6 +74,12 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
assert result["image"]["url"] == "https://somebanner"
end
+ test "renders an invisible user with the invisible property set to true" do
+ user = insert(:user, invisible: true)
+
+ assert %{"invisible" => true} = UserView.render("service.json", %{user: user})
+ end
+
describe "endpoints" do
test "local users have a usable endpoints structure" do
user = insert(:user)
@@ -105,9 +125,17 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
other_user = insert(:user)
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
- info = Map.put(user.info, :hide_followers, true)
- user = Map.put(user, :info, info)
- assert %{"totalItems" => 0} = UserView.render("followers.json", %{user: user})
+ user = Map.merge(user, %{hide_followers_count: true, hide_followers: true})
+ refute UserView.render("followers.json", %{user: user}) |> Map.has_key?("totalItems")
+ end
+
+ test "sets correct totalItems when followers are hidden but the follower counter is not" do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
+ assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
+ user = Map.merge(user, %{hide_followers_count: false, hide_followers: true})
+ assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
end
end
@@ -117,40 +145,48 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
other_user = insert(:user)
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
- info = Map.put(user.info, :hide_follows, true)
- user = Map.put(user, :info, info)
+ user = Map.merge(user, %{hide_follows_count: true, hide_follows: true})
assert %{"totalItems" => 0} = UserView.render("following.json", %{user: user})
end
- test "activity collection page aginates correctly" do
+ test "sets correct totalItems when follows are hidden but the follow counter is not" do
user = insert(:user)
+ other_user = insert(:user)
+ {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
+ assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
+ user = Map.merge(user, %{hide_follows_count: false, hide_follows: true})
+ assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
+ end
+ end
- posts =
- for i <- 0..25 do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "post #{i}"})
- activity
- end
+ test "activity collection page aginates correctly" do
+ user = insert(:user)
- # outbox sorts chronologically, newest first, with ten per page
- posts = Enum.reverse(posts)
+ posts =
+ for i <- 0..25 do
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "post #{i}"})
+ activity
+ end
- %{"next" => next_url} =
- UserView.render("activity_collection_page.json", %{
- iri: "#{user.ap_id}/outbox",
- activities: Enum.take(posts, 10)
- })
+ # outbox sorts chronologically, newest first, with ten per page
+ posts = Enum.reverse(posts)
- next_id = Enum.at(posts, 9).id
- assert next_url =~ next_id
+ %{"next" => next_url} =
+ UserView.render("activity_collection_page.json", %{
+ iri: "#{user.ap_id}/outbox",
+ activities: Enum.take(posts, 10)
+ })
- %{"next" => next_url} =
- UserView.render("activity_collection_page.json", %{
- iri: "#{user.ap_id}/outbox",
- activities: Enum.take(Enum.drop(posts, 10), 10)
- })
+ next_id = Enum.at(posts, 9).id
+ assert next_url =~ next_id
- next_id = Enum.at(posts, 19).id
- assert next_url =~ next_id
- end
+ %{"next" => next_url} =
+ UserView.render("activity_collection_page.json", %{
+ iri: "#{user.ap_id}/outbox",
+ activities: Enum.take(Enum.drop(posts, 10), 10)
+ })
+
+ next_id = Enum.at(posts, 19).id
+ assert next_url =~ next_id
end
end
diff --git a/test/web/activity_pub/visibilty_test.exs b/test/web/activity_pub/visibilty_test.exs
index b62a89e68..5b91630d4 100644
--- a/test/web/activity_pub/visibilty_test.exs
+++ b/test/web/activity_pub/visibilty_test.exs
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.VisibilityTest do
@@ -212,7 +212,8 @@ defmodule Pleroma.Web.ActivityPub.VisibilityTest do
test "returns true if user following to author" do
author = insert(:user)
- user = insert(:user, following: [author.ap_id])
+ user = insert(:user)
+ Pleroma.User.follow(user, author)
activity =
insert(:note_activity,