From d1d2744ee3e6015064cf50ac5725bfe45b682466 Mon Sep 17 00:00:00 2001
From: Alexander Strizhakov <alex.strizhakov@gmail.com>
Date: Wed, 3 Mar 2021 15:41:05 +0300
Subject: [PATCH] featured_address valition in AddRemoveValidator

---
 .../web/activity_pub/object_validator.ex      |  2 +-
 .../object_validators/add_remove_validator.ex | 12 +++++-----
 .../web/activity_pub/transmogrifier.ex        |  7 ++++--
 lib/pleroma/web/common_api.ex                 | 13 +++++++----
 test/fixtures/users_mock/user.json            |  1 +
 .../activity_pub_controller_test.exs          | 22 +++++++++++++++++++
 .../web/activity_pub/transmogrifier_test.exs  | 11 ++++++++++
 7 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex
index 14c3e8531..3ca9136aa 100644
--- a/lib/pleroma/web/activity_pub/object_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validator.ex
@@ -238,7 +238,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
   def validate(%{"type" => type} = object, meta) when type in ~w(Add Remove) do
     with {:ok, object} <-
            object
-           |> AddRemoveValidator.cast_and_validate()
+           |> AddRemoveValidator.cast_and_validate(meta)
            |> Ecto.Changeset.apply_action(:insert) do
       object = stringify_keys(object)
       {:ok, object, meta}
diff --git a/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex b/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
index 73d1c03f0..885282f32 100644
--- a/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
@@ -22,28 +22,28 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
     field(:cc, ObjectValidators.Recipients, default: [])
   end
 
-  def cast_and_validate(data) do
+  def cast_and_validate(data, meta) do
     data
     |> cast_data()
-    |> validate_data()
+    |> validate_data(meta)
   end
 
   defp cast_data(data) do
     cast(%__MODULE__{}, data, __schema__(:fields))
   end
 
-  defp validate_data(changeset) do
+  defp validate_data(changeset, meta) do
     changeset
     |> validate_required([:id, :target, :object, :actor, :type, :to, :cc])
     |> validate_inclusion(:type, ~w(Add Remove))
     |> validate_actor_presence()
-    |> validate_collection_belongs_to_actor()
+    |> validate_collection_belongs_to_actor(meta)
     |> validate_object_presence()
   end
 
-  defp validate_collection_belongs_to_actor(changeset) do
+  defp validate_collection_belongs_to_actor(changeset, meta) do
     validate_change(changeset, :target, fn :target, target ->
-      if String.starts_with?(target, changeset.changes[:actor]) do
+      if target == meta[:featured_address] do
         []
       else
         [target: "collection doesn't belong to actor"]
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index b662f5379..fa62e0db2 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -557,7 +557,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   end
 
   def handle_incoming(%{"type" => type} = data, _options) when type in ~w(Add Remove) do
-    with {:ok, user} <- ObjectValidator.fetch_actor(data),
+    with {:ok, %User{} = user} <- ObjectValidator.fetch_actor(data),
          %Object{} <- Object.normalize(data["object"], fetch: true) do
       # Mastodon sends pin/unpin objects without id, to, cc fields
       data =
@@ -566,7 +566,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
         |> Map.put_new("to", [Pleroma.Constants.as_public()])
         |> Map.put_new("cc", [user.follower_address])
 
-      case Pipeline.common_pipeline(data, local: false) do
+      case Pipeline.common_pipeline(data,
+             local: false,
+             featured_address: user.featured_address
+           ) do
         {:ok, activity, _meta} -> {:ok, activity}
         error -> error
       end
diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex
index d35a0f219..175d690cc 100644
--- a/lib/pleroma/web/common_api.ex
+++ b/lib/pleroma/web/common_api.ex
@@ -412,14 +412,18 @@ defmodule Pleroma.Web.CommonAPI do
   end
 
   @spec pin(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, term()}
-  def pin(id, %User{ap_id: actor} = user) do
+  def pin(id, %User{} = user) do
     with %Activity{} = activity <- create_activity_by_id(id),
-         true <- activity_belongs_to_actor(activity, actor),
+         true <- activity_belongs_to_actor(activity, user.ap_id),
          true <- object_type_is_allowed_for_pin(activity.object),
          true <- activity_is_public(activity),
          {:ok, pin_data, _} <- Builder.pin(user, activity.object),
          {:ok, _pin, _} <-
-           Pipeline.common_pipeline(pin_data, local: true, activity_id: id) do
+           Pipeline.common_pipeline(pin_data,
+             local: true,
+             activity_id: id,
+             featured_address: user.featured_address
+           ) do
       {:ok, activity}
     else
       {:error, {:execute_side_effects, error}} -> error
@@ -456,7 +460,8 @@ defmodule Pleroma.Web.CommonAPI do
            Pipeline.common_pipeline(unpin_data,
              local: true,
              activity_id: activity.id,
-             expires_at: activity.data["expires_at"]
+             expires_at: activity.data["expires_at"],
+             featured_address: user.featured_address
            ) do
       {:ok, activity}
     end
diff --git a/test/fixtures/users_mock/user.json b/test/fixtures/users_mock/user.json
index da2483d02..c722a1145 100644
--- a/test/fixtures/users_mock/user.json
+++ b/test/fixtures/users_mock/user.json
@@ -34,6 +34,7 @@
     "owner": "https://example.com/users/{{nickname}}",
     "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5DLtwGXNZElJyxFGfcVc\nXANhaMadj/iYYQwZjOJTV9QsbtiNBeIK54PJrYuU0/0YIdrvS1iqheX5IwXRhcwa\nhm3ZyLz7XeN9st7FBni4BmZMBtMpxAuYuu5p/jbWy13qAiYOhPreCx0wrWgm/lBD\n9mkgaxIxPooBE0S4ZWEJIDIV1Vft3AWcRUyWW1vIBK0uZzs6GYshbQZB952S0yo4\nFzI1hABGHncH8UvuFauh4EZ8tY7/X5I0pGRnDOcRN1dAht5w5yTA+6r5kebiFQjP\nIzN/eCO/a9Flrj9YGW7HDNtjSOH0A31PLRGlJtJO3yK57dnf5ppyCZGfL4emShQo\ncQIDAQAB\n-----END PUBLIC KEY-----\n\n"
   },
+  "featured": "https://example.com/users/{{nickname}}/collections/featured",
   "summary": "your friendly neighborhood pleroma developer<br>I like cute things and distributed systems, and really hate delete and redrafts",
   "tag": [],
   "type": "Person",
diff --git a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs
index d9fa25d94..cea4b3a97 100644
--- a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs
@@ -673,6 +673,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
             body: user,
             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)
 
       data = %{
@@ -753,6 +764,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
             body: user,
             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)
 
       data = %{
diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs
index 9bc27f89e..fb8284aaf 100644
--- a/test/pleroma/web/activity_pub/transmogrifier_test.exs
+++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs
@@ -147,6 +147,17 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
             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 = %{