diff options
Diffstat (limited to 'test/web/activity_pub')
65 files changed, 0 insertions, 12693 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 804305a13..000000000 --- a/test/web/activity_pub/activity_pub_test.exs +++ /dev/null @@ -1,2260 +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} = 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 -    setup do -      [user: insert(:user)] -    end - -    test "it reverts create", %{user: user} do -      with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do -        assert {:error, :reverted} = -                 ActivityPub.create(%{ -                   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 "creates activity if expiration is not configured and expires_at is not passed", %{ -      user: user -    } do -      clear_config([Pleroma.Workers.PurgeExpiredActivity, :enabled], false) - -      assert {:ok, _} = -               ActivityPub.create(%{ -                 to: ["user1", "user2"], -                 actor: user, -                 context: "", -                 object: %{ -                   "to" => ["user1", "user2"], -                   "type" => "Note", -                   "content" => "testing" -                 } -               }) -    end - -    test "rejects activity if expires_at present but expiration is not configured", %{user: user} do -      clear_config([Pleroma.Workers.PurgeExpiredActivity, :enabled], false) - -      assert {:error, :expired_activities_disabled} = -               ActivityPub.create(%{ -                 to: ["user1", "user2"], -                 actor: user, -                 context: "", -                 object: %{ -                   "to" => ["user1", "user2"], -                   "type" => "Note", -                   "content" => "testing" -                 }, -                 additional: %{ -                   "expires_at" => DateTime.utc_now() -                 } -               }) - -      assert Repo.aggregate(Activity, :count, :id) == 0 -      assert Repo.aggregate(Object, :count, :id) == 0 -    end - -    test "removes doubled 'to' recipients", %{user: user} do -      {:ok, activity} = -        ActivityPub.create(%{ -          to: ["user1", "user1", "user2"], -          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", %{user: user} do -      {: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", %{user: user} do -      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 -    test "creates an activity expiration for local Create activities" do -      clear_config([:mrf, :policies], Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy) - -      {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"}) -      {:ok, follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"}) - -      assert_enqueued( -        worker: Pleroma.Workers.PurgeExpiredActivity, -        args: %{activity_id: activity.id}, -        scheduled_at: -          activity.inserted_at -          |> DateTime.from_naive!("Etc/UTC") -          |> Timex.shift(days: 365) -      ) - -      refute_enqueued( -        worker: Pleroma.Workers.PurgeExpiredActivity, -        args: %{activity_id: follow.id} -      ) -    end -  end - -  describe "handling of clashing nicknames" do -    test "renames an existing user with a clashing nickname and a different ap id" do -      orig_user = -        insert( -          :user, -          local: false, -          nickname: "admin@mastodon.example.org", -          ap_id: "http://mastodon.example.org/users/harinezumigari" -        ) - -      %{ -        nickname: orig_user.nickname, -        ap_id: orig_user.ap_id <> "part_2" -      } -      |> ActivityPub.maybe_handle_clashing_nickname() - -      user = User.get_by_id(orig_user.id) - -      assert user.nickname == "#{orig_user.id}.admin@mastodon.example.org" -    end - -    test "does nothing with a clashing nickname and the same ap id" do -      orig_user = -        insert( -          :user, -          local: false, -          nickname: "admin@mastodon.example.org", -          ap_id: "http://mastodon.example.org/users/harinezumigari" -        ) - -      %{ -        nickname: orig_user.nickname, -        ap_id: orig_user.ap_id -      } -      |> ActivityPub.maybe_handle_clashing_nickname() - -      user = User.get_by_id(orig_user.id) - -      assert user.nickname == orig_user.nickname -    end -  end - -  describe "reply filtering" do -    test "`following` still contains announcements by friends" do -      user = insert(:user) -      followed = insert(:user) -      not_followed = insert(:user) - -      User.follow(user, followed) - -      {:ok, followed_post} = CommonAPI.post(followed, %{status: "Hello"}) - -      {:ok, not_followed_to_followed} = -        CommonAPI.post(not_followed, %{ -          status: "Also hello", -          in_reply_to_status_id: followed_post.id -        }) - -      {:ok, retoot} = CommonAPI.repeat(not_followed_to_followed.id, followed) - -      params = -        %{} -        |> Map.put(:type, ["Create", "Announce"]) -        |> Map.put(:blocking_user, user) -        |> Map.put(:muting_user, user) -        |> Map.put(:reply_filtering_user, user) -        |> Map.put(:reply_visibility, "following") -        |> Map.put(:announce_filtering_user, user) -        |> Map.put(:user, user) - -      activities = -        [user.ap_id | User.following(user)] -        |> ActivityPub.fetch_activities(params) - -      followed_post_id = followed_post.id -      retoot_id = retoot.id - -      assert [%{id: ^followed_post_id}, %{id: ^retoot_id}] = activities - -      assert length(activities) == 2 -    end - -    # This test is skipped because, while this is the desired behavior, -    # there seems to be no good way to achieve it with the method that -    # we currently use for detecting to who a reply is directed. -    # This is a TODO and should be fixed by a later rewrite of the code -    # in question. -    @tag skip: true -    test "`following` still contains self-replies by friends" do -      user = insert(:user) -      followed = insert(:user) -      not_followed = insert(:user) - -      User.follow(user, followed) - -      {:ok, followed_post} = CommonAPI.post(followed, %{status: "Hello"}) -      {:ok, not_followed_post} = CommonAPI.post(not_followed, %{status: "Also hello"}) - -      {:ok, _followed_to_not_followed} = -        CommonAPI.post(followed, %{status: "sup", in_reply_to_status_id: not_followed_post.id}) - -      {:ok, _followed_self_reply} = -        CommonAPI.post(followed, %{status: "Also cofe", in_reply_to_status_id: followed_post.id}) - -      params = -        %{} -        |> Map.put(:type, ["Create", "Announce"]) -        |> Map.put(:blocking_user, user) -        |> Map.put(:muting_user, user) -        |> Map.put(:reply_filtering_user, user) -        |> Map.put(:reply_visibility, "following") -        |> Map.put(:announce_filtering_user, user) -        |> Map.put(:user, user) - -      activities = -        [user.ap_id | User.following(user)] -        |> ActivityPub.fetch_activities(params) - -      assert length(activities) == 2 -    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 e7370d4ef..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, DateTime.utc_now(), :days) == 364 -  end - -  test "keeps existing `expires_at` if it less than the config setting" do -    expires_at = DateTime.utc_now() |> Timex.shift(days: 1) - -    assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} = -             ActivityExpirationPolicy.filter(%{ -               "id" => @id, -               "actor" => @local_actor, -               "type" => "Create", -               "expires_at" => expires_at, -               "object" => %{"type" => "Note"} -             }) -  end - -  test "overwrites existing `expires_at` if it greater than the config setting" do -    too_distant_future = DateTime.utc_now() |> Timex.shift(years: 2) - -    assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} = -             ActivityExpirationPolicy.filter(%{ -               "id" => @id, -               "actor" => @local_actor, -               "type" => "Create", -               "expires_at" => too_distant_future, -               "object" => %{"type" => "Note"} -             }) - -    assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364 -  end - -  test "ignores remote activities" do -    assert {:ok, activity} = -             ActivityExpirationPolicy.filter(%{ -               "id" => "https://example.com/123", -               "actor" => "https://example.com/users/cofe", -               "type" => "Create", -               "object" => %{"type" => "Note"} -             }) - -    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/force_bot_unlisted_policy_test.exs b/test/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs deleted file mode 100644 index 86dd9ddae..000000000 --- a/test/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs +++ /dev/null @@ -1,60 +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.ForceBotUnlistedPolicyTest do -  use Pleroma.DataCase -  import Pleroma.Factory - -  alias Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy -  @public "https://www.w3.org/ns/activitystreams#Public" - -  defp generate_messages(actor) do -    {%{ -       "actor" => actor.ap_id, -       "type" => "Create", -       "object" => %{}, -       "to" => [@public, "f"], -       "cc" => [actor.follower_address, "d"] -     }, -     %{ -       "actor" => actor.ap_id, -       "type" => "Create", -       "object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]}, -       "to" => ["f", actor.follower_address], -       "cc" => ["d", @public] -     }} -  end - -  test "removes from the federated timeline by nickname heuristics 1" do -    actor = insert(:user, %{nickname: "annoying_ebooks@example.com"}) - -    {message, except_message} = generate_messages(actor) - -    assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message} -  end - -  test "removes from the federated timeline by nickname heuristics 2" do -    actor = insert(:user, %{nickname: "cirnonewsnetworkbot@meow.cat"}) - -    {message, except_message} = generate_messages(actor) - -    assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message} -  end - -  test "removes from the federated timeline by actor type Application" do -    actor = insert(:user, %{actor_type: "Application"}) - -    {message, except_message} = generate_messages(actor) - -    assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message} -  end - -  test "removes from the federated timeline by actor type Service" do -    actor = insert(:user, %{actor_type: "Service"}) - -    {message, except_message} = generate_messages(actor) - -    assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message} -  end -end diff --git a/test/web/activity_pub/mrf/hellthread_policy_test.exs b/test/web/activity_pub/mrf/hellthread_policy_test.exs 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 1710c4d2a..000000000 --- a/test/web/activity_pub/mrf/mediaproxy_warming_policy_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.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"}]} -      ] -    } -  } - -  setup do: clear_config([:media_proxy, :enabled], true) - -  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 e82c8afa6..000000000 --- a/test/web/activity_pub/mrf/mrf_test.exs +++ /dev/null @@ -1,86 +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 -      clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.NoOpPolicy]) - -      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 "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a> -    this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a> -    this is an image: <img src="http://example.com/image.jpg"/><br/> -    alert('hacked') -    """ - -    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/article_note_validator_test.exs b/test/web/activity_pub/object_validators/article_note_validator_test.exs deleted file mode 100644 index cc6dab872..000000000 --- a/test/web/activity_pub/object_validators/article_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.ArticleNoteValidatorTest do -  use Pleroma.DataCase - -  alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator -  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} = ArticleNoteValidator.cast_and_validate(note) -    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 16e4808e5..000000000 --- a/test/web/activity_pub/object_validators/chat_validation_test.exs +++ /dev/null @@ -1,212 +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('uguu')" -    end - -    test "validates for a basic object we build", %{valid_chat_message: valid_chat_message} do -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert Map.put(valid_chat_message, "attachment", nil) == object -      assert match?(%{"firefox" => _}, object["emoji"]) -    end - -    test "validates for a basic object with an attachment", %{ -      valid_chat_message: valid_chat_message, -      user: user -    } do -      file = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) - -      valid_chat_message = -        valid_chat_message -        |> Map.put("attachment", attachment.data) - -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert object["attachment"] -    end - -    test "validates for a basic object with an attachment in an array", %{ -      valid_chat_message: valid_chat_message, -      user: user -    } do -      file = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) - -      valid_chat_message = -        valid_chat_message -        |> Map.put("attachment", [attachment.data]) - -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert object["attachment"] -    end - -    test "validates for a basic object with an attachment but without content", %{ -      valid_chat_message: valid_chat_message, -      user: user -    } do -      file = %Plug.Upload{ -        content_type: "image/jpg", -        path: Path.absname("test/fixtures/image.jpg"), -        filename: "an_image.jpg" -      } - -      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) - -      valid_chat_message = -        valid_chat_message -        |> Map.put("attachment", attachment.data) -        |> Map.delete("content") - -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert object["attachment"] -    end - -    test "does not validate if the message has no content", %{ -      valid_chat_message: valid_chat_message -    } do -      contentless = -        valid_chat_message -        |> Map.delete("content") - -      refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, [])) -    end - -    test "does not validate if the message is longer than the remote_limit", %{ -      valid_chat_message: valid_chat_message -    } do -      Pleroma.Config.put([:instance, :remote_limit], 2) -      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) -    end - -    test "does not validate if the recipient is blocking the actor", %{ -      valid_chat_message: valid_chat_message, -      user: user, -      recipient: recipient -    } do -      Pleroma.User.block(recipient, user) -      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) -    end - -    test "does not validate if the recipient is not accepting chat messages", %{ -      valid_chat_message: valid_chat_message, -      recipient: recipient -    } do -      recipient -      |> Ecto.Changeset.change(%{accepts_chat_messages: false}) -      |> Pleroma.Repo.update!() - -      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) -    end - -    test "does not validate if the actor or the recipient is not in our system", %{ -      valid_chat_message: valid_chat_message -    } do -      chat_message = -        valid_chat_message -        |> Map.put("actor", "https://raymoo.com/raymoo") - -      {:error, _} = ObjectValidator.validate(chat_message, []) - -      chat_message = -        valid_chat_message -        |> Map.put("to", ["https://raymoo.com/raymoo"]) - -      {:error, _} = ObjectValidator.validate(chat_message, []) -    end - -    test "does not validate for a message with multiple recipients", %{ -      valid_chat_message: valid_chat_message, -      user: user, -      recipient: recipient -    } do -      chat_message = -        valid_chat_message -        |> Map.put("to", [user.ap_id, recipient.ap_id]) - -      assert {:error, _} = ObjectValidator.validate(chat_message, []) -    end - -    test "does not validate if it doesn't concern local users" do -      user = insert(:user, local: false) -      recipient = insert(:user, local: false) - -      {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey") -      assert {:error, _} = ObjectValidator.validate(valid_chat_message, []) -    end -  end -end diff --git a/test/web/activity_pub/object_validators/delete_validation_test.exs b/test/web/activity_pub/object_validators/delete_validation_test.exs 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/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('foo')"} == 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('foo')"} == -             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 3284980f7..000000000 --- a/test/web/activity_pub/relay_test.exs +++ /dev/null @@ -1,168 +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 - -    test "force unfollow when target service is dead" do -      user = insert(:user) -      user_ap_id = user.ap_id -      user_id = user.id - -      Tesla.Mock.mock(fn %{method: :get, url: ^user_ap_id} -> -        %Tesla.Env{status: 404} -      end) - -      service_actor = Relay.get_actor() -      CommonAPI.follow(service_actor, user) -      assert "#{user.ap_id}/followers" in User.following(service_actor) - -      assert Pleroma.Repo.get_by( -               Pleroma.FollowingRelationship, -               follower_id: service_actor.id, -               following_id: user_id -             ) - -      Pleroma.Repo.delete(user) -      Cachex.clear(:user_cache) - -      assert {:ok, %Activity{} = activity} = Relay.unfollow(user_ap_id, %{force: true}) - -      assert refresh_record(service_actor).following_count == 0 - -      refute Pleroma.Repo.get_by( -               Pleroma.FollowingRelationship, -               follower_id: service_actor.id, -               following_id: user_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/article_handling_test.exs b/test/web/activity_pub/transmogrifier/article_handling_test.exs deleted file mode 100644 index 9b12a470a..000000000 --- a/test/web/activity_pub/transmogrifier/article_handling_test.exs +++ /dev/null @@ -1,75 +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.ArticleHandlingTest do -  use Oban.Testing, repo: Pleroma.Repo -  use Pleroma.DataCase - -  alias Pleroma.Activity -  alias Pleroma.Object -  alias Pleroma.Object.Fetcher -  alias Pleroma.Web.ActivityPub.Transmogrifier - -  test "Pterotype (Wordpress Plugin) Article" do -    Tesla.Mock.mock(fn %{url: "https://wedistribute.org/wp-json/pterotype/v1/actor/-blog"} -> -      %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/wedistribute-user.json")} -    end) - -    data = -      File.read!("test/fixtures/tesla_mock/wedistribute-create-article.json") |> Jason.decode!() - -    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - -    object = Object.normalize(data["object"]) - -    assert object.data["name"] == "The end is near: Mastodon plans to drop OStatus support" - -    assert object.data["summary"] == -             "One of the largest platforms in the federated social web is dropping the protocol that it started with." - -    assert object.data["url"] == "https://wedistribute.org/2019/07/mastodon-drops-ostatus/" -  end - -  test "Plume Article" do -    Tesla.Mock.mock(fn -      %{url: "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"} -> -        %Tesla.Env{ -          status: 200, -          body: File.read!("test/fixtures/tesla_mock/baptiste.gelex.xyz-article.json") -        } - -      %{url: "https://baptiste.gelez.xyz/@/BaptisteGelez"} -> -        %Tesla.Env{ -          status: 200, -          body: File.read!("test/fixtures/tesla_mock/baptiste.gelex.xyz-user.json") -        } -    end) - -    {:ok, object} = -      Fetcher.fetch_object_from_id( -        "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" -      ) - -    assert object.data["name"] == "This Month in Plume: June 2018" - -    assert object.data["url"] == -             "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" -  end - -  test "Prismo Article" do -    Tesla.Mock.mock(fn %{url: "https://prismo.news/@mxb"} -> -      %Tesla.Env{ -        status: 200, -        body: File.read!("test/fixtures/tesla_mock/https___prismo.news__mxb.json") -      } -    end) - -    data = File.read!("test/fixtures/prismo-url-map.json") |> Jason.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 -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('XSS')" -      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 d2822ce75..000000000 --- a/test/web/activity_pub/transmogrifier/question_handling_test.exs +++ /dev/null @@ -1,176 +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 "Mastodon Question activity with custom emojis" do -    options = [ -      %{ -        "type" => "Note", -        "name" => ":blobcat:", -        "replies" => %{"totalItems" => 0, "type" => "Collection"} -      }, -      %{ -        "type" => "Note", -        "name" => ":blobfox:", -        "replies" => %{"totalItems" => 0, "type" => "Collection"} -      } -    ] - -    tag = [ -      %{ -        "icon" => %{ -          "type" => "Image", -          "url" => "https://blob.cat/emoji/custom/blobcats/blobcat.png" -        }, -        "id" => "https://blob.cat/emoji/custom/blobcats/blobcat.png", -        "name" => ":blobcat:", -        "type" => "Emoji", -        "updated" => "1970-01-01T00:00:00Z" -      }, -      %{ -        "icon" => %{"type" => "Image", "url" => "https://blob.cat/emoji/blobfox/blobfox.png"}, -        "id" => "https://blob.cat/emoji/blobfox/blobfox.png", -        "name" => ":blobfox:", -        "type" => "Emoji", -        "updated" => "1970-01-01T00:00:00Z" -      } -    ] - -    data = -      File.read!("test/fixtures/mastodon-question-activity.json") -      |> Poison.decode!() -      |> Kernel.put_in(["object", "oneOf"], options) -      |> Kernel.put_in(["object", "tag"], tag) - -    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) -    object = Object.normalize(activity, false) - -    assert object.data["oneOf"] == options - -    assert object.data["emoji"] == %{ -             "blobcat" => "https://blob.cat/emoji/custom/blobcats/blobcat.png", -             "blobfox" => "https://blob.cat/emoji/blobfox/blobfox.png" -           } -  end - -  test "returns same activity 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 {:ok, ^activity} = 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/video_handling_test.exs b/test/web/activity_pub/transmogrifier/video_handling_test.exs deleted file mode 100644 index 69c953a2e..000000000 --- a/test/web/activity_pub/transmogrifier/video_handling_test.exs +++ /dev/null @@ -1,93 +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.VideoHandlingTest do -  use Oban.Testing, repo: Pleroma.Repo -  use Pleroma.DataCase - -  alias Pleroma.Activity -  alias Pleroma.Object -  alias Pleroma.Object.Fetcher -  alias Pleroma.Web.ActivityPub.Transmogrifier - -  setup_all do -    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) -    :ok -  end - -  test "skip converting the content when it is nil" do -    data = -      File.read!("test/fixtures/tesla_mock/framatube.org-video.json") -      |> Jason.decode!() -      |> Kernel.put_in(["object", "content"], nil) - -    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - -    assert object = Object.normalize(activity, false) - -    assert object.data["content"] == nil -  end - -  test "it converts content of object to html" do -    data = File.read!("test/fixtures/tesla_mock/framatube.org-video.json") |> Jason.decode!() - -    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - -    assert object = Object.normalize(activity, false) - -    assert object.data["content"] == -             "<p>Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?</p><p>Transcription par @aprilorg ici : <a href=\"https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft\">https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft</a></p>" -  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", -               "name" => nil, -               "url" => [ -                 %{ -                   "href" => -                     "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", -                   "mediaType" => "video/mp4", -                   "type" => "Link" -                 } -               ] -             } -           ] - -    data = File.read!("test/fixtures/tesla_mock/framatube.org-video.json") |> Jason.decode!() - -    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - -    assert object = Object.normalize(activity, false) - -    assert object.data["attachment"] == [ -             %{ -               "type" => "Link", -               "mediaType" => "video/mp4", -               "name" => nil, -               "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 -end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs deleted file mode 100644 index 561674f01..000000000 --- a/test/web/activity_pub/transmogrifier_test.exs +++ /dev/null @@ -1,1220 +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.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 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://mstdn.io/users/mayuutann/statuses/99568293732299394") - -      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( -                 "https://mstdn.io/users/mayuutann/statuses/99568293732299394" -               ) - -      assert returned_object.data["inReplyTo"] == -               "https://mstdn.io/users/mayuutann/statuses/99568293732299394" -    end - -    test "it does not fetch reply-to activities beyond max replies depth limit" do -      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["inReplyTo"] == "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 "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 inReplyTo 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" - -      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"} - -      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"] - -      object_with_reply = Map.put(data["object"], "inReplyTo", []) -      modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) -      assert modified_object["inReplyTo"] == [] -    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://mstdn.io/users/mayuutann/statuses/99568293732299394" -        ) - -      Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 5) -      modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) - -      assert modified_object["inReplyTo"] == -               "https://mstdn.io/users/mayuutann/statuses/99568293732299394" - -      assert modified_object["context"] == -               "tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4" -    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 "returns non-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://mstdn.io/users/mayuutann/statuses/99568293732299394" -               ) -    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 | 
