Merge branch 'improving-test-coverage' into 'develop'
[akkoma] / lib / pleroma / web / activity_pub / transmogrifier.ex
index 09bd9a44290679477778ffa6548e290632daa43a..0a8ad62ad28c2ceb04398b707fa34d65b63e6c10 100644 (file)
@@ -13,6 +13,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   alias Pleroma.Repo
   alias Pleroma.User
   alias Pleroma.Web.ActivityPub.ActivityPub
+  alias Pleroma.Web.ActivityPub.ObjectValidator
+  alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
+  alias Pleroma.Web.ActivityPub.Pipeline
   alias Pleroma.Web.ActivityPub.Utils
   alias Pleroma.Web.ActivityPub.Visibility
   alias Pleroma.Web.Federator
@@ -609,17 +612,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     |> handle_incoming(options)
   end
 
-  def handle_incoming(
-        %{"type" => "Like", "object" => object_id, "actor" => _actor, "id" => id} = data,
-        _options
-      ) do
-    with actor <- Containment.get_actor(data),
-         {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor),
-         {:ok, object} <- get_obj_helper(object_id),
-         {:ok, activity, _object} <- ActivityPub.like(actor, object, id, false) do
+  def handle_incoming(%{"type" => "Like"} = data, _options) do
+    with {_, {:ok, cast_data_sym}} <-
+           {:casting_data,
+            data |> LikeValidator.cast_data() |> Ecto.Changeset.apply_action(:insert)},
+         cast_data = ObjectValidator.stringify_keys(Map.from_struct(cast_data_sym)),
+         :ok <- ObjectValidator.fetch_actor_and_object(cast_data),
+         {_, {:ok, cast_data}} <- {:ensure_context_presence, ensure_context_presence(cast_data)},
+         {_, {:ok, cast_data}} <-
+           {:ensure_recipients_presence, ensure_recipients_presence(cast_data)},
+         {_, {:ok, activity, _meta}} <-
+           {:common_pipeline, Pipeline.common_pipeline(cast_data, local: false)} do
       {:ok, activity}
     else
-      _e -> :error
+      e -> {:error, e}
     end
   end
 
@@ -1243,4 +1249,45 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   def maybe_fix_user_url(data), do: data
 
   def maybe_fix_user_object(data), do: maybe_fix_user_url(data)
+
+  defp ensure_context_presence(%{"context" => context} = data) when is_binary(context),
+    do: {:ok, data}
+
+  defp ensure_context_presence(%{"object" => object} = data) when is_binary(object) do
+    with %{data: %{"context" => context}} when is_binary(context) <- Object.normalize(object) do
+      {:ok, Map.put(data, "context", context)}
+    else
+      _ ->
+        {:error, :no_context}
+    end
+  end
+
+  defp ensure_context_presence(_) do
+    {:error, :no_context}
+  end
+
+  defp ensure_recipients_presence(%{"to" => [_ | _], "cc" => [_ | _]} = data),
+    do: {:ok, data}
+
+  defp ensure_recipients_presence(%{"object" => object} = data) do
+    case Object.normalize(object) do
+      %{data: %{"actor" => actor}} ->
+        data =
+          data
+          |> Map.put("to", [actor])
+          |> Map.put("cc", data["cc"] || [])
+
+        {:ok, data}
+
+      nil ->
+        {:error, :no_object}
+
+      _ ->
+        {:error, :no_actor}
+    end
+  end
+
+  defp ensure_recipients_presence(_) do
+    {:error, :no_object}
+  end
 end