refetch user on incoming add/remove activity
[akkoma] / test / pleroma / web / activity_pub / transmogrifier_test.exs
index 333bb4f9bf9812167719796463e1418a6990f1c3..07ed3920f74c4f4369190fc42b9115f6cf891d3d 100644 (file)
@@ -1,11 +1,13 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 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
 
+  require Pleroma.Constants
+
   alias Pleroma.Activity
   alias Pleroma.Object
   alias Pleroma.Tests.ObanHelpers
@@ -31,14 +33,14 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
 
       follow_data =
         File.read!("test/fixtures/mastodon-follow-activity.json")
-        |> Poison.decode!()
+        |> Jason.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!()
+        |> Jason.decode!()
         |> Map.put("object", follow_data)
 
       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
@@ -56,7 +58,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       other_user = insert(:user)
 
       {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
-      object = Object.normalize(activity)
+      object = Object.normalize(activity, fetch: false)
 
       note_obj = %{
         "type" => "Note",
@@ -106,6 +108,167 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert activity.data["target"] == new_user.ap_id
       assert activity.data["type"] == "Move"
     end
+
+    test "it accepts Add/Remove activities" do
+      user =
+        "test/fixtures/users_mock/user.json"
+        |> File.read!()
+        |> String.replace("{{nickname}}", "lain")
+
+      object_id = "c61d6733-e256-4fe1-ab13-1e369789423f"
+
+      object =
+        "test/fixtures/statuses/note.json"
+        |> File.read!()
+        |> String.replace("{{nickname}}", "lain")
+        |> String.replace("{{object_id}}", object_id)
+
+      object_url = "https://example.com/objects/#{object_id}"
+
+      actor = "https://example.com/users/lain"
+
+      Tesla.Mock.mock(fn
+        %{
+          method: :get,
+          url: ^actor
+        } ->
+          %Tesla.Env{
+            status: 200,
+            body: user,
+            headers: [{"content-type", "application/activity+json"}]
+          }
+
+        %{
+          method: :get,
+          url: ^object_url
+        } ->
+          %Tesla.Env{
+            status: 200,
+            body: object,
+            headers: [{"content-type", "application/activity+json"}]
+          }
+
+        %{method: :get, url: "https://example.com/users/lain/collections/featured"} ->
+          %Tesla.Env{
+            status: 200,
+            body:
+              "test/fixtures/users_mock/masto_featured.json"
+              |> File.read!()
+              |> String.replace("{{domain}}", "example.com")
+              |> String.replace("{{nickname}}", "lain"),
+            headers: [{"content-type", "application/activity+json"}]
+          }
+      end)
+
+      message = %{
+        "id" => "https://example.com/objects/d61d6733-e256-4fe1-ab13-1e369789423f",
+        "actor" => actor,
+        "object" => object_url,
+        "target" => "https://example.com/users/lain/collections/featured",
+        "type" => "Add",
+        "to" => [Pleroma.Constants.as_public()],
+        "cc" => ["https://example.com/users/lain/followers"]
+      }
+
+      assert {:ok, activity} = Transmogrifier.handle_incoming(message)
+      assert activity.data == message
+      user = User.get_cached_by_ap_id(actor)
+      assert user.pinned_objects[object_url]
+
+      remove = %{
+        "id" => "http://localhost:400/objects/d61d6733-e256-4fe1-ab13-1e369789423d",
+        "actor" => actor,
+        "object" => object_url,
+        "target" => "https://example.com/users/lain/collections/featured",
+        "type" => "Remove",
+        "to" => [Pleroma.Constants.as_public()],
+        "cc" => ["https://example.com/users/lain/followers"]
+      }
+
+      assert {:ok, activity} = Transmogrifier.handle_incoming(remove)
+      assert activity.data == remove
+
+      user = refresh_record(user)
+      refute user.pinned_objects[object_url]
+    end
+
+    test "Add/Remove activities for remote users without featured address" do
+      user = insert(:user, local: false, domain: "example.com")
+
+      user =
+        user
+        |> Ecto.Changeset.change(featured_address: nil)
+        |> Repo.update!()
+
+      %{host: host} = URI.parse(user.ap_id)
+
+      user_data =
+        "test/fixtures/users_mock/user.json"
+        |> File.read!()
+        |> String.replace("{{nickname}}", user.nickname)
+
+      object_id = "c61d6733-e256-4fe1-ab13-1e369789423f"
+
+      object =
+        "test/fixtures/statuses/note.json"
+        |> File.read!()
+        |> String.replace("{{nickname}}", user.nickname)
+        |> String.replace("{{object_id}}", object_id)
+
+      object_url = "https://#{host}/objects/#{object_id}"
+
+      actor = "https://#{host}/users/#{user.nickname}"
+
+      featured = "https://#{host}/users/#{user.nickname}/collections/featured"
+
+      Tesla.Mock.mock(fn
+        %{
+          method: :get,
+          url: ^actor
+        } ->
+          %Tesla.Env{
+            status: 200,
+            body: user_data,
+            headers: [{"content-type", "application/activity+json"}]
+          }
+
+        %{
+          method: :get,
+          url: ^object_url
+        } ->
+          %Tesla.Env{
+            status: 200,
+            body: object,
+            headers: [{"content-type", "application/activity+json"}]
+          }
+
+        %{method: :get, url: ^featured} ->
+          %Tesla.Env{
+            status: 200,
+            body:
+              "test/fixtures/users_mock/masto_featured.json"
+              |> File.read!()
+              |> String.replace("{{domain}}", "#{host}")
+              |> String.replace("{{nickname}}", user.nickname),
+            headers: [{"content-type", "application/activity+json"}]
+          }
+      end)
+
+      message = %{
+        "id" => "https://#{host}/objects/d61d6733-e256-4fe1-ab13-1e369789423f",
+        "actor" => actor,
+        "object" => object_url,
+        "target" => "https://#{host}/users/#{user.nickname}/collections/featured",
+        "type" => "Add",
+        "to" => [Pleroma.Constants.as_public()],
+        "cc" => ["https://#{host}/users/#{user.nickname}/followers"]
+      }
+
+      assert {:ok, activity} = Transmogrifier.handle_incoming(message)
+      assert activity.data == message
+      user = User.get_cached_by_ap_id(actor)
+      assert user.pinned_objects[object_url]
+    end
   end
 
   describe "prepare outgoing" do
@@ -153,15 +316,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       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)
 
@@ -202,7 +356,20 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
     test "it strips internal fields" do
       user = insert(:user)
 
-      {:ok, activity} = CommonAPI.post(user, %{status: "#2hu :firefox:"})
+      {:ok, activity} =
+        CommonAPI.post(user, %{
+          status: "#2hu :firefox:",
+          generator: %{type: "Application", name: "TestClient", url: "https://pleroma.social"}
+        })
+
+      # Ensure injected application data made it into the activity
+      # as we don't have a Token to derive it from, otherwise it will
+      # be nil and the test will pass
+      assert %{
+               type: "Application",
+               name: "TestClient",
+               url: "https://pleroma.social"
+             } == activity.object.data["generator"]
 
       {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
 
@@ -213,6 +380,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       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"]["generator"])
     end
 
     test "it strips internal fields of article" do
@@ -281,6 +449,21 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
 
       {:ok, _modified} = Transmogrifier.prepare_outgoing(activity.data)
     end
+
+    test "custom emoji urls are URI encoded" do
+      # :dinosaur: filename has a space -> dino walking.gif
+      user = insert(:user)
+
+      {:ok, activity} = CommonAPI.post(user, %{status: "everybody do the dinosaur :dinosaur:"})
+
+      {:ok, prepared} = Transmogrifier.prepare_outgoing(activity.data)
+
+      assert length(prepared["object"]["tag"]) == 1
+
+      url = prepared["object"]["tag"] |> List.first() |> Map.get("icon") |> Map.get("url")
+
+      assert url == "http://localhost:4001/emoji/dino%20walking.gif"
+    end
   end
 
   describe "user upgrade" do