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.exs1550
-rw-r--r--test/web/activity_pub/activity_pub_test.exs2136
-rw-r--r--test/web/activity_pub/mrf/activity_expiration_policy_test.exs84
-rw-r--r--test/web/activity_pub/mrf/anti_followbot_policy_test.exs72
-rw-r--r--test/web/activity_pub/mrf/anti_link_spam_policy_test.exs166
-rw-r--r--test/web/activity_pub/mrf/ensure_re_prepended_test.exs92
-rw-r--r--test/web/activity_pub/mrf/hellthread_policy_test.exs92
-rw-r--r--test/web/activity_pub/mrf/keyword_policy_test.exs225
-rw-r--r--test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs51
-rw-r--r--test/web/activity_pub/mrf/mention_policy_test.exs96
-rw-r--r--test/web/activity_pub/mrf/mrf_test.exs84
-rw-r--r--test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs37
-rw-r--r--test/web/activity_pub/mrf/normalize_markup_test.exs42
-rw-r--r--test/web/activity_pub/mrf/object_age_policy_test.exs148
-rw-r--r--test/web/activity_pub/mrf/reject_non_public_test.exs100
-rw-r--r--test/web/activity_pub/mrf/simple_policy_test.exs539
-rw-r--r--test/web/activity_pub/mrf/steal_emoji_policy_test.exs68
-rw-r--r--test/web/activity_pub/mrf/subchain_policy_test.exs33
-rw-r--r--test/web/activity_pub/mrf/tag_policy_test.exs123
-rw-r--r--test/web/activity_pub/mrf/user_allowlist_policy_test.exs31
-rw-r--r--test/web/activity_pub/mrf/vocabulary_policy_test.exs106
-rw-r--r--test/web/activity_pub/object_validators/accept_validation_test.exs56
-rw-r--r--test/web/activity_pub/object_validators/announce_validation_test.exs106
-rw-r--r--test/web/activity_pub/object_validators/attachment_validator_test.exs74
-rw-r--r--test/web/activity_pub/object_validators/block_validation_test.exs39
-rw-r--r--test/web/activity_pub/object_validators/chat_validation_test.exs211
-rw-r--r--test/web/activity_pub/object_validators/delete_validation_test.exs106
-rw-r--r--test/web/activity_pub/object_validators/emoji_react_validation_test.exs53
-rw-r--r--test/web/activity_pub/object_validators/follow_validation_test.exs26
-rw-r--r--test/web/activity_pub/object_validators/like_validation_test.exs113
-rw-r--r--test/web/activity_pub/object_validators/note_validator_test.exs35
-rw-r--r--test/web/activity_pub/object_validators/reject_validation_test.exs56
-rw-r--r--test/web/activity_pub/object_validators/types/date_time_test.exs32
-rw-r--r--test/web/activity_pub/object_validators/types/object_id_test.exs41
-rw-r--r--test/web/activity_pub/object_validators/types/recipients_test.exs27
-rw-r--r--test/web/activity_pub/object_validators/types/safe_text_test.exs30
-rw-r--r--test/web/activity_pub/object_validators/undo_validation_test.exs53
-rw-r--r--test/web/activity_pub/object_validators/update_validation_test.exs44
-rw-r--r--test/web/activity_pub/pipeline_test.exs179
-rw-r--r--test/web/activity_pub/publisher_test.exs365
-rw-r--r--test/web/activity_pub/relay_test.exs128
-rw-r--r--test/web/activity_pub/side_effects_test.exs639
-rw-r--r--test/web/activity_pub/transmogrifier/accept_handling_test.exs91
-rw-r--r--test/web/activity_pub/transmogrifier/announce_handling_test.exs172
-rw-r--r--test/web/activity_pub/transmogrifier/answer_handling_test.exs78
-rw-r--r--test/web/activity_pub/transmogrifier/audio_handling_test.exs83
-rw-r--r--test/web/activity_pub/transmogrifier/block_handling_test.exs63
-rw-r--r--test/web/activity_pub/transmogrifier/chat_message_test.exs171
-rw-r--r--test/web/activity_pub/transmogrifier/delete_handling_test.exs114
-rw-r--r--test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs61
-rw-r--r--test/web/activity_pub/transmogrifier/event_handling_test.exs40
-rw-r--r--test/web/activity_pub/transmogrifier/follow_handling_test.exs208
-rw-r--r--test/web/activity_pub/transmogrifier/like_handling_test.exs78
-rw-r--r--test/web/activity_pub/transmogrifier/question_handling_test.exs125
-rw-r--r--test/web/activity_pub/transmogrifier/reject_handling_test.exs67
-rw-r--r--test/web/activity_pub/transmogrifier/undo_handling_test.exs185
-rw-r--r--test/web/activity_pub/transmogrifier/user_update_handling_test.exs159
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs1379
-rw-r--r--test/web/activity_pub/utils_test.exs548
-rw-r--r--test/web/activity_pub/views/object_view_test.exs84
-rw-r--r--test/web/activity_pub/views/user_view_test.exs180
-rw-r--r--test/web/activity_pub/visibilty_test.exs230
62 files changed, 0 insertions, 12404 deletions
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
deleted file mode 100644
index 0517571f2..000000000
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ /dev/null
@@ -1,1550 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
- use Pleroma.Web.ConnCase
- use Oban.Testing, repo: Pleroma.Repo
-
- alias Pleroma.Activity
- alias Pleroma.Config
- alias Pleroma.Delivery
- alias Pleroma.Instances
- alias Pleroma.Object
- alias Pleroma.Tests.ObanHelpers
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ActivityPub
- alias Pleroma.Web.ActivityPub.ObjectView
- alias Pleroma.Web.ActivityPub.Relay
- alias Pleroma.Web.ActivityPub.UserView
- alias Pleroma.Web.ActivityPub.Utils
- alias Pleroma.Web.CommonAPI
- alias Pleroma.Web.Endpoint
- alias Pleroma.Workers.ReceiverWorker
-
- import Pleroma.Factory
-
- require Pleroma.Constants
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- setup do: clear_config([:instance, :federating], true)
-
- describe "/relay" do
- setup do: clear_config([:instance, :allow_relay])
-
- test "with the relay active, it returns the relay user", %{conn: conn} do
- res =
- conn
- |> get(activity_pub_path(conn, :relay))
- |> json_response(200)
-
- assert res["id"] =~ "/relay"
- end
-
- test "with the relay disabled, it returns 404", %{conn: conn} do
- Config.put([:instance, :allow_relay], false)
-
- conn
- |> get(activity_pub_path(conn, :relay))
- |> json_response(404)
- end
-
- test "on non-federating instance, it returns 404", %{conn: conn} do
- Config.put([:instance, :federating], false)
- user = insert(:user)
-
- conn
- |> assign(:user, user)
- |> get(activity_pub_path(conn, :relay))
- |> json_response(404)
- end
- end
-
- describe "/internal/fetch" do
- test "it returns the internal fetch user", %{conn: conn} do
- res =
- conn
- |> get(activity_pub_path(conn, :internal_fetch))
- |> json_response(200)
-
- assert res["id"] =~ "/fetch"
- end
-
- test "on non-federating instance, it returns 404", %{conn: conn} do
- Config.put([:instance, :federating], false)
- user = insert(:user)
-
- conn
- |> assign(:user, user)
- |> get(activity_pub_path(conn, :internal_fetch))
- |> json_response(404)
- end
- end
-
- describe "/users/:nickname" do
- test "it returns a json representation of the user with accept application/json", %{
- conn: conn
- } do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/users/#{user.nickname}")
-
- user = User.get_cached_by_id(user.id)
-
- assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
- end
-
- test "it returns a json representation of the user with accept application/activity+json", %{
- conn: conn
- } do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/users/#{user.nickname}")
-
- user = User.get_cached_by_id(user.id)
-
- assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
- end
-
- test "it returns a json representation of the user with accept application/ld+json", %{
- conn: conn
- } do
- user = insert(:user)
-
- conn =
- conn
- |> put_req_header(
- "accept",
- "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
- )
- |> get("/users/#{user.nickname}")
-
- user = User.get_cached_by_id(user.id)
-
- 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
-
- test "it returns error when user is not found", %{conn: conn} do
- response =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/users/jimm")
- |> json_response(404)
-
- assert response == "Not found"
- end
-
- test "it requires authentication if instance is NOT federating", %{
- conn: conn
- } do
- user = insert(:user)
-
- conn =
- put_req_header(
- conn,
- "accept",
- "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
- )
-
- ensure_federating_or_authenticated(conn, "/users/#{user.nickname}.json", user)
- end
- end
-
- describe "mastodon compatibility routes" do
- test "it returns a json representation of the object with accept application/json", %{
- conn: conn
- } do
- {:ok, object} =
- %{
- "type" => "Note",
- "content" => "hey",
- "id" => Endpoint.url() <> "/users/raymoo/statuses/999999999",
- "actor" => Endpoint.url() <> "/users/raymoo",
- "to" => [Pleroma.Constants.as_public()]
- }
- |> Object.create()
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/users/raymoo/statuses/999999999")
-
- assert json_response(conn, 200) == ObjectView.render("object.json", %{object: object})
- end
-
- test "it returns a json representation of the activity with accept application/json", %{
- conn: conn
- } do
- {:ok, object} =
- %{
- "type" => "Note",
- "content" => "hey",
- "id" => Endpoint.url() <> "/users/raymoo/statuses/999999999",
- "actor" => Endpoint.url() <> "/users/raymoo",
- "to" => [Pleroma.Constants.as_public()]
- }
- |> Object.create()
-
- {:ok, activity, _} =
- %{
- "id" => object.data["id"] <> "/activity",
- "type" => "Create",
- "object" => object.data["id"],
- "actor" => object.data["actor"],
- "to" => object.data["to"]
- }
- |> ActivityPub.persist(local: true)
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/users/raymoo/statuses/999999999/activity")
-
- assert json_response(conn, 200) == ObjectView.render("object.json", %{object: activity})
- end
- end
-
- describe "/objects/:uuid" do
- test "it returns a json representation of the object with accept application/json", %{
- conn: conn
- } do
- note = insert(:note)
- uuid = String.split(note.data["id"], "/") |> List.last()
-
- conn =
- conn
- |> put_req_header("accept", "application/json")
- |> get("/objects/#{uuid}")
-
- assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
- end
-
- test "it returns a json representation of the object with accept application/activity+json",
- %{conn: conn} do
- note = insert(:note)
- uuid = String.split(note.data["id"], "/") |> List.last()
-
- conn =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/objects/#{uuid}")
-
- assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
- end
-
- test "it returns a json representation of the object with accept application/ld+json", %{
- conn: conn
- } do
- note = insert(:note)
- uuid = String.split(note.data["id"], "/") |> List.last()
-
- conn =
- conn
- |> put_req_header(
- "accept",
- "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
- )
- |> get("/objects/#{uuid}")
-
- assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
- end
-
- test "it returns 404 for non-public messages", %{conn: conn} do
- note = insert(:direct_note)
- uuid = String.split(note.data["id"], "/") |> List.last()
-
- conn =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/objects/#{uuid}")
-
- assert json_response(conn, 404)
- end
-
- test "it returns 404 for tombstone objects", %{conn: conn} do
- tombstone = insert(:tombstone)
- uuid = String.split(tombstone.data["id"], "/") |> List.last()
-
- conn =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/objects/#{uuid}")
-
- assert json_response(conn, 404)
- end
-
- test "it caches a response", %{conn: conn} do
- note = insert(:note)
- uuid = String.split(note.data["id"], "/") |> List.last()
-
- conn1 =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/objects/#{uuid}")
-
- assert json_response(conn1, :ok)
- assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
-
- conn2 =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/objects/#{uuid}")
-
- assert json_response(conn1, :ok) == json_response(conn2, :ok)
- assert Enum.any?(conn2.resp_headers, &(&1 == {"x-cache", "HIT from Pleroma"}))
- end
-
- test "cached purged after object deletion", %{conn: conn} do
- note = insert(:note)
- uuid = String.split(note.data["id"], "/") |> List.last()
-
- conn1 =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/objects/#{uuid}")
-
- assert json_response(conn1, :ok)
- assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
-
- Object.delete(note)
-
- conn2 =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/objects/#{uuid}")
-
- assert "Not found" == json_response(conn2, :not_found)
- end
-
- test "it requires authentication if instance is NOT federating", %{
- conn: conn
- } do
- user = insert(:user)
- note = insert(:note)
- uuid = String.split(note.data["id"], "/") |> List.last()
-
- conn = put_req_header(conn, "accept", "application/activity+json")
-
- ensure_federating_or_authenticated(conn, "/objects/#{uuid}", user)
- end
- end
-
- describe "/activities/:uuid" do
- test "it returns a json representation of the activity", %{conn: conn} do
- activity = insert(:note_activity)
- uuid = String.split(activity.data["id"], "/") |> List.last()
-
- conn =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/activities/#{uuid}")
-
- assert json_response(conn, 200) == ObjectView.render("object.json", %{object: activity})
- end
-
- test "it returns 404 for non-public activities", %{conn: conn} do
- activity = insert(:direct_note_activity)
- uuid = String.split(activity.data["id"], "/") |> List.last()
-
- conn =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/activities/#{uuid}")
-
- assert json_response(conn, 404)
- end
-
- test "it caches a response", %{conn: conn} do
- activity = insert(:note_activity)
- uuid = String.split(activity.data["id"], "/") |> List.last()
-
- conn1 =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/activities/#{uuid}")
-
- assert json_response(conn1, :ok)
- assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
-
- conn2 =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/activities/#{uuid}")
-
- assert json_response(conn1, :ok) == json_response(conn2, :ok)
- assert Enum.any?(conn2.resp_headers, &(&1 == {"x-cache", "HIT from Pleroma"}))
- end
-
- test "cached purged after activity deletion", %{conn: conn} do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: "cofe"})
-
- uuid = String.split(activity.data["id"], "/") |> List.last()
-
- conn1 =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/activities/#{uuid}")
-
- assert json_response(conn1, :ok)
- assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
-
- Activity.delete_all_by_object_ap_id(activity.object.data["id"])
-
- conn2 =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get("/activities/#{uuid}")
-
- assert "Not found" == json_response(conn2, :not_found)
- end
-
- test "it requires authentication if instance is NOT federating", %{
- conn: conn
- } do
- user = insert(:user)
- activity = insert(:note_activity)
- uuid = String.split(activity.data["id"], "/") |> List.last()
-
- conn = put_req_header(conn, "accept", "application/activity+json")
-
- ensure_federating_or_authenticated(conn, "/activities/#{uuid}", user)
- end
- end
-
- describe "/inbox" do
- test "it inserts an incoming activity into the database", %{conn: conn} do
- data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
-
- conn =
- conn
- |> assign(:valid_signature, true)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/inbox", data)
-
- assert "ok" == json_response(conn, 200)
-
- ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
- assert Activity.get_by_ap_id(data["id"])
- end
-
- @tag capture_log: true
- test "it inserts an incoming activity into the database" <>
- "even if we can't fetch the user but have it in our db",
- %{conn: conn} do
- user =
- insert(:user,
- ap_id: "https://mastodon.example.org/users/raymoo",
- ap_enabled: true,
- local: false,
- last_refreshed_at: nil
- )
-
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", user.ap_id)
- |> put_in(["object", "attridbutedTo"], user.ap_id)
-
- conn =
- conn
- |> assign(:valid_signature, true)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/inbox", data)
-
- assert "ok" == json_response(conn, 200)
-
- ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
- assert Activity.get_by_ap_id(data["id"])
- end
-
- test "it clears `unreachable` federation status of the sender", %{conn: conn} do
- data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
-
- sender_url = data["actor"]
- Instances.set_consistently_unreachable(sender_url)
- refute Instances.reachable?(sender_url)
-
- conn =
- conn
- |> assign(:valid_signature, true)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/inbox", data)
-
- assert "ok" == json_response(conn, 200)
- assert Instances.reachable?(sender_url)
- end
-
- test "accept follow activity", %{conn: conn} do
- Pleroma.Config.put([:instance, :federating], true)
- relay = Relay.get_actor()
-
- assert {:ok, %Activity{} = activity} = Relay.follow("https://relay.mastodon.host/actor")
-
- followed_relay = Pleroma.User.get_by_ap_id("https://relay.mastodon.host/actor")
- relay = refresh_record(relay)
-
- accept =
- File.read!("test/fixtures/relay/accept-follow.json")
- |> String.replace("{{ap_id}}", relay.ap_id)
- |> String.replace("{{activity_id}}", activity.data["id"])
-
- assert "ok" ==
- conn
- |> assign(:valid_signature, true)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/inbox", accept)
- |> json_response(200)
-
- ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
-
- assert Pleroma.FollowingRelationship.following?(
- relay,
- followed_relay
- )
-
- Mix.shell(Mix.Shell.Process)
-
- on_exit(fn ->
- Mix.shell(Mix.Shell.IO)
- end)
-
- :ok = Mix.Tasks.Pleroma.Relay.run(["list"])
- assert_receive {:mix_shell, :info, ["https://relay.mastodon.host/actor"]}
- end
-
- @tag capture_log: true
- test "without valid signature, " <>
- "it only accepts Create activities and requires enabled federation",
- %{conn: conn} do
- data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
- non_create_data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!()
-
- conn = put_req_header(conn, "content-type", "application/activity+json")
-
- Config.put([:instance, :federating], false)
-
- conn
- |> post("/inbox", data)
- |> json_response(403)
-
- conn
- |> post("/inbox", non_create_data)
- |> json_response(403)
-
- Config.put([:instance, :federating], true)
-
- ret_conn = post(conn, "/inbox", data)
- assert "ok" == json_response(ret_conn, 200)
-
- conn
- |> post("/inbox", non_create_data)
- |> json_response(400)
- end
- end
-
- describe "/users/:nickname/inbox" do
- setup do
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
-
- [data: data]
- end
-
- test "it inserts an incoming activity into the database", %{conn: conn, data: data} do
- user = insert(:user)
- data = Map.put(data, "bcc", [user.ap_id])
-
- 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 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)
-
- {:ok, post} = CommonAPI.post(user, %{status: "hey"})
- announcer = insert(:user, local: false)
-
- data = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "actor" => announcer.ap_id,
- "id" => "#{announcer.ap_id}/statuses/19512778738411822/activity",
- "object" => post.data["object"],
- "to" => "https://www.w3.org/ns/activitystreams#Public",
- "cc" => [user.ap_id],
- "type" => "Announce"
- }
-
- 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
- } do
- recipient = insert(:user)
- actor = insert(:user, %{ap_id: "http://mastodon.example.org/users/actor"})
-
- {:ok, recipient} = User.follow(recipient, actor)
-
- object =
- data["object"]
- |> Map.put("attributedTo", actor.ap_id)
-
- data =
- data
- |> Map.put("actor", actor.ap_id)
- |> Map.put("object", object)
-
- conn =
- conn
- |> assign(:valid_signature, true)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{recipient.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 rejects reads from other users", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- conn =
- conn
- |> assign(:user, other_user)
- |> put_req_header("accept", "application/activity+json")
- |> get("/users/#{user.nickname}/inbox")
-
- assert json_response(conn, 403)
- end
-
- test "it returns a note activity in a collection", %{conn: conn} do
- note_activity = insert(:direct_note_activity)
- note_object = Object.normalize(note_activity)
- user = User.get_cached_by_ap_id(hd(note_activity.data["to"]))
-
- conn =
- conn
- |> assign(:user, user)
- |> put_req_header("accept", "application/activity+json")
- |> get("/users/#{user.nickname}/inbox?page=true")
-
- assert response(conn, 200) =~ note_object.data["content"]
- end
-
- test "it clears `unreachable` federation status of the sender", %{conn: conn, data: data} do
- user = insert(:user)
- data = Map.put(data, "bcc", [user.ap_id])
-
- sender_host = URI.parse(data["actor"]).host
- Instances.set_consistently_unreachable(sender_host)
- refute Instances.reachable?(sender_host)
-
- 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)
- assert Instances.reachable?(sender_host)
- end
-
- test "it removes all follower collections but actor's", %{conn: conn} do
- [actor, recipient] = insert_pair(:user)
-
- data =
- File.read!("test/fixtures/activitypub-client-post-activity.json")
- |> Poison.decode!()
-
- object = Map.put(data["object"], "attributedTo", actor.ap_id)
-
- data =
- data
- |> Map.put("id", Utils.generate_object_id())
- |> Map.put("actor", actor.ap_id)
- |> Map.put("object", object)
- |> Map.put("cc", [
- recipient.follower_address,
- actor.follower_address
- ])
- |> Map.put("to", [
- recipient.ap_id,
- recipient.follower_address,
- "https://www.w3.org/ns/activitystreams#Public"
- ])
-
- conn
- |> assign(:valid_signature, true)
- |> put_req_header("content-type", "application/activity+json")
- |> 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
- assert actor.follower_address in activity.recipients
- assert actor.follower_address in activity.data["cc"]
-
- refute recipient.follower_address in activity.recipients
- refute recipient.follower_address in activity.data["cc"]
- refute recipient.follower_address in activity.data["to"]
- end
-
- test "it requires authentication", %{conn: conn} do
- user = insert(:user)
- conn = put_req_header(conn, "accept", "application/activity+json")
-
- ret_conn = get(conn, "/users/#{user.nickname}/inbox")
- assert json_response(ret_conn, 403)
-
- ret_conn =
- conn
- |> assign(:user, user)
- |> get("/users/#{user.nickname}/inbox")
-
- assert json_response(ret_conn, 200)
- end
- end
-
- describe "GET /users/:nickname/outbox" do
- test "it paginates correctly", %{conn: conn} do
- user = insert(:user)
- conn = assign(conn, :user, user)
- outbox_endpoint = user.ap_id <> "/outbox"
-
- _posts =
- for i <- 0..25 do
- {:ok, activity} = CommonAPI.post(user, %{status: "post #{i}"})
- activity
- end
-
- result =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get(outbox_endpoint <> "?page=true")
- |> json_response(200)
-
- result_ids = Enum.map(result["orderedItems"], fn x -> x["id"] end)
- assert length(result["orderedItems"]) == 20
- assert length(result_ids) == 20
- assert result["next"]
- assert String.starts_with?(result["next"], outbox_endpoint)
-
- result_next =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get(result["next"])
- |> json_response(200)
-
- result_next_ids = Enum.map(result_next["orderedItems"], fn x -> x["id"] end)
- assert length(result_next["orderedItems"]) == 6
- assert length(result_next_ids) == 6
- refute Enum.find(result_next_ids, fn x -> x in result_ids end)
- refute Enum.find(result_ids, fn x -> x in result_next_ids end)
- assert String.starts_with?(result["id"], outbox_endpoint)
-
- result_next_again =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get(result_next["id"])
- |> json_response(200)
-
- assert result_next == result_next_again
- end
-
- test "it returns 200 even if there're no activities", %{conn: conn} do
- user = insert(:user)
- outbox_endpoint = user.ap_id <> "/outbox"
-
- conn =
- conn
- |> assign(:user, user)
- |> put_req_header("accept", "application/activity+json")
- |> get(outbox_endpoint)
-
- result = json_response(conn, 200)
- assert outbox_endpoint == result["id"]
- end
-
- test "it returns a note activity in a collection", %{conn: conn} do
- note_activity = insert(:note_activity)
- note_object = Object.normalize(note_activity)
- user = User.get_cached_by_ap_id(note_activity.data["actor"])
-
- conn =
- conn
- |> assign(:user, user)
- |> put_req_header("accept", "application/activity+json")
- |> get("/users/#{user.nickname}/outbox?page=true")
-
- assert response(conn, 200) =~ note_object.data["content"]
- end
-
- test "it returns an announce activity in a collection", %{conn: conn} do
- announce_activity = insert(:announce_activity)
- user = User.get_cached_by_ap_id(announce_activity.data["actor"])
-
- conn =
- conn
- |> assign(:user, user)
- |> put_req_header("accept", "application/activity+json")
- |> get("/users/#{user.nickname}/outbox?page=true")
-
- assert response(conn, 200) =~ announce_activity.data["object"]
- end
-
- test "it requires authentication if instance is NOT federating", %{
- conn: conn
- } do
- user = insert(:user)
- conn = put_req_header(conn, "accept", "application/activity+json")
-
- ensure_federating_or_authenticated(conn, "/users/#{user.nickname}/outbox", user)
- end
- end
-
- describe "POST /users/:nickname/outbox (C2S)" do
- setup do: clear_config([:instance, :limit])
-
- setup do
- [
- activity: %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "type" => "Create",
- "object" => %{"type" => "Note", "content" => "AP C2S test"},
- "to" => "https://www.w3.org/ns/activitystreams#Public",
- "cc" => []
- }
- ]
- end
-
- test "it rejects posts from other users / unauthenticated users", %{
- conn: conn,
- activity: activity
- } do
- user = insert(:user)
- other_user = insert(:user)
- conn = put_req_header(conn, "content-type", "application/activity+json")
-
- conn
- |> post("/users/#{user.nickname}/outbox", activity)
- |> json_response(403)
-
- conn
- |> assign(:user, other_user)
- |> post("/users/#{user.nickname}/outbox", activity)
- |> json_response(403)
- end
-
- test "it inserts an incoming create activity into the database", %{
- conn: conn,
- activity: activity
- } do
- user = insert(:user)
-
- result =
- conn
- |> assign(:user, user)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", activity)
- |> json_response(201)
-
- assert Activity.get_by_ap_id(result["id"])
- assert result["object"]
- assert %Object{data: object} = Object.normalize(result["object"])
- assert object["content"] == activity["object"]["content"]
- end
-
- test "it rejects anything beyond 'Note' creations", %{conn: conn, activity: activity} do
- user = insert(:user)
-
- activity =
- activity
- |> put_in(["object", "type"], "Benis")
-
- _result =
- conn
- |> assign(:user, user)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", activity)
- |> json_response(400)
- end
-
- test "it inserts an incoming sensitive activity into the database", %{
- conn: conn,
- activity: activity
- } do
- user = insert(:user)
- conn = assign(conn, :user, user)
- object = Map.put(activity["object"], "sensitive", true)
- activity = Map.put(activity, "object", object)
-
- response =
- conn
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", activity)
- |> json_response(201)
-
- assert Activity.get_by_ap_id(response["id"])
- assert response["object"]
- assert %Object{data: response_object} = Object.normalize(response["object"])
- assert response_object["sensitive"] == true
- assert response_object["content"] == activity["object"]["content"]
-
- representation =
- conn
- |> put_req_header("accept", "application/activity+json")
- |> get(response["id"])
- |> json_response(200)
-
- assert representation["object"]["sensitive"] == true
- end
-
- test "it rejects an incoming activity with bogus type", %{conn: conn, activity: activity} do
- user = insert(:user)
- activity = Map.put(activity, "type", "BadType")
-
- conn =
- conn
- |> assign(:user, user)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", activity)
-
- assert json_response(conn, 400)
- end
-
- test "it erects a tombstone when receiving a delete activity", %{conn: conn} do
- note_activity = insert(:note_activity)
- note_object = Object.normalize(note_activity)
- user = User.get_cached_by_ap_id(note_activity.data["actor"])
-
- data = %{
- type: "Delete",
- object: %{
- id: note_object.data["id"]
- }
- }
-
- conn =
- conn
- |> assign(:user, user)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", data)
-
- result = json_response(conn, 201)
- assert Activity.get_by_ap_id(result["id"])
-
- assert object = Object.get_by_ap_id(note_object.data["id"])
- assert object.data["type"] == "Tombstone"
- end
-
- test "it rejects delete activity of object from other actor", %{conn: conn} do
- note_activity = insert(:note_activity)
- note_object = Object.normalize(note_activity)
- user = insert(:user)
-
- data = %{
- type: "Delete",
- object: %{
- id: note_object.data["id"]
- }
- }
-
- conn =
- conn
- |> assign(:user, user)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", data)
-
- assert json_response(conn, 400)
- end
-
- test "it increases like count when receiving a like action", %{conn: conn} do
- note_activity = insert(:note_activity)
- note_object = Object.normalize(note_activity)
- user = User.get_cached_by_ap_id(note_activity.data["actor"])
-
- data = %{
- type: "Like",
- object: %{
- id: note_object.data["id"]
- }
- }
-
- conn =
- conn
- |> assign(:user, user)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", data)
-
- result = json_response(conn, 201)
- assert Activity.get_by_ap_id(result["id"])
-
- assert object = Object.get_by_ap_id(note_object.data["id"])
- assert object.data["like_count"] == 1
- end
-
- test "it doesn't spreads faulty attributedTo or actor fields", %{
- conn: conn,
- activity: activity
- } do
- reimu = insert(:user, nickname: "reimu")
- cirno = insert(:user, nickname: "cirno")
-
- assert reimu.ap_id
- assert cirno.ap_id
-
- activity =
- activity
- |> put_in(["object", "actor"], reimu.ap_id)
- |> put_in(["object", "attributedTo"], reimu.ap_id)
- |> put_in(["actor"], reimu.ap_id)
- |> put_in(["attributedTo"], reimu.ap_id)
-
- _reimu_outbox =
- conn
- |> assign(:user, cirno)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{reimu.nickname}/outbox", activity)
- |> json_response(403)
-
- cirno_outbox =
- conn
- |> assign(:user, cirno)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{cirno.nickname}/outbox", activity)
- |> json_response(201)
-
- assert cirno_outbox["attributedTo"] == nil
- assert cirno_outbox["actor"] == cirno.ap_id
-
- assert cirno_object = Object.normalize(cirno_outbox["object"])
- assert cirno_object.data["actor"] == cirno.ap_id
- assert cirno_object.data["attributedTo"] == cirno.ap_id
- end
-
- test "Character limitation", %{conn: conn, activity: activity} do
- Pleroma.Config.put([:instance, :limit], 5)
- user = insert(:user)
-
- result =
- conn
- |> assign(:user, user)
- |> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", activity)
- |> json_response(400)
-
- assert result == "Note is over the character limit"
- end
- end
-
- describe "/relay/followers" do
- test "it returns relay followers", %{conn: conn} do
- relay_actor = Relay.get_actor()
- user = insert(:user)
- User.follow(user, relay_actor)
-
- result =
- conn
- |> get("/relay/followers")
- |> json_response(200)
-
- assert result["first"]["orderedItems"] == [user.ap_id]
- end
-
- test "on non-federating instance, it returns 404", %{conn: conn} do
- Config.put([:instance, :federating], false)
- user = insert(:user)
-
- conn
- |> assign(:user, user)
- |> get("/relay/followers")
- |> json_response(404)
- end
- end
-
- describe "/relay/following" do
- test "it returns relay following", %{conn: conn} do
- result =
- conn
- |> get("/relay/following")
- |> json_response(200)
-
- assert result["first"]["orderedItems"] == []
- end
-
- test "on non-federating instance, it returns 404", %{conn: conn} do
- Config.put([:instance, :federating], false)
- user = insert(:user)
-
- conn
- |> assign(:user, user)
- |> get("/relay/following")
- |> json_response(404)
- end
- end
-
- describe "/users/:nickname/followers" do
- test "it returns the followers in a collection", %{conn: conn} do
- user = insert(:user)
- user_two = insert(:user)
- User.follow(user, user_two)
-
- result =
- conn
- |> assign(:user, user_two)
- |> get("/users/#{user_two.nickname}/followers")
- |> json_response(200)
-
- assert result["first"]["orderedItems"] == [user.ap_id]
- end
-
- test "it returns a uri if the user has 'hide_followers' set", %{conn: conn} do
- user = insert(:user)
- user_two = insert(:user, hide_followers: true)
- User.follow(user, user_two)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user_two.nickname}/followers")
- |> json_response(200)
-
- assert is_binary(result["first"])
- end
-
- test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is from another user",
- %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user, hide_followers: true)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{other_user.nickname}/followers?page=1")
-
- assert result.status == 403
- assert result.resp_body == ""
- end
-
- 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, hide_followers: true)
- other_user = insert(:user)
- {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user.nickname}/followers?page=1")
- |> json_response(200)
-
- assert result["totalItems"] == 1
- assert result["orderedItems"] == [other_user.ap_id]
- end
-
- test "it works for more than 10 users", %{conn: conn} do
- user = insert(:user)
-
- Enum.each(1..15, fn _ ->
- other_user = insert(:user)
- User.follow(other_user, user)
- end)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user.nickname}/followers")
- |> json_response(200)
-
- assert length(result["first"]["orderedItems"]) == 10
- assert result["first"]["totalItems"] == 15
- assert result["totalItems"] == 15
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user.nickname}/followers?page=2")
- |> json_response(200)
-
- assert length(result["orderedItems"]) == 5
- assert result["totalItems"] == 15
- end
-
- test "does not require authentication", %{conn: conn} do
- user = insert(:user)
-
- conn
- |> get("/users/#{user.nickname}/followers")
- |> json_response(200)
- end
- end
-
- describe "/users/:nickname/following" do
- test "it returns the following in a collection", %{conn: conn} do
- user = insert(:user)
- user_two = insert(:user)
- User.follow(user, user_two)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user.nickname}/following")
- |> json_response(200)
-
- assert result["first"]["orderedItems"] == [user_two.ap_id]
- end
-
- test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do
- user = insert(:user)
- user_two = insert(:user, hide_follows: true)
- User.follow(user, user_two)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user_two.nickname}/following")
- |> json_response(200)
-
- assert is_binary(result["first"])
- end
-
- test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is from another user",
- %{conn: conn} do
- user = insert(:user)
- user_two = insert(:user, hide_follows: true)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user_two.nickname}/following?page=1")
-
- assert result.status == 403
- assert result.resp_body == ""
- end
-
- 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, hide_follows: true)
- other_user = insert(:user)
- {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user.nickname}/following?page=1")
- |> json_response(200)
-
- assert result["totalItems"] == 1
- assert result["orderedItems"] == [other_user.ap_id]
- end
-
- test "it works for more than 10 users", %{conn: conn} do
- user = insert(:user)
-
- Enum.each(1..15, fn _ ->
- user = User.get_cached_by_id(user.id)
- other_user = insert(:user)
- User.follow(user, other_user)
- end)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user.nickname}/following")
- |> json_response(200)
-
- assert length(result["first"]["orderedItems"]) == 10
- assert result["first"]["totalItems"] == 15
- assert result["totalItems"] == 15
-
- result =
- conn
- |> assign(:user, user)
- |> get("/users/#{user.nickname}/following?page=2")
- |> json_response(200)
-
- assert length(result["orderedItems"]) == 5
- assert result["totalItems"] == 15
- end
-
- test "does not require authentication", %{conn: conn} do
- user = insert(:user)
-
- conn
- |> get("/users/#{user.nickname}/following")
- |> json_response(200)
- 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 "Additional ActivityPub C2S endpoints" do
- test "GET /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)
-
- conn
- |> get("/api/ap/whoami")
- |> json_response(403)
- end
-
- setup do: clear_config([:media_proxy])
- setup do: clear_config([Pleroma.Upload])
-
- test "POST /api/ap/upload_media", %{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"
- }
-
- object =
- conn
- |> assign(:user, user)
- |> post("/api/ap/upload_media", %{"file" => image, "description" => desc})
- |> json_response(:created)
-
- assert object["name"] == desc
- assert object["type"] == "Document"
- assert object["actor"] == user.ap_id
- assert [%{"href" => object_href, "mediaType" => object_mediatype}] = object["url"]
- assert is_binary(object_href)
- assert object_mediatype == "image/jpeg"
-
- activity_request = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "type" => "Create",
- "object" => %{
- "type" => "Note",
- "content" => "AP C2S test, attachment",
- "attachment" => [object]
- },
- "to" => "https://www.w3.org/ns/activitystreams#Public",
- "cc" => []
- }
-
- activity_response =
- conn
- |> assign(:user, user)
- |> post("/users/#{user.nickname}/outbox", activity_request)
- |> json_response(:created)
-
- assert activity_response["id"]
- assert activity_response["object"]
- assert activity_response["actor"] == user.ap_id
-
- assert %Object{data: %{"attachment" => [attachment]}} =
- Object.normalize(activity_response["object"])
-
- assert attachment["type"] == "Document"
- assert attachment["name"] == desc
-
- assert [
- %{
- "href" => ^object_href,
- "type" => "Link",
- "mediaType" => ^object_mediatype
- }
- ] = attachment["url"]
-
- # Fails if unauthenticated
- conn
- |> post("/api/ap/upload_media", %{"file" => image, "description" => desc})
- |> json_response(403)
- end
- end
-end
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
deleted file mode 100644
index b579bb0bb..000000000
--- a/test/web/activity_pub/activity_pub_test.exs
+++ /dev/null
@@ -1,2136 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.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
-
- import ExUnit.CaptureLog
- import Mock
- import Pleroma.Factory
- import Tesla.Mock
-
- setup do
- mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- setup do: clear_config([:instance, :federating])
-
- describe "streaming out participations" do
- test "it streams them out" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
-
- {:ok, conversation} = Pleroma.Conversation.create_or_bump_for(activity)
-
- participations =
- conversation.participations
- |> Repo.preload(:user)
-
- with_mock Pleroma.Web.Streamer,
- stream: fn _, _ -> nil end do
- ActivityPub.stream_out_participations(conversation.participations)
-
- 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
- test "it restricts 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([], %{visibility: "direct", actor_id: user.ap_id})
-
- assert activities == [direct_activity]
-
- activities =
- ActivityPub.fetch_activities([], %{visibility: "unlisted", actor_id: user.ap_id})
-
- assert activities == [unlisted_activity]
-
- activities =
- ActivityPub.fetch_activities([], %{visibility: "private", actor_id: user.ap_id})
-
- assert activities == [private_activity]
-
- activities = ActivityPub.fetch_activities([], %{visibility: "public", actor_id: user.ap_id})
-
- assert activities == [public_activity]
-
- activities =
- ActivityPub.fetch_activities([], %{
- visibility: ~w[private public],
- actor_id: user.ap_id
- })
-
- assert activities == [public_activity, private_activity]
- 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.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 returns a user that accepts chat messages" do
- user_id = "http://mastodon.example.org/users/admin"
- {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
-
- assert user.accepts_chat_messages
- end
- end
-
- test "it fetches the appropriate tag-restricted posts" do
- user = insert(:user)
-
- {:ok, status_one} = CommonAPI.post(user, %{status: ". #test"})
- {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"})
- {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"})
-
- fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"})
-
- fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]})
-
- fetch_three =
- ActivityPub.fetch_activities([], %{
- type: "Create",
- tag: ["test", "essais"],
- tag_reject: ["reject"]
- })
-
- fetch_four =
- ActivityPub.fetch_activities([], %{
- type: "Create",
- tag: ["test"],
- tag_all: ["test", "reject"]
- })
-
- assert fetch_one == [status_one, status_three]
- assert fetch_two == [status_one, status_two, status_three]
- assert fetch_three == [status_one, status_two]
- assert fetch_four == [status_three]
- end
-
- describe "insertion" do
- test "drops activities beyond a certain limit" do
- limit = Config.get([:instance, :remote_limit])
-
- random_text =
- :crypto.strong_rand_bytes(limit + 1)
- |> Base.encode64()
- |> binary_part(0, limit + 1)
-
- data = %{
- "ok" => true,
- "object" => %{
- "content" => random_text
- }
- }
-
- assert {:error, {:remote_limit_error, _}} = ActivityPub.insert(data)
- end
-
- test "doesn't drop activities with content being null" do
- user = insert(:user)
-
- data = %{
- "actor" => user.ap_id,
- "to" => [],
- "object" => %{
- "actor" => user.ap_id,
- "to" => [],
- "type" => "Note",
- "content" => nil
- }
- }
-
- assert {:ok, _} = ActivityPub.insert(data)
- end
-
- test "returns the activity if one with the same id is already in" do
- activity = insert(:note_activity)
- {:ok, new_activity} = ActivityPub.insert(activity.data)
-
- assert activity.id == new_activity.id
- end
-
- test "inserts a given map into the activity database, giving it an id if it has none." do
- user = insert(:user)
-
- data = %{
- "actor" => user.ap_id,
- "to" => [],
- "object" => %{
- "actor" => user.ap_id,
- "to" => [],
- "type" => "Note",
- "content" => "hey"
- }
- }
-
- {:ok, %Activity{} = activity} = ActivityPub.insert(data)
- assert activity.data["ok"] == data["ok"]
- assert is_binary(activity.data["id"])
-
- given_id = "bla"
-
- data = %{
- "id" => given_id,
- "actor" => user.ap_id,
- "to" => [],
- "context" => "blabla",
- "object" => %{
- "actor" => user.ap_id,
- "to" => [],
- "type" => "Note",
- "content" => "hey"
- }
- }
-
- {:ok, %Activity{} = activity} = ActivityPub.insert(data)
- assert activity.data["ok"] == data["ok"]
- assert activity.data["id"] == given_id
- assert activity.data["context"] == "blabla"
- assert activity.data["context_id"]
- end
-
- test "adds a context when none is there" do
- user = insert(:user)
-
- data = %{
- "actor" => user.ap_id,
- "to" => [],
- "object" => %{
- "actor" => user.ap_id,
- "to" => [],
- "type" => "Note",
- "content" => "hey"
- }
- }
-
- {:ok, %Activity{} = activity} = ActivityPub.insert(data)
- object = Pleroma.Object.normalize(activity)
-
- assert is_binary(activity.data["context"])
- assert is_binary(object.data["context"])
- assert activity.data["context_id"]
- assert object.data["context_id"]
- end
-
- test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do
- user = insert(:user)
-
- data = %{
- "actor" => user.ap_id,
- "to" => [],
- "object" => %{
- "actor" => user.ap_id,
- "to" => [],
- "type" => "Note",
- "content" => "hey"
- }
- }
-
- {:ok, %Activity{} = activity} = ActivityPub.insert(data)
- assert object = Object.normalize(activity)
- assert is_binary(object.data["id"])
- 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)
-
- {:ok, activity} =
- ActivityPub.create(%{
- to: ["user1", "user1", "user2"],
- actor: user,
- context: "",
- object: %{
- "to" => ["user1", "user1", "user2"],
- "type" => "Note",
- "content" => "testing"
- }
- })
-
- assert activity.data["to"] == ["user1", "user2"]
- assert activity.actor == user.ap_id
- assert activity.recipients == ["user1", "user2", user.ap_id]
- end
-
- test "increases user note count only for public activities" do
- user = insert(:user)
-
- {:ok, _} =
- CommonAPI.post(User.get_cached_by_id(user.id), %{
- status: "1",
- visibility: "public"
- })
-
- {:ok, _} =
- CommonAPI.post(User.get_cached_by_id(user.id), %{
- status: "2",
- visibility: "unlisted"
- })
-
- {:ok, _} =
- CommonAPI.post(User.get_cached_by_id(user.id), %{
- status: "2",
- visibility: "private"
- })
-
- {:ok, _} =
- CommonAPI.post(User.get_cached_by_id(user.id), %{
- status: "3",
- visibility: "direct"
- })
-
- user = User.get_cached_by_id(user.id)
- assert user.note_count == 2
- end
-
- test "increases replies count" do
- user = insert(:user)
- user2 = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"})
- ap_id = activity.data["id"]
- reply_data = %{status: "1", in_reply_to_status_id: activity.id}
-
- # public
- {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "public"))
- assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
- assert object.data["repliesCount"] == 1
-
- # unlisted
- {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "unlisted"))
- assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
- assert object.data["repliesCount"] == 2
-
- # private
- {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "private"))
- assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
- assert object.data["repliesCount"] == 2
-
- # direct
- {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "direct"))
- assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
- assert object.data["repliesCount"] == 2
- end
- end
-
- describe "fetch activities for recipients" do
- test "retrieve the activities for certain recipients" do
- {:ok, activity_one} = ActivityBuilder.insert(%{"to" => ["someone"]})
- {:ok, activity_two} = ActivityBuilder.insert(%{"to" => ["someone_else"]})
- {:ok, _activity_three} = ActivityBuilder.insert(%{"to" => ["noone"]})
-
- activities = ActivityPub.fetch_activities(["someone", "someone_else"])
- assert length(activities) == 2
- assert activities == [activity_one, activity_two]
- end
- end
-
- describe "fetch activities in context" do
- test "retrieves activities that have a given context" do
- {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
- {:ok, activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
- {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
- {:ok, _activity_four} = ActivityBuilder.insert(%{"type" => "Announce", "context" => "2hu"})
- activity_five = insert(:note_activity)
- user = insert(:user)
-
- {: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]
- end
-
- test "doesn't return activities with filtered words" do
- user = insert(:user)
- user_two = insert(:user)
- insert(:filter, user: user, phrase: "test", hide: true)
-
- {:ok, %{id: id1, data: %{"context" => context}}} = CommonAPI.post(user, %{status: "1"})
-
- {:ok, %{id: id2}} = CommonAPI.post(user_two, %{status: "2", in_reply_to_status_id: id1})
-
- {:ok, %{id: id3} = user_activity} =
- CommonAPI.post(user, %{status: "3 test?", in_reply_to_status_id: id2})
-
- {:ok, %{id: id4} = filtered_activity} =
- CommonAPI.post(user_two, %{status: "4 test!", in_reply_to_status_id: id3})
-
- {:ok, _} = CommonAPI.post(user, %{status: "5", in_reply_to_status_id: id4})
-
- activities =
- context
- |> ActivityPub.fetch_activities_for_context(%{user: user})
- |> Enum.map(& &1.id)
-
- assert length(activities) == 4
- assert user_activity.id in activities
- refute filtered_activity.id in activities
- end
- end
-
- test "doesn't return blocked activities" do
- activity_one = insert(:note_activity)
- activity_two = insert(:note_activity)
- activity_three = insert(:note_activity)
- user = insert(:user)
- booster = insert(:user)
- {:ok, _user_relationship} = User.block(user, %{ap_id: activity_one.data["actor"]})
-
- activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
-
- assert Enum.member?(activities, activity_two)
- assert Enum.member?(activities, activity_three)
- refute Enum.member?(activities, activity_one)
-
- {:ok, _user_block} = User.unblock(user, %{ap_id: activity_one.data["actor"]})
-
- activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
-
- assert Enum.member?(activities, activity_two)
- assert Enum.member?(activities, activity_three)
- assert Enum.member?(activities, activity_one)
-
- {:ok, _user_relationship} = User.block(user, %{ap_id: activity_three.data["actor"]})
- {:ok, %{data: %{"object" => id}}} = CommonAPI.repeat(activity_three.id, booster)
- %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
- activity_three = Activity.get_by_id(activity_three.id)
-
- activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
-
- assert Enum.member?(activities, activity_two)
- refute Enum.member?(activities, activity_three)
- refute Enum.member?(activities, boost_activity)
- assert Enum.member?(activities, activity_one)
-
- activities = ActivityPub.fetch_activities([], %{blocking_user: nil, skip_preload: true})
-
- assert Enum.member?(activities, activity_two)
- assert Enum.member?(activities, activity_three)
- assert Enum.member?(activities, boost_activity)
- assert Enum.member?(activities, activity_one)
- end
-
- test "doesn't return transitive interactions concerning blocked users" do
- blocker = insert(:user)
- blockee = insert(:user)
- friend = insert(:user)
-
- {:ok, _user_relationship} = User.block(blocker, blockee)
-
- {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
-
- {:ok, activity_two} = CommonAPI.post(friend, %{status: "hey! @#{blockee.nickname}"})
-
- {:ok, activity_three} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
-
- {:ok, activity_four} = CommonAPI.post(blockee, %{status: "hey! @#{blocker.nickname}"})
-
- activities = ActivityPub.fetch_activities([], %{blocking_user: blocker})
-
- assert Enum.member?(activities, activity_one)
- refute Enum.member?(activities, activity_two)
- refute Enum.member?(activities, activity_three)
- refute Enum.member?(activities, activity_four)
- end
-
- test "doesn't return announce activities with blocked users in 'to'" do
- blocker = insert(:user)
- blockee = insert(:user)
- friend = insert(:user)
-
- {:ok, _user_relationship} = User.block(blocker, blockee)
-
- {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
-
- {:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
-
- {:ok, activity_three} = CommonAPI.repeat(activity_two.id, friend)
-
- activities =
- ActivityPub.fetch_activities([], %{blocking_user: blocker})
- |> Enum.map(fn act -> act.id end)
-
- assert Enum.member?(activities, activity_one.id)
- refute Enum.member?(activities, activity_two.id)
- refute Enum.member?(activities, activity_three.id)
- end
-
- test "doesn't return announce activities with blocked users in 'cc'" do
- blocker = insert(:user)
- blockee = insert(:user)
- friend = insert(:user)
-
- {:ok, _user_relationship} = User.block(blocker, blockee)
-
- {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
-
- {:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
-
- assert object = Pleroma.Object.normalize(activity_two)
-
- data = %{
- "actor" => friend.ap_id,
- "object" => object.data["id"],
- "context" => object.data["context"],
- "type" => "Announce",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [blockee.ap_id]
- }
-
- assert {:ok, activity_three} = ActivityPub.insert(data)
-
- activities =
- ActivityPub.fetch_activities([], %{blocking_user: blocker})
- |> Enum.map(fn act -> act.id end)
-
- assert Enum.member?(activities, activity_one.id)
- refute Enum.member?(activities, activity_two.id)
- refute Enum.member?(activities, activity_three.id)
- end
-
- test "doesn't return activities from blocked domains" do
- domain = "dogwhistle.zone"
- domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"})
- note = insert(:note, %{data: %{"actor" => domain_user.ap_id}})
- activity = insert(:note_activity, %{note: note})
- user = insert(:user)
- {:ok, user} = User.block_domain(user, domain)
-
- activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
-
- refute activity in activities
-
- followed_user = insert(:user)
- CommonAPI.follow(user, followed_user)
- {:ok, repeat_activity} = CommonAPI.repeat(activity.id, followed_user)
-
- activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
-
- 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)
-
- 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})
-
- assert Enum.member?(activities, activity_two)
- assert Enum.member?(activities, activity_three)
- refute Enum.member?(activities, activity_one)
-
- # Calling with 'with_muted' will deliver muted activities, too.
- activities =
- ActivityPub.fetch_activities([], %{
- muting_user: user,
- with_muted: true,
- skip_preload: true
- })
-
- assert Enum.member?(activities, activity_two)
- assert Enum.member?(activities, activity_three)
- assert Enum.member?(activities, activity_one)
-
- {:ok, _user_mute} = User.unmute(user, activity_one_actor)
-
- activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true})
-
- assert Enum.member?(activities, activity_two)
- assert Enum.member?(activities, activity_three)
- assert Enum.member?(activities, activity_one)
-
- activity_three_actor = User.get_by_ap_id(activity_three.data["actor"])
- {:ok, _user_relationships} = User.mute(user, activity_three_actor)
- {:ok, %{data: %{"object" => id}}} = CommonAPI.repeat(activity_three.id, booster)
- %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
- activity_three = Activity.get_by_id(activity_three.id)
-
- activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true})
-
- assert Enum.member?(activities, activity_two)
- refute Enum.member?(activities, activity_three)
- refute Enum.member?(activities, boost_activity)
- assert Enum.member?(activities, activity_one)
-
- activities = ActivityPub.fetch_activities([], %{muting_user: nil, skip_preload: true})
-
- assert Enum.member?(activities, activity_two)
- assert Enum.member?(activities, activity_three)
- assert Enum.member?(activities, boost_activity)
- assert Enum.member?(activities, activity_one)
- end
-
- test "doesn't return thread muted activities" do
- user = insert(:user)
- _activity_one = insert(:note_activity)
- note_two = insert(:note, data: %{"context" => "suya.."})
- activity_two = insert(:note_activity, note: note_two)
-
- {:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
-
- assert [_activity_one] = ActivityPub.fetch_activities([], %{muting_user: user})
- end
-
- test "returns thread muted activities when with_muted is set" do
- user = insert(:user)
- _activity_one = insert(:note_activity)
- note_two = insert(:note, data: %{"context" => "suya.."})
- activity_two = insert(:note_activity, note: note_two)
-
- {:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
-
- assert [_activity_two, _activity_one] =
- ActivityPub.fetch_activities([], %{muting_user: user, with_muted: true})
- end
-
- test "does include announces on request" do
- activity_three = insert(:note_activity)
- user = insert(:user)
- booster = insert(:user)
-
- {:ok, user} = User.follow(user, booster)
-
- {:ok, announce} = CommonAPI.repeat(activity_three.id, booster)
-
- [announce_activity] = ActivityPub.fetch_activities([user.ap_id | User.following(user)])
-
- assert announce_activity.id == announce.id
- end
-
- test "excludes reblogs on request" do
- user = insert(:user)
- {:ok, expected_activity} = ActivityBuilder.insert(%{"type" => "Create"}, %{:user => user})
- {:ok, _} = ActivityBuilder.insert(%{"type" => "Announce"}, %{:user => user})
-
- [activity] = ActivityPub.fetch_user_activities(user, nil, %{exclude_reblogs: true})
-
- assert activity == expected_activity
- end
-
- describe "irreversible filters" do
- setup do
- user = insert(:user)
- user_two = insert(:user)
-
- insert(:filter, user: user_two, phrase: "cofe", hide: true)
- insert(:filter, user: user_two, phrase: "ok boomer", hide: true)
- insert(:filter, user: user_two, phrase: "test", hide: false)
-
- params = %{
- type: ["Create", "Announce"],
- user: user_two
- }
-
- {:ok, %{user: user, user_two: user_two, params: params}}
- end
-
- test "it returns statuses if they don't contain exact filter words", %{
- user: user,
- params: params
- } do
- {:ok, _} = CommonAPI.post(user, %{status: "hey"})
- {:ok, _} = CommonAPI.post(user, %{status: "got cofefe?"})
- {:ok, _} = CommonAPI.post(user, %{status: "I am not a boomer"})
- {:ok, _} = CommonAPI.post(user, %{status: "ok boomers"})
- {:ok, _} = CommonAPI.post(user, %{status: "ccofee is not a word"})
- {:ok, _} = CommonAPI.post(user, %{status: "this is a test"})
-
- activities = ActivityPub.fetch_activities([], params)
-
- assert Enum.count(activities) == 6
- end
-
- test "it does not filter user's own statuses", %{user_two: user_two, params: params} do
- {:ok, _} = CommonAPI.post(user_two, %{status: "Give me some cofe!"})
- {:ok, _} = CommonAPI.post(user_two, %{status: "ok boomer"})
-
- activities = ActivityPub.fetch_activities([], params)
-
- assert Enum.count(activities) == 2
- end
-
- test "it excludes statuses with filter words", %{user: user, params: params} do
- {:ok, _} = CommonAPI.post(user, %{status: "Give me some cofe!"})
- {:ok, _} = CommonAPI.post(user, %{status: "ok boomer"})
- {:ok, _} = CommonAPI.post(user, %{status: "is it a cOfE?"})
- {:ok, _} = CommonAPI.post(user, %{status: "cofe is all I need"})
- {:ok, _} = CommonAPI.post(user, %{status: "— ok BOOMER\n"})
-
- activities = ActivityPub.fetch_activities([], params)
-
- assert Enum.empty?(activities)
- end
-
- test "it returns all statuses if user does not have any filters" do
- another_user = insert(:user)
- {:ok, _} = CommonAPI.post(another_user, %{status: "got cofe?"})
- {:ok, _} = CommonAPI.post(another_user, %{status: "test!"})
-
- activities =
- ActivityPub.fetch_activities([], %{
- type: ["Create", "Announce"],
- user: another_user
- })
-
- assert Enum.count(activities) == 2
- end
- end
-
- describe "public fetch activities" do
- test "doesn't retrieve unlisted activities" do
- user = insert(:user)
-
- {:ok, _unlisted_activity} = CommonAPI.post(user, %{status: "yeah", visibility: "unlisted"})
-
- {:ok, listed_activity} = CommonAPI.post(user, %{status: "yeah"})
-
- [activity] = ActivityPub.fetch_public_activities()
-
- assert activity == listed_activity
- end
-
- test "retrieves public activities" do
- _activities = ActivityPub.fetch_public_activities()
-
- %{public: public} = ActivityBuilder.public_and_non_public()
-
- activities = ActivityPub.fetch_public_activities()
- assert length(activities) == 1
- assert Enum.at(activities, 0) == public
- end
-
- test "retrieves a maximum of 20 activities" do
- ActivityBuilder.insert_list(10)
- expected_activities = ActivityBuilder.insert_list(20)
-
- activities = ActivityPub.fetch_public_activities()
-
- assert collect_ids(activities) == collect_ids(expected_activities)
- assert length(activities) == 20
- end
-
- test "retrieves ids starting from a since_id" do
- activities = ActivityBuilder.insert_list(30)
- expected_activities = ActivityBuilder.insert_list(10)
- since_id = List.last(activities).id
-
- activities = ActivityPub.fetch_public_activities(%{since_id: since_id})
-
- assert collect_ids(activities) == collect_ids(expected_activities)
- assert length(activities) == 10
- end
-
- test "retrieves ids up to max_id" do
- 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})
-
- assert length(activities) == 20
- 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, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
-
- {:ok, activity} = CommonAPI.repeat(activity.id, booster)
-
- activities = ActivityPub.fetch_activities([], %{muting_user: user})
-
- refute Enum.any?(activities, fn %{id: id} -> id == activity.id end)
- end
-
- test "returns reblogs for users for whom reblogs have not been muted" do
- activity = insert(:note_activity)
- user = insert(:user)
- booster = insert(:user)
- {:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
- {:ok, _reblog_mute} = CommonAPI.show_reblogs(user, booster)
-
- {:ok, activity} = CommonAPI.repeat(activity.id, booster)
-
- activities = ActivityPub.fetch_activities([], %{muting_user: user})
-
- assert Enum.any?(activities, fn %{id: id} -> id == activity.id end)
- end
- end
-
- describe "uploading files" do
- setup do
- test_file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- %{test_file: test_file}
- end
-
- test "sets a description if given", %{test_file: file} do
- {:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file")
- assert object.data["name"] == "a cool file"
- end
-
- test "it sets the default description depending on the configuration", %{test_file: file} do
- clear_config([Pleroma.Upload, :default_description])
-
- Pleroma.Config.put([Pleroma.Upload, :default_description], nil)
- {:ok, %Object{} = object} = ActivityPub.upload(file)
- assert object.data["name"] == ""
-
- Pleroma.Config.put([Pleroma.Upload, :default_description], :filename)
- {:ok, %Object{} = object} = ActivityPub.upload(file)
- assert object.data["name"] == "an_image.jpg"
-
- Pleroma.Config.put([Pleroma.Upload, :default_description], "unnamed attachment")
- {:ok, %Object{} = object} = ActivityPub.upload(file)
- assert object.data["name"] == "unnamed attachment"
- end
-
- test "copies the file to the configured folder", %{test_file: file} do
- clear_config([Pleroma.Upload, :default_description], :filename)
- {:ok, %Object{} = object} = ActivityPub.upload(file)
- assert object.data["name"] == "an_image.jpg"
- end
-
- test "works with base64 encoded images" do
- file = %{
- img: data_uri()
- }
-
- {:ok, %Object{}} = ActivityPub.upload(file)
- end
- end
-
- describe "fetch the latest Follow" do
- test "fetches the latest Follow activity" do
- %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
- follower = Repo.get_by(User, ap_id: activity.data["actor"])
- followed = Repo.get_by(User, ap_id: activity.data["object"])
-
- assert activity == Utils.fetch_latest_follow(follower, followed)
- end
- end
-
- describe "unfollowing" do
- test "it reverts unfollow activity" do
- follower = insert(:user)
- followed = insert(:user)
-
- {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.unfollow(follower, followed)
- 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 an undo activity for the last follow" do
- follower = insert(:user)
- followed = insert(:user)
-
- {:ok, _, _, follow_activity} = CommonAPI.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
-
- test "creates an undo activity for a pending follow request" do
- follower = insert(:user)
- followed = insert(:user, %{locked: true})
-
- {:ok, _, _, follow_activity} = CommonAPI.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 "timeline post-processing" do
- test "it filters broken threads" do
- user1 = insert(:user)
- user2 = insert(:user)
- user3 = insert(:user)
-
- {:ok, user1} = User.follow(user1, user3)
- assert User.following?(user1, user3)
-
- {:ok, user2} = User.follow(user2, user3)
- assert User.following?(user2, user3)
-
- {:ok, user3} = User.follow(user3, user2)
- assert User.following?(user3, user2)
-
- {:ok, public_activity} = CommonAPI.post(user3, %{status: "hi 1"})
-
- {:ok, private_activity_1} = CommonAPI.post(user3, %{status: "hi 2", visibility: "private"})
-
- {:ok, private_activity_2} =
- CommonAPI.post(user2, %{
- status: "hi 3",
- visibility: "private",
- in_reply_to_status_id: private_activity_1.id
- })
-
- {:ok, private_activity_3} =
- CommonAPI.post(user3, %{
- status: "hi 4",
- visibility: "private",
- in_reply_to_status_id: private_activity_2.id
- })
-
- activities =
- 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"])
-
- assert [public_activity.id, private_activity_1.id, private_activity_3.id] == activities
-
- assert length(activities) == 3
-
- activities =
- 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
- assert length(activities) == 2
- end
- end
-
- 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, skip_visibility_check: true})
- }
-
- 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
- user = insert(:user)
- member = insert(:user)
- {:ok, list} = Pleroma.List.create("foo", user)
- {:ok, list} = Pleroma.List.follow(list, member)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
-
- activity = Repo.preload(activity, :bookmark)
- activity = %Activity{activity | thread_muted?: !!activity.thread_muted?}
-
- assert ActivityPub.fetch_activities([], %{user: user}) == [activity]
- end
-
- def data_uri do
- File.read!("test/fixtures/avatar_data_uri")
- end
-
- describe "fetch_activities_bounded" do
- test "fetches private posts for followed users" do
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- status: "thought I looked cute might delete later :3",
- visibility: "private"
- })
-
- [result] = ActivityPub.fetch_activities_bounded([user.follower_address], [])
- assert result.id == activity.id
- end
-
- test "fetches only public posts for other users" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: "#cofe", visibility: "public"})
-
- {:ok, _private_activity} =
- CommonAPI.post(user, %{
- status: "why is tenshi eating a corndog so cute?",
- visibility: "private"
- })
-
- [result] = ActivityPub.fetch_activities_bounded([], [user.follower_address])
- assert result.id == activity.id
- end
- end
-
- describe "fetch_follow_information_for_user" do
- test "syncronizes following/followers counters" do
- user =
- insert(:user,
- local: false,
- follower_address: "http://localhost:4001/users/fuser2/followers",
- following_address: "http://localhost:4001/users/fuser2/following"
- )
-
- {:ok, info} = ActivityPub.fetch_follow_information_for_user(user)
- assert info.follower_count == 527
- assert info.following_count == 267
- end
-
- test "detects hidden followers" do
- mock(fn env ->
- case env.url do
- "http://localhost:4001/users/masto_closed/followers?page=1" ->
- %Tesla.Env{status: 403, body: ""}
-
- _ ->
- apply(HttpRequestMock, :request, [env])
- end
- end)
-
- user =
- insert(:user,
- local: false,
- follower_address: "http://localhost:4001/users/masto_closed/followers",
- following_address: "http://localhost:4001/users/masto_closed/following"
- )
-
- {: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
- mock(fn env ->
- case env.url do
- "http://localhost:4001/users/masto_closed/following?page=1" ->
- %Tesla.Env{status: 403, body: ""}
-
- _ ->
- apply(HttpRequestMock, :request, [env])
- end
- end)
-
- user =
- insert(:user,
- local: false,
- follower_address: "http://localhost:4001/users/masto_closed/followers",
- following_address: "http://localhost:4001/users/masto_closed/following"
- )
-
- {: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(user, a4.id)
- {:ok, _} = CommonAPI.favorite(other_user, a3.id)
- {:ok, _} = CommonAPI.favorite(user, a3.id)
- {:ok, _} = CommonAPI.favorite(other_user, a5.id)
- {:ok, _} = CommonAPI.favorite(user, a5.id)
- {:ok, _} = CommonAPI.favorite(other_user, a4.id)
- {:ok, _} = CommonAPI.favorite(user, a1.id)
- {:ok, _} = CommonAPI.favorite(other_user, a1.id)
- 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(%Oban.Job{args: params})
-
- 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)
-
- assert [%Notification{activity: ^activity}] = Notification.for_user(follower_move_opted_out)
- 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
-
- test "doesn't retrieve replies activities with exclude_replies" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
-
- {:ok, _reply} = CommonAPI.post(user, %{status: "yeah", in_reply_to_status_id: activity.id})
-
- [result] = ActivityPub.fetch_public_activities(%{exclude_replies: true})
-
- assert result.id == activity.id
-
- assert length(ActivityPub.fetch_public_activities()) == 2
- end
-
- describe "replies filtering with public messages" do
- setup :public_messages
-
- test "public timeline", %{users: %{u1: user}} do
- activities_ids =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:local_only, false)
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:reply_filtering_user, user)
- |> ActivityPub.fetch_public_activities()
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 16
- end
-
- test "public timeline with reply_visibility `following`", %{
- users: %{u1: user},
- u1: u1,
- u2: u2,
- u3: u3,
- u4: u4,
- activities: activities
- } do
- activities_ids =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:local_only, false)
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:reply_visibility, "following")
- |> Map.put(:reply_filtering_user, user)
- |> ActivityPub.fetch_public_activities()
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 14
-
- visible_ids =
- Map.values(u1) ++ Map.values(u2) ++ Map.values(u4) ++ Map.values(activities) ++ [u3[:r1]]
-
- assert Enum.all?(visible_ids, &(&1 in activities_ids))
- end
-
- test "public timeline with reply_visibility `self`", %{
- users: %{u1: user},
- u1: u1,
- u2: u2,
- u3: u3,
- u4: u4,
- activities: activities
- } do
- activities_ids =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:local_only, false)
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:reply_visibility, "self")
- |> Map.put(:reply_filtering_user, user)
- |> ActivityPub.fetch_public_activities()
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 10
- visible_ids = Map.values(u1) ++ [u2[:r1], u3[:r1], u4[:r1]] ++ Map.values(activities)
- assert Enum.all?(visible_ids, &(&1 in activities_ids))
- end
-
- test "home timeline", %{
- users: %{u1: user},
- activities: activities,
- u1: u1,
- u2: u2,
- u3: u3,
- u4: u4
- } do
- params =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:user, user)
- |> Map.put(:reply_filtering_user, user)
-
- activities_ids =
- ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 13
-
- visible_ids =
- Map.values(u1) ++
- Map.values(u3) ++
- [
- activities[:a1],
- activities[:a2],
- activities[:a4],
- u2[:r1],
- u2[:r3],
- u4[:r1],
- u4[:r2]
- ]
-
- assert Enum.all?(visible_ids, &(&1 in activities_ids))
- end
-
- test "home timeline with reply_visibility `following`", %{
- users: %{u1: user},
- activities: activities,
- u1: u1,
- u2: u2,
- u3: u3,
- u4: u4
- } do
- params =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:user, user)
- |> Map.put(:reply_visibility, "following")
- |> Map.put(:reply_filtering_user, user)
-
- activities_ids =
- ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 11
-
- visible_ids =
- Map.values(u1) ++
- [
- activities[:a1],
- activities[:a2],
- activities[:a4],
- u2[:r1],
- u2[:r3],
- u3[:r1],
- u4[:r1],
- u4[:r2]
- ]
-
- assert Enum.all?(visible_ids, &(&1 in activities_ids))
- end
-
- test "home timeline with reply_visibility `self`", %{
- users: %{u1: user},
- activities: activities,
- u1: u1,
- u2: u2,
- u3: u3,
- u4: u4
- } do
- params =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:user, user)
- |> Map.put(:reply_visibility, "self")
- |> Map.put(:reply_filtering_user, user)
-
- activities_ids =
- ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 9
-
- visible_ids =
- Map.values(u1) ++
- [
- activities[:a1],
- activities[:a2],
- activities[:a4],
- u2[:r1],
- u3[:r1],
- u4[:r1]
- ]
-
- assert Enum.all?(visible_ids, &(&1 in activities_ids))
- end
-
- test "filtering out announces where the user is the actor of the announced message" do
- user = insert(:user)
- other_user = insert(:user)
- third_user = insert(:user)
- User.follow(user, other_user)
-
- {:ok, post} = CommonAPI.post(user, %{status: "yo"})
- {:ok, other_post} = CommonAPI.post(third_user, %{status: "yo"})
- {:ok, _announce} = CommonAPI.repeat(post.id, other_user)
- {:ok, _announce} = CommonAPI.repeat(post.id, third_user)
- {:ok, announce} = CommonAPI.repeat(other_post.id, other_user)
-
- params = %{
- type: ["Announce"]
- }
-
- results =
- [user.ap_id | User.following(user)]
- |> ActivityPub.fetch_activities(params)
-
- assert length(results) == 3
-
- params = %{
- type: ["Announce"],
- announce_filtering_user: user
- }
-
- [result] =
- [user.ap_id | User.following(user)]
- |> ActivityPub.fetch_activities(params)
-
- assert result.id == announce.id
- end
- end
-
- describe "replies filtering with private messages" do
- setup :private_messages
-
- test "public timeline", %{users: %{u1: user}} do
- activities_ids =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:local_only, false)
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:user, user)
- |> ActivityPub.fetch_public_activities()
- |> Enum.map(& &1.id)
-
- assert activities_ids == []
- end
-
- test "public timeline with default reply_visibility `following`", %{users: %{u1: user}} do
- activities_ids =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:local_only, false)
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:reply_visibility, "following")
- |> Map.put(:reply_filtering_user, user)
- |> Map.put(:user, user)
- |> ActivityPub.fetch_public_activities()
- |> Enum.map(& &1.id)
-
- assert activities_ids == []
- end
-
- test "public timeline with default reply_visibility `self`", %{users: %{u1: user}} do
- activities_ids =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:local_only, false)
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:reply_visibility, "self")
- |> Map.put(:reply_filtering_user, user)
- |> Map.put(:user, user)
- |> ActivityPub.fetch_public_activities()
- |> Enum.map(& &1.id)
-
- assert activities_ids == []
-
- activities_ids =
- %{}
- |> Map.put(:reply_visibility, "self")
- |> Map.put(:reply_filtering_user, nil)
- |> ActivityPub.fetch_public_activities()
-
- assert activities_ids == []
- end
-
- test "home timeline", %{users: %{u1: user}} do
- params =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:user, user)
-
- activities_ids =
- ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 12
- end
-
- test "home timeline with default reply_visibility `following`", %{users: %{u1: user}} do
- params =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:user, user)
- |> Map.put(:reply_visibility, "following")
- |> Map.put(:reply_filtering_user, user)
-
- activities_ids =
- ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 12
- end
-
- test "home timeline with default reply_visibility `self`", %{
- users: %{u1: user},
- activities: activities,
- u1: u1,
- u2: u2,
- u3: u3,
- u4: u4
- } do
- params =
- %{}
- |> Map.put(:type, ["Create", "Announce"])
- |> Map.put(:blocking_user, user)
- |> Map.put(:muting_user, user)
- |> Map.put(:user, user)
- |> Map.put(:reply_visibility, "self")
- |> Map.put(:reply_filtering_user, user)
-
- activities_ids =
- ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
- |> Enum.map(& &1.id)
-
- assert length(activities_ids) == 10
-
- visible_ids =
- Map.values(u1) ++ Map.values(u4) ++ [u2[:r1], u3[:r1]] ++ Map.values(activities)
-
- assert Enum.all?(visible_ids, &(&1 in activities_ids))
- end
- end
-
- defp public_messages(_) do
- [u1, u2, u3, u4] = insert_list(4, :user)
- {:ok, u1} = User.follow(u1, u2)
- {:ok, u2} = User.follow(u2, u1)
- {:ok, u1} = User.follow(u1, u4)
- {:ok, u4} = User.follow(u4, u1)
-
- {:ok, u2} = User.follow(u2, u3)
- {:ok, u3} = User.follow(u3, u2)
-
- {:ok, a1} = CommonAPI.post(u1, %{status: "Status"})
-
- {:ok, r1_1} =
- CommonAPI.post(u2, %{
- status: "@#{u1.nickname} reply from u2 to u1",
- in_reply_to_status_id: a1.id
- })
-
- {:ok, r1_2} =
- CommonAPI.post(u3, %{
- status: "@#{u1.nickname} reply from u3 to u1",
- in_reply_to_status_id: a1.id
- })
-
- {:ok, r1_3} =
- CommonAPI.post(u4, %{
- status: "@#{u1.nickname} reply from u4 to u1",
- in_reply_to_status_id: a1.id
- })
-
- {:ok, a2} = CommonAPI.post(u2, %{status: "Status"})
-
- {:ok, r2_1} =
- CommonAPI.post(u1, %{
- status: "@#{u2.nickname} reply from u1 to u2",
- in_reply_to_status_id: a2.id
- })
-
- {:ok, r2_2} =
- CommonAPI.post(u3, %{
- status: "@#{u2.nickname} reply from u3 to u2",
- in_reply_to_status_id: a2.id
- })
-
- {:ok, r2_3} =
- CommonAPI.post(u4, %{
- status: "@#{u2.nickname} reply from u4 to u2",
- in_reply_to_status_id: a2.id
- })
-
- {:ok, a3} = CommonAPI.post(u3, %{status: "Status"})
-
- {:ok, r3_1} =
- CommonAPI.post(u1, %{
- status: "@#{u3.nickname} reply from u1 to u3",
- in_reply_to_status_id: a3.id
- })
-
- {:ok, r3_2} =
- CommonAPI.post(u2, %{
- status: "@#{u3.nickname} reply from u2 to u3",
- in_reply_to_status_id: a3.id
- })
-
- {:ok, r3_3} =
- CommonAPI.post(u4, %{
- status: "@#{u3.nickname} reply from u4 to u3",
- in_reply_to_status_id: a3.id
- })
-
- {:ok, a4} = CommonAPI.post(u4, %{status: "Status"})
-
- {:ok, r4_1} =
- CommonAPI.post(u1, %{
- status: "@#{u4.nickname} reply from u1 to u4",
- in_reply_to_status_id: a4.id
- })
-
- {:ok, r4_2} =
- CommonAPI.post(u2, %{
- status: "@#{u4.nickname} reply from u2 to u4",
- in_reply_to_status_id: a4.id
- })
-
- {:ok, r4_3} =
- CommonAPI.post(u3, %{
- status: "@#{u4.nickname} reply from u3 to u4",
- in_reply_to_status_id: a4.id
- })
-
- {:ok,
- users: %{u1: u1, u2: u2, u3: u3, u4: u4},
- activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id},
- u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id},
- u2: %{r1: r2_1.id, r2: r2_2.id, r3: r2_3.id},
- u3: %{r1: r3_1.id, r2: r3_2.id, r3: r3_3.id},
- u4: %{r1: r4_1.id, r2: r4_2.id, r3: r4_3.id}}
- end
-
- defp private_messages(_) do
- [u1, u2, u3, u4] = insert_list(4, :user)
- {:ok, u1} = User.follow(u1, u2)
- {:ok, u2} = User.follow(u2, u1)
- {:ok, u1} = User.follow(u1, u3)
- {:ok, u3} = User.follow(u3, u1)
- {:ok, u1} = User.follow(u1, u4)
- {:ok, u4} = User.follow(u4, u1)
-
- {:ok, u2} = User.follow(u2, u3)
- {:ok, u3} = User.follow(u3, u2)
-
- {:ok, a1} = CommonAPI.post(u1, %{status: "Status", visibility: "private"})
-
- {:ok, r1_1} =
- CommonAPI.post(u2, %{
- status: "@#{u1.nickname} reply from u2 to u1",
- in_reply_to_status_id: a1.id,
- visibility: "private"
- })
-
- {:ok, r1_2} =
- CommonAPI.post(u3, %{
- status: "@#{u1.nickname} reply from u3 to u1",
- in_reply_to_status_id: a1.id,
- visibility: "private"
- })
-
- {:ok, r1_3} =
- CommonAPI.post(u4, %{
- status: "@#{u1.nickname} reply from u4 to u1",
- in_reply_to_status_id: a1.id,
- visibility: "private"
- })
-
- {:ok, a2} = CommonAPI.post(u2, %{status: "Status", visibility: "private"})
-
- {:ok, r2_1} =
- CommonAPI.post(u1, %{
- status: "@#{u2.nickname} reply from u1 to u2",
- in_reply_to_status_id: a2.id,
- visibility: "private"
- })
-
- {:ok, r2_2} =
- CommonAPI.post(u3, %{
- status: "@#{u2.nickname} reply from u3 to u2",
- in_reply_to_status_id: a2.id,
- visibility: "private"
- })
-
- {:ok, a3} = CommonAPI.post(u3, %{status: "Status", visibility: "private"})
-
- {:ok, r3_1} =
- CommonAPI.post(u1, %{
- status: "@#{u3.nickname} reply from u1 to u3",
- in_reply_to_status_id: a3.id,
- visibility: "private"
- })
-
- {:ok, r3_2} =
- CommonAPI.post(u2, %{
- status: "@#{u3.nickname} reply from u2 to u3",
- in_reply_to_status_id: a3.id,
- visibility: "private"
- })
-
- {:ok, a4} = CommonAPI.post(u4, %{status: "Status", visibility: "private"})
-
- {:ok, r4_1} =
- CommonAPI.post(u1, %{
- status: "@#{u4.nickname} reply from u1 to u4",
- in_reply_to_status_id: a4.id,
- visibility: "private"
- })
-
- {:ok,
- users: %{u1: u1, u2: u2, u3: u3, u4: u4},
- activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id},
- u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id},
- u2: %{r1: r2_1.id, r2: r2_2.id},
- u3: %{r1: r3_1.id, r2: r3_2.id},
- u4: %{r1: r4_1.id}}
- end
-
- describe "maybe_update_follow_information/1" do
- setup do
- clear_config([:instance, :external_user_synchronization], true)
-
- user = %{
- local: false,
- ap_id: "https://gensokyo.2hu/users/raymoo",
- following_address: "https://gensokyo.2hu/users/following",
- follower_address: "https://gensokyo.2hu/users/followers",
- type: "Person"
- }
-
- %{user: user}
- end
-
- test "logs an error when it can't fetch the info", %{user: user} do
- assert capture_log(fn ->
- ActivityPub.maybe_update_follow_information(user)
- end) =~ "Follower/Following counter update for #{user.ap_id} failed"
- end
-
- test "just returns the input if the user type is Application", %{
- user: user
- } do
- user =
- user
- |> Map.put(:type, "Application")
-
- refute capture_log(fn ->
- assert ^user = ActivityPub.maybe_update_follow_information(user)
- end) =~ "Follower/Following counter update for #{user.ap_id} failed"
- end
-
- test "it just returns the input if the user has no following/follower addresses", %{
- user: user
- } do
- user =
- user
- |> Map.put(:following_address, nil)
- |> Map.put(:follower_address, nil)
-
- refute capture_log(fn ->
- assert ^user = ActivityPub.maybe_update_follow_information(user)
- end) =~ "Follower/Following counter update for #{user.ap_id} failed"
- end
- end
-
- describe "global activity expiration" do
- setup do: clear_config([:mrf, :policies])
-
- test "creates an activity expiration for local Create activities" do
- Pleroma.Config.put(
- [:mrf, :policies],
- Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy
- )
-
- {:ok, %{id: id_create}} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
- {:ok, _follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"})
-
- assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all()
- end
- end
-
- describe "handling of clashing nicknames" do
- test "renames an existing user with a clashing nickname and a different ap id" do
- orig_user =
- insert(
- :user,
- local: false,
- nickname: "admin@mastodon.example.org",
- ap_id: "http://mastodon.example.org/users/harinezumigari"
- )
-
- %{
- nickname: orig_user.nickname,
- ap_id: orig_user.ap_id <> "part_2"
- }
- |> ActivityPub.maybe_handle_clashing_nickname()
-
- user = User.get_by_id(orig_user.id)
-
- assert user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
- end
-
- test "does nothing with a clashing nickname and the same ap id" do
- orig_user =
- insert(
- :user,
- local: false,
- nickname: "admin@mastodon.example.org",
- ap_id: "http://mastodon.example.org/users/harinezumigari"
- )
-
- %{
- nickname: orig_user.nickname,
- ap_id: orig_user.ap_id
- }
- |> ActivityPub.maybe_handle_clashing_nickname()
-
- user = User.get_by_id(orig_user.id)
-
- assert user.nickname == orig_user.nickname
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/activity_expiration_policy_test.exs b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs
deleted file mode 100644
index f25cf8b12..000000000
--- a/test/web/activity_pub/mrf/activity_expiration_policy_test.exs
+++ /dev/null
@@ -1,84 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
- use ExUnit.Case, async: true
- alias Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy
-
- @id Pleroma.Web.Endpoint.url() <> "/activities/cofe"
- @local_actor Pleroma.Web.Endpoint.url() <> "/users/cofe"
-
- test "adds `expires_at` property" do
- assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
- ActivityExpirationPolicy.filter(%{
- "id" => @id,
- "actor" => @local_actor,
- "type" => "Create",
- "object" => %{"type" => "Note"}
- })
-
- assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364
- end
-
- test "keeps existing `expires_at` if it less than the config setting" do
- expires_at = NaiveDateTime.utc_now() |> Timex.shift(days: 1)
-
- assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} =
- ActivityExpirationPolicy.filter(%{
- "id" => @id,
- "actor" => @local_actor,
- "type" => "Create",
- "expires_at" => expires_at,
- "object" => %{"type" => "Note"}
- })
- end
-
- test "overwrites existing `expires_at` if it greater than the config setting" do
- too_distant_future = NaiveDateTime.utc_now() |> Timex.shift(years: 2)
-
- assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
- ActivityExpirationPolicy.filter(%{
- "id" => @id,
- "actor" => @local_actor,
- "type" => "Create",
- "expires_at" => too_distant_future,
- "object" => %{"type" => "Note"}
- })
-
- assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364
- end
-
- test "ignores remote activities" do
- assert {:ok, activity} =
- ActivityExpirationPolicy.filter(%{
- "id" => "https://example.com/123",
- "actor" => "https://example.com/users/cofe",
- "type" => "Create",
- "object" => %{"type" => "Note"}
- })
-
- refute Map.has_key?(activity, "expires_at")
- end
-
- test "ignores non-Create/Note activities" do
- assert {:ok, activity} =
- ActivityExpirationPolicy.filter(%{
- "id" => "https://example.com/123",
- "actor" => "https://example.com/users/cofe",
- "type" => "Follow"
- })
-
- refute Map.has_key?(activity, "expires_at")
-
- assert {:ok, activity} =
- ActivityExpirationPolicy.filter(%{
- "id" => "https://example.com/123",
- "actor" => "https://example.com/users/cofe",
- "type" => "Create",
- "object" => %{"type" => "Cofe"}
- })
-
- refute Map.has_key?(activity, "expires_at")
- end
-end
diff --git a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs
deleted file mode 100644
index 3c795f5ac..000000000
--- a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs
+++ /dev/null
@@ -1,72 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
- use Pleroma.DataCase
- import Pleroma.Factory
-
- alias Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy
-
- describe "blocking based on attributes" do
- test "matches followbots by nickname" do
- actor = insert(:user, %{nickname: "followbot@example.com"})
- target = insert(:user)
-
- message = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "type" => "Follow",
- "actor" => actor.ap_id,
- "object" => target.ap_id,
- "id" => "https://example.com/activities/1234"
- }
-
- assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
- end
-
- test "matches followbots by display name" do
- actor = insert(:user, %{name: "Federation Bot"})
- target = insert(:user)
-
- message = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "type" => "Follow",
- "actor" => actor.ap_id,
- "object" => target.ap_id,
- "id" => "https://example.com/activities/1234"
- }
-
- assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
- end
- end
-
- test "it allows non-followbots" do
- actor = insert(:user)
- target = insert(:user)
-
- message = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "type" => "Follow",
- "actor" => actor.ap_id,
- "object" => target.ap_id,
- "id" => "https://example.com/activities/1234"
- }
-
- {:ok, _} = AntiFollowbotPolicy.filter(message)
- end
-
- test "it gracefully handles nil display names" do
- actor = insert(:user, %{name: nil})
- target = insert(:user)
-
- message = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "type" => "Follow",
- "actor" => actor.ap_id,
- "object" => target.ap_id,
- "id" => "https://example.com/activities/1234"
- }
-
- {:ok, _} = AntiFollowbotPolicy.filter(message)
- end
-end
diff --git a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs
deleted file mode 100644
index 6867c9853..000000000
--- a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs
+++ /dev/null
@@ -1,166 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
- use Pleroma.DataCase
- import Pleroma.Factory
- import ExUnit.CaptureLog
-
- alias Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy
-
- @linkless_message %{
- "type" => "Create",
- "object" => %{
- "content" => "hi world!"
- }
- }
-
- @linkful_message %{
- "type" => "Create",
- "object" => %{
- "content" => "<a href='https://example.com'>hi world!</a>"
- }
- }
-
- @response_message %{
- "type" => "Create",
- "object" => %{
- "name" => "yes",
- "type" => "Answer"
- }
- }
-
- describe "with new user" do
- test "it allows posts without links" do
- user = insert(:user, local: false)
-
- assert user.note_count == 0
-
- message =
- @linkless_message
- |> Map.put("actor", user.ap_id)
-
- {:ok, _message} = AntiLinkSpamPolicy.filter(message)
- end
-
- test "it disallows posts with links" do
- user = insert(:user, local: false)
-
- assert user.note_count == 0
-
- message =
- @linkful_message
- |> Map.put("actor", user.ap_id)
-
- {:reject, _} = AntiLinkSpamPolicy.filter(message)
- end
-
- test "it allows posts with links for local users" do
- user = insert(:user)
-
- assert user.note_count == 0
-
- message =
- @linkful_message
- |> Map.put("actor", user.ap_id)
-
- {:ok, _message} = AntiLinkSpamPolicy.filter(message)
- end
- end
-
- describe "with old user" do
- test "it allows posts without links" do
- user = insert(:user, note_count: 1)
-
- assert user.note_count == 1
-
- message =
- @linkless_message
- |> Map.put("actor", user.ap_id)
-
- {:ok, _message} = AntiLinkSpamPolicy.filter(message)
- end
-
- test "it allows posts with links" do
- user = insert(:user, note_count: 1)
-
- assert user.note_count == 1
-
- message =
- @linkful_message
- |> Map.put("actor", user.ap_id)
-
- {:ok, _message} = AntiLinkSpamPolicy.filter(message)
- end
- end
-
- describe "with followed new user" do
- test "it allows posts without links" do
- user = insert(:user, follower_count: 1)
-
- assert user.follower_count == 1
-
- message =
- @linkless_message
- |> Map.put("actor", user.ap_id)
-
- {:ok, _message} = AntiLinkSpamPolicy.filter(message)
- end
-
- test "it allows posts with links" do
- user = insert(:user, follower_count: 1)
-
- assert user.follower_count == 1
-
- message =
- @linkful_message
- |> Map.put("actor", user.ap_id)
-
- {:ok, _message} = AntiLinkSpamPolicy.filter(message)
- end
- end
-
- describe "with unknown actors" do
- setup do
- Tesla.Mock.mock(fn
- %{method: :get, url: "http://invalid.actor"} ->
- %Tesla.Env{status: 500, body: ""}
- end)
-
- :ok
- end
-
- test "it rejects posts without links" do
- message =
- @linkless_message
- |> Map.put("actor", "http://invalid.actor")
-
- assert capture_log(fn ->
- {:reject, _} = AntiLinkSpamPolicy.filter(message)
- end) =~ "[error] Could not decode user at fetch http://invalid.actor"
- end
-
- test "it rejects posts with links" do
- message =
- @linkful_message
- |> Map.put("actor", "http://invalid.actor")
-
- assert capture_log(fn ->
- {:reject, _} = AntiLinkSpamPolicy.filter(message)
- end) =~ "[error] Could not decode user at fetch http://invalid.actor"
- end
- end
-
- describe "with contentless-objects" do
- test "it does not reject them or error out" do
- user = insert(:user, note_count: 1)
-
- message =
- @response_message
- |> Map.put("actor", user.ap_id)
-
- {:ok, _message} = AntiLinkSpamPolicy.filter(message)
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/ensure_re_prepended_test.exs b/test/web/activity_pub/mrf/ensure_re_prepended_test.exs
deleted file mode 100644
index 9a283f27d..000000000
--- a/test/web/activity_pub/mrf/ensure_re_prepended_test.exs
+++ /dev/null
@@ -1,92 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.MRF.EnsureRePrepended
-
- describe "rewrites summary" do
- test "it adds `re:` to summary object when child summary and parent summary equal" do
- message = %{
- "type" => "Create",
- "object" => %{
- "summary" => "object-summary",
- "inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
- }
- }
-
- assert {:ok, res} = EnsureRePrepended.filter(message)
- assert res["object"]["summary"] == "re: object-summary"
- end
-
- test "it adds `re:` to summary object when child summary containts re-subject of parent summary " do
- message = %{
- "type" => "Create",
- "object" => %{
- "summary" => "object-summary",
- "inReplyTo" => %Activity{object: %Object{data: %{"summary" => "re: object-summary"}}}
- }
- }
-
- assert {:ok, res} = EnsureRePrepended.filter(message)
- assert res["object"]["summary"] == "re: object-summary"
- end
- end
-
- describe "skip filter" do
- test "it skip if type isn't 'Create'" do
- message = %{
- "type" => "Annotation",
- "object" => %{"summary" => "object-summary"}
- }
-
- assert {:ok, res} = EnsureRePrepended.filter(message)
- assert res == message
- end
-
- test "it skip if summary is empty" do
- message = %{
- "type" => "Create",
- "object" => %{
- "inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
- }
- }
-
- assert {:ok, res} = EnsureRePrepended.filter(message)
- assert res == message
- end
-
- test "it skip if inReplyTo is empty" do
- message = %{"type" => "Create", "object" => %{"summary" => "summary"}}
- assert {:ok, res} = EnsureRePrepended.filter(message)
- assert res == message
- end
-
- test "it skip if parent and child summary isn't equal" do
- message = %{
- "type" => "Create",
- "object" => %{
- "summary" => "object-summary",
- "inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
- }
- }
-
- assert {:ok, res} = EnsureRePrepended.filter(message)
- assert res == message
- end
-
- test "it skips if the object is only a reference" do
- message = %{
- "type" => "Create",
- "object" => "somereference"
- }
-
- assert {:ok, res} = EnsureRePrepended.filter(message)
- assert res == message
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/hellthread_policy_test.exs b/test/web/activity_pub/mrf/hellthread_policy_test.exs
deleted file mode 100644
index 26f5bcdaa..000000000
--- a/test/web/activity_pub/mrf/hellthread_policy_test.exs
+++ /dev/null
@@ -1,92 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do
- use Pleroma.DataCase
- import Pleroma.Factory
-
- import Pleroma.Web.ActivityPub.MRF.HellthreadPolicy
-
- alias Pleroma.Web.CommonAPI
-
- setup do
- user = insert(:user)
-
- message = %{
- "actor" => user.ap_id,
- "cc" => [user.follower_address],
- "type" => "Create",
- "to" => [
- "https://www.w3.org/ns/activitystreams#Public",
- "https://instance.tld/users/user1",
- "https://instance.tld/users/user2",
- "https://instance.tld/users/user3"
- ],
- "object" => %{
- "type" => "Note"
- }
- }
-
- [user: user, message: message]
- end
-
- setup do: clear_config(:mrf_hellthread)
-
- test "doesn't die on chat messages" do
- Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 2, reject_threshold: 0})
-
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post_chat_message(user, other_user, "moin")
-
- assert {:ok, _} = filter(activity.data)
- end
-
- describe "reject" do
- test "rejects the message if the recipient count is above reject_threshold", %{
- message: message
- } do
- Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 2})
-
- assert {:reject, "[HellthreadPolicy] 3 recipients is over the limit of 2"} ==
- filter(message)
- end
-
- test "does not reject the message if the recipient count is below reject_threshold", %{
- message: message
- } do
- Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
-
- assert {:ok, ^message} = filter(message)
- end
- end
-
- describe "delist" do
- test "delists the message if the recipient count is above delist_threshold", %{
- user: user,
- message: message
- } do
- Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 2, reject_threshold: 0})
-
- {:ok, message} = filter(message)
- assert user.follower_address in message["to"]
- assert "https://www.w3.org/ns/activitystreams#Public" in message["cc"]
- end
-
- test "does not delist the message if the recipient count is below delist_threshold", %{
- message: message
- } do
- Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 4, reject_threshold: 0})
-
- assert {:ok, ^message} = filter(message)
- end
- end
-
- test "excludes follower collection and public URI from threshold count", %{message: message} do
- Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
-
- assert {:ok, ^message} = filter(message)
- end
-end
diff --git a/test/web/activity_pub/mrf/keyword_policy_test.exs b/test/web/activity_pub/mrf/keyword_policy_test.exs
deleted file mode 100644
index b3d0f3d90..000000000
--- a/test/web/activity_pub/mrf/keyword_policy_test.exs
+++ /dev/null
@@ -1,225 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.MRF.KeywordPolicy
-
- setup do: clear_config(:mrf_keyword)
-
- setup do
- Pleroma.Config.put([:mrf_keyword], %{reject: [], federated_timeline_removal: [], replace: []})
- end
-
- describe "rejecting based on keywords" do
- test "rejects if string matches in content" do
- Pleroma.Config.put([:mrf_keyword, :reject], ["pun"])
-
- message = %{
- "type" => "Create",
- "object" => %{
- "content" => "just a daily reminder that compLAINer is a good pun",
- "summary" => ""
- }
- }
-
- assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} =
- KeywordPolicy.filter(message)
- end
-
- test "rejects if string matches in summary" do
- Pleroma.Config.put([:mrf_keyword, :reject], ["pun"])
-
- message = %{
- "type" => "Create",
- "object" => %{
- "summary" => "just a daily reminder that compLAINer is a good pun",
- "content" => ""
- }
- }
-
- assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} =
- KeywordPolicy.filter(message)
- end
-
- test "rejects if regex matches in content" do
- Pleroma.Config.put([:mrf_keyword, :reject], [~r/comp[lL][aA][iI][nN]er/])
-
- assert true ==
- Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
- message = %{
- "type" => "Create",
- "object" => %{
- "content" => "just a daily reminder that #{content} is a good pun",
- "summary" => ""
- }
- }
-
- {:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
- KeywordPolicy.filter(message)
- end)
- end
-
- test "rejects if regex matches in summary" do
- Pleroma.Config.put([:mrf_keyword, :reject], [~r/comp[lL][aA][iI][nN]er/])
-
- assert true ==
- Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
- message = %{
- "type" => "Create",
- "object" => %{
- "summary" => "just a daily reminder that #{content} is a good pun",
- "content" => ""
- }
- }
-
- {:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
- KeywordPolicy.filter(message)
- end)
- end
- end
-
- describe "delisting from ftl based on keywords" do
- test "delists if string matches in content" do
- Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], ["pun"])
-
- message = %{
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "type" => "Create",
- "object" => %{
- "content" => "just a daily reminder that compLAINer is a good pun",
- "summary" => ""
- }
- }
-
- {:ok, result} = KeywordPolicy.filter(message)
- assert ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"]
- refute ["https://www.w3.org/ns/activitystreams#Public"] == result["to"]
- end
-
- test "delists if string matches in summary" do
- Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], ["pun"])
-
- message = %{
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "type" => "Create",
- "object" => %{
- "summary" => "just a daily reminder that compLAINer is a good pun",
- "content" => ""
- }
- }
-
- {:ok, result} = KeywordPolicy.filter(message)
- assert ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"]
- refute ["https://www.w3.org/ns/activitystreams#Public"] == result["to"]
- end
-
- test "delists if regex matches in content" do
- Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], [~r/comp[lL][aA][iI][nN]er/])
-
- assert true ==
- Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
- message = %{
- "type" => "Create",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => %{
- "content" => "just a daily reminder that #{content} is a good pun",
- "summary" => ""
- }
- }
-
- {:ok, result} = KeywordPolicy.filter(message)
-
- ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"] and
- not (["https://www.w3.org/ns/activitystreams#Public"] == result["to"])
- end)
- end
-
- test "delists if regex matches in summary" do
- Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], [~r/comp[lL][aA][iI][nN]er/])
-
- assert true ==
- Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
- message = %{
- "type" => "Create",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => %{
- "summary" => "just a daily reminder that #{content} is a good pun",
- "content" => ""
- }
- }
-
- {:ok, result} = KeywordPolicy.filter(message)
-
- ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"] and
- not (["https://www.w3.org/ns/activitystreams#Public"] == result["to"])
- end)
- end
- end
-
- describe "replacing keywords" do
- test "replaces keyword if string matches in content" do
- Pleroma.Config.put([:mrf_keyword, :replace], [{"opensource", "free software"}])
-
- message = %{
- "type" => "Create",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => %{"content" => "ZFS is opensource", "summary" => ""}
- }
-
- {:ok, %{"object" => %{"content" => result}}} = KeywordPolicy.filter(message)
- assert result == "ZFS is free software"
- end
-
- test "replaces keyword if string matches in summary" do
- Pleroma.Config.put([:mrf_keyword, :replace], [{"opensource", "free software"}])
-
- message = %{
- "type" => "Create",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => %{"summary" => "ZFS is opensource", "content" => ""}
- }
-
- {:ok, %{"object" => %{"summary" => result}}} = KeywordPolicy.filter(message)
- assert result == "ZFS is free software"
- end
-
- test "replaces keyword if regex matches in content" do
- Pleroma.Config.put([:mrf_keyword, :replace], [
- {~r/open(-|\s)?source\s?(software)?/, "free software"}
- ])
-
- assert true ==
- Enum.all?(["opensource", "open-source", "open source"], fn content ->
- message = %{
- "type" => "Create",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => %{"content" => "ZFS is #{content}", "summary" => ""}
- }
-
- {:ok, %{"object" => %{"content" => result}}} = KeywordPolicy.filter(message)
- result == "ZFS is free software"
- end)
- end
-
- test "replaces keyword if regex matches in summary" do
- Pleroma.Config.put([:mrf_keyword, :replace], [
- {~r/open(-|\s)?source\s?(software)?/, "free software"}
- ])
-
- assert true ==
- Enum.all?(["opensource", "open-source", "open source"], fn content ->
- message = %{
- "type" => "Create",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => %{"summary" => "ZFS is #{content}", "content" => ""}
- }
-
- {:ok, %{"object" => %{"summary" => result}}} = KeywordPolicy.filter(message)
- result == "ZFS is free software"
- end)
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs b/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs
deleted file mode 100644
index 313d59a66..000000000
--- a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs
+++ /dev/null
@@ -1,51 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
- use Pleroma.DataCase
-
- alias Pleroma.HTTP
- alias Pleroma.Tests.ObanHelpers
- alias Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy
-
- import Mock
-
- @message %{
- "type" => "Create",
- "object" => %{
- "type" => "Note",
- "content" => "content",
- "attachment" => [
- %{"url" => [%{"href" => "http://example.com/image.jpg"}]}
- ]
- }
- }
-
- 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
-
- test "it does nothing when no attachments are present" do
- object =
- @message["object"]
- |> Map.delete("attachment")
-
- message =
- @message
- |> Map.put("object", object)
-
- with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do
- MediaProxyWarmingPolicy.filter(message)
- refute called(HTTP.get(:_, :_, :_))
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/mention_policy_test.exs b/test/web/activity_pub/mrf/mention_policy_test.exs
deleted file mode 100644
index 220309cc9..000000000
--- a/test/web/activity_pub/mrf/mention_policy_test.exs
+++ /dev/null
@@ -1,96 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.MRF.MentionPolicy
-
- setup do: clear_config(:mrf_mention)
-
- test "pass filter if allow list is empty" do
- Pleroma.Config.delete([:mrf_mention])
-
- message = %{
- "type" => "Create",
- "to" => ["https://example.com/ok"],
- "cc" => ["https://example.com/blocked"]
- }
-
- assert MentionPolicy.filter(message) == {:ok, message}
- end
-
- describe "allow" do
- test "empty" do
- Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
-
- message = %{
- "type" => "Create"
- }
-
- assert MentionPolicy.filter(message) == {:ok, message}
- end
-
- test "to" do
- Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
-
- message = %{
- "type" => "Create",
- "to" => ["https://example.com/ok"]
- }
-
- assert MentionPolicy.filter(message) == {:ok, message}
- end
-
- test "cc" do
- Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
-
- message = %{
- "type" => "Create",
- "cc" => ["https://example.com/ok"]
- }
-
- assert MentionPolicy.filter(message) == {:ok, message}
- end
-
- test "both" do
- Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
-
- message = %{
- "type" => "Create",
- "to" => ["https://example.com/ok"],
- "cc" => ["https://example.com/ok2"]
- }
-
- assert MentionPolicy.filter(message) == {:ok, message}
- end
- end
-
- describe "deny" do
- test "to" do
- Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
-
- message = %{
- "type" => "Create",
- "to" => ["https://example.com/blocked"]
- }
-
- assert MentionPolicy.filter(message) ==
- {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
- end
-
- test "cc" do
- Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
-
- message = %{
- "type" => "Create",
- "to" => ["https://example.com/ok"],
- "cc" => ["https://example.com/blocked"]
- }
-
- assert MentionPolicy.filter(message) ==
- {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/mrf_test.exs b/test/web/activity_pub/mrf/mrf_test.exs
deleted file mode 100644
index a63b25423..000000000
--- a/test/web/activity_pub/mrf/mrf_test.exs
+++ /dev/null
@@ -1,84 +0,0 @@
-defmodule Pleroma.Web.ActivityPub.MRFTest do
- use ExUnit.Case, async: true
- use Pleroma.Tests.Helpers
- alias Pleroma.Web.ActivityPub.MRF
-
- test "subdomains_regex/1" do
- assert MRF.subdomains_regex(["unsafe.tld", "*.unsafe.tld"]) == [
- ~r/^unsafe.tld$/i,
- ~r/^(.*\.)*unsafe.tld$/i
- ]
- end
-
- describe "subdomain_match/2" do
- test "common domains" do
- regexes = MRF.subdomains_regex(["unsafe.tld", "unsafe2.tld"])
-
- assert regexes == [~r/^unsafe.tld$/i, ~r/^unsafe2.tld$/i]
-
- assert MRF.subdomain_match?(regexes, "unsafe.tld")
- assert MRF.subdomain_match?(regexes, "unsafe2.tld")
-
- refute MRF.subdomain_match?(regexes, "example.com")
- end
-
- test "wildcard domains with one subdomain" do
- regexes = MRF.subdomains_regex(["*.unsafe.tld"])
-
- assert regexes == [~r/^(.*\.)*unsafe.tld$/i]
-
- assert MRF.subdomain_match?(regexes, "unsafe.tld")
- assert MRF.subdomain_match?(regexes, "sub.unsafe.tld")
- refute MRF.subdomain_match?(regexes, "anotherunsafe.tld")
- refute MRF.subdomain_match?(regexes, "unsafe.tldanother")
- end
-
- test "wildcard domains with two subdomains" do
- regexes = MRF.subdomains_regex(["*.unsafe.tld"])
-
- assert regexes == [~r/^(.*\.)*unsafe.tld$/i]
-
- assert MRF.subdomain_match?(regexes, "unsafe.tld")
- assert MRF.subdomain_match?(regexes, "sub.sub.unsafe.tld")
- refute MRF.subdomain_match?(regexes, "sub.anotherunsafe.tld")
- refute MRF.subdomain_match?(regexes, "sub.unsafe.tldanother")
- end
-
- test "matches are case-insensitive" do
- regexes = MRF.subdomains_regex(["UnSafe.TLD", "UnSAFE2.Tld"])
-
- assert regexes == [~r/^UnSafe.TLD$/i, ~r/^UnSAFE2.Tld$/i]
-
- assert MRF.subdomain_match?(regexes, "UNSAFE.TLD")
- assert MRF.subdomain_match?(regexes, "UNSAFE2.TLD")
- assert MRF.subdomain_match?(regexes, "unsafe.tld")
- assert MRF.subdomain_match?(regexes, "unsafe2.tld")
-
- refute MRF.subdomain_match?(regexes, "EXAMPLE.COM")
- refute MRF.subdomain_match?(regexes, "example.com")
- end
- end
-
- describe "describe/0" do
- test "it works as expected with noop policy" do
- expected = %{
- mrf_policies: ["NoOpPolicy"],
- exclusions: false
- }
-
- {:ok, ^expected} = MRF.describe()
- end
-
- test "it works as expected with mock policy" do
- clear_config([:mrf, :policies], [MRFModuleMock])
-
- expected = %{
- mrf_policies: ["MRFModuleMock"],
- mrf_module_mock: "some config data",
- exclusions: false
- }
-
- {:ok, ^expected} = MRF.describe()
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs b/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs
deleted file mode 100644
index 64ea61dd4..000000000
--- a/test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs
+++ /dev/null
@@ -1,37 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do
- use Pleroma.DataCase
- alias Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy
-
- test "it clears content object" do
- message = %{
- "type" => "Create",
- "object" => %{"content" => ".", "attachment" => "image"}
- }
-
- assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
- assert res["object"]["content"] == ""
-
- message = put_in(message, ["object", "content"], "<p>.</p>")
- assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
- assert res["object"]["content"] == ""
- end
-
- @messages [
- %{
- "type" => "Create",
- "object" => %{"content" => "test", "attachment" => "image"}
- },
- %{"type" => "Create", "object" => %{"content" => "."}},
- %{"type" => "Create", "object" => %{"content" => "<p>.</p>"}}
- ]
- test "it skips filter" do
- Enum.each(@messages, fn message ->
- assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
- assert res == message
- end)
- end
-end
diff --git a/test/web/activity_pub/mrf/normalize_markup_test.exs b/test/web/activity_pub/mrf/normalize_markup_test.exs
deleted file mode 100644
index 9b39c45bd..000000000
--- a/test/web/activity_pub/mrf/normalize_markup_test.exs
+++ /dev/null
@@ -1,42 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
- use Pleroma.DataCase
- alias Pleroma.Web.ActivityPub.MRF.NormalizeMarkup
-
- @html_sample """
- <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/" rel="tag noallowed">example.com</a>
- this is an image: <img src="http://example.com/image.jpg"><br />
- <script>alert('hacked')</script>
- """
-
- test "it filter html tags" 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 &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}}
-
- assert {:ok, res} = NormalizeMarkup.filter(message)
- assert res["object"]["content"] == expected
- end
-
- test "it skips filter if type isn't `Create`" do
- message = %{"type" => "Note", "object" => %{}}
-
- assert {:ok, res} = NormalizeMarkup.filter(message)
- assert res == message
- end
-end
diff --git a/test/web/activity_pub/mrf/object_age_policy_test.exs b/test/web/activity_pub/mrf/object_age_policy_test.exs
deleted file mode 100644
index cf6acc9a2..000000000
--- a/test/web/activity_pub/mrf/object_age_policy_test.exs
+++ /dev/null
@@ -1,148 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
- use Pleroma.DataCase
- alias Pleroma.Config
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy
- alias Pleroma.Web.ActivityPub.Visibility
-
- setup do:
- clear_config(:mrf_object_age,
- threshold: 172_800,
- actions: [:delist, :strip_followers]
- )
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- defp get_old_message do
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- end
-
- defp get_new_message do
- old_message = get_old_message()
-
- new_object =
- old_message
- |> Map.get("object")
- |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
-
- old_message
- |> Map.put("object", new_object)
- end
-
- describe "with reject action" do
- test "works with objects with empty to or cc fields" do
- Config.put([:mrf_object_age, :actions], [:reject])
-
- data =
- get_old_message()
- |> Map.put("cc", nil)
- |> Map.put("to", nil)
-
- assert match?({:reject, _}, ObjectAgePolicy.filter(data))
- end
-
- test "it rejects an old post" do
- Config.put([:mrf_object_age, :actions], [:reject])
-
- data = get_old_message()
-
- assert match?({:reject, _}, ObjectAgePolicy.filter(data))
- end
-
- test "it allows a new post" do
- Config.put([:mrf_object_age, :actions], [:reject])
-
- data = get_new_message()
-
- assert match?({:ok, _}, ObjectAgePolicy.filter(data))
- end
- end
-
- describe "with delist action" do
- test "works with objects with empty to or cc fields" do
- Config.put([:mrf_object_age, :actions], [:delist])
-
- data =
- get_old_message()
- |> Map.put("cc", nil)
- |> Map.put("to", nil)
-
- {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
-
- {:ok, data} = ObjectAgePolicy.filter(data)
-
- assert Visibility.get_visibility(%{data: data}) == "unlisted"
- end
-
- test "it delists an old post" do
- Config.put([:mrf_object_age, :actions], [:delist])
-
- data = get_old_message()
-
- {: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 = get_new_message()
-
- {:ok, _user} = User.get_or_fetch_by_ap_id(data["actor"])
-
- assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))
- end
- end
-
- describe "with strip_followers action" do
- test "works with objects with empty to or cc fields" do
- Config.put([:mrf_object_age, :actions], [:strip_followers])
-
- data =
- get_old_message()
- |> Map.put("cc", nil)
- |> Map.put("to", nil)
-
- {:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
-
- {:ok, data} = ObjectAgePolicy.filter(data)
-
- refute user.follower_address in data["to"]
- refute user.follower_address in data["cc"]
- end
-
- test "it strips followers collections from an old post" do
- Config.put([:mrf_object_age, :actions], [:strip_followers])
-
- data = get_old_message()
-
- {: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 = get_new_message()
-
- {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
-
- assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/reject_non_public_test.exs b/test/web/activity_pub/mrf/reject_non_public_test.exs
deleted file mode 100644
index 58b46b9a2..000000000
--- a/test/web/activity_pub/mrf/reject_non_public_test.exs
+++ /dev/null
@@ -1,100 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do
- use Pleroma.DataCase
- import Pleroma.Factory
-
- alias Pleroma.Web.ActivityPub.MRF.RejectNonPublic
-
- setup do: clear_config([:mrf_rejectnonpublic])
-
- describe "public message" do
- test "it's allowed when address is public" do
- actor = insert(:user, follower_address: "test-address")
-
- message = %{
- "actor" => actor.ap_id,
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
- "type" => "Create"
- }
-
- assert {:ok, message} = RejectNonPublic.filter(message)
- end
-
- test "it's allowed when cc address contain public address" do
- actor = insert(:user, follower_address: "test-address")
-
- message = %{
- "actor" => actor.ap_id,
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
- "type" => "Create"
- }
-
- assert {:ok, message} = RejectNonPublic.filter(message)
- end
- end
-
- describe "followers message" do
- test "it's allowed when addrer of message in the follower addresses of user and it enabled in config" do
- actor = insert(:user, follower_address: "test-address")
-
- message = %{
- "actor" => actor.ap_id,
- "to" => ["test-address"],
- "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
- "type" => "Create"
- }
-
- Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], true)
- assert {:ok, message} = RejectNonPublic.filter(message)
- end
-
- test "it's rejected when addrer of message in the follower addresses of user and it disabled in config" do
- actor = insert(:user, follower_address: "test-address")
-
- message = %{
- "actor" => actor.ap_id,
- "to" => ["test-address"],
- "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
- "type" => "Create"
- }
-
- Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], false)
- assert {:reject, _} = RejectNonPublic.filter(message)
- end
- end
-
- describe "direct message" do
- test "it's allows when direct messages are allow" do
- actor = insert(:user)
-
- message = %{
- "actor" => actor.ap_id,
- "to" => ["https://www.w3.org/ns/activitystreams#Publid"],
- "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
- "type" => "Create"
- }
-
- Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], true)
- assert {:ok, message} = RejectNonPublic.filter(message)
- end
-
- test "it's reject when direct messages aren't allow" do
- actor = insert(:user)
-
- message = %{
- "actor" => actor.ap_id,
- "to" => ["https://www.w3.org/ns/activitystreams#Publid~~~"],
- "cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
- "type" => "Create"
- }
-
- Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], false)
- assert {:reject, _} = RejectNonPublic.filter(message)
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs
deleted file mode 100644
index d7dde62c4..000000000
--- a/test/web/activity_pub/mrf/simple_policy_test.exs
+++ /dev/null
@@ -1,539 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
- use Pleroma.DataCase
- import Pleroma.Factory
- alias Pleroma.Config
- alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
- alias Pleroma.Web.CommonAPI
-
- setup do:
- clear_config(:mrf_simple,
- media_removal: [],
- media_nsfw: [],
- federated_timeline_removal: [],
- report_removal: [],
- reject: [],
- followers_only: [],
- accept: [],
- avatar_removal: [],
- banner_removal: [],
- reject_deletes: []
- )
-
- describe "when :media_removal" do
- test "is empty" do
- Config.put([:mrf_simple, :media_removal], [])
- media_message = build_media_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(media_message) == {:ok, media_message}
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "has a matching host" do
- Config.put([:mrf_simple, :media_removal], ["remote.instance"])
- media_message = build_media_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(media_message) ==
- {:ok,
- media_message
- |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "match with wildcard domain" do
- Config.put([:mrf_simple, :media_removal], ["*.remote.instance"])
- media_message = build_media_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(media_message) ==
- {:ok,
- media_message
- |> Map.put("object", Map.delete(media_message["object"], "attachment"))}
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
- end
-
- describe "when :media_nsfw" do
- test "is empty" do
- Config.put([:mrf_simple, :media_nsfw], [])
- media_message = build_media_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(media_message) == {:ok, media_message}
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "has a matching host" do
- Config.put([:mrf_simple, :media_nsfw], ["remote.instance"])
- media_message = build_media_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(media_message) ==
- {:ok,
- media_message
- |> put_in(["object", "tag"], ["foo", "nsfw"])
- |> put_in(["object", "sensitive"], true)}
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "match with wildcard domain" do
- Config.put([:mrf_simple, :media_nsfw], ["*.remote.instance"])
- media_message = build_media_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(media_message) ==
- {:ok,
- media_message
- |> put_in(["object", "tag"], ["foo", "nsfw"])
- |> put_in(["object", "sensitive"], true)}
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
- end
-
- defp build_media_message do
- %{
- "actor" => "https://remote.instance/users/bob",
- "type" => "Create",
- "object" => %{
- "attachment" => [%{}],
- "tag" => ["foo"],
- "sensitive" => false
- }
- }
- end
-
- describe "when :report_removal" do
- test "is empty" do
- Config.put([:mrf_simple, :report_removal], [])
- report_message = build_report_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(report_message) == {:ok, report_message}
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "has a matching host" do
- Config.put([:mrf_simple, :report_removal], ["remote.instance"])
- report_message = build_report_message()
- local_message = build_local_message()
-
- assert {:reject, _} = SimplePolicy.filter(report_message)
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "match with wildcard domain" do
- Config.put([:mrf_simple, :report_removal], ["*.remote.instance"])
- report_message = build_report_message()
- local_message = build_local_message()
-
- assert {:reject, _} = SimplePolicy.filter(report_message)
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
- end
-
- defp build_report_message do
- %{
- "actor" => "https://remote.instance/users/bob",
- "type" => "Flag"
- }
- end
-
- describe "when :federated_timeline_removal" do
- test "is empty" do
- Config.put([:mrf_simple, :federated_timeline_removal], [])
- {_, ftl_message} = build_ftl_actor_and_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "has a matching host" do
- {actor, ftl_message} = build_ftl_actor_and_message()
-
- ftl_message_actor_host =
- ftl_message
- |> Map.fetch!("actor")
- |> URI.parse()
- |> Map.fetch!(:host)
-
- Config.put([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
- local_message = build_local_message()
-
- assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
- assert actor.follower_address in ftl_message["to"]
- refute actor.follower_address in ftl_message["cc"]
- refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
- assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "match with wildcard domain" do
- {actor, ftl_message} = build_ftl_actor_and_message()
-
- ftl_message_actor_host =
- ftl_message
- |> Map.fetch!("actor")
- |> URI.parse()
- |> Map.fetch!(:host)
-
- Config.put([:mrf_simple, :federated_timeline_removal], ["*." <> ftl_message_actor_host])
- local_message = build_local_message()
-
- assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
- assert actor.follower_address in ftl_message["to"]
- refute actor.follower_address in ftl_message["cc"]
- refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
- assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "has a matching host but only as:Public in to" do
- {_actor, ftl_message} = build_ftl_actor_and_message()
-
- ftl_message_actor_host =
- ftl_message
- |> Map.fetch!("actor")
- |> URI.parse()
- |> Map.fetch!(:host)
-
- ftl_message = Map.put(ftl_message, "cc", [])
-
- Config.put([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
-
- assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
- refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
- assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
- end
- end
-
- defp build_ftl_actor_and_message do
- actor = insert(:user)
-
- {actor,
- %{
- "actor" => actor.ap_id,
- "to" => ["https://www.w3.org/ns/activitystreams#Public", "http://foo.bar/baz"],
- "cc" => [actor.follower_address, "http://foo.bar/qux"]
- }}
- end
-
- describe "when :reject" do
- test "is empty" do
- Config.put([:mrf_simple, :reject], [])
-
- remote_message = build_remote_message()
-
- assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
- end
-
- test "activity has a matching host" do
- Config.put([:mrf_simple, :reject], ["remote.instance"])
-
- remote_message = build_remote_message()
-
- assert {:reject, _} = SimplePolicy.filter(remote_message)
- end
-
- test "activity matches with wildcard domain" do
- Config.put([:mrf_simple, :reject], ["*.remote.instance"])
-
- remote_message = build_remote_message()
-
- assert {:reject, _} = SimplePolicy.filter(remote_message)
- end
-
- test "actor has a matching host" do
- Config.put([:mrf_simple, :reject], ["remote.instance"])
-
- remote_user = build_remote_user()
-
- assert {:reject, _} = SimplePolicy.filter(remote_user)
- end
- end
-
- describe "when :followers_only" do
- test "is empty" do
- Config.put([:mrf_simple, :followers_only], [])
- {_, ftl_message} = build_ftl_actor_and_message()
- local_message = build_local_message()
-
- assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- end
-
- test "has a matching host" do
- actor = insert(:user)
- following_user = insert(:user)
- non_following_user = insert(:user)
-
- {:ok, _, _, _} = CommonAPI.follow(following_user, actor)
-
- activity = %{
- "actor" => actor.ap_id,
- "to" => [
- "https://www.w3.org/ns/activitystreams#Public",
- following_user.ap_id,
- non_following_user.ap_id
- ],
- "cc" => [actor.follower_address, "http://foo.bar/qux"]
- }
-
- dm_activity = %{
- "actor" => actor.ap_id,
- "to" => [
- following_user.ap_id,
- non_following_user.ap_id
- ],
- "cc" => []
- }
-
- actor_domain =
- activity
- |> Map.fetch!("actor")
- |> URI.parse()
- |> Map.fetch!(:host)
-
- Config.put([:mrf_simple, :followers_only], [actor_domain])
-
- assert {:ok, new_activity} = SimplePolicy.filter(activity)
- assert actor.follower_address in new_activity["cc"]
- assert following_user.ap_id in new_activity["to"]
- refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["to"]
- refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["cc"]
- refute non_following_user.ap_id in new_activity["to"]
- refute non_following_user.ap_id in new_activity["cc"]
-
- assert {:ok, new_dm_activity} = SimplePolicy.filter(dm_activity)
- assert new_dm_activity["to"] == [following_user.ap_id]
- assert new_dm_activity["cc"] == []
- end
- end
-
- describe "when :accept" do
- test "is empty" do
- Config.put([:mrf_simple, :accept], [])
-
- local_message = build_local_message()
- remote_message = build_remote_message()
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
- end
-
- 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()
- remote_message = build_remote_message()
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- assert {:reject, _} = SimplePolicy.filter(remote_message)
- end
-
- test "activity has a matching host" do
- Config.put([:mrf_simple, :accept], ["remote.instance"])
-
- local_message = build_local_message()
- remote_message = build_remote_message()
-
- assert SimplePolicy.filter(local_message) == {:ok, local_message}
- assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
- end
-
- test "activity matches with wildcard domain" do
- Config.put([:mrf_simple, :accept], ["*.remote.instance"])
-
- local_message = build_local_message()
- remote_message = build_remote_message()
-
- 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
- test "is empty" do
- Config.put([:mrf_simple, :avatar_removal], [])
-
- remote_user = build_remote_user()
-
- assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
- end
-
- test "is not empty but it doesn't have a matching host" do
- Config.put([:mrf_simple, :avatar_removal], ["non.matching.remote"])
-
- remote_user = build_remote_user()
-
- assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
- end
-
- test "has a matching host" do
- Config.put([:mrf_simple, :avatar_removal], ["remote.instance"])
-
- remote_user = build_remote_user()
- {:ok, filtered} = SimplePolicy.filter(remote_user)
-
- refute filtered["icon"]
- end
-
- test "match with wildcard domain" do
- Config.put([:mrf_simple, :avatar_removal], ["*.remote.instance"])
-
- remote_user = build_remote_user()
- {:ok, filtered} = SimplePolicy.filter(remote_user)
-
- refute filtered["icon"]
- end
- end
-
- describe "when :banner_removal" do
- test "is empty" do
- Config.put([:mrf_simple, :banner_removal], [])
-
- remote_user = build_remote_user()
-
- assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
- end
-
- test "is not empty but it doesn't have a matching host" do
- Config.put([:mrf_simple, :banner_removal], ["non.matching.remote"])
-
- remote_user = build_remote_user()
-
- assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
- end
-
- test "has a matching host" do
- Config.put([:mrf_simple, :banner_removal], ["remote.instance"])
-
- remote_user = build_remote_user()
- {:ok, filtered} = SimplePolicy.filter(remote_user)
-
- refute filtered["image"]
- end
-
- test "match with wildcard domain" do
- Config.put([:mrf_simple, :banner_removal], ["*.remote.instance"])
-
- remote_user = build_remote_user()
- {:ok, filtered} = SimplePolicy.filter(remote_user)
-
- refute filtered["image"]
- end
- end
-
- describe "when :reject_deletes is empty" do
- setup do: Config.put([:mrf_simple, :reject_deletes], [])
-
- test "it accepts deletions even from rejected servers" do
- Config.put([:mrf_simple, :reject], ["remote.instance"])
-
- deletion_message = build_remote_deletion_message()
-
- assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
- end
-
- test "it accepts deletions even from non-whitelisted servers" do
- Config.put([:mrf_simple, :accept], ["non.matching.remote"])
-
- deletion_message = build_remote_deletion_message()
-
- assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
- end
- end
-
- describe "when :reject_deletes is not empty but it doesn't have a matching host" do
- setup do: Config.put([:mrf_simple, :reject_deletes], ["non.matching.remote"])
-
- test "it accepts deletions even from rejected servers" do
- Config.put([:mrf_simple, :reject], ["remote.instance"])
-
- deletion_message = build_remote_deletion_message()
-
- assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
- end
-
- test "it accepts deletions even from non-whitelisted servers" do
- Config.put([:mrf_simple, :accept], ["non.matching.remote"])
-
- deletion_message = build_remote_deletion_message()
-
- assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
- end
- end
-
- describe "when :reject_deletes has a matching host" do
- setup do: Config.put([:mrf_simple, :reject_deletes], ["remote.instance"])
-
- test "it rejects the deletion" do
- deletion_message = build_remote_deletion_message()
-
- assert {:reject, _} = SimplePolicy.filter(deletion_message)
- end
- end
-
- describe "when :reject_deletes match with wildcard domain" do
- setup do: Config.put([:mrf_simple, :reject_deletes], ["*.remote.instance"])
-
- test "it rejects the deletion" do
- deletion_message = build_remote_deletion_message()
-
- assert {:reject, _} = SimplePolicy.filter(deletion_message)
- end
- end
-
- defp build_local_message do
- %{
- "actor" => "#{Pleroma.Web.base_url()}/users/alice",
- "to" => [],
- "cc" => []
- }
- end
-
- defp build_remote_message do
- %{"actor" => "https://remote.instance/users/bob"}
- end
-
- defp build_remote_user do
- %{
- "id" => "https://remote.instance/users/bob",
- "icon" => %{
- "url" => "http://example.com/image.jpg",
- "type" => "Image"
- },
- "image" => %{
- "url" => "http://example.com/image.jpg",
- "type" => "Image"
- },
- "type" => "Person"
- }
- end
-
- defp build_remote_deletion_message do
- %{
- "type" => "Delete",
- "actor" => "https://remote.instance/users/bob"
- }
- end
-end
diff --git a/test/web/activity_pub/mrf/steal_emoji_policy_test.exs b/test/web/activity_pub/mrf/steal_emoji_policy_test.exs
deleted file mode 100644
index 3f8222736..000000000
--- a/test/web/activity_pub/mrf/steal_emoji_policy_test.exs
+++ /dev/null
@@ -1,68 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do
- use Pleroma.DataCase
-
- alias Pleroma.Config
- alias Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- setup do
- emoji_path = Path.join(Config.get([:instance, :static_dir]), "emoji/stolen")
- File.rm_rf!(emoji_path)
- File.mkdir!(emoji_path)
-
- Pleroma.Emoji.reload()
-
- on_exit(fn ->
- File.rm_rf!(emoji_path)
- end)
-
- :ok
- end
-
- test "does nothing by default" do
- installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
- refute "firedfox" in installed_emoji
-
- message = %{
- "type" => "Create",
- "object" => %{
- "emoji" => [{"firedfox", "https://example.org/emoji/firedfox.png"}],
- "actor" => "https://example.org/users/admin"
- }
- }
-
- assert {:ok, message} == StealEmojiPolicy.filter(message)
-
- installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
- refute "firedfox" in installed_emoji
- end
-
- test "Steals emoji on unknown shortcode from allowed remote host" do
- installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
- refute "firedfox" in installed_emoji
-
- message = %{
- "type" => "Create",
- "object" => %{
- "emoji" => [{"firedfox", "https://example.org/emoji/firedfox.png"}],
- "actor" => "https://example.org/users/admin"
- }
- }
-
- clear_config([:mrf_steal_emoji, :hosts], ["example.org"])
- clear_config([:mrf_steal_emoji, :size_limit], 284_468)
-
- assert {:ok, message} == StealEmojiPolicy.filter(message)
-
- installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
- assert "firedfox" in installed_emoji
- end
-end
diff --git a/test/web/activity_pub/mrf/subchain_policy_test.exs b/test/web/activity_pub/mrf/subchain_policy_test.exs
deleted file mode 100644
index fff66cb7e..000000000
--- a/test/web/activity_pub/mrf/subchain_policy_test.exs
+++ /dev/null
@@ -1,33 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicyTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.MRF.DropPolicy
- alias Pleroma.Web.ActivityPub.MRF.SubchainPolicy
-
- @message %{
- "actor" => "https://banned.com",
- "type" => "Create",
- "object" => %{"content" => "hi"}
- }
- setup do: 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]
- })
-
- {:reject, _} = SubchainPolicy.filter(@message)
- end
-
- test "it doesn't match and process subchains when the actor doesn't match a configured target" do
- Pleroma.Config.put([:mrf_subchain, :match_actor], %{
- ~r/^https:\/\/borked.com/s => [DropPolicy]
- })
-
- {:ok, _message} = SubchainPolicy.filter(@message)
- end
-end
diff --git a/test/web/activity_pub/mrf/tag_policy_test.exs b/test/web/activity_pub/mrf/tag_policy_test.exs
deleted file mode 100644
index 6ff71d640..000000000
--- a/test/web/activity_pub/mrf/tag_policy_test.exs
+++ /dev/null
@@ -1,123 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
- use Pleroma.DataCase
- import Pleroma.Factory
-
- alias Pleroma.Web.ActivityPub.MRF.TagPolicy
- @public "https://www.w3.org/ns/activitystreams#Public"
-
- describe "mrf_tag:disable-any-subscription" do
- test "rejects message" do
- actor = insert(:user, tags: ["mrf_tag:disable-any-subscription"])
- message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => actor.ap_id}
- assert {:reject, _} = TagPolicy.filter(message)
- end
- end
-
- describe "mrf_tag:disable-remote-subscription" do
- test "rejects non-local follow requests" do
- actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
- follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: false)
- message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
- assert {:reject, _} = TagPolicy.filter(message)
- end
-
- test "allows non-local follow requests" do
- actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
- follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: true)
- message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
- assert {:ok, message} = TagPolicy.filter(message)
- end
- end
-
- describe "mrf_tag:sandbox" do
- test "removes from public timelines" do
- actor = insert(:user, tags: ["mrf_tag:sandbox"])
-
- message = %{
- "actor" => actor.ap_id,
- "type" => "Create",
- "object" => %{},
- "to" => [@public, "f"],
- "cc" => [@public, "d"]
- }
-
- except_message = %{
- "actor" => actor.ap_id,
- "type" => "Create",
- "object" => %{"to" => ["f", actor.follower_address], "cc" => ["d"]},
- "to" => ["f", actor.follower_address],
- "cc" => ["d"]
- }
-
- assert TagPolicy.filter(message) == {:ok, except_message}
- end
- end
-
- describe "mrf_tag:force-unlisted" do
- test "removes from the federated timeline" do
- actor = insert(:user, tags: ["mrf_tag:force-unlisted"])
-
- message = %{
- "actor" => actor.ap_id,
- "type" => "Create",
- "object" => %{},
- "to" => [@public, "f"],
- "cc" => [actor.follower_address, "d"]
- }
-
- except_message = %{
- "actor" => actor.ap_id,
- "type" => "Create",
- "object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]},
- "to" => ["f", actor.follower_address],
- "cc" => ["d", @public]
- }
-
- assert TagPolicy.filter(message) == {:ok, except_message}
- end
- end
-
- describe "mrf_tag:media-strip" do
- test "removes attachments" do
- actor = insert(:user, tags: ["mrf_tag:media-strip"])
-
- message = %{
- "actor" => actor.ap_id,
- "type" => "Create",
- "object" => %{"attachment" => ["file1"]}
- }
-
- except_message = %{
- "actor" => actor.ap_id,
- "type" => "Create",
- "object" => %{}
- }
-
- assert TagPolicy.filter(message) == {:ok, except_message}
- end
- end
-
- describe "mrf_tag:media-force-nsfw" do
- test "Mark as sensitive on presence of attachments" do
- actor = insert(:user, tags: ["mrf_tag:media-force-nsfw"])
-
- message = %{
- "actor" => actor.ap_id,
- "type" => "Create",
- "object" => %{"tag" => ["test"], "attachment" => ["file1"]}
- }
-
- except_message = %{
- "actor" => actor.ap_id,
- "type" => "Create",
- "object" => %{"tag" => ["test", "nsfw"], "attachment" => ["file1"], "sensitive" => true}
- }
-
- assert TagPolicy.filter(message) == {:ok, except_message}
- end
- end
-end
diff --git a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
deleted file mode 100644
index 8e1ad5bc8..000000000
--- a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs
+++ /dev/null
@@ -1,31 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
- use Pleroma.DataCase
- import Pleroma.Factory
-
- alias Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy
-
- setup do: clear_config(:mrf_user_allowlist)
-
- test "pass filter if allow list is empty" do
- actor = insert(:user)
- message = %{"actor" => actor.ap_id}
- assert UserAllowListPolicy.filter(message) == {:ok, message}
- end
-
- test "pass filter if allow list isn't empty and user in allow list" do
- actor = insert(:user)
- Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => [actor.ap_id, "test-ap-id"]})
- message = %{"actor" => actor.ap_id}
- assert UserAllowListPolicy.filter(message) == {:ok, message}
- end
-
- test "rejected if allow list isn't empty and user not in allow list" do
- actor = insert(:user)
- Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => ["test-ap-id"]})
- message = %{"actor" => actor.ap_id}
- assert {:reject, _} = UserAllowListPolicy.filter(message)
- end
-end
diff --git a/test/web/activity_pub/mrf/vocabulary_policy_test.exs b/test/web/activity_pub/mrf/vocabulary_policy_test.exs
deleted file mode 100644
index 2bceb67ee..000000000
--- a/test/web/activity_pub/mrf/vocabulary_policy_test.exs
+++ /dev/null
@@ -1,106 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.MRF.VocabularyPolicy
-
- describe "accept" do
- setup do: clear_config([:mrf_vocabulary, :accept])
-
- test "it accepts based on parent activity type" do
- Pleroma.Config.put([:mrf_vocabulary, :accept], ["Like"])
-
- message = %{
- "type" => "Like",
- "object" => "whatever"
- }
-
- {:ok, ^message} = VocabularyPolicy.filter(message)
- end
-
- test "it accepts based on child object type" do
- Pleroma.Config.put([:mrf_vocabulary, :accept], ["Create", "Note"])
-
- message = %{
- "type" => "Create",
- "object" => %{
- "type" => "Note",
- "content" => "whatever"
- }
- }
-
- {:ok, ^message} = VocabularyPolicy.filter(message)
- end
-
- test "it does not accept disallowed child objects" do
- Pleroma.Config.put([:mrf_vocabulary, :accept], ["Create", "Note"])
-
- message = %{
- "type" => "Create",
- "object" => %{
- "type" => "Article",
- "content" => "whatever"
- }
- }
-
- {:reject, _} = VocabularyPolicy.filter(message)
- end
-
- test "it does not accept disallowed parent types" do
- Pleroma.Config.put([:mrf_vocabulary, :accept], ["Announce", "Note"])
-
- message = %{
- "type" => "Create",
- "object" => %{
- "type" => "Note",
- "content" => "whatever"
- }
- }
-
- {:reject, _} = VocabularyPolicy.filter(message)
- end
- end
-
- describe "reject" do
- setup do: clear_config([:mrf_vocabulary, :reject])
-
- test "it rejects based on parent activity type" do
- Pleroma.Config.put([:mrf_vocabulary, :reject], ["Like"])
-
- message = %{
- "type" => "Like",
- "object" => "whatever"
- }
-
- {:reject, _} = VocabularyPolicy.filter(message)
- end
-
- test "it rejects based on child object type" do
- Pleroma.Config.put([:mrf_vocabulary, :reject], ["Note"])
-
- message = %{
- "type" => "Create",
- "object" => %{
- "type" => "Note",
- "content" => "whatever"
- }
- }
-
- {:reject, _} = VocabularyPolicy.filter(message)
- end
-
- test "it passes through objects that aren't disallowed" do
- Pleroma.Config.put([:mrf_vocabulary, :reject], ["Like"])
-
- message = %{
- "type" => "Announce",
- "object" => "whatever"
- }
-
- {:ok, ^message} = VocabularyPolicy.filter(message)
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/accept_validation_test.exs b/test/web/activity_pub/object_validators/accept_validation_test.exs
deleted file mode 100644
index d6111ba41..000000000
--- a/test/web/activity_pub/object_validators/accept_validation_test.exs
+++ /dev/null
@@ -1,56 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidationTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.ActivityPub.Pipeline
-
- import Pleroma.Factory
-
- setup do
- follower = insert(:user)
- followed = insert(:user, local: false)
-
- {:ok, follow_data, _} = Builder.follow(follower, followed)
- {:ok, follow_activity, _} = Pipeline.common_pipeline(follow_data, local: true)
-
- {:ok, accept_data, _} = Builder.accept(followed, follow_activity)
-
- %{accept_data: accept_data, followed: followed}
- end
-
- test "it validates a basic 'accept'", %{accept_data: accept_data} do
- assert {:ok, _, _} = ObjectValidator.validate(accept_data, [])
- end
-
- test "it fails when the actor doesn't exist", %{accept_data: accept_data} do
- accept_data =
- accept_data
- |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
-
- assert {:error, _} = ObjectValidator.validate(accept_data, [])
- end
-
- test "it fails when the accepted activity doesn't exist", %{accept_data: accept_data} do
- accept_data =
- accept_data
- |> Map.put("object", "https://gensokyo.2hu/users/raymoo/follows/1")
-
- assert {:error, _} = ObjectValidator.validate(accept_data, [])
- end
-
- test "for an accepted follow, it only validates if the actor of the accept is the followed actor",
- %{accept_data: accept_data} do
- stranger = insert(:user)
-
- accept_data =
- accept_data
- |> Map.put("actor", stranger.ap_id)
-
- assert {:error, _} = ObjectValidator.validate(accept_data, [])
- end
-end
diff --git a/test/web/activity_pub/object_validators/announce_validation_test.exs b/test/web/activity_pub/object_validators/announce_validation_test.exs
deleted file mode 100644
index 623342f76..000000000
--- a/test/web/activity_pub/object_validators/announce_validation_test.exs
+++ /dev/null
@@ -1,106 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnouncValidationTest do
- use Pleroma.DataCase
-
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- describe "announces" do
- setup do
- user = insert(:user)
- announcer = insert(:user)
- {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
-
- object = Object.normalize(post_activity, false)
- {:ok, valid_announce, []} = Builder.announce(announcer, object)
-
- %{
- valid_announce: valid_announce,
- user: user,
- post_activity: post_activity,
- announcer: announcer
- }
- end
-
- test "returns ok for a valid announce", %{valid_announce: valid_announce} do
- assert {:ok, _object, _meta} = ObjectValidator.validate(valid_announce, [])
- end
-
- test "returns an error if the object can't be found", %{valid_announce: valid_announce} do
- without_object =
- valid_announce
- |> Map.delete("object")
-
- {:error, cng} = ObjectValidator.validate(without_object, [])
-
- assert {:object, {"can't be blank", [validation: :required]}} in cng.errors
-
- nonexisting_object =
- valid_announce
- |> Map.put("object", "https://gensokyo.2hu/objects/99999999")
-
- {:error, cng} = ObjectValidator.validate(nonexisting_object, [])
-
- assert {:object, {"can't find object", []}} in cng.errors
- end
-
- test "returns an error if we don't have the actor", %{valid_announce: valid_announce} do
- nonexisting_actor =
- valid_announce
- |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
-
- {:error, cng} = ObjectValidator.validate(nonexisting_actor, [])
-
- assert {:actor, {"can't find user", []}} in cng.errors
- end
-
- test "returns an error if the actor already announced the object", %{
- valid_announce: valid_announce,
- announcer: announcer,
- post_activity: post_activity
- } do
- _announce = CommonAPI.repeat(post_activity.id, announcer)
-
- {:error, cng} = ObjectValidator.validate(valid_announce, [])
-
- assert {:actor, {"already announced this object", []}} in cng.errors
- assert {:object, {"already announced by this actor", []}} in cng.errors
- end
-
- test "returns an error if the actor can't announce the object", %{
- announcer: announcer,
- user: user
- } do
- {:ok, post_activity} =
- CommonAPI.post(user, %{status: "a secret post", visibility: "private"})
-
- object = Object.normalize(post_activity, false)
-
- # Another user can't announce it
- {:ok, announce, []} = Builder.announce(announcer, object, public: false)
-
- {:error, cng} = ObjectValidator.validate(announce, [])
-
- assert {:actor, {"can not announce this object", []}} in cng.errors
-
- # The actor of the object can announce it
- {:ok, announce, []} = Builder.announce(user, object, public: false)
-
- assert {:ok, _, _} = ObjectValidator.validate(announce, [])
-
- # The actor of the object can not announce it publicly
- {:ok, announce, []} = Builder.announce(user, object, public: true)
-
- {:error, cng} = ObjectValidator.validate(announce, [])
-
- assert {:actor, {"can not announce this object publicly", []}} in cng.errors
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/attachment_validator_test.exs b/test/web/activity_pub/object_validators/attachment_validator_test.exs
deleted file mode 100644
index 558bb3131..000000000
--- a/test/web/activity_pub/object_validators/attachment_validator_test.exs
+++ /dev/null
@@ -1,74 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.ActivityPub
- alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
-
- import Pleroma.Factory
-
- describe "attachments" do
- test "works with honkerific attachments" do
- attachment = %{
- "mediaType" => "",
- "name" => "",
- "summary" => "298p3RG7j27tfsZ9RQ.jpg",
- "type" => "Document",
- "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg"
- }
-
- assert {:ok, attachment} =
- AttachmentValidator.cast_and_validate(attachment)
- |> Ecto.Changeset.apply_action(:insert)
-
- assert attachment.mediaType == "application/octet-stream"
- end
-
- test "it turns mastodon attachments into our attachments" do
- attachment = %{
- "url" =>
- "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
- "type" => "Document",
- "name" => nil,
- "mediaType" => "image/jpeg"
- }
-
- {:ok, attachment} =
- AttachmentValidator.cast_and_validate(attachment)
- |> Ecto.Changeset.apply_action(:insert)
-
- assert [
- %{
- href:
- "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
- type: "Link",
- mediaType: "image/jpeg"
- }
- ] = attachment.url
-
- assert attachment.mediaType == "image/jpeg"
- end
-
- test "it handles our own uploads" do
- user = insert(:user)
-
- file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
-
- {:ok, attachment} =
- attachment.data
- |> AttachmentValidator.cast_and_validate()
- |> Ecto.Changeset.apply_action(:insert)
-
- assert attachment.mediaType == "image/jpeg"
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/block_validation_test.exs b/test/web/activity_pub/object_validators/block_validation_test.exs
deleted file mode 100644
index c08d4b2e8..000000000
--- a/test/web/activity_pub/object_validators/block_validation_test.exs
+++ /dev/null
@@ -1,39 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidationTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
-
- import Pleroma.Factory
-
- describe "blocks" do
- setup do
- user = insert(:user, local: false)
- blocked = insert(:user)
-
- {:ok, valid_block, []} = Builder.block(user, blocked)
-
- %{user: user, valid_block: valid_block}
- end
-
- test "validates a basic object", %{
- valid_block: valid_block
- } do
- assert {:ok, _block, []} = ObjectValidator.validate(valid_block, [])
- end
-
- test "returns an error if we don't know the blocked user", %{
- valid_block: valid_block
- } do
- block =
- valid_block
- |> Map.put("object", "https://gensokyo.2hu/users/raymoo")
-
- assert {:error, _cng} = ObjectValidator.validate(block, [])
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/chat_validation_test.exs b/test/web/activity_pub/object_validators/chat_validation_test.exs
deleted file mode 100644
index 50bf03515..000000000
--- a/test/web/activity_pub/object_validators/chat_validation_test.exs
+++ /dev/null
@@ -1,211 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do
- use Pleroma.DataCase
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.ActivityPub
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- describe "chat message create activities" do
- test "it is invalid if the object already exists" do
- user = insert(:user)
- recipient = insert(:user)
- {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "hey")
- object = Object.normalize(activity, false)
-
- {:ok, create_data, _} = Builder.create(user, object.data, [recipient.ap_id])
-
- {:error, cng} = ObjectValidator.validate(create_data, [])
-
- assert {:object, {"The object to create already exists", []}} in cng.errors
- end
-
- test "it is invalid if the object data has a different `to` or `actor` field" do
- user = insert(:user)
- recipient = insert(:user)
- {:ok, object_data, _} = Builder.chat_message(recipient, user.ap_id, "Hey")
-
- {:ok, create_data, _} = Builder.create(user, object_data, [recipient.ap_id])
-
- {:error, cng} = ObjectValidator.validate(create_data, [])
-
- assert {:to, {"Recipients don't match with object recipients", []}} in cng.errors
- assert {:actor, {"Actor doesn't match with object actor", []}} in cng.errors
- end
- end
-
- describe "chat messages" do
- setup do
- clear_config([:instance, :remote_limit])
- user = insert(:user)
- recipient = insert(:user, local: false)
-
- {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey :firefox:")
-
- %{user: user, recipient: recipient, valid_chat_message: valid_chat_message}
- end
-
- test "let's through some basic html", %{user: user, recipient: recipient} do
- {:ok, valid_chat_message, _} =
- Builder.chat_message(
- user,
- recipient.ap_id,
- "hey <a href='https://example.org'>example</a> <script>alert('uguu')</script>"
- )
-
- assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
-
- assert object["content"] ==
- "hey <a href=\"https://example.org\">example</a> alert(&#39;uguu&#39;)"
- end
-
- test "validates for a basic object we build", %{valid_chat_message: valid_chat_message} do
- assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
-
- assert Map.put(valid_chat_message, "attachment", nil) == object
- end
-
- test "validates for a basic object with an attachment", %{
- valid_chat_message: valid_chat_message,
- user: user
- } do
- file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
-
- valid_chat_message =
- valid_chat_message
- |> Map.put("attachment", attachment.data)
-
- assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
-
- assert object["attachment"]
- end
-
- test "validates for a basic object with an attachment in an array", %{
- valid_chat_message: valid_chat_message,
- user: user
- } do
- file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
-
- valid_chat_message =
- valid_chat_message
- |> Map.put("attachment", [attachment.data])
-
- assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
-
- assert object["attachment"]
- end
-
- test "validates for a basic object with an attachment but without content", %{
- valid_chat_message: valid_chat_message,
- user: user
- } do
- file = %Plug.Upload{
- content_type: "image/jpg",
- path: Path.absname("test/fixtures/image.jpg"),
- filename: "an_image.jpg"
- }
-
- {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
-
- valid_chat_message =
- valid_chat_message
- |> Map.put("attachment", attachment.data)
- |> Map.delete("content")
-
- assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
-
- assert object["attachment"]
- end
-
- test "does not validate if the message has no content", %{
- valid_chat_message: valid_chat_message
- } do
- contentless =
- valid_chat_message
- |> Map.delete("content")
-
- refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, []))
- end
-
- test "does not validate if the message is longer than the remote_limit", %{
- valid_chat_message: valid_chat_message
- } do
- Pleroma.Config.put([:instance, :remote_limit], 2)
- refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
- end
-
- test "does not validate if the recipient is blocking the actor", %{
- valid_chat_message: valid_chat_message,
- user: user,
- recipient: recipient
- } do
- Pleroma.User.block(recipient, user)
- refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
- end
-
- test "does not validate if the recipient is not accepting chat messages", %{
- valid_chat_message: valid_chat_message,
- recipient: recipient
- } do
- recipient
- |> Ecto.Changeset.change(%{accepts_chat_messages: false})
- |> Pleroma.Repo.update!()
-
- refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
- end
-
- test "does not validate if the actor or the recipient is not in our system", %{
- valid_chat_message: valid_chat_message
- } do
- chat_message =
- valid_chat_message
- |> Map.put("actor", "https://raymoo.com/raymoo")
-
- {:error, _} = ObjectValidator.validate(chat_message, [])
-
- chat_message =
- valid_chat_message
- |> Map.put("to", ["https://raymoo.com/raymoo"])
-
- {:error, _} = ObjectValidator.validate(chat_message, [])
- end
-
- test "does not validate for a message with multiple recipients", %{
- valid_chat_message: valid_chat_message,
- user: user,
- recipient: recipient
- } do
- chat_message =
- valid_chat_message
- |> Map.put("to", [user.ap_id, recipient.ap_id])
-
- assert {:error, _} = ObjectValidator.validate(chat_message, [])
- end
-
- test "does not validate if it doesn't concern local users" do
- user = insert(:user, local: false)
- recipient = insert(:user, local: false)
-
- {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey")
- assert {:error, _} = ObjectValidator.validate(valid_chat_message, [])
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/delete_validation_test.exs b/test/web/activity_pub/object_validators/delete_validation_test.exs
deleted file mode 100644
index 02683b899..000000000
--- a/test/web/activity_pub/object_validators/delete_validation_test.exs
+++ /dev/null
@@ -1,106 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidationTest do
- use Pleroma.DataCase
-
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- describe "deletes" do
- setup do
- user = insert(:user)
- {:ok, post_activity} = CommonAPI.post(user, %{status: "cancel me daddy"})
-
- {:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"])
- {:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id)
-
- %{user: user, valid_post_delete: valid_post_delete, valid_user_delete: valid_user_delete}
- end
-
- test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do
- {:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, [])
-
- assert valid_post_delete["deleted_activity_id"]
- end
-
- test "it is invalid if the object isn't in a list of certain types", %{
- valid_post_delete: valid_post_delete
- } do
- object = Object.get_by_ap_id(valid_post_delete["object"])
-
- data =
- object.data
- |> Map.put("type", "Like")
-
- {:ok, _object} =
- object
- |> Ecto.Changeset.change(%{data: data})
- |> Object.update_and_set_cache()
-
- {:error, cng} = ObjectValidator.validate(valid_post_delete, [])
- assert {:object, {"object not in allowed types", []}} in cng.errors
- end
-
- test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do
- assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, []))
- end
-
- test "it's invalid if the id is missing", %{valid_post_delete: valid_post_delete} do
- no_id =
- valid_post_delete
- |> Map.delete("id")
-
- {:error, cng} = ObjectValidator.validate(no_id, [])
-
- assert {:id, {"can't be blank", [validation: :required]}} in cng.errors
- end
-
- test "it's invalid if the object doesn't exist", %{valid_post_delete: valid_post_delete} do
- missing_object =
- valid_post_delete
- |> Map.put("object", "http://does.not/exist")
-
- {:error, cng} = ObjectValidator.validate(missing_object, [])
-
- assert {:object, {"can't find object", []}} in cng.errors
- end
-
- test "it's invalid if the actor of the object and the actor of delete are from different domains",
- %{valid_post_delete: valid_post_delete} do
- valid_user = insert(:user)
-
- valid_other_actor =
- valid_post_delete
- |> Map.put("actor", valid_user.ap_id)
-
- assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, []))
-
- invalid_other_actor =
- valid_post_delete
- |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
-
- {:error, cng} = ObjectValidator.validate(invalid_other_actor, [])
-
- assert {:actor, {"is not allowed to modify object", []}} in cng.errors
- end
-
- test "it's valid if the actor of the object is a local superuser",
- %{valid_post_delete: valid_post_delete} do
- user =
- insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo")
-
- valid_other_actor =
- valid_post_delete
- |> Map.put("actor", user.ap_id)
-
- {:ok, _, meta} = ObjectValidator.validate(valid_other_actor, [])
- assert meta[:do_not_federate]
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/emoji_react_validation_test.exs b/test/web/activity_pub/object_validators/emoji_react_validation_test.exs
deleted file mode 100644
index 582e6d785..000000000
--- a/test/web/activity_pub/object_validators/emoji_react_validation_test.exs
+++ /dev/null
@@ -1,53 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- describe "EmojiReacts" do
- setup do
- user = insert(:user)
- {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
-
- object = Pleroma.Object.get_by_ap_id(post_activity.data["object"])
-
- {:ok, valid_emoji_react, []} = Builder.emoji_react(user, object, "👌")
-
- %{user: user, post_activity: post_activity, valid_emoji_react: valid_emoji_react}
- end
-
- test "it validates a valid EmojiReact", %{valid_emoji_react: valid_emoji_react} do
- assert {:ok, _, _} = ObjectValidator.validate(valid_emoji_react, [])
- end
-
- test "it is not valid without a 'content' field", %{valid_emoji_react: valid_emoji_react} do
- without_content =
- valid_emoji_react
- |> Map.delete("content")
-
- {:error, cng} = ObjectValidator.validate(without_content, [])
-
- refute cng.valid?
- assert {:content, {"can't be blank", [validation: :required]}} in cng.errors
- end
-
- test "it is not valid with a non-emoji content field", %{valid_emoji_react: valid_emoji_react} do
- without_emoji_content =
- valid_emoji_react
- |> Map.put("content", "x")
-
- {:error, cng} = ObjectValidator.validate(without_emoji_content, [])
-
- refute cng.valid?
-
- assert {:content, {"must be a single character emoji", []}} in cng.errors
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/follow_validation_test.exs b/test/web/activity_pub/object_validators/follow_validation_test.exs
deleted file mode 100644
index 6e1378be2..000000000
--- a/test/web/activity_pub/object_validators/follow_validation_test.exs
+++ /dev/null
@@ -1,26 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidationTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
-
- import Pleroma.Factory
-
- describe "Follows" do
- setup do
- follower = insert(:user)
- followed = insert(:user)
-
- {:ok, valid_follow, []} = Builder.follow(follower, followed)
- %{follower: follower, followed: followed, valid_follow: valid_follow}
- end
-
- test "validates a basic follow object", %{valid_follow: valid_follow} do
- assert {:ok, _follow, []} = ObjectValidator.validate(valid_follow, [])
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/like_validation_test.exs b/test/web/activity_pub/object_validators/like_validation_test.exs
deleted file mode 100644
index 2c033b7e2..000000000
--- a/test/web/activity_pub/object_validators/like_validation_test.exs
+++ /dev/null
@@ -1,113 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidationTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
- alias Pleroma.Web.ActivityPub.Utils
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- describe "likes" do
- setup do
- user = insert(:user)
- {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
-
- valid_like = %{
- "to" => [user.ap_id],
- "cc" => [],
- "type" => "Like",
- "id" => Utils.generate_activity_id(),
- "object" => post_activity.data["object"],
- "actor" => user.ap_id,
- "context" => "a context"
- }
-
- %{valid_like: valid_like, user: user, post_activity: post_activity}
- end
-
- test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do
- {:ok, object, _meta} = ObjectValidator.validate(valid_like, [])
-
- assert "id" in Map.keys(object)
- end
-
- test "is valid for a valid object", %{valid_like: valid_like} do
- assert LikeValidator.cast_and_validate(valid_like).valid?
- end
-
- test "sets the 'to' field to the object actor if no recipients are given", %{
- valid_like: valid_like,
- user: user
- } do
- without_recipients =
- valid_like
- |> Map.delete("to")
-
- {:ok, object, _meta} = ObjectValidator.validate(without_recipients, [])
-
- assert object["to"] == [user.ap_id]
- end
-
- test "sets the context field to the context of the object if no context is given", %{
- valid_like: valid_like,
- post_activity: post_activity
- } do
- without_context =
- valid_like
- |> Map.delete("context")
-
- {:ok, object, _meta} = ObjectValidator.validate(without_context, [])
-
- assert object["context"] == post_activity.data["context"]
- end
-
- test "it errors when the actor is missing or not known", %{valid_like: valid_like} do
- without_actor = Map.delete(valid_like, "actor")
-
- refute LikeValidator.cast_and_validate(without_actor).valid?
-
- with_invalid_actor = Map.put(valid_like, "actor", "invalidactor")
-
- refute LikeValidator.cast_and_validate(with_invalid_actor).valid?
- end
-
- test "it errors when the object is missing or not known", %{valid_like: valid_like} do
- without_object = Map.delete(valid_like, "object")
-
- refute LikeValidator.cast_and_validate(without_object).valid?
-
- with_invalid_object = Map.put(valid_like, "object", "invalidobject")
-
- refute LikeValidator.cast_and_validate(with_invalid_object).valid?
- end
-
- test "it errors when the actor has already like the object", %{
- valid_like: valid_like,
- user: user,
- post_activity: post_activity
- } do
- _like = CommonAPI.favorite(user, post_activity.id)
-
- refute LikeValidator.cast_and_validate(valid_like).valid?
- end
-
- test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do
- wrapped_like =
- valid_like
- |> Map.put("actor", %{"id" => valid_like["actor"]})
- |> Map.put("object", %{"id" => valid_like["object"]})
-
- validated = LikeValidator.cast_and_validate(wrapped_like)
-
- assert validated.valid?
-
- assert {:actor, valid_like["actor"]} in validated.changes
- assert {:object, valid_like["object"]} in validated.changes
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/note_validator_test.exs b/test/web/activity_pub/object_validators/note_validator_test.exs
deleted file mode 100644
index 30c481ffb..000000000
--- a/test/web/activity_pub/object_validators/note_validator_test.exs
+++ /dev/null
@@ -1,35 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidatorTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator
- alias Pleroma.Web.ActivityPub.Utils
-
- import Pleroma.Factory
-
- describe "Notes" do
- setup do
- user = insert(:user)
-
- note = %{
- "id" => Utils.generate_activity_id(),
- "type" => "Note",
- "actor" => user.ap_id,
- "to" => [user.follower_address],
- "cc" => [],
- "content" => "Hellow this is content.",
- "context" => "xxx",
- "summary" => "a post"
- }
-
- %{user: user, note: note}
- end
-
- test "a basic note validates", %{note: note} do
- %{valid?: true} = NoteValidator.cast_and_validate(note)
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/reject_validation_test.exs b/test/web/activity_pub/object_validators/reject_validation_test.exs
deleted file mode 100644
index 370bb6e5c..000000000
--- a/test/web/activity_pub/object_validators/reject_validation_test.exs
+++ /dev/null
@@ -1,56 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.RejectValidationTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.ActivityPub.Pipeline
-
- import Pleroma.Factory
-
- setup do
- follower = insert(:user)
- followed = insert(:user, local: false)
-
- {:ok, follow_data, _} = Builder.follow(follower, followed)
- {:ok, follow_activity, _} = Pipeline.common_pipeline(follow_data, local: true)
-
- {:ok, reject_data, _} = Builder.reject(followed, follow_activity)
-
- %{reject_data: reject_data, followed: followed}
- end
-
- test "it validates a basic 'reject'", %{reject_data: reject_data} do
- assert {:ok, _, _} = ObjectValidator.validate(reject_data, [])
- end
-
- test "it fails when the actor doesn't exist", %{reject_data: reject_data} do
- reject_data =
- reject_data
- |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
-
- assert {:error, _} = ObjectValidator.validate(reject_data, [])
- end
-
- test "it fails when the rejected activity doesn't exist", %{reject_data: reject_data} do
- reject_data =
- reject_data
- |> Map.put("object", "https://gensokyo.2hu/users/raymoo/follows/1")
-
- assert {:error, _} = ObjectValidator.validate(reject_data, [])
- end
-
- test "for an rejected follow, it only validates if the actor of the reject is the followed actor",
- %{reject_data: reject_data} do
- stranger = insert(:user)
-
- reject_data =
- reject_data
- |> Map.put("actor", stranger.ap_id)
-
- assert {:error, _} = ObjectValidator.validate(reject_data, [])
- end
-end
diff --git a/test/web/activity_pub/object_validators/types/date_time_test.exs b/test/web/activity_pub/object_validators/types/date_time_test.exs
deleted file mode 100644
index 43be8e936..000000000
--- a/test/web/activity_pub/object_validators/types/date_time_test.exs
+++ /dev/null
@@ -1,32 +0,0 @@
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTimeTest do
- alias Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime
- use Pleroma.DataCase
-
- test "it validates an xsd:Datetime" do
- valid_strings = [
- "2004-04-12T13:20:00",
- "2004-04-12T13:20:15.5",
- "2004-04-12T13:20:00-05:00",
- "2004-04-12T13:20:00Z"
- ]
-
- invalid_strings = [
- "2004-04-12T13:00",
- "2004-04-1213:20:00",
- "99-04-12T13:00",
- "2004-04-12"
- ]
-
- assert {:ok, "2004-04-01T12:00:00Z"} == DateTime.cast("2004-04-01T12:00:00Z")
-
- Enum.each(valid_strings, fn date_time ->
- result = DateTime.cast(date_time)
- assert {:ok, _} = result
- end)
-
- Enum.each(invalid_strings, fn date_time ->
- result = DateTime.cast(date_time)
- assert :error == result
- end)
- end
-end
diff --git a/test/web/activity_pub/object_validators/types/object_id_test.exs b/test/web/activity_pub/object_validators/types/object_id_test.exs
deleted file mode 100644
index e0ab76379..000000000
--- a/test/web/activity_pub/object_validators/types/object_id_test.exs
+++ /dev/null
@@ -1,41 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ObjectValidators.Types.ObjectIDTest do
- alias Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectID
- use Pleroma.DataCase
-
- @uris [
- "http://lain.com/users/lain",
- "http://lain.com",
- "https://lain.com/object/1"
- ]
-
- @non_uris [
- "https://",
- "rin",
- 1,
- :x,
- %{"1" => 2}
- ]
-
- test "it accepts http uris" do
- Enum.each(@uris, fn uri ->
- assert {:ok, uri} == ObjectID.cast(uri)
- end)
- end
-
- test "it accepts an object with a nested uri id" do
- Enum.each(@uris, fn uri ->
- assert {:ok, uri} == ObjectID.cast(%{"id" => uri})
- end)
- end
-
- test "it rejects non-uri strings" do
- Enum.each(@non_uris, fn non_uri ->
- assert :error == ObjectID.cast(non_uri)
- assert :error == ObjectID.cast(%{"id" => non_uri})
- end)
- end
-end
diff --git a/test/web/activity_pub/object_validators/types/recipients_test.exs b/test/web/activity_pub/object_validators/types/recipients_test.exs
deleted file mode 100644
index 053916bdd..000000000
--- a/test/web/activity_pub/object_validators/types/recipients_test.exs
+++ /dev/null
@@ -1,27 +0,0 @@
-defmodule Pleroma.Web.ObjectValidators.Types.RecipientsTest do
- alias Pleroma.EctoType.ActivityPub.ObjectValidators.Recipients
- use Pleroma.DataCase
-
- test "it asserts that all elements of the list are object ids" do
- list = ["https://lain.com/users/lain", "invalid"]
-
- assert :error == Recipients.cast(list)
- end
-
- test "it works with a list" do
- list = ["https://lain.com/users/lain"]
- assert {:ok, list} == Recipients.cast(list)
- end
-
- test "it works with a list with whole objects" do
- list = ["https://lain.com/users/lain", %{"id" => "https://gensokyo.2hu/users/raymoo"}]
- resulting_list = ["https://gensokyo.2hu/users/raymoo", "https://lain.com/users/lain"]
- assert {:ok, resulting_list} == Recipients.cast(list)
- end
-
- test "it turns a single string into a list" do
- recipient = "https://lain.com/users/lain"
-
- assert {:ok, [recipient]} == Recipients.cast(recipient)
- end
-end
diff --git a/test/web/activity_pub/object_validators/types/safe_text_test.exs b/test/web/activity_pub/object_validators/types/safe_text_test.exs
deleted file mode 100644
index 9c08606f6..000000000
--- a/test/web/activity_pub/object_validators/types/safe_text_test.exs
+++ /dev/null
@@ -1,30 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.SafeTextTest do
- use Pleroma.DataCase
-
- alias Pleroma.EctoType.ActivityPub.ObjectValidators.SafeText
-
- test "it lets normal text go through" do
- text = "hey how are you"
- assert {:ok, text} == SafeText.cast(text)
- end
-
- test "it removes html tags from text" do
- text = "hey look xss <script>alert('foo')</script>"
- assert {:ok, "hey look xss alert(&#39;foo&#39;)"} == SafeText.cast(text)
- end
-
- test "it keeps basic html tags" do
- text = "hey <a href='http://gensokyo.2hu'>look</a> xss <script>alert('foo')</script>"
-
- assert {:ok, "hey <a href=\"http://gensokyo.2hu\">look</a> xss alert(&#39;foo&#39;)"} ==
- SafeText.cast(text)
- end
-
- test "errors for non-text" do
- assert :error == SafeText.cast(1)
- end
-end
diff --git a/test/web/activity_pub/object_validators/undo_validation_test.exs b/test/web/activity_pub/object_validators/undo_validation_test.exs
deleted file mode 100644
index 75bbcc4b6..000000000
--- a/test/web/activity_pub/object_validators/undo_validation_test.exs
+++ /dev/null
@@ -1,53 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.UndoHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- describe "Undos" do
- setup do
- user = insert(:user)
- {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
- {:ok, like} = CommonAPI.favorite(user, post_activity.id)
- {:ok, valid_like_undo, []} = Builder.undo(user, like)
-
- %{user: user, like: like, valid_like_undo: valid_like_undo}
- end
-
- test "it validates a basic like undo", %{valid_like_undo: valid_like_undo} do
- assert {:ok, _, _} = ObjectValidator.validate(valid_like_undo, [])
- end
-
- test "it does not validate if the actor of the undo is not the actor of the object", %{
- valid_like_undo: valid_like_undo
- } do
- other_user = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo")
-
- bad_actor =
- valid_like_undo
- |> Map.put("actor", other_user.ap_id)
-
- {:error, cng} = ObjectValidator.validate(bad_actor, [])
-
- assert {:actor, {"not the same as object actor", []}} in cng.errors
- end
-
- test "it does not validate if the object is missing", %{valid_like_undo: valid_like_undo} do
- missing_object =
- valid_like_undo
- |> Map.put("object", "https://gensokyo.2hu/objects/1")
-
- {:error, cng} = ObjectValidator.validate(missing_object, [])
-
- assert {:object, {"can't find object", []}} in cng.errors
- assert length(cng.errors) == 1
- end
- end
-end
diff --git a/test/web/activity_pub/object_validators/update_validation_test.exs b/test/web/activity_pub/object_validators/update_validation_test.exs
deleted file mode 100644
index 5e80cf731..000000000
--- a/test/web/activity_pub/object_validators/update_validation_test.exs
+++ /dev/null
@@ -1,44 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.UpdateHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.ObjectValidator
-
- import Pleroma.Factory
-
- describe "updates" do
- setup do
- user = insert(:user)
-
- object = %{
- "id" => user.ap_id,
- "name" => "A new name",
- "summary" => "A new bio"
- }
-
- {:ok, valid_update, []} = Builder.update(user, object)
-
- %{user: user, valid_update: valid_update}
- end
-
- test "validates a basic object", %{valid_update: valid_update} do
- assert {:ok, _update, []} = ObjectValidator.validate(valid_update, [])
- end
-
- test "returns an error if the object can't be updated by the actor", %{
- valid_update: valid_update
- } do
- other_user = insert(:user)
-
- update =
- valid_update
- |> Map.put("actor", other_user.ap_id)
-
- assert {:error, _cng} = ObjectValidator.validate(update, [])
- end
- end
-end
diff --git a/test/web/activity_pub/pipeline_test.exs b/test/web/activity_pub/pipeline_test.exs
deleted file mode 100644
index 210a06563..000000000
--- a/test/web/activity_pub/pipeline_test.exs
+++ /dev/null
@@ -1,179 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.PipelineTest do
- use Pleroma.DataCase
-
- import Mock
- import Pleroma.Factory
-
- describe "common_pipeline/2" do
- setup do
- clear_config([:instance, :federating], true)
- :ok
- end
-
- test "when given an `object_data` in meta, Federation will receive a the original activity with the `object` field set to this embedded object" do
- activity = insert(:note_activity)
- object = %{"id" => "1", "type" => "Love"}
- meta = [local: true, object_data: object]
-
- activity_with_object = %{activity | data: Map.put(activity.data, "object", object)}
-
- with_mocks([
- {Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
- {
- Pleroma.Web.ActivityPub.MRF,
- [],
- [pipeline_filter: fn o, m -> {:ok, o, m} end]
- },
- {
- Pleroma.Web.ActivityPub.ActivityPub,
- [],
- [persist: fn o, m -> {:ok, o, m} end]
- },
- {
- Pleroma.Web.ActivityPub.SideEffects,
- [],
- [
- handle: fn o, m -> {:ok, o, m} end,
- handle_after_transaction: fn m -> m end
- ]
- },
- {
- Pleroma.Web.Federator,
- [],
- [publish: fn _o -> :ok end]
- }
- ]) do
- assert {:ok, ^activity, ^meta} =
- Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
-
- assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
- refute called(Pleroma.Web.Federator.publish(activity))
- assert_called(Pleroma.Web.Federator.publish(activity_with_object))
- end
- end
-
- test "it goes through validation, filtering, persisting, side effects and federation for local activities" do
- activity = insert(:note_activity)
- meta = [local: true]
-
- with_mocks([
- {Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
- {
- Pleroma.Web.ActivityPub.MRF,
- [],
- [pipeline_filter: fn o, m -> {:ok, o, m} end]
- },
- {
- Pleroma.Web.ActivityPub.ActivityPub,
- [],
- [persist: fn o, m -> {:ok, o, m} end]
- },
- {
- Pleroma.Web.ActivityPub.SideEffects,
- [],
- [
- handle: fn o, m -> {:ok, o, m} end,
- handle_after_transaction: fn m -> m end
- ]
- },
- {
- Pleroma.Web.Federator,
- [],
- [publish: fn _o -> :ok end]
- }
- ]) do
- assert {:ok, ^activity, ^meta} =
- Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
-
- assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
- assert_called(Pleroma.Web.Federator.publish(activity))
- end
- end
-
- test "it goes through validation, filtering, persisting, side effects without federation for remote activities" do
- activity = insert(:note_activity)
- meta = [local: false]
-
- with_mocks([
- {Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
- {
- Pleroma.Web.ActivityPub.MRF,
- [],
- [pipeline_filter: fn o, m -> {:ok, o, m} end]
- },
- {
- Pleroma.Web.ActivityPub.ActivityPub,
- [],
- [persist: fn o, m -> {:ok, o, m} end]
- },
- {
- Pleroma.Web.ActivityPub.SideEffects,
- [],
- [handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end]
- },
- {
- Pleroma.Web.Federator,
- [],
- []
- }
- ]) do
- assert {:ok, ^activity, ^meta} =
- Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
-
- assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
- end
- end
-
- test "it goes through validation, filtering, persisting, side effects without federation for local activities if federation is deactivated" do
- clear_config([:instance, :federating], false)
-
- activity = insert(:note_activity)
- meta = [local: true]
-
- with_mocks([
- {Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
- {
- Pleroma.Web.ActivityPub.MRF,
- [],
- [pipeline_filter: fn o, m -> {:ok, o, m} end]
- },
- {
- Pleroma.Web.ActivityPub.ActivityPub,
- [],
- [persist: fn o, m -> {:ok, o, m} end]
- },
- {
- Pleroma.Web.ActivityPub.SideEffects,
- [],
- [handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end]
- },
- {
- Pleroma.Web.Federator,
- [],
- []
- }
- ]) do
- assert {:ok, ^activity, ^meta} =
- Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
-
- assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
- assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
- end
- end
- end
-end
diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs
deleted file mode 100644
index b9388b966..000000000
--- a/test/web/activity_pub/publisher_test.exs
+++ /dev/null
@@ -1,365 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.PublisherTest do
- 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"
-
- setup do
- mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- setup_all do: clear_config([:instance, :federating], true)
-
- 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, %{shared_inbox: "http://example.com/inbox"})
-
- activity = %Activity{
- data: %{"to" => [@as_public], "cc" => [user.follower_address]}
- }
-
- assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
- end
-
- test "it returns sharedInbox for messages involving as:Public in cc" do
- user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
-
- activity = %Activity{
- data: %{"cc" => [@as_public], "to" => [user.follower_address]}
- }
-
- assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
- end
-
- test "it returns sharedInbox for messages involving multiple recipients in to" do
- user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
- user_two = insert(:user)
- user_three = insert(:user)
-
- activity = %Activity{
- data: %{"cc" => [], "to" => [user.ap_id, user_two.ap_id, user_three.ap_id]}
- }
-
- assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
- end
-
- test "it returns sharedInbox for messages involving multiple recipients in cc" do
- user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
- user_two = insert(:user)
- user_three = insert(:user)
-
- activity = %Activity{
- data: %{"to" => [], "cc" => [user.ap_id, user_two.ap_id, user_three.ap_id]}
- }
-
- assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
- end
-
- test "it returns sharedInbox for messages involving multiple recipients in total" do
- user =
- insert(:user, %{
- shared_inbox: "http://example.com/inbox",
- inbox: "http://example.com/personal-inbox"
- })
-
- user_two = insert(:user)
-
- activity = %Activity{
- data: %{"to" => [user_two.ap_id], "cc" => [user.ap_id]}
- }
-
- assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
- end
-
- test "it returns inbox for messages involving single recipients in total" do
- user =
- insert(:user, %{
- shared_inbox: "http://example.com/inbox",
- inbox: "http://example.com/personal-inbox"
- })
-
- activity = %Activity{
- data: %{"to" => [user.ap_id], "cc" => []}
- }
-
- assert Publisher.determine_inbox(activity, user) == "http://example.com/personal-inbox"
- end
- end
-
- describe "publish_one/1" do
- test "publish to url with with different ports" do
- inbox80 = "http://42.site/users/nick1/inbox"
- inbox42 = "http://42.site:42/users/nick1/inbox"
-
- mock(fn
- %{method: :post, url: "http://42.site:42/users/nick1/inbox"} ->
- {:ok, %Tesla.Env{status: 200, body: "port 42"}}
-
- %{method: :post, url: "http://42.site/users/nick1/inbox"} ->
- {:ok, %Tesla.Env{status: 200, body: "port 80"}}
- end)
-
- actor = insert(:user)
-
- assert {:ok, %{body: "port 42"}} =
- Publisher.publish_one(%{
- inbox: inbox42,
- json: "{}",
- actor: actor,
- id: 1,
- unreachable_since: true
- })
-
- assert {:ok, %{body: "port 80"}} =
- Publisher.publish_one(%{
- inbox: inbox80,
- json: "{}",
- actor: actor,
- id: 1,
- unreachable_since: true
- })
- end
-
- test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
- Instances,
- [:passthrough],
- [] do
- actor = insert(:user)
- inbox = "http://200.site/users/nick1/inbox"
-
- assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
- assert called(Instances.set_reachable(inbox))
- end
-
- test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is set",
- Instances,
- [:passthrough],
- [] do
- actor = insert(:user)
- inbox = "http://200.site/users/nick1/inbox"
-
- assert {:ok, _} =
- Publisher.publish_one(%{
- inbox: inbox,
- json: "{}",
- actor: actor,
- id: 1,
- unreachable_since: NaiveDateTime.utc_now()
- })
-
- assert called(Instances.set_reachable(inbox))
- end
-
- test_with_mock "does NOT call `Instances.set_reachable` on successful federation if `unreachable_since` is nil",
- Instances,
- [:passthrough],
- [] do
- actor = insert(:user)
- inbox = "http://200.site/users/nick1/inbox"
-
- assert {:ok, _} =
- Publisher.publish_one(%{
- inbox: inbox,
- json: "{}",
- actor: actor,
- id: 1,
- unreachable_since: nil
- })
-
- refute called(Instances.set_reachable(inbox))
- end
-
- test_with_mock "calls `Instances.set_unreachable` on target inbox on non-2xx HTTP response code",
- Instances,
- [:passthrough],
- [] do
- actor = insert(:user)
- inbox = "http://404.site/users/nick1/inbox"
-
- assert {:error, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
-
- assert called(Instances.set_unreachable(inbox))
- end
-
- test_with_mock "it calls `Instances.set_unreachable` on target inbox on request error of any kind",
- Instances,
- [:passthrough],
- [] do
- actor = insert(:user)
- inbox = "http://connrefused.site/users/nick1/inbox"
-
- 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
-
- test_with_mock "does NOT call `Instances.set_unreachable` if target is reachable",
- Instances,
- [:passthrough],
- [] do
- actor = insert(:user)
- inbox = "http://200.site/users/nick1/inbox"
-
- assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
-
- refute called(Instances.set_unreachable(inbox))
- end
-
- test_with_mock "does NOT call `Instances.set_unreachable` if target instance has non-nil `unreachable_since`",
- Instances,
- [:passthrough],
- [] do
- actor = insert(:user)
- inbox = "http://connrefused.site/users/nick1/inbox"
-
- 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
- end
-
- describe "publish/2" do
- test_with_mock "publishes an activity with BCC to all relevant peers.",
- Pleroma.Web.Federator.Publisher,
- [:passthrough],
- [] do
- follower =
- insert(:user, %{
- local: false,
- inbox: "https://domain.com/users/nick1/inbox",
- ap_enabled: true
- })
-
- actor = insert(:user, follower_address: follower.ap_id)
- user = insert(:user)
-
- {:ok, _follower_one} = Pleroma.User.follow(follower, actor)
- actor = refresh_record(actor)
-
- note_activity =
- insert(:note_activity,
- recipients: [follower.ap_id],
- data_attrs: %{"bcc" => [user.ap_id]}
- )
-
- res = Publisher.publish(actor, note_activity)
- assert res == :ok
-
- assert called(
- Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
- inbox: "https://domain.com/users/nick1/inbox",
- 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,
- inbox: "https://domain.com/users/nick1/inbox",
- ap_enabled: true
- )
-
- another_fetcher =
- insert(:user,
- local: false,
- 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
deleted file mode 100644
index 9d657ac4f..000000000
--- a/test/web/activity_pub/relay_test.exs
+++ /dev/null
@@ -1,128 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.RelayTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Relay
- alias Pleroma.Web.CommonAPI
-
- import ExUnit.CaptureLog
- import Pleroma.Factory
- import Mock
-
- test "gets an actor for the relay" do
- user = Relay.get_actor()
- 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 capture_log(fn ->
- {:error, _} = Relay.follow("test-ap-id")
- end) =~ "Could not decode user at fetch"
- end
-
- test "returns activity" do
- user = insert(:user)
- service_actor = Relay.get_actor()
- assert {:ok, %Activity{} = activity} = Relay.follow(user.ap_id)
- assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
- assert user.ap_id in activity.recipients
- assert activity.data["type"] == "Follow"
- assert activity.data["actor"] == service_actor.ap_id
- assert activity.data["object"] == user.ap_id
- end
- end
-
- describe "unfollow/1" do
- test "returns errors when user not found" do
- assert capture_log(fn ->
- {:error, _} = Relay.unfollow("test-ap-id")
- end) =~ "Could not decode user at fetch"
- end
-
- test "returns activity" do
- user = insert(:user)
- service_actor = Relay.get_actor()
- CommonAPI.follow(service_actor, user)
- assert "#{user.ap_id}/followers" in User.following(service_actor)
- assert {:ok, %Activity{} = activity} = Relay.unfollow(user.ap_id)
- assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
- assert user.ap_id in activity.recipients
- assert activity.data["type"] == "Undo"
- assert activity.data["actor"] == service_actor.ap_id
- assert activity.data["to"] == [user.ap_id]
- refute "#{user.ap_id}/followers" in User.following(service_actor)
- end
- end
-
- describe "publish/1" do
- setup do: clear_config([:instance, :federating])
-
- test "returns error when activity not `Create` type" do
- activity = insert(:like_activity)
- assert Relay.publish(activity) == {:error, "Not implemented"}
- end
-
- @tag capture_log: true
- test "returns error when activity not public" do
- activity = insert(:direct_note_activity)
- assert Relay.publish(activity) == {:error, false}
- end
-
- test "returns error when object is unknown" do
- activity =
- insert(:note_activity,
- data: %{
- "type" => "Create",
- "object" => "http://mastodon.example.org/eee/99541947525187367"
- }
- )
-
- Tesla.Mock.mock(fn
- %{method: :get, url: "http://mastodon.example.org/eee/99541947525187367"} ->
- %Tesla.Env{status: 500, body: ""}
- end)
-
- assert capture_log(fn ->
- assert Relay.publish(activity) == {:error, false}
- end) =~ "[error] error: false"
- end
-
- test_with_mock "returns announce activity and publish to federate",
- Pleroma.Web.Federator,
- [:passthrough],
- [] do
- clear_config([:instance, :federating], true)
- service_actor = Relay.get_actor()
- note = insert(:note_activity)
- assert {:ok, %Activity{} = activity} = Relay.publish(note)
- assert activity.data["type"] == "Announce"
- assert activity.data["actor"] == service_actor.ap_id
- assert activity.data["to"] == [service_actor.follower_address]
- assert called(Pleroma.Web.Federator.publish(activity))
- end
-
- test_with_mock "returns announce activity and not publish to federate",
- Pleroma.Web.Federator,
- [:passthrough],
- [] do
- clear_config([:instance, :federating], false)
- service_actor = Relay.get_actor()
- note = insert(:note_activity)
- assert {:ok, %Activity{} = activity} = Relay.publish(note)
- assert activity.data["type"] == "Announce"
- assert activity.data["actor"] == service_actor.ap_id
- refute called(Pleroma.Web.Federator.publish(activity))
- end
- end
-end
diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs
deleted file mode 100644
index 9efbaad04..000000000
--- a/test/web/activity_pub/side_effects_test.exs
+++ /dev/null
@@ -1,639 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
- use Oban.Testing, repo: Pleroma.Repo
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Chat
- alias Pleroma.Chat.MessageReference
- alias Pleroma.Notification
- alias Pleroma.Object
- alias Pleroma.Repo
- alias Pleroma.Tests.ObanHelpers
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ActivityPub
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.SideEffects
- alias Pleroma.Web.CommonAPI
-
- import ExUnit.CaptureLog
- import Mock
- import Pleroma.Factory
-
- describe "handle_after_transaction" do
- test "it streams out notifications and streams" do
- author = insert(:user, local: true)
- recipient = insert(:user, local: true)
-
- {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
-
- {:ok, create_activity_data, _meta} =
- Builder.create(author, chat_message_data["id"], [recipient.ap_id])
-
- {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
-
- {:ok, _create_activity, meta} =
- SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
-
- assert [notification] = meta[:notifications]
-
- with_mocks([
- {
- Pleroma.Web.Streamer,
- [],
- [
- stream: fn _, _ -> nil end
- ]
- },
- {
- Pleroma.Web.Push,
- [],
- [
- send: fn _ -> nil end
- ]
- }
- ]) do
- SideEffects.handle_after_transaction(meta)
-
- assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
- assert called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
- assert called(Pleroma.Web.Push.send(notification))
- end
- end
- end
-
- describe "blocking users" do
- setup do
- user = insert(:user)
- blocked = insert(:user)
- User.follow(blocked, user)
- User.follow(user, blocked)
-
- {:ok, block_data, []} = Builder.block(user, blocked)
- {:ok, block, _meta} = ActivityPub.persist(block_data, local: true)
-
- %{user: user, blocked: blocked, block: block}
- end
-
- test "it unfollows and blocks", %{user: user, blocked: blocked, block: block} do
- assert User.following?(user, blocked)
- assert User.following?(blocked, user)
-
- {:ok, _, _} = SideEffects.handle(block)
-
- refute User.following?(user, blocked)
- refute User.following?(blocked, user)
- assert User.blocks?(user, blocked)
- end
-
- test "it blocks but does not unfollow if the relevant setting is set", %{
- user: user,
- blocked: blocked,
- block: block
- } do
- clear_config([:activitypub, :unfollow_blocked], false)
- assert User.following?(user, blocked)
- assert User.following?(blocked, user)
-
- {:ok, _, _} = SideEffects.handle(block)
-
- refute User.following?(user, blocked)
- assert User.following?(blocked, user)
- assert User.blocks?(user, blocked)
- end
- end
-
- describe "update users" do
- setup do
- user = insert(:user)
- {:ok, update_data, []} = Builder.update(user, %{"id" => user.ap_id, "name" => "new name!"})
- {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
-
- %{user: user, update_data: update_data, update: update}
- end
-
- test "it updates the user", %{user: user, update: update} do
- {:ok, _, _} = SideEffects.handle(update)
- user = User.get_by_id(user.id)
- assert user.name == "new name!"
- end
-
- test "it uses a given changeset to update", %{user: user, update: update} do
- changeset = Ecto.Changeset.change(user, %{default_scope: "direct"})
-
- assert user.default_scope == "public"
- {:ok, _, _} = SideEffects.handle(update, user_update_changeset: changeset)
- user = User.get_by_id(user.id)
- assert user.default_scope == "direct"
- end
- end
-
- describe "delete objects" do
- setup do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
- {:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
- {:ok, favorite} = CommonAPI.favorite(user, post.id)
- object = Object.normalize(post)
- {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
- {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
- {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
- {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
-
- %{
- user: user,
- delete: delete,
- post: post,
- object: object,
- delete_user: delete_user,
- op: op,
- favorite: favorite
- }
- end
-
- test "it handles object deletions", %{
- delete: delete,
- post: post,
- object: object,
- user: user,
- op: op,
- favorite: favorite
- } do
- with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
- stream_out: fn _ -> nil end,
- stream_out_participations: fn _, _ -> nil end do
- {:ok, delete, _} = SideEffects.handle(delete)
- user = User.get_cached_by_ap_id(object.data["actor"])
-
- assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
- assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
- end
-
- object = Object.get_by_id(object.id)
- assert object.data["type"] == "Tombstone"
- refute Activity.get_by_id(post.id)
- refute Activity.get_by_id(favorite.id)
-
- user = User.get_by_id(user.id)
- assert user.note_count == 0
-
- object = Object.normalize(op.data["object"], false)
-
- assert object.data["repliesCount"] == 0
- end
-
- test "it handles object deletions when the object itself has been pruned", %{
- delete: delete,
- post: post,
- object: object,
- user: user,
- op: op
- } do
- with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
- stream_out: fn _ -> nil end,
- stream_out_participations: fn _, _ -> nil end do
- {:ok, delete, _} = SideEffects.handle(delete)
- user = User.get_cached_by_ap_id(object.data["actor"])
-
- assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
- assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
- end
-
- object = Object.get_by_id(object.id)
- assert object.data["type"] == "Tombstone"
- refute Activity.get_by_id(post.id)
-
- user = User.get_by_id(user.id)
- assert user.note_count == 0
-
- object = Object.normalize(op.data["object"], false)
-
- assert object.data["repliesCount"] == 0
- end
-
- test "it handles user deletions", %{delete_user: delete, user: user} do
- {:ok, _delete, _} = SideEffects.handle(delete)
- ObanHelpers.perform_all()
-
- assert User.get_cached_by_ap_id(user.ap_id).deactivated
- end
-
- test "it logs issues with objects deletion", %{
- delete: delete,
- object: object
- } do
- {:ok, object} =
- object
- |> Object.change(%{data: Map.delete(object.data, "actor")})
- |> Repo.update()
-
- Object.invalid_object_cache(object)
-
- assert capture_log(fn ->
- {:error, :no_object_actor} = SideEffects.handle(delete)
- end) =~ "object doesn't have an actor"
- end
- end
-
- describe "EmojiReact objects" do
- setup do
- poster = insert(:user)
- user = insert(:user)
-
- {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
-
- {:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
- {:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
-
- %{emoji_react: emoji_react, user: user, poster: poster}
- end
-
- test "adds the reaction to the object", %{emoji_react: emoji_react, user: user} do
- {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
- object = Object.get_by_ap_id(emoji_react.data["object"])
-
- assert object.data["reaction_count"] == 1
- assert ["👌", [user.ap_id]] in object.data["reactions"]
- end
-
- test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
- {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
- assert Repo.get_by(Notification, user_id: poster.id, activity_id: emoji_react.id)
- end
- end
-
- describe "delete users with confirmation pending" do
- setup do
- user = insert(:user, confirmation_pending: true)
- {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
- {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
- {:ok, delete: delete_user, user: user}
- end
-
- test "when activation is not required", %{delete: delete, user: user} do
- clear_config([:instance, :account_activation_required], false)
- {:ok, _, _} = SideEffects.handle(delete)
- ObanHelpers.perform_all()
-
- assert User.get_cached_by_id(user.id).deactivated
- end
-
- test "when activation is required", %{delete: delete, user: user} do
- clear_config([:instance, :account_activation_required], true)
- {:ok, _, _} = SideEffects.handle(delete)
- ObanHelpers.perform_all()
-
- refute User.get_cached_by_id(user.id)
- end
- end
-
- describe "Undo objects" do
- setup do
- poster = insert(:user)
- user = insert(:user)
- {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
- {:ok, like} = CommonAPI.favorite(user, post.id)
- {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
- {:ok, announce} = CommonAPI.repeat(post.id, user)
- {:ok, block} = CommonAPI.block(user, poster)
-
- {:ok, undo_data, _meta} = Builder.undo(user, like)
- {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
-
- {:ok, undo_data, _meta} = Builder.undo(user, reaction)
- {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true)
-
- {:ok, undo_data, _meta} = Builder.undo(user, announce)
- {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true)
-
- {:ok, undo_data, _meta} = Builder.undo(user, block)
- {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
-
- %{
- like_undo: like_undo,
- post: post,
- like: like,
- reaction_undo: reaction_undo,
- reaction: reaction,
- announce_undo: announce_undo,
- announce: announce,
- block_undo: block_undo,
- block: block,
- poster: poster,
- user: user
- }
- end
-
- test "deletes the original block", %{
- block_undo: block_undo,
- block: block
- } do
- {:ok, _block_undo, _meta} = SideEffects.handle(block_undo)
-
- refute Activity.get_by_id(block.id)
- end
-
- test "unblocks the blocked user", %{block_undo: block_undo, block: block} do
- blocker = User.get_by_ap_id(block.data["actor"])
- blocked = User.get_by_ap_id(block.data["object"])
-
- {:ok, _block_undo, _} = SideEffects.handle(block_undo)
- refute User.blocks?(blocker, blocked)
- end
-
- test "an announce undo removes the announce from the object", %{
- announce_undo: announce_undo,
- post: post
- } do
- {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
-
- object = Object.get_by_ap_id(post.data["object"])
-
- assert object.data["announcement_count"] == 0
- assert object.data["announcements"] == []
- end
-
- test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do
- {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
- refute Activity.get_by_id(announce.id)
- end
-
- test "a reaction undo removes the reaction from the object", %{
- reaction_undo: reaction_undo,
- post: post
- } do
- {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
-
- object = Object.get_by_ap_id(post.data["object"])
-
- assert object.data["reaction_count"] == 0
- assert object.data["reactions"] == []
- end
-
- test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do
- {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
- refute Activity.get_by_id(reaction.id)
- end
-
- test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do
- {:ok, _like_undo, _} = SideEffects.handle(like_undo)
-
- object = Object.get_by_ap_id(post.data["object"])
-
- assert object.data["like_count"] == 0
- assert object.data["likes"] == []
- end
-
- test "deletes the original like", %{like_undo: like_undo, like: like} do
- {:ok, _like_undo, _} = SideEffects.handle(like_undo)
- refute Activity.get_by_id(like.id)
- end
- end
-
- describe "like objects" do
- setup do
- poster = insert(:user)
- user = insert(:user)
- {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
-
- {:ok, like_data, _meta} = Builder.like(user, post.object)
- {:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
-
- %{like: like, user: user, poster: poster}
- end
-
- test "add the like to the original object", %{like: like, user: user} do
- {:ok, like, _} = SideEffects.handle(like)
- object = Object.get_by_ap_id(like.data["object"])
- assert object.data["like_count"] == 1
- assert user.ap_id in object.data["likes"]
- end
-
- test "creates a notification", %{like: like, poster: poster} do
- {:ok, like, _} = SideEffects.handle(like)
- assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
- end
- end
-
- describe "creation of ChatMessages" do
- test "notifies the recipient" do
- author = insert(:user, local: false)
- recipient = insert(:user, local: true)
-
- {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
-
- {:ok, create_activity_data, _meta} =
- Builder.create(author, chat_message_data["id"], [recipient.ap_id])
-
- {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
-
- {:ok, _create_activity, _meta} =
- SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
-
- assert Repo.get_by(Notification, user_id: recipient.id, activity_id: create_activity.id)
- end
-
- test "it streams the created ChatMessage" do
- author = insert(:user, local: true)
- recipient = insert(:user, local: true)
-
- {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
-
- {:ok, create_activity_data, _meta} =
- Builder.create(author, chat_message_data["id"], [recipient.ap_id])
-
- {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
-
- {:ok, _create_activity, meta} =
- SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
-
- assert [_, _] = meta[:streamables]
- end
-
- test "it creates a Chat and MessageReferences for the local users and bumps the unread count, except for the author" do
- author = insert(:user, local: true)
- recipient = insert(:user, local: true)
-
- {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
-
- {:ok, create_activity_data, _meta} =
- Builder.create(author, chat_message_data["id"], [recipient.ap_id])
-
- {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
-
- with_mocks([
- {
- Pleroma.Web.Streamer,
- [],
- [
- stream: fn _, _ -> nil end
- ]
- },
- {
- Pleroma.Web.Push,
- [],
- [
- send: fn _ -> nil end
- ]
- }
- ]) do
- {:ok, _create_activity, meta} =
- SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
-
- # The notification gets created
- assert [notification] = meta[:notifications]
- assert notification.activity_id == create_activity.id
-
- # But it is not sent out
- refute called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
- refute called(Pleroma.Web.Push.send(notification))
-
- # Same for the user chat stream
- assert [{topics, _}, _] = meta[:streamables]
- assert topics == ["user", "user:pleroma_chat"]
- refute called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
-
- chat = Chat.get(author.id, recipient.ap_id)
-
- [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all()
-
- assert cm_ref.object.data["content"] == "hey"
- assert cm_ref.unread == false
-
- chat = Chat.get(recipient.id, author.ap_id)
-
- [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all()
-
- assert cm_ref.object.data["content"] == "hey"
- assert cm_ref.unread == true
- end
- end
-
- test "it creates a Chat for the local users and bumps the unread count" do
- author = insert(:user, local: false)
- recipient = insert(:user, local: true)
-
- {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
-
- {:ok, create_activity_data, _meta} =
- Builder.create(author, chat_message_data["id"], [recipient.ap_id])
-
- {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
-
- {:ok, _create_activity, _meta} =
- SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
-
- # An object is created
- assert Object.get_by_ap_id(chat_message_data["id"])
-
- # The remote user won't get a chat
- chat = Chat.get(author.id, recipient.ap_id)
- refute chat
-
- # The local user will get a chat
- chat = Chat.get(recipient.id, author.ap_id)
- assert chat
-
- author = insert(:user, local: true)
- recipient = insert(:user, local: true)
-
- {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
-
- {:ok, create_activity_data, _meta} =
- Builder.create(author, chat_message_data["id"], [recipient.ap_id])
-
- {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
-
- {:ok, _create_activity, _meta} =
- SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
-
- # Both users are local and get the chat
- chat = Chat.get(author.id, recipient.ap_id)
- assert chat
-
- chat = Chat.get(recipient.id, author.ap_id)
- assert chat
- end
- end
-
- describe "announce objects" do
- setup do
- poster = insert(:user)
- user = insert(:user)
- {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
- {:ok, private_post} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
-
- {:ok, announce_data, _meta} = Builder.announce(user, post.object, public: true)
-
- {:ok, private_announce_data, _meta} =
- Builder.announce(user, private_post.object, public: false)
-
- {:ok, relay_announce_data, _meta} =
- Builder.announce(Pleroma.Web.ActivityPub.Relay.get_actor(), post.object, public: true)
-
- {:ok, announce, _meta} = ActivityPub.persist(announce_data, local: true)
- {:ok, private_announce, _meta} = ActivityPub.persist(private_announce_data, local: true)
- {:ok, relay_announce, _meta} = ActivityPub.persist(relay_announce_data, local: true)
-
- %{
- announce: announce,
- user: user,
- poster: poster,
- private_announce: private_announce,
- relay_announce: relay_announce
- }
- end
-
- test "adds the announce to the original object", %{announce: announce, user: user} do
- {:ok, announce, _} = SideEffects.handle(announce)
- object = Object.get_by_ap_id(announce.data["object"])
- assert object.data["announcement_count"] == 1
- assert user.ap_id in object.data["announcements"]
- end
-
- test "does not add the announce to the original object if the actor is a service actor", %{
- relay_announce: announce
- } do
- {:ok, announce, _} = SideEffects.handle(announce)
- object = Object.get_by_ap_id(announce.data["object"])
- assert object.data["announcement_count"] == nil
- end
-
- test "creates a notification", %{announce: announce, poster: poster} do
- {:ok, announce, _} = SideEffects.handle(announce)
- assert Repo.get_by(Notification, user_id: poster.id, activity_id: announce.id)
- end
-
- test "it streams out the announce", %{announce: announce} do
- with_mocks([
- {
- Pleroma.Web.Streamer,
- [],
- [
- stream: fn _, _ -> nil end
- ]
- },
- {
- Pleroma.Web.Push,
- [],
- [
- send: fn _ -> nil end
- ]
- }
- ]) do
- {:ok, announce, _} = SideEffects.handle(announce)
-
- assert called(
- Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], announce)
- )
-
- assert called(Pleroma.Web.Push.send(:_))
- end
- end
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/accept_handling_test.exs b/test/web/activity_pub/transmogrifier/accept_handling_test.exs
deleted file mode 100644
index 77d468f5c..000000000
--- a/test/web/activity_pub/transmogrifier/accept_handling_test.exs
+++ /dev/null
@@ -1,91 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.AcceptHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- test "it works for incoming accepts which were pre-accepted" do
- follower = insert(:user)
- followed = insert(:user)
-
- {:ok, follower} = User.follow(follower, followed)
- assert User.following?(follower, followed) == true
-
- {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
-
- accept_data =
- File.read!("test/fixtures/mastodon-accept-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
-
- object =
- accept_data["object"]
- |> Map.put("actor", follower.ap_id)
- |> Map.put("id", follow_activity.data["id"])
-
- accept_data = Map.put(accept_data, "object", object)
-
- {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
- refute activity.local
-
- assert activity.data["object"] == follow_activity.data["id"]
-
- assert activity.data["id"] == accept_data["id"]
-
- follower = User.get_cached_by_id(follower.id)
-
- assert User.following?(follower, followed) == true
- end
-
- test "it works for incoming accepts which are referenced by IRI only" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
-
- accept_data =
- File.read!("test/fixtures/mastodon-accept-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
- |> Map.put("object", follow_activity.data["id"])
-
- {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
- assert activity.data["object"] == follow_activity.data["id"]
-
- follower = User.get_cached_by_id(follower.id)
-
- assert User.following?(follower, followed) == true
-
- follower = User.get_by_id(follower.id)
- assert follower.following_count == 1
-
- followed = User.get_by_id(followed.id)
- assert followed.follower_count == 1
- end
-
- test "it fails for incoming accepts which cannot be correlated" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- accept_data =
- File.read!("test/fixtures/mastodon-accept-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
-
- accept_data =
- Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
-
- {:error, _} = Transmogrifier.handle_incoming(accept_data)
-
- follower = User.get_cached_by_id(follower.id)
-
- refute User.following?(follower, followed) == true
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/announce_handling_test.exs b/test/web/activity_pub/transmogrifier/announce_handling_test.exs
deleted file mode 100644
index e895636b5..000000000
--- a/test/web/activity_pub/transmogrifier/announce_handling_test.exs
+++ /dev/null
@@ -1,172 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- test "it works for incoming honk announces" do
- user = insert(:user, ap_id: "https://honktest/u/test", local: false)
- other_user = insert(:user)
- {:ok, post} = CommonAPI.post(other_user, %{status: "bonkeronk"})
-
- announce = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "actor" => "https://honktest/u/test",
- "id" => "https://honktest/u/test/bonk/1793M7B9MQ48847vdx",
- "object" => post.data["object"],
- "published" => "2019-06-25T19:33:58Z",
- "to" => "https://www.w3.org/ns/activitystreams#Public",
- "type" => "Announce"
- }
-
- {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(announce)
-
- object = Object.get_by_ap_id(post.data["object"])
-
- assert length(object.data["announcements"]) == 1
- assert user.ap_id in object.data["announcements"]
- end
-
- test "it works for incoming announces with actor being inlined (kroeg)" do
- data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!()
-
- _user = insert(:user, local: false, ap_id: data["actor"]["id"])
- other_user = insert(:user)
-
- {:ok, post} = CommonAPI.post(other_user, %{status: "kroegeroeg"})
-
- data =
- data
- |> put_in(["object", "id"], post.data["object"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "https://puckipedia.com/"
- end
-
- test "it works for incoming announces, fetching the announced object" do
- data =
- File.read!("test/fixtures/mastodon-announce.json")
- |> Poison.decode!()
- |> Map.put("object", "http://mastodon.example.org/users/admin/statuses/99541947525187367")
-
- Tesla.Mock.mock(fn
- %{method: :get} ->
- %Tesla.Env{status: 200, body: File.read!("test/fixtures/mastodon-note-object.json")}
- end)
-
- _user = insert(:user, local: false, ap_id: data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Announce"
-
- assert data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
-
- assert data["object"] ==
- "http://mastodon.example.org/users/admin/statuses/99541947525187367"
-
- assert(Activity.get_create_by_object_ap_id(data["object"]))
- end
-
- @tag capture_log: true
- test "it works for incoming announces with an existing activity" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
-
- data =
- File.read!("test/fixtures/mastodon-announce.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- _user = insert(:user, local: false, ap_id: data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Announce"
-
- assert data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
-
- assert data["object"] == activity.data["object"]
-
- assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id
- end
-
- # Ignore inlined activities for now
- @tag skip: true
- test "it works for incoming announces with an inlined activity" do
- data =
- File.read!("test/fixtures/mastodon-announce-private.json")
- |> Poison.decode!()
-
- _user =
- insert(:user,
- local: false,
- ap_id: data["actor"],
- follower_address: data["actor"] <> "/followers"
- )
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Announce"
-
- assert data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
-
- object = Object.normalize(data["object"])
-
- assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368"
- assert object.data["content"] == "this is a private toot"
- end
-
- @tag capture_log: true
- test "it rejects incoming announces with an inlined activity from another origin" do
- Tesla.Mock.mock(fn
- %{method: :get} -> %Tesla.Env{status: 404, body: ""}
- end)
-
- data =
- File.read!("test/fixtures/bogus-mastodon-announce.json")
- |> Poison.decode!()
-
- _user = insert(:user, local: false, ap_id: data["actor"])
-
- assert {:error, e} = Transmogrifier.handle_incoming(data)
- end
-
- test "it does not clobber the addressing on announce activities" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
-
- data =
- File.read!("test/fixtures/mastodon-announce.json")
- |> Poison.decode!()
- |> Map.put("object", Object.normalize(activity).data["id"])
- |> Map.put("to", ["http://mastodon.example.org/users/admin/followers"])
- |> Map.put("cc", [])
-
- _user =
- insert(:user,
- local: false,
- ap_id: data["actor"],
- follower_address: "http://mastodon.example.org/users/admin/followers"
- )
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["to"] == ["http://mastodon.example.org/users/admin/followers"]
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/answer_handling_test.exs b/test/web/activity_pub/transmogrifier/answer_handling_test.exs
deleted file mode 100644
index 0f6605c3f..000000000
--- a/test/web/activity_pub/transmogrifier/answer_handling_test.exs
+++ /dev/null
@@ -1,78 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnswerHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- test "incoming, rewrites Note to Answer and increments vote counters" do
- user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- status: "suya...",
- poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
- })
-
- object = Object.normalize(activity)
-
- data =
- File.read!("test/fixtures/mastodon-vote.json")
- |> Poison.decode!()
- |> Kernel.put_in(["to"], user.ap_id)
- |> Kernel.put_in(["object", "inReplyTo"], object.data["id"])
- |> Kernel.put_in(["object", "to"], user.ap_id)
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
- answer_object = Object.normalize(activity)
- assert answer_object.data["type"] == "Answer"
- assert answer_object.data["inReplyTo"] == object.data["id"]
-
- new_object = Object.get_by_ap_id(object.data["id"])
- assert new_object.data["replies_count"] == object.data["replies_count"]
-
- assert Enum.any?(
- new_object.data["oneOf"],
- fn
- %{"name" => "suya..", "replies" => %{"totalItems" => 1}} -> true
- _ -> false
- end
- )
- end
-
- test "outgoing, rewrites Answer to Note" do
- user = insert(:user)
-
- {:ok, poll_activity} =
- CommonAPI.post(user, %{
- status: "suya...",
- poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10}
- })
-
- poll_object = Object.normalize(poll_activity)
- # TODO: Replace with CommonAPI vote creation when implemented
- data =
- File.read!("test/fixtures/mastodon-vote.json")
- |> Poison.decode!()
- |> Kernel.put_in(["to"], user.ap_id)
- |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"])
- |> Kernel.put_in(["object", "to"], user.ap_id)
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
- {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert data["object"]["type"] == "Note"
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/audio_handling_test.exs b/test/web/activity_pub/transmogrifier/audio_handling_test.exs
deleted file mode 100644
index 0636d00c5..000000000
--- a/test/web/activity_pub/transmogrifier/audio_handling_test.exs
+++ /dev/null
@@ -1,83 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do
- use Oban.Testing, repo: Pleroma.Repo
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.Transmogrifier
-
- import Pleroma.Factory
-
- test "it works for incoming listens" do
- _user = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
-
- data = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [],
- "type" => "Listen",
- "id" => "http://mastodon.example.org/users/admin/listens/1234/activity",
- "actor" => "http://mastodon.example.org/users/admin",
- "object" => %{
- "type" => "Audio",
- "id" => "http://mastodon.example.org/users/admin/listens/1234",
- "attributedTo" => "http://mastodon.example.org/users/admin",
- "title" => "lain radio episode 1",
- "artist" => "lain",
- "album" => "lain radio",
- "length" => 180_000
- }
- }
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- object = Object.normalize(activity)
-
- assert object.data["title"] == "lain radio episode 1"
- assert object.data["artist"] == "lain"
- assert object.data["album"] == "lain radio"
- assert object.data["length"] == 180_000
- end
-
- test "Funkwhale Audio object" do
- Tesla.Mock.mock(fn
- %{url: "https://channels.tests.funkwhale.audio/federation/actors/compositions"} ->
- %Tesla.Env{
- status: 200,
- body: File.read!("test/fixtures/tesla_mock/funkwhale_channel.json")
- }
- end)
-
- data = File.read!("test/fixtures/tesla_mock/funkwhale_create_audio.json") |> Poison.decode!()
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- assert object = Object.normalize(activity, false)
-
- assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
-
- assert object.data["cc"] == []
-
- assert object.data["url"] == "https://channels.tests.funkwhale.audio/library/tracks/74"
-
- assert object.data["attachment"] == [
- %{
- "mediaType" => "audio/ogg",
- "type" => "Link",
- "name" => nil,
- "url" => [
- %{
- "href" =>
- "https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false",
- "mediaType" => "audio/ogg",
- "type" => "Link"
- }
- ]
- }
- ]
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/block_handling_test.exs b/test/web/activity_pub/transmogrifier/block_handling_test.exs
deleted file mode 100644
index 71f1a0ed5..000000000
--- a/test/web/activity_pub/transmogrifier/block_handling_test.exs
+++ /dev/null
@@ -1,63 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.BlockHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Transmogrifier
-
- import Pleroma.Factory
-
- test "it works for incoming blocks" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-block-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- blocker = insert(:user, ap_id: data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Block"
- assert data["object"] == user.ap_id
- assert data["actor"] == "http://mastodon.example.org/users/admin"
-
- assert User.blocks?(blocker, user)
- end
-
- test "incoming blocks successfully tear down any follow relationship" do
- blocker = insert(:user)
- blocked = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-block-activity.json")
- |> Poison.decode!()
- |> Map.put("object", blocked.ap_id)
- |> Map.put("actor", blocker.ap_id)
-
- {:ok, blocker} = User.follow(blocker, blocked)
- {:ok, blocked} = User.follow(blocked, blocker)
-
- assert User.following?(blocker, blocked)
- assert User.following?(blocked, blocker)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Block"
- assert data["object"] == blocked.ap_id
- assert data["actor"] == blocker.ap_id
-
- blocker = User.get_cached_by_ap_id(data["actor"])
- blocked = User.get_cached_by_ap_id(data["object"])
-
- assert User.blocks?(blocker, blocked)
-
- refute User.following?(blocker, blocked)
- refute User.following?(blocked, blocker)
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/chat_message_test.exs b/test/web/activity_pub/transmogrifier/chat_message_test.exs
deleted file mode 100644
index 31274c067..000000000
--- a/test/web/activity_pub/transmogrifier/chat_message_test.exs
+++ /dev/null
@@ -1,171 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do
- use Pleroma.DataCase
-
- import Pleroma.Factory
-
- alias Pleroma.Activity
- alias Pleroma.Chat
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.Transmogrifier
-
- describe "handle_incoming" do
- test "handles chonks with attachment" do
- data = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "actor" => "https://honk.tedunangst.com/u/tedu",
- "id" => "https://honk.tedunangst.com/u/tedu/honk/x6gt8X8PcyGkQcXxzg1T",
- "object" => %{
- "attachment" => [
- %{
- "mediaType" => "image/jpeg",
- "name" => "298p3RG7j27tfsZ9RQ.jpg",
- "summary" => "298p3RG7j27tfsZ9RQ.jpg",
- "type" => "Document",
- "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg"
- }
- ],
- "attributedTo" => "https://honk.tedunangst.com/u/tedu",
- "content" => "",
- "id" => "https://honk.tedunangst.com/u/tedu/chonk/26L4wl5yCbn4dr4y1b",
- "published" => "2020-05-18T01:13:03Z",
- "to" => [
- "https://dontbulling.me/users/lain"
- ],
- "type" => "ChatMessage"
- },
- "published" => "2020-05-18T01:13:03Z",
- "to" => [
- "https://dontbulling.me/users/lain"
- ],
- "type" => "Create"
- }
-
- _user = insert(:user, ap_id: data["actor"])
- _user = insert(:user, ap_id: hd(data["to"]))
-
- assert {:ok, _activity} = Transmogrifier.handle_incoming(data)
- end
-
- test "it rejects messages that don't contain content" do
- data =
- File.read!("test/fixtures/create-chat-message.json")
- |> Poison.decode!()
-
- object =
- data["object"]
- |> Map.delete("content")
-
- data =
- data
- |> Map.put("object", object)
-
- _author =
- insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now())
-
- _recipient =
- insert(:user,
- ap_id: List.first(data["to"]),
- local: true,
- last_refreshed_at: DateTime.utc_now()
- )
-
- {:error, _} = Transmogrifier.handle_incoming(data)
- end
-
- test "it rejects messages that don't concern local users" do
- data =
- File.read!("test/fixtures/create-chat-message.json")
- |> Poison.decode!()
-
- _author =
- insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now())
-
- _recipient =
- insert(:user,
- ap_id: List.first(data["to"]),
- local: false,
- last_refreshed_at: DateTime.utc_now()
- )
-
- {:error, _} = Transmogrifier.handle_incoming(data)
- end
-
- test "it rejects messages where the `to` field of activity and object don't match" do
- data =
- File.read!("test/fixtures/create-chat-message.json")
- |> Poison.decode!()
-
- author = insert(:user, ap_id: data["actor"])
- _recipient = insert(:user, ap_id: List.first(data["to"]))
-
- data =
- data
- |> Map.put("to", author.ap_id)
-
- assert match?({:error, _}, Transmogrifier.handle_incoming(data))
- refute Object.get_by_ap_id(data["object"]["id"])
- end
-
- test "it fetches the actor if they aren't in our system" do
- Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
-
- data =
- File.read!("test/fixtures/create-chat-message.json")
- |> Poison.decode!()
- |> Map.put("actor", "http://mastodon.example.org/users/admin")
- |> put_in(["object", "actor"], "http://mastodon.example.org/users/admin")
-
- _recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
-
- {:ok, %Activity{} = _activity} = Transmogrifier.handle_incoming(data)
- end
-
- test "it doesn't work for deactivated users" do
- data =
- File.read!("test/fixtures/create-chat-message.json")
- |> Poison.decode!()
-
- _author =
- insert(:user,
- ap_id: data["actor"],
- local: false,
- last_refreshed_at: DateTime.utc_now(),
- deactivated: true
- )
-
- _recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
-
- assert {:error, _} = Transmogrifier.handle_incoming(data)
- end
-
- test "it inserts it and creates a chat" do
- data =
- File.read!("test/fixtures/create-chat-message.json")
- |> Poison.decode!()
-
- author =
- insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now())
-
- recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
-
- {:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(data)
- assert activity.local == false
-
- assert activity.actor == author.ap_id
- assert activity.recipients == [recipient.ap_id, author.ap_id]
-
- %Object{} = object = Object.get_by_ap_id(activity.data["object"])
-
- assert object
- assert object.data["content"] == "You expected a cute girl? Too bad. alert(&#39;XSS&#39;)"
- assert match?(%{"firefox" => _}, object.data["emoji"])
-
- refute Chat.get(author.id, recipient.ap_id)
- assert Chat.get(recipient.id, author.ap_id)
- end
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/delete_handling_test.exs b/test/web/activity_pub/transmogrifier/delete_handling_test.exs
deleted file mode 100644
index c9a53918c..000000000
--- a/test/web/activity_pub/transmogrifier/delete_handling_test.exs
+++ /dev/null
@@ -1,114 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do
- use Oban.Testing, repo: Pleroma.Repo
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Tests.ObanHelpers
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Transmogrifier
-
- import Pleroma.Factory
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- test "it works for incoming deletes" do
- activity = insert(:note_activity)
- deleting_user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-delete.json")
- |> Poison.decode!()
- |> Map.put("actor", deleting_user.ap_id)
- |> put_in(["object", "id"], activity.data["object"])
-
- {:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
- Transmogrifier.handle_incoming(data)
-
- assert id == data["id"]
-
- # We delete the Create activity because we base our timelines on it.
- # This should be changed after we unify objects and activities
- refute Activity.get_by_id(activity.id)
- assert actor == deleting_user.ap_id
-
- # Objects are replaced by a tombstone object.
- object = Object.normalize(activity.data["object"])
- assert object.data["type"] == "Tombstone"
- end
-
- test "it works for incoming when the object has been pruned" do
- activity = insert(:note_activity)
-
- {:ok, object} =
- Object.normalize(activity.data["object"])
- |> Repo.delete()
-
- Cachex.del(:object_cache, "object:#{object.data["id"]}")
-
- deleting_user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-delete.json")
- |> Poison.decode!()
- |> Map.put("actor", deleting_user.ap_id)
- |> put_in(["object", "id"], activity.data["object"])
-
- {:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
- Transmogrifier.handle_incoming(data)
-
- assert id == data["id"]
-
- # We delete the Create activity because we base our timelines on it.
- # This should be changed after we unify objects and activities
- refute Activity.get_by_id(activity.id)
- assert actor == deleting_user.ap_id
- end
-
- test "it fails for incoming deletes with spoofed origin" do
- activity = insert(:note_activity)
- %{ap_id: ap_id} = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo")
-
- data =
- File.read!("test/fixtures/mastodon-delete.json")
- |> Poison.decode!()
- |> Map.put("actor", ap_id)
- |> put_in(["object", "id"], activity.data["object"])
-
- assert match?({:error, _}, Transmogrifier.handle_incoming(data))
- end
-
- @tag capture_log: true
- test "it works for incoming user deletes" do
- %{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
-
- data =
- File.read!("test/fixtures/mastodon-delete-user.json")
- |> Poison.decode!()
-
- {:ok, _} = Transmogrifier.handle_incoming(data)
- ObanHelpers.perform_all()
-
- assert User.get_cached_by_ap_id(ap_id).deactivated
- end
-
- test "it fails for incoming user deletes with spoofed origin" do
- %{ap_id: ap_id} = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-delete-user.json")
- |> Poison.decode!()
- |> Map.put("actor", ap_id)
-
- assert match?({:error, _}, Transmogrifier.handle_incoming(data))
-
- assert User.get_cached_by_ap_id(ap_id)
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs b/test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs
deleted file mode 100644
index 0fb056b50..000000000
--- a/test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs
+++ /dev/null
@@ -1,61 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- test "it works for incoming emoji reactions" do
- user = insert(:user)
- other_user = insert(:user, local: false)
- {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
-
- data =
- File.read!("test/fixtures/emoji-reaction.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
- |> Map.put("actor", other_user.ap_id)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == other_user.ap_id
- assert data["type"] == "EmojiReact"
- assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
- assert data["object"] == activity.data["object"]
- assert data["content"] == "👌"
-
- object = Object.get_by_ap_id(data["object"])
-
- assert object.data["reaction_count"] == 1
- assert match?([["👌", _]], object.data["reactions"])
- end
-
- test "it reject invalid emoji reactions" do
- user = insert(:user)
- other_user = insert(:user, local: false)
- {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
-
- data =
- File.read!("test/fixtures/emoji-reaction-too-long.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
- |> Map.put("actor", other_user.ap_id)
-
- assert {:error, _} = Transmogrifier.handle_incoming(data)
-
- data =
- File.read!("test/fixtures/emoji-reaction-no-emoji.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
- |> Map.put("actor", other_user.ap_id)
-
- assert {:error, _} = Transmogrifier.handle_incoming(data)
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/event_handling_test.exs b/test/web/activity_pub/transmogrifier/event_handling_test.exs
deleted file mode 100644
index 7f1ef2cbd..000000000
--- a/test/web/activity_pub/transmogrifier/event_handling_test.exs
+++ /dev/null
@@ -1,40 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.EventHandlingTest do
- use Oban.Testing, repo: Pleroma.Repo
- use Pleroma.DataCase
-
- alias Pleroma.Object.Fetcher
-
- test "Mobilizon Event object" do
- Tesla.Mock.mock(fn
- %{url: "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"} ->
- %Tesla.Env{
- status: 200,
- body: File.read!("test/fixtures/tesla_mock/mobilizon.org-event.json")
- }
-
- %{url: "https://mobilizon.org/@tcit"} ->
- %Tesla.Env{
- status: 200,
- body: File.read!("test/fixtures/tesla_mock/mobilizon.org-user.json")
- }
- end)
-
- assert {:ok, object} =
- Fetcher.fetch_object_from_id(
- "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
- )
-
- assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
- assert object.data["cc"] == []
-
- assert object.data["url"] ==
- "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
-
- assert object.data["published"] == "2019-12-17T11:33:56Z"
- assert object.data["name"] == "Mobilizon Launching Party"
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs
deleted file mode 100644
index 757d90941..000000000
--- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs
+++ /dev/null
@@ -1,208 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
- use Pleroma.DataCase
- alias Pleroma.Activity
- alias Pleroma.Notification
- alias Pleroma.Repo
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.ActivityPub.Utils
-
- import Pleroma.Factory
- import Ecto.Query
- import Mock
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- describe "handle_incoming" do
- setup do: clear_config([:user, :deny_follow_blocked])
-
- test "it works for osada follow request" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/osada-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "https://apfed.club/channel/indio"
- assert data["type"] == "Follow"
- assert data["id"] == "https://apfed.club/follow/9"
-
- activity = Repo.get(Activity, activity.id)
- assert activity.data["state"] == "accept"
- assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
- end
-
- test "it works for incoming follow requests" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Follow"
- assert data["id"] == "http://mastodon.example.org/users/admin#follows/2"
-
- activity = Repo.get(Activity, activity.id)
- assert activity.data["state"] == "accept"
- assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
-
- [notification] = Notification.for_user(user)
- assert notification.type == "follow"
- end
-
- test "with locked accounts, it does create a Follow, but not an Accept" do
- 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["state"] == "pending"
-
- refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
-
- accepts =
- from(
- a in Activity,
- where: fragment("?->>'type' = ?", a.data, "Accept")
- )
- |> Repo.all()
-
- assert Enum.empty?(accepts)
-
- [notification] = Notification.for_user(user)
- assert notification.type == "follow_request"
- end
-
- test "it works for follow requests when you are already followed, creating a new accept activity" do
- # This is important because the remote might have the wrong idea about the
- # current follow status. This can lead to instance A thinking that x@A is
- # followed by y@B, but B thinks they are not. In this case, the follow can
- # never go through again because it will never get an Accept.
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
-
- accepts =
- from(
- a in Activity,
- where: fragment("?->>'type' = ?", a.data, "Accept")
- )
- |> Repo.all()
-
- assert length(accepts) == 1
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("id", String.replace(data["id"], "2", "3"))
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
-
- accepts =
- from(
- a in Activity,
- where: fragment("?->>'type' = ?", a.data, "Accept")
- )
- |> Repo.all()
-
- assert length(accepts) == 2
- end
-
- test "it rejects incoming follow requests from blocked users when deny_follow_blocked is enabled" do
- Pleroma.Config.put([:user, :deny_follow_blocked], true)
-
- user = insert(:user)
- {:ok, target} = User.get_or_fetch("http://mastodon.example.org/users/admin")
-
- {:ok, _user_relationship} = User.block(user, target)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
-
- %Activity{} = activity = Activity.get_by_ap_id(id)
-
- assert activity.data["state"] == "reject"
- end
-
- test "it rejects incoming follow requests if the following errors for some reason" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- with_mock Pleroma.User, [:passthrough], follow: fn _, _, _ -> {:error, :testing} end do
- {:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
-
- %Activity{} = activity = Activity.get_by_ap_id(id)
-
- assert activity.data["state"] == "reject"
- end
- end
-
- test "it works for incoming follow requests from hubzilla" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/hubzilla-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
- |> Utils.normalize_params()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
- assert data["type"] == "Follow"
- assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
- assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
- end
-
- test "it works for incoming follows to locked account" do
- pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
- user = insert(:user, locked: true)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Follow"
- assert data["object"] == user.ap_id
- assert data["state"] == "pending"
- assert data["actor"] == "http://mastodon.example.org/users/admin"
-
- assert [^pending_follower] = User.get_follow_requests(user)
- end
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/like_handling_test.exs b/test/web/activity_pub/transmogrifier/like_handling_test.exs
deleted file mode 100644
index 53fe1d550..000000000
--- a/test/web/activity_pub/transmogrifier/like_handling_test.exs
+++ /dev/null
@@ -1,78 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- test "it works for incoming likes" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
-
- data =
- File.read!("test/fixtures/mastodon-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- _actor = insert(:user, ap_id: data["actor"], local: false)
-
- {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- refute Enum.empty?(activity.recipients)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Like"
- assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
- assert data["object"] == activity.data["object"]
- end
-
- test "it works for incoming misskey likes, turning them into EmojiReacts" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
-
- data =
- File.read!("test/fixtures/misskey-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- _actor = insert(:user, ap_id: data["actor"], local: false)
-
- {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert activity_data["actor"] == data["actor"]
- assert activity_data["type"] == "EmojiReact"
- assert activity_data["id"] == data["id"]
- assert activity_data["object"] == activity.data["object"]
- assert activity_data["content"] == "🍮"
- end
-
- test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReacts" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
-
- data =
- File.read!("test/fixtures/misskey-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
- |> Map.put("_misskey_reaction", "⭐")
-
- _actor = insert(:user, ap_id: data["actor"], local: false)
-
- {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert activity_data["actor"] == data["actor"]
- assert activity_data["type"] == "EmojiReact"
- assert activity_data["id"] == data["id"]
- assert activity_data["object"] == activity.data["object"]
- assert activity_data["content"] == "⭐"
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs
deleted file mode 100644
index c82361828..000000000
--- a/test/web/activity_pub/transmogrifier/question_handling_test.exs
+++ /dev/null
@@ -1,125 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- test "Mastodon Question activity" do
- data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!()
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- object = Object.normalize(activity, false)
-
- assert object.data["url"] == "https://mastodon.sdf.org/@rinpatch/102070944809637304"
-
- assert object.data["closed"] == "2019-05-11T09:03:36Z"
-
- assert object.data["context"] == activity.data["context"]
-
- assert object.data["context"] ==
- "tag:mastodon.sdf.org,2019-05-10:objectId=15095122:objectType=Conversation"
-
- assert object.data["context_id"]
-
- assert object.data["anyOf"] == []
-
- assert Enum.sort(object.data["oneOf"]) ==
- Enum.sort([
- %{
- "name" => "25 char limit is dumb",
- "replies" => %{"totalItems" => 0, "type" => "Collection"},
- "type" => "Note"
- },
- %{
- "name" => "Dunno",
- "replies" => %{"totalItems" => 0, "type" => "Collection"},
- "type" => "Note"
- },
- %{
- "name" => "Everyone knows that!",
- "replies" => %{"totalItems" => 1, "type" => "Collection"},
- "type" => "Note"
- },
- %{
- "name" => "I can't even fit a funny",
- "replies" => %{"totalItems" => 1, "type" => "Collection"},
- "type" => "Note"
- }
- ])
-
- user = insert(:user)
-
- {:ok, reply_activity} = CommonAPI.post(user, %{status: "hewwo", in_reply_to_id: activity.id})
-
- reply_object = Object.normalize(reply_activity, false)
-
- assert reply_object.data["context"] == object.data["context"]
- assert reply_object.data["context_id"] == object.data["context_id"]
- end
-
- test "Mastodon Question activity with HTML tags in plaintext" do
- options = [
- %{
- "type" => "Note",
- "name" => "<input type=\"date\">",
- "replies" => %{"totalItems" => 0, "type" => "Collection"}
- },
- %{
- "type" => "Note",
- "name" => "<input type=\"date\"/>",
- "replies" => %{"totalItems" => 0, "type" => "Collection"}
- },
- %{
- "type" => "Note",
- "name" => "<input type=\"date\" />",
- "replies" => %{"totalItems" => 1, "type" => "Collection"}
- },
- %{
- "type" => "Note",
- "name" => "<input type=\"date\"></input>",
- "replies" => %{"totalItems" => 1, "type" => "Collection"}
- }
- ]
-
- data =
- File.read!("test/fixtures/mastodon-question-activity.json")
- |> Poison.decode!()
- |> Kernel.put_in(["object", "oneOf"], options)
-
- {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(activity, false)
-
- assert Enum.sort(object.data["oneOf"]) == Enum.sort(options)
- end
-
- test "returns an error if received a second time" do
- data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!()
-
- assert {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- assert {:error, {:validate_object, {:error, _}}} = Transmogrifier.handle_incoming(data)
- end
-
- test "accepts a Question with no content" do
- data =
- File.read!("test/fixtures/mastodon-question-activity.json")
- |> Poison.decode!()
- |> Kernel.put_in(["object", "content"], "")
-
- assert {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/reject_handling_test.exs b/test/web/activity_pub/transmogrifier/reject_handling_test.exs
deleted file mode 100644
index 7592fbe1c..000000000
--- a/test/web/activity_pub/transmogrifier/reject_handling_test.exs
+++ /dev/null
@@ -1,67 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.RejectHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- test "it fails for incoming rejects which cannot be correlated" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- accept_data =
- File.read!("test/fixtures/mastodon-reject-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
-
- accept_data =
- Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
-
- {:error, _} = Transmogrifier.handle_incoming(accept_data)
-
- follower = User.get_cached_by_id(follower.id)
-
- refute User.following?(follower, followed) == true
- end
-
- test "it works for incoming rejects which are referenced by IRI only" do
- follower = insert(:user)
- followed = insert(:user, locked: true)
-
- {:ok, follower} = User.follow(follower, followed)
- {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
-
- assert User.following?(follower, followed) == true
-
- reject_data =
- File.read!("test/fixtures/mastodon-reject-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", followed.ap_id)
- |> Map.put("object", follow_activity.data["id"])
-
- {:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data)
-
- follower = User.get_cached_by_id(follower.id)
-
- assert User.following?(follower, followed) == false
- end
-
- test "it rejects activities without a valid ID" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
- |> Map.put("id", "")
-
- :error = Transmogrifier.handle_incoming(data)
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs
deleted file mode 100644
index 8683f7135..000000000
--- a/test/web/activity_pub/transmogrifier/undo_handling_test.exs
+++ /dev/null
@@ -1,185 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- test "it works for incoming emoji reaction undos" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
- {:ok, reaction_activity} = CommonAPI.react_with_emoji(activity.id, user, "👌")
-
- data =
- File.read!("test/fixtures/mastodon-undo-like.json")
- |> Poison.decode!()
- |> Map.put("object", reaction_activity.data["id"])
- |> Map.put("actor", user.ap_id)
-
- {:ok, activity} = Transmogrifier.handle_incoming(data)
-
- assert activity.actor == user.ap_id
- assert activity.data["id"] == data["id"]
- assert activity.data["type"] == "Undo"
- end
-
- test "it returns an error for incoming unlikes wihout a like activity" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
-
- data =
- File.read!("test/fixtures/mastodon-undo-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- assert Transmogrifier.handle_incoming(data) == :error
- end
-
- test "it works for incoming unlikes with an existing like activity" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
-
- like_data =
- File.read!("test/fixtures/mastodon-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- _liker = insert(:user, ap_id: like_data["actor"], local: false)
-
- {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
-
- data =
- File.read!("test/fixtures/mastodon-undo-like.json")
- |> Poison.decode!()
- |> Map.put("object", like_data)
- |> Map.put("actor", like_data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Undo"
- assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
- assert data["object"] == "http://mastodon.example.org/users/admin#likes/2"
-
- note = Object.get_by_ap_id(like_data["object"])
- assert note.data["like_count"] == 0
- assert note.data["likes"] == []
- end
-
- test "it works for incoming unlikes with an existing like activity and a compact object" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
-
- like_data =
- File.read!("test/fixtures/mastodon-like.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- _liker = insert(:user, ap_id: like_data["actor"], local: false)
-
- {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
-
- data =
- File.read!("test/fixtures/mastodon-undo-like.json")
- |> Poison.decode!()
- |> Map.put("object", like_data["id"])
- |> Map.put("actor", like_data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Undo"
- assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
- assert data["object"] == "http://mastodon.example.org/users/admin#likes/2"
- end
-
- test "it works for incoming unannounces with an existing notice" do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
-
- announce_data =
- File.read!("test/fixtures/mastodon-announce.json")
- |> Poison.decode!()
- |> Map.put("object", activity.data["object"])
-
- _announcer = insert(:user, ap_id: announce_data["actor"], local: false)
-
- {:ok, %Activity{data: announce_data, local: false}} =
- Transmogrifier.handle_incoming(announce_data)
-
- data =
- File.read!("test/fixtures/mastodon-undo-announce.json")
- |> Poison.decode!()
- |> Map.put("object", announce_data)
- |> Map.put("actor", announce_data["actor"])
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Undo"
-
- assert data["object"] ==
- "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
- end
-
- test "it works for incoming unfollows with an existing follow" do
- user = insert(:user)
-
- follow_data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- _follower = insert(:user, ap_id: follow_data["actor"], local: false)
-
- {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data)
-
- data =
- File.read!("test/fixtures/mastodon-unfollow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", follow_data)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Undo"
- assert data["object"]["type"] == "Follow"
- assert data["object"]["object"] == user.ap_id
- assert data["actor"] == "http://mastodon.example.org/users/admin"
-
- refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
- end
-
- test "it works for incoming unblocks with an existing block" do
- user = insert(:user)
-
- block_data =
- File.read!("test/fixtures/mastodon-block-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- _blocker = insert(:user, ap_id: block_data["actor"], local: false)
-
- {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data)
-
- data =
- File.read!("test/fixtures/mastodon-unblock-activity.json")
- |> Poison.decode!()
- |> Map.put("object", block_data)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- assert data["type"] == "Undo"
- assert data["object"] == block_data["id"]
-
- blocker = User.get_cached_by_ap_id(data["actor"])
-
- refute User.blocks?(blocker, user)
- end
-end
diff --git a/test/web/activity_pub/transmogrifier/user_update_handling_test.exs b/test/web/activity_pub/transmogrifier/user_update_handling_test.exs
deleted file mode 100644
index 64636656c..000000000
--- a/test/web/activity_pub/transmogrifier/user_update_handling_test.exs
+++ /dev/null
@@ -1,159 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.Transmogrifier.UserUpdateHandlingTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Transmogrifier
-
- import Pleroma.Factory
-
- test "it works for incoming update activities" do
- user = insert(:user, local: false)
-
- update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
-
- object =
- update_data["object"]
- |> Map.put("actor", user.ap_id)
- |> Map.put("id", user.ap_id)
-
- update_data =
- update_data
- |> Map.put("actor", user.ap_id)
- |> Map.put("object", object)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
-
- assert data["id"] == update_data["id"]
-
- user = User.get_cached_by_ap_id(data["actor"])
- assert user.name == "gargle"
-
- assert user.avatar["url"] == [
- %{
- "href" =>
- "https://cd.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
- }
- ]
-
- assert user.banner["url"] == [
- %{
- "href" =>
- "https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
- }
- ]
-
- assert user.bio == "<p>Some bio</p>"
- end
-
- test "it works with alsoKnownAs" do
- %{ap_id: actor} = insert(:user, local: false)
-
- assert User.get_cached_by_ap_id(actor).also_known_as == []
-
- {:ok, _activity} =
- "test/fixtures/mastodon-update.json"
- |> File.read!()
- |> Poison.decode!()
- |> Map.put("actor", actor)
- |> Map.update!("object", fn object ->
- object
- |> Map.put("actor", actor)
- |> Map.put("id", actor)
- |> Map.put("alsoKnownAs", [
- "http://mastodon.example.org/users/foo",
- "http://example.org/users/bar"
- ])
- end)
- |> Transmogrifier.handle_incoming()
-
- assert User.get_cached_by_ap_id(actor).also_known_as == [
- "http://mastodon.example.org/users/foo",
- "http://example.org/users/bar"
- ]
- end
-
- test "it works with custom profile fields" do
- user = insert(:user, local: false)
-
- assert user.fields == []
-
- update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
-
- object =
- update_data["object"]
- |> Map.put("actor", user.ap_id)
- |> Map.put("id", user.ap_id)
-
- update_data =
- update_data
- |> Map.put("actor", user.ap_id)
- |> Map.put("object", object)
-
- {:ok, _update_activity} = Transmogrifier.handle_incoming(update_data)
-
- user = User.get_cached_by_ap_id(user.ap_id)
-
- assert user.fields == [
- %{"name" => "foo", "value" => "updated"},
- %{"name" => "foo1", "value" => "updated"}
- ]
-
- Pleroma.Config.put([:instance, :max_remote_account_fields], 2)
-
- update_data =
- update_data
- |> put_in(["object", "attachment"], [
- %{"name" => "foo", "type" => "PropertyValue", "value" => "bar"},
- %{"name" => "foo11", "type" => "PropertyValue", "value" => "bar11"},
- %{"name" => "foo22", "type" => "PropertyValue", "value" => "bar22"}
- ])
- |> Map.put("id", update_data["id"] <> ".")
-
- {:ok, _} = Transmogrifier.handle_incoming(update_data)
-
- user = User.get_cached_by_ap_id(user.ap_id)
-
- assert user.fields == [
- %{"name" => "foo", "value" => "updated"},
- %{"name" => "foo1", "value" => "updated"}
- ]
-
- update_data =
- update_data
- |> put_in(["object", "attachment"], [])
- |> Map.put("id", update_data["id"] <> ".")
-
- {:ok, _} = Transmogrifier.handle_incoming(update_data)
-
- user = User.get_cached_by_ap_id(user.ap_id)
-
- assert user.fields == []
- end
-
- test "it works for incoming update activities which lock the account" do
- user = insert(:user, local: false)
-
- update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
-
- object =
- update_data["object"]
- |> Map.put("actor", user.ap_id)
- |> Map.put("id", user.ap_id)
- |> Map.put("manuallyApprovesFollowers", true)
-
- update_data =
- update_data
- |> Map.put("actor", user.ap_id)
- |> Map.put("object", object)
-
- {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(update_data)
-
- user = User.get_cached_by_ap_id(user.ap_id)
- assert user.locked == true
- end
-end
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
deleted file mode 100644
index 3fa41b0c7..000000000
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ /dev/null
@@ -1,1379 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
- use Oban.Testing, repo: Pleroma.Repo
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Object.Fetcher
- alias Pleroma.Tests.ObanHelpers
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.AdminAPI.AccountView
- alias Pleroma.Web.CommonAPI
-
- import Mock
- import Pleroma.Factory
- import ExUnit.CaptureLog
-
- setup_all do
- Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
- :ok
- end
-
- setup do: clear_config([:instance, :max_remote_account_fields])
-
- describe "handle_incoming" do
- test "it works for incoming notices with tag not being an array (kroeg)" do
- data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert object.data["emoji"] == %{
- "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
- }
-
- data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert "test" in object.data["tag"]
- end
-
- test "it works for incoming notices with url not being a string (prismo)" do
- data = File.read!("test/fixtures/prismo-url-map.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert object.data["url"] == "https://prismo.news/posts/83"
- end
-
- test "it cleans up incoming notices which are not really DMs" do
- user = insert(:user)
- other_user = insert(:user)
-
- to = [user.ap_id, other_user.ap_id]
-
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("to", to)
- |> Map.put("cc", [])
-
- object =
- data["object"]
- |> Map.put("to", to)
- |> Map.put("cc", [])
-
- data = Map.put(data, "object", object)
-
- {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
-
- assert data["to"] == []
- assert data["cc"] == to
-
- object_data = Object.normalize(activity).data
-
- assert object_data["to"] == []
- assert object_data["cc"] == to
- end
-
- test "it ignores an incoming notice if we already have it" do
- activity = insert(:note_activity)
-
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("object", Object.normalize(activity).data)
-
- {:ok, returned_activity} = Transmogrifier.handle_incoming(data)
-
- assert activity == returned_activity
- end
-
- @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!()
-
- object =
- data["object"]
- |> Map.put("inReplyTo", "https://shitposter.club/notice/2827873")
-
- data = Map.put(data, "object", object)
- {:ok, returned_activity} = Transmogrifier.handle_incoming(data)
- returned_object = Object.normalize(returned_activity, false)
-
- assert activity =
- Activity.get_create_by_object_ap_id(
- "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
- )
-
- assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
- end
-
- 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!()
-
- object =
- data["object"]
- |> Map.put("inReplyTo", "https://shitposter.club/notice/2827873")
-
- data = Map.put(data, "object", object)
-
- with_mock Pleroma.Web.Federator,
- allowed_thread_distance?: fn _ -> false end do
- {:ok, returned_activity} = Transmogrifier.handle_incoming(data)
-
- returned_object = Object.normalize(returned_activity, false)
-
- refute Activity.get_create_by_object_ap_id(
- "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
- )
-
- assert returned_object.data["inReplyToAtomUri"] ==
- "https://shitposter.club/notice/2827873"
- end
- end
-
- test "it does not crash if the object in inReplyTo can't be fetched" do
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
-
- object =
- data["object"]
- |> Map.put("inReplyTo", "https://404.site/whatever")
-
- data =
- data
- |> Map.put("object", object)
-
- assert capture_log(fn ->
- {:ok, _returned_activity} = Transmogrifier.handle_incoming(data)
- end) =~ "[warn] Couldn't fetch \"https://404.site/whatever\", error: nil"
- end
-
- test "it does not work for deactivated users" do
- data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
-
- insert(:user, ap_id: data["actor"], deactivated: true)
-
- assert {:error, _} = Transmogrifier.handle_incoming(data)
- end
-
- test "it works for incoming notices" do
- data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99512778738411822/activity"
-
- assert data["context"] ==
- "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
-
- assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
-
- assert data["cc"] == [
- "http://mastodon.example.org/users/admin/followers",
- "http://localtesting.pleroma.lol/users/lain"
- ]
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
-
- object_data = Object.normalize(data["object"]).data
-
- assert object_data["id"] ==
- "http://mastodon.example.org/users/admin/statuses/99512778738411822"
-
- assert object_data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
-
- assert object_data["cc"] == [
- "http://mastodon.example.org/users/admin/followers",
- "http://localtesting.pleroma.lol/users/lain"
- ]
-
- assert object_data["actor"] == "http://mastodon.example.org/users/admin"
- assert object_data["attributedTo"] == "http://mastodon.example.org/users/admin"
-
- assert object_data["context"] ==
- "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
-
- assert object_data["sensitive"] == true
-
- user = User.get_cached_by_ap_id(object_data["actor"])
-
- assert user.note_count == 1
- end
-
- test "it works for incoming notices with hashtags" do
- data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert Enum.at(object.data["tag"], 2) == "moo"
- end
-
- test "it works for incoming notices with contentMap" do
- data =
- File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert object.data["content"] ==
- "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
- end
-
- test "it works for incoming notices with to/cc not being an array (kroeg)" do
- data = File.read!("test/fixtures/kroeg-post-activity.json") |> Poison.decode!()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
- object = Object.normalize(data["object"])
-
- assert object.data["content"] ==
- "<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
- end
-
- test "it ensures that as:Public activities make it to their followers collection" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", user.ap_id)
- |> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"])
- |> Map.put("cc", [])
-
- object =
- data["object"]
- |> Map.put("attributedTo", user.ap_id)
- |> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"])
- |> Map.put("cc", [])
- |> Map.put("id", user.ap_id <> "/activities/12345678")
-
- data = Map.put(data, "object", object)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["cc"] == [User.ap_followers(user)]
- end
-
- test "it ensures that address fields become lists" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("actor", user.ap_id)
- |> Map.put("to", nil)
- |> Map.put("cc", nil)
-
- object =
- data["object"]
- |> Map.put("attributedTo", user.ap_id)
- |> Map.put("to", nil)
- |> Map.put("cc", nil)
- |> Map.put("id", user.ap_id <> "/activities/12345678")
-
- data = Map.put(data, "object", object)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert !is_nil(data["to"])
- assert !is_nil(data["cc"])
- end
-
- test "it strips internal likes" do
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
-
- likes = %{
- "first" =>
- "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes?page=1",
- "id" => "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes",
- "totalItems" => 3,
- "type" => "OrderedCollection"
- }
-
- object = Map.put(data["object"], "likes", likes)
- data = Map.put(data, "object", object)
-
- {:ok, %Activity{object: object}} = Transmogrifier.handle_incoming(data)
-
- 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 unfollows with an existing follow" do
- user = insert(:user)
-
- follow_data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data)
-
- data =
- File.read!("test/fixtures/mastodon-unfollow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", follow_data)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["type"] == "Undo"
- assert data["object"]["type"] == "Follow"
- assert data["object"]["object"] == user.ap_id
- assert data["actor"] == "http://mastodon.example.org/users/admin"
-
- refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
- end
-
- test "skip converting the content when it is nil" do
- object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe"
-
- {:ok, object} = Fetcher.fetch_and_contain_remote_object_from_id(object_id)
-
- result =
- Pleroma.Web.ActivityPub.Transmogrifier.fix_object(Map.merge(object, %{"content" => nil}))
-
- assert result["content"] == nil
- end
-
- test "it converts content of object to html" do
- object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe"
-
- {:ok, %{"content" => content_markdown}} =
- Fetcher.fetch_and_contain_remote_object_from_id(object_id)
-
- {:ok, %Pleroma.Object{data: %{"content" => content}} = object} =
- Fetcher.fetch_object_from_id(object_id)
-
- assert content_markdown ==
- "Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership\n\nTwenty Years in Jail: FreeBSD's Jails, Then and Now\n\nJails started as a limited virtualization system, but over the last two years they've..."
-
- assert content ==
- "<p>Support this and our other Michigan!/usr/group videos and meetings. Learn more at <a href=\"http://mug.org/membership\">http://mug.org/membership</a></p><p>Twenty Years in Jail: FreeBSD’s Jails, Then and Now</p><p>Jails started as a limited virtualization system, but over the last two years they’ve…</p>"
-
- assert object.data["mediaType"] == "text/html"
- end
-
- test "it remaps video URLs as attachments if necessary" do
- {:ok, object} =
- Fetcher.fetch_object_from_id(
- "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
- )
-
- assert object.data["url"] ==
- "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
-
- assert object.data["attachment"] == [
- %{
- "type" => "Link",
- "mediaType" => "video/mp4",
- "url" => [
- %{
- "href" =>
- "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
- "mediaType" => "video/mp4",
- "type" => "Link"
- }
- ]
- }
- ]
-
- {:ok, object} =
- Fetcher.fetch_object_from_id(
- "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"
- )
-
- assert object.data["attachment"] == [
- %{
- "type" => "Link",
- "mediaType" => "video/mp4",
- "url" => [
- %{
- "href" =>
- "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4",
- "mediaType" => "video/mp4",
- "type" => "Link"
- }
- ]
- }
- ]
-
- assert object.data["url"] ==
- "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"
- end
-
- test "it accepts Flag activities" do
- user = insert(:user)
- other_user = insert(:user)
-
- {: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, skip_visibility_check: true})
- }
-
- message = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "cc" => [user.ap_id],
- "object" => [user.ap_id, activity.data["id"]],
- "type" => "Flag",
- "content" => "blocked AND reported!!!",
- "actor" => other_user.ap_id
- }
-
- assert {:ok, activity} = Transmogrifier.handle_incoming(message)
-
- 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 correctly processes messages with weirdness in address fields" do
- user = insert(:user)
-
- message = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "to" => [nil, user.follower_address],
- "cc" => ["https://www.w3.org/ns/activitystreams#Public", ["¿"]],
- "type" => "Create",
- "object" => %{
- "content" => "…",
- "type" => "Note",
- "attributedTo" => user.ap_id,
- "inReplyTo" => nil
- },
- "actor" => user.ap_id
- }
-
- assert {:ok, activity} = Transmogrifier.handle_incoming(message)
-
- assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"]
- assert [user.follower_address] == activity.data["to"]
- end
-
- test "it accepts Move activities" do
- old_user = insert(:user)
- new_user = insert(:user)
-
- 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
- setup do: clear_config([:activitypub, :note_replies_output_limit], 5)
- setup do: 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
- setup do: clear_config([:activitypub, :note_replies_output_limit], 5)
- setup do: 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)
-
- {:ok, activity} =
- CommonAPI.post(user, %{status: "hey, @#{other_user.nickname}, how are ya? #2hu"})
-
- with_mock Pleroma.Notification,
- get_notified_from_activity: fn _, _ -> [] end do
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- object = modified["object"]
-
- expected_mention = %{
- "href" => other_user.ap_id,
- "name" => "@#{other_user.nickname}",
- "type" => "Mention"
- }
-
- expected_tag = %{
- "href" => Pleroma.Web.Endpoint.url() <> "/tags/2hu",
- "type" => "Hashtag",
- "name" => "#2hu"
- }
-
- refute called(Pleroma.Notification.get_notified_from_activity(:_, :_))
- assert Enum.member?(object["tag"], expected_tag)
- assert Enum.member?(object["tag"], expected_mention)
- end
- end
-
- test "it adds the sensitive property" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "#nsfw hey"})
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["object"]["sensitive"]
- end
-
- test "it adds the json-ld context and the conversation property" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["@context"] ==
- Pleroma.Web.ActivityPub.Utils.make_json_ld_header()["@context"]
-
- assert modified["object"]["conversation"] == modified["context"]
- end
-
- test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["object"]["actor"] == modified["object"]["attributedTo"]
- end
-
- test "it strips internal hashtag data" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "#2hu"})
-
- expected_tag = %{
- "href" => Pleroma.Web.Endpoint.url() <> "/tags/2hu",
- "type" => "Hashtag",
- "name" => "#2hu"
- }
-
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["object"]["tag"] == [expected_tag]
- end
-
- test "it strips internal fields" do
- user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "#2hu :firefox:"})
-
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert length(modified["object"]["tag"]) == 2
-
- assert is_nil(modified["object"]["emoji"])
- assert is_nil(modified["object"]["like_count"])
- assert is_nil(modified["object"]["announcements"])
- assert is_nil(modified["object"]["announcement_count"])
- assert is_nil(modified["object"]["context_id"])
- end
-
- test "it strips internal fields of article" do
- activity = insert(:article_activity)
-
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert length(modified["object"]["tag"]) == 2
-
- assert is_nil(modified["object"]["emoji"])
- assert is_nil(modified["object"]["like_count"])
- assert is_nil(modified["object"]["announcements"])
- assert is_nil(modified["object"]["announcement_count"])
- assert is_nil(modified["object"]["context_id"])
- assert is_nil(modified["object"]["likes"])
- end
-
- test "the directMessage flag is present" do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "2hu :moominmamma:"})
-
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["directMessage"] == false
-
- {:ok, activity} = CommonAPI.post(user, %{status: "@#{other_user.nickname} :moominmamma:"})
-
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["directMessage"] == false
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- status: "@#{other_user.nickname} :moominmamma:",
- visibility: "direct"
- })
-
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- assert modified["directMessage"] == true
- end
-
- test "it strips BCC field" do
- user = insert(:user)
- {:ok, list} = Pleroma.List.create("foo", user)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
-
- {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
-
- 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
- test "it upgrades a user to activitypub" do
- user =
- insert(:user, %{
- nickname: "rye@niu.moe",
- local: false,
- ap_id: "https://niu.moe/users/rye",
- follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
- })
-
- user_two = insert(:user)
- Pleroma.FollowingRelationship.follow(user_two, user, :follow_accept)
-
- {:ok, activity} = CommonAPI.post(user, %{status: "test"})
- {:ok, unrelated_activity} = CommonAPI.post(user_two, %{status: "test"})
- assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
-
- user = User.get_cached_by_id(user.id)
- assert user.note_count == 1
-
- {:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
- 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.note_count == 1
-
- activity = Activity.get_by_id(activity.id)
- assert user.follower_address in activity.recipients
-
- assert %{
- "url" => [
- %{
- "href" =>
- "https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
- }
- ]
- } = user.avatar
-
- assert %{
- "url" => [
- %{
- "href" =>
- "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
- }
- ]
- } = user.banner
-
- refute "..." in activity.recipients
-
- unrelated_activity = Activity.get_by_id(unrelated_activity.id)
- refute user.follower_address in unrelated_activity.recipients
-
- user_two = User.get_cached_by_id(user_two.id)
- assert User.following?(user_two, user)
- refute "..." in User.following(user_two)
- end
- end
-
- describe "actor rewriting" do
- test "it fixes the actor URL property to be a proper URI" do
- data = %{
- "url" => %{"href" => "http://example.com"}
- }
-
- rewritten = Transmogrifier.maybe_fix_user_object(data)
- assert rewritten["url"] == "http://example.com"
- end
- end
-
- describe "actor origin containment" do
- test "it rejects activities which reference objects with bogus origins" do
- data = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => "http://mastodon.example.org/users/admin/activities/1234",
- "actor" => "http://mastodon.example.org/users/admin",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => "https://info.pleroma.site/activity.json",
- "type" => "Announce"
- }
-
- 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
- data = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => "http://mastodon.example.org/users/admin/activities/1234",
- "actor" => "http://mastodon.example.org/users/admin",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => "https://info.pleroma.site/activity2.json",
- "type" => "Announce"
- }
-
- 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
- data = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => "http://mastodon.example.org/users/admin/activities/1234",
- "actor" => "http://mastodon.example.org/users/admin",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => "https://info.pleroma.site/activity3.json",
- "type" => "Announce"
- }
-
- assert capture_log(fn ->
- {:error, _} = Transmogrifier.handle_incoming(data)
- end) =~ "Object containment failed"
- end
- end
-
- describe "reserialization" do
- test "successfully reserializes a message with inReplyTo == nil" do
- user = insert(:user)
-
- message = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [],
- "type" => "Create",
- "object" => %{
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [],
- "type" => "Note",
- "content" => "Hi",
- "inReplyTo" => nil,
- "attributedTo" => user.ap_id
- },
- "actor" => user.ap_id
- }
-
- {:ok, activity} = Transmogrifier.handle_incoming(message)
-
- {:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
- end
-
- test "successfully reserializes a message with AS2 objects in IR" do
- user = insert(:user)
-
- message = %{
- "@context" => "https://www.w3.org/ns/activitystreams",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [],
- "type" => "Create",
- "object" => %{
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [],
- "type" => "Note",
- "content" => "Hi",
- "inReplyTo" => nil,
- "attributedTo" => user.ap_id,
- "tag" => [
- %{"name" => "#2hu", "href" => "http://example.com/2hu", "type" => "Hashtag"},
- %{"name" => "Bob", "href" => "http://example.com/bob", "type" => "Mention"}
- ]
- },
- "actor" => user.ap_id
- }
-
- {:ok, activity} = Transmogrifier.handle_incoming(message)
-
- {:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
- end
- end
-
- describe "fix_explicit_addressing" do
- setup do
- user = insert(:user)
- [user: user]
- end
-
- test "moves non-explicitly mentioned actors to cc", %{user: user} do
- explicitly_mentioned_actors = [
- "https://pleroma.gold/users/user1",
- "https://pleroma.gold/user2"
- ]
-
- object = %{
- "actor" => user.ap_id,
- "to" => explicitly_mentioned_actors ++ ["https://social.beepboop.ga/users/dirb"],
- "cc" => [],
- "tag" =>
- Enum.map(explicitly_mentioned_actors, fn href ->
- %{"type" => "Mention", "href" => href}
- end)
- }
-
- fixed_object = Transmogrifier.fix_explicit_addressing(object)
- assert Enum.all?(explicitly_mentioned_actors, &(&1 in fixed_object["to"]))
- refute "https://social.beepboop.ga/users/dirb" in fixed_object["to"]
- assert "https://social.beepboop.ga/users/dirb" in fixed_object["cc"]
- end
-
- test "does not move actor's follower collection to cc", %{user: user} do
- object = %{
- "actor" => user.ap_id,
- "to" => [user.follower_address],
- "cc" => []
- }
-
- fixed_object = Transmogrifier.fix_explicit_addressing(object)
- assert user.follower_address in fixed_object["to"]
- refute user.follower_address in fixed_object["cc"]
- end
-
- test "removes recipient's follower collection from cc", %{user: user} do
- recipient = insert(:user)
-
- object = %{
- "actor" => user.ap_id,
- "to" => [recipient.ap_id, "https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [user.follower_address, recipient.follower_address]
- }
-
- fixed_object = Transmogrifier.fix_explicit_addressing(object)
-
- assert user.follower_address in fixed_object["cc"]
- refute recipient.follower_address in fixed_object["cc"]
- 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
- setup 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["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",
- "type" => "Document",
- "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",
- "type" => "Document",
- "url" => [
- %{
- "href" => "https://pe.er/stat-480.mp4",
- "mediaType" => "video/mp4",
- "type" => "Link"
- }
- ]
- },
- %{
- "mediaType" => "video/mp4",
- "type" => "Document",
- "url" => [
- %{
- "href" => "https://pe.er/stat-480.mp4",
- "mediaType" => "video/mp4",
- "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
- setup do: clear_config([:activitypub, :note_replies_output_limit], 2)
-
- 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
-
- test "take_emoji_tags/1" do
- user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}})
-
- assert Transmogrifier.take_emoji_tags(user) == [
- %{
- "icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"},
- "id" => "https://example.org/firefox.png",
- "name" => ":firefox:",
- "type" => "Emoji",
- "updated" => "1970-01-01T00:00:00Z"
- }
- ]
- end
-end
diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs
deleted file mode 100644
index d50213545..000000000
--- a/test/web/activity_pub/utils_test.exs
+++ /dev/null
@@ -1,548 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.UtilsTest do
- use Pleroma.DataCase
- alias Pleroma.Activity
- alias Pleroma.Object
- alias Pleroma.Repo
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.Utils
- alias Pleroma.Web.AdminAPI.AccountView
- alias Pleroma.Web.CommonAPI
-
- import Pleroma.Factory
-
- require Pleroma.Constants
-
- describe "fetch the latest Follow" do
- test "fetches the latest Follow activity" do
- %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
- follower = User.get_cached_by_ap_id(activity.data["actor"])
- followed = User.get_cached_by_ap_id(activity.data["object"])
-
- assert activity == Utils.fetch_latest_follow(follower, followed)
- end
- end
-
- describe "determine_explicit_mentions()" do
- test "works with an object that has mentions" 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
-
- test "works with an object that does not have mentions" do
- object = %{
- "tag" => [
- %{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
- ]
- }
-
- assert Utils.determine_explicit_mentions(object) == []
- end
-
- test "works with an object that has mentions and other tags" do
- object = %{
- "tag" => [
- %{
- "type" => "Mention",
- "href" => "https://example.com/~alyssa",
- "name" => "Alyssa P. Hacker"
- },
- %{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
- ]
- }
-
- assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
- end
-
- test "works with an object that has no tags" do
- object = %{}
-
- assert Utils.determine_explicit_mentions(object) == []
- end
-
- test "works with an object that has only IR tags" do
- object = %{"tag" => ["2hu"]}
-
- 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_like_data" do
- setup do
- user = insert(:user)
- other_user = insert(:user)
- third_user = insert(:user)
- [user: user, other_user: other_user, third_user: third_user]
- end
-
- test "addresses actor's follower address if the activity is public", %{
- user: user,
- other_user: other_user,
- third_user: third_user
- } do
- expected_to = Enum.sort([user.ap_id, other_user.follower_address])
- expected_cc = Enum.sort(["https://www.w3.org/ns/activitystreams#Public", third_user.ap_id])
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- status:
- "hey @#{other_user.nickname}, @#{third_user.nickname} how about beering together this weekend?"
- })
-
- %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
- assert Enum.sort(to) == expected_to
- assert Enum.sort(cc) == expected_cc
- end
-
- test "does not adress actor's follower address if the activity is not public", %{
- user: user,
- other_user: other_user,
- third_user: third_user
- } do
- expected_to = Enum.sort([user.ap_id])
- expected_cc = [third_user.ap_id]
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- status: "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!",
- visibility: "private"
- })
-
- %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
- assert Enum.sort(to) == expected_to
- assert Enum.sort(cc) == expected_cc
- end
- end
-
- test "make_json_ld_header/0" do
- assert Utils.make_json_ld_header() == %{
- "@context" => [
- "https://www.w3.org/ns/activitystreams",
- "http://localhost:4001/schemas/litepub-0.1.jsonld",
- %{
- "@language" => "und"
- }
- ]
- }
- end
-
- describe "get_existing_votes" do
- test "fetches existing votes" do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- status: "How do I pronounce LaTeX?",
- poll: %{
- options: ["laytekh", "lahtekh", "latex"],
- expires_in: 20,
- multiple: true
- }
- })
-
- object = Object.normalize(activity)
- {:ok, votes, object} = CommonAPI.vote(other_user, object, [0, 1])
- assert Enum.sort(Utils.get_existing_votes(other_user.ap_id, object)) == Enum.sort(votes)
- end
-
- test "fetches only Create activities" do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- status: "Are we living in a society?",
- poll: %{
- options: ["yes", "no"],
- expires_in: 20
- }
- })
-
- object = Object.normalize(activity)
- {:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
- {:ok, _activity} = CommonAPI.favorite(user, activity.id)
- [fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
- assert fetched_vote.id == vote.id
- end
- end
-
- 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, locked: true)
- follower = insert(:user)
-
- {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
- {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
-
- data =
- follow_activity_two.data
- |> Map.put("state", "accept")
-
- cng = Ecto.Changeset.change(follow_activity_two, data: data)
-
- {:ok, follow_activity_two} = Repo.update(cng)
-
- {:ok, follow_activity_two} =
- Utils.update_follow_state_for_all(follow_activity_two, "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, locked: true)
- follower = insert(:user)
-
- {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
- {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
-
- data =
- follow_activity_two.data
- |> Map.put("state", "accept")
-
- cng = Ecto.Changeset.change(follow_activity_two, data: data)
-
- {:ok, follow_activity_two} = Repo.update(cng)
-
- {:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
-
- assert refresh_record(follow_activity).data["state"] == "pending"
- assert refresh_record(follow_activity_two).data["state"] == "reject"
- end
- end
-
- describe "update_element_in_object/3" do
- test "updates likes" do
- user = insert(:user)
- activity = insert(:note_activity)
- object = Object.normalize(activity)
-
- assert {:ok, updated_object} =
- Utils.update_element_in_object(
- "like",
- [user.ap_id],
- object
- )
-
- assert updated_object.data["likes"] == [user.ap_id]
- assert updated_object.data["like_count"] == 1
- end
- end
-
- describe "add_like_to_object/2" do
- test "add actor to likes" do
- user = insert(:user)
- user2 = insert(:user)
- object = insert(:note)
-
- assert {:ok, updated_object} =
- Utils.add_like_to_object(
- %Activity{data: %{"actor" => user.ap_id}},
- object
- )
-
- assert updated_object.data["likes"] == [user.ap_id]
- assert updated_object.data["like_count"] == 1
-
- assert {:ok, updated_object2} =
- Utils.add_like_to_object(
- %Activity{data: %{"actor" => user2.ap_id}},
- updated_object
- )
-
- assert updated_object2.data["likes"] == [user2.ap_id, user.ap_id]
- assert updated_object2.data["like_count"] == 2
- end
- end
-
- describe "remove_like_from_object/2" do
- test "removes ap_id from likes" do
- user = insert(:user)
- user2 = insert(:user)
- object = insert(:note, data: %{"likes" => [user.ap_id, user2.ap_id], "like_count" => 2})
-
- assert {:ok, updated_object} =
- Utils.remove_like_from_object(
- %Activity{data: %{"actor" => user.ap_id}},
- object
- )
-
- assert updated_object.data["likes"] == [user2.ap_id]
- assert updated_object.data["like_count"] == 1
- end
- end
-
- describe "get_existing_like/2" do
- test "fetches existing like" do
- note_activity = insert(:note_activity)
- assert object = Object.normalize(note_activity)
-
- user = insert(:user)
- refute Utils.get_existing_like(user.ap_id, object)
- {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
-
- 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} = CommonAPI.repeat(note_activity.id, actor)
- 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{} = _} = CommonAPI.block(user1, user2)
- assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
- assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)
-
- assert Utils.fetch_latest_block(user1, user2) == activity
- end
- 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, skip_visibility_check: true})
- }
-
- 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
deleted file mode 100644
index f0389845d..000000000
--- a/test/web/activity_pub/views/object_view_test.exs
+++ /dev/null
@@ -1,84 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
- use Pleroma.DataCase
- import Pleroma.Factory
-
- alias Pleroma.Object
- alias Pleroma.Web.ActivityPub.ObjectView
- alias Pleroma.Web.CommonAPI
-
- test "renders a note object" do
- note = insert(:note)
-
- result = ObjectView.render("object.json", %{object: note})
-
- assert result["id"] == note.data["id"]
- assert result["to"] == note.data["to"]
- assert result["content"] == note.data["content"]
- assert result["type"] == "Note"
- assert result["@context"]
- end
-
- test "renders a note activity" do
- note = insert(:note_activity)
- object = Object.normalize(note)
-
- result = ObjectView.render("object.json", %{object: note})
-
- assert result["id"] == note.data["id"]
- assert result["to"] == note.data["to"]
- assert result["object"]["type"] == "Note"
- assert result["object"]["content"] == object.data["content"]
- assert result["type"] == "Create"
- assert result["@context"]
- end
-
- describe "note activity's `replies` collection rendering" do
- setup do: clear_config([:activitypub, :note_replies_output_limit], 5)
-
- 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)
- user = insert(:user)
-
- {:ok, like_activity} = CommonAPI.favorite(user, note.id)
-
- result = ObjectView.render("object.json", %{object: like_activity})
-
- assert result["id"] == like_activity.data["id"]
- assert result["object"] == object.data["id"]
- assert result["type"] == "Like"
- end
-
- test "renders an announce activity" do
- note = insert(:note_activity)
- object = Object.normalize(note)
- user = insert(:user)
-
- {:ok, announce_activity} = CommonAPI.repeat(note.id, user)
-
- result = ObjectView.render("object.json", %{object: announce_activity})
-
- assert result["id"] == announce_activity.data["id"]
- assert result["object"] == object.data["id"]
- assert result["type"] == "Announce"
- end
-end
diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs
deleted file mode 100644
index 98c7c9d09..000000000
--- a/test/web/activity_pub/views/user_view_test.exs
+++ /dev/null
@@ -1,180 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.UserViewTest do
- use Pleroma.DataCase
- import Pleroma.Factory
-
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.UserView
- alias Pleroma.Web.CommonAPI
-
- test "Renders a user, including the public key" do
- user = insert(:user)
- {:ok, user} = User.ensure_keys_present(user)
-
- result = UserView.render("user.json", %{user: user})
-
- assert result["id"] == user.ap_id
- assert result["preferredUsername"] == user.nickname
-
- assert String.contains?(result["publicKey"]["publicKeyPem"], "BEGIN PUBLIC KEY")
- end
-
- test "Renders profile fields" do
- fields = [
- %{"name" => "foo", "value" => "bar"}
- ]
-
- {:ok, user} =
- insert(:user)
- |> User.update_changeset(%{fields: fields})
- |> User.update_and_set_cache()
-
- assert %{
- "attachment" => [%{"name" => "foo", "type" => "PropertyValue", "value" => "bar"}]
- } = 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)
-
- result = UserView.render("user.json", %{user: user})
- refute result["icon"]
- refute result["image"]
-
- user =
- insert(:user,
- avatar: %{"url" => [%{"href" => "https://someurl"}]},
- banner: %{"url" => [%{"href" => "https://somebanner"}]}
- )
-
- {:ok, user} = User.ensure_keys_present(user)
-
- result = UserView.render("user.json", %{user: user})
- assert result["icon"]["url"] == "https://someurl"
- 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)
- {:ok, user} = User.ensure_keys_present(user)
-
- result = UserView.render("user.json", %{user: user})
-
- assert result["id"] == user.ap_id
-
- %{
- "sharedInbox" => _,
- "oauthAuthorizationEndpoint" => _,
- "oauthRegistrationEndpoint" => _,
- "oauthTokenEndpoint" => _
- } = result["endpoints"]
- end
-
- test "remote users have an empty endpoints structure" do
- user = insert(:user, local: false)
- {:ok, user} = User.ensure_keys_present(user)
-
- result = UserView.render("user.json", %{user: user})
-
- assert result["id"] == user.ap_id
- assert result["endpoints"] == %{}
- end
-
- test "instance users do not expose oAuth endpoints" do
- user = insert(:user, nickname: nil, local: true)
- {:ok, user} = User.ensure_keys_present(user)
-
- result = UserView.render("user.json", %{user: user})
-
- refute result["endpoints"]["oauthAuthorizationEndpoint"]
- refute result["endpoints"]["oauthRegistrationEndpoint"]
- refute result["endpoints"]["oauthTokenEndpoint"]
- end
- end
-
- describe "followers" do
- test "sets totalItems to zero when followers are hidden" 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: 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
-
- describe "following" do
- test "sets totalItems to zero when follows are hidden" 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: true, hide_follows: true})
- assert %{"totalItems" => 0} = UserView.render("following.json", %{user: user})
- end
-
- 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
-
- describe "acceptsChatMessages" do
- test "it returns this value if it is set" do
- true_user = insert(:user, accepts_chat_messages: true)
- false_user = insert(:user, accepts_chat_messages: false)
- nil_user = insert(:user, accepts_chat_messages: nil)
-
- assert %{"capabilities" => %{"acceptsChatMessages" => true}} =
- UserView.render("user.json", user: true_user)
-
- assert %{"capabilities" => %{"acceptsChatMessages" => false}} =
- UserView.render("user.json", user: false_user)
-
- refute Map.has_key?(
- UserView.render("user.json", user: nil_user)["capabilities"],
- "acceptsChatMessages"
- )
- end
- end
-end
diff --git a/test/web/activity_pub/visibilty_test.exs b/test/web/activity_pub/visibilty_test.exs
deleted file mode 100644
index 8e9354c65..000000000
--- a/test/web/activity_pub/visibilty_test.exs
+++ /dev/null
@@ -1,230 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ActivityPub.VisibilityTest do
- use Pleroma.DataCase
-
- alias Pleroma.Activity
- alias Pleroma.Web.ActivityPub.Visibility
- alias Pleroma.Web.CommonAPI
- import Pleroma.Factory
-
- setup do
- user = insert(:user)
- mentioned = insert(:user)
- following = insert(:user)
- unrelated = insert(:user)
- {:ok, following} = Pleroma.User.follow(following, user)
- {:ok, list} = Pleroma.List.create("foo", user)
-
- Pleroma.List.follow(list, unrelated)
-
- {:ok, public} =
- CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "public"})
-
- {:ok, private} =
- CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "private"})
-
- {:ok, direct} =
- CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "direct"})
-
- {:ok, unlisted} =
- CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "unlisted"})
-
- {:ok, list} =
- CommonAPI.post(user, %{
- status: "@#{mentioned.nickname}",
- visibility: "list:#{list.id}"
- })
-
- %{
- public: public,
- private: private,
- direct: direct,
- unlisted: unlisted,
- user: user,
- mentioned: mentioned,
- following: following,
- unrelated: unrelated,
- list: list
- }
- end
-
- test "is_direct?", %{
- public: public,
- private: private,
- direct: direct,
- unlisted: unlisted,
- list: list
- } do
- assert Visibility.is_direct?(direct)
- refute Visibility.is_direct?(public)
- refute Visibility.is_direct?(private)
- refute Visibility.is_direct?(unlisted)
- assert Visibility.is_direct?(list)
- end
-
- test "is_public?", %{
- public: public,
- private: private,
- direct: direct,
- unlisted: unlisted,
- list: list
- } do
- refute Visibility.is_public?(direct)
- assert Visibility.is_public?(public)
- refute Visibility.is_public?(private)
- assert Visibility.is_public?(unlisted)
- refute Visibility.is_public?(list)
- end
-
- test "is_private?", %{
- public: public,
- private: private,
- direct: direct,
- unlisted: unlisted,
- list: list
- } do
- refute Visibility.is_private?(direct)
- refute Visibility.is_private?(public)
- assert Visibility.is_private?(private)
- refute Visibility.is_private?(unlisted)
- refute Visibility.is_private?(list)
- end
-
- test "is_list?", %{
- public: public,
- private: private,
- direct: direct,
- unlisted: unlisted,
- list: list
- } do
- refute Visibility.is_list?(direct)
- refute Visibility.is_list?(public)
- refute Visibility.is_list?(private)
- refute Visibility.is_list?(unlisted)
- assert Visibility.is_list?(list)
- end
-
- test "visible_for_user?", %{
- public: public,
- private: private,
- direct: direct,
- unlisted: unlisted,
- user: user,
- mentioned: mentioned,
- following: following,
- unrelated: unrelated,
- list: list
- } do
- # All visible to author
-
- assert Visibility.visible_for_user?(public, user)
- assert Visibility.visible_for_user?(private, user)
- assert Visibility.visible_for_user?(unlisted, user)
- assert Visibility.visible_for_user?(direct, user)
- assert Visibility.visible_for_user?(list, user)
-
- # All visible to a mentioned user
-
- assert Visibility.visible_for_user?(public, mentioned)
- assert Visibility.visible_for_user?(private, mentioned)
- assert Visibility.visible_for_user?(unlisted, mentioned)
- assert Visibility.visible_for_user?(direct, mentioned)
- assert Visibility.visible_for_user?(list, mentioned)
-
- # DM not visible for just follower
-
- assert Visibility.visible_for_user?(public, following)
- assert Visibility.visible_for_user?(private, following)
- assert Visibility.visible_for_user?(unlisted, following)
- refute Visibility.visible_for_user?(direct, following)
- refute Visibility.visible_for_user?(list, following)
-
- # Public and unlisted visible for unrelated user
-
- assert Visibility.visible_for_user?(public, unrelated)
- assert Visibility.visible_for_user?(unlisted, unrelated)
- refute Visibility.visible_for_user?(private, unrelated)
- refute Visibility.visible_for_user?(direct, unrelated)
-
- # Visible for a list member
- assert Visibility.visible_for_user?(list, unrelated)
- end
-
- test "doesn't die when the user doesn't exist",
- %{
- direct: direct,
- user: user
- } do
- Repo.delete(user)
- Cachex.clear(:user_cache)
- refute Visibility.is_private?(direct)
- end
-
- test "get_visibility", %{
- public: public,
- private: private,
- direct: direct,
- unlisted: unlisted,
- list: list
- } do
- assert Visibility.get_visibility(public) == "public"
- assert Visibility.get_visibility(private) == "private"
- assert Visibility.get_visibility(direct) == "direct"
- assert Visibility.get_visibility(unlisted) == "unlisted"
- assert Visibility.get_visibility(list) == "list"
- end
-
- test "get_visibility with directMessage flag" do
- assert Visibility.get_visibility(%{data: %{"directMessage" => true}}) == "direct"
- end
-
- test "get_visibility with listMessage flag" do
- assert Visibility.get_visibility(%{data: %{"listMessage" => ""}}) == "list"
- end
-
- describe "entire_thread_visible_for_user?/2" do
- test "returns false if not found activity", %{user: user} do
- refute Visibility.entire_thread_visible_for_user?(%Activity{}, user)
- end
-
- test "returns true if activity hasn't 'Create' type", %{user: user} do
- activity = insert(:like_activity)
- assert Visibility.entire_thread_visible_for_user?(activity, user)
- end
-
- test "returns false when invalid recipients", %{user: user} do
- author = insert(:user)
-
- activity =
- insert(:note_activity,
- note:
- insert(:note,
- user: author,
- data: %{"to" => ["test-user"]}
- )
- )
-
- refute Visibility.entire_thread_visible_for_user?(activity, user)
- end
-
- test "returns true if user following to author" do
- author = insert(:user)
- user = insert(:user)
- Pleroma.User.follow(user, author)
-
- activity =
- insert(:note_activity,
- note:
- insert(:note,
- user: author,
- data: %{"to" => [user.ap_id]}
- )
- )
-
- assert Visibility.entire_thread_visible_for_user?(activity, user)
- end
- end
-end