Merge remote-tracking branch 'upstream/develop' into attachment-meta
[akkoma] / lib / pleroma / web / activity_pub / object_validators / create_generic_validator.ex
index 54ea14f89dd8e9edee81158b008e400c2194fab1..e06e442f41a0bf49fc330ea57eccc06984f75b18 100644 (file)
@@ -1,5 +1,5 @@
 # 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
 
 # Code based on CreateChatMessageValidator
@@ -10,9 +10,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
 
   alias Pleroma.EctoType.ActivityPub.ObjectValidators
   alias Pleroma.Object
+  alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
+  alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
 
   import Ecto.Changeset
-  import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
 
   @primary_key false
 
@@ -24,9 +25,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
     field(:cc, ObjectValidators.Recipients, default: [])
     field(:object, ObjectValidators.ObjectID)
     field(:expires_at, ObjectValidators.DateTime)
+
+    # Should be moved to object, done for CommonAPI.Utils.make_context
+    field(:context, :string)
   end
 
-  def cast_data(data) do
+  def cast_data(data, meta \\ []) do
+    data = fix(data, meta)
+
     %__MODULE__{}
     |> changeset(data)
   end
@@ -39,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
 
   def cast_and_validate(data, meta \\ []) do
     data
-    |> cast_data
+    |> cast_data(meta)
     |> validate_data(meta)
   end
 
@@ -48,13 +54,39 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
     |> cast(data, __schema__(:fields))
   end
 
-  def validate_data(cng, meta \\ []) do
+  defp fix_context(data, meta) do
+    if object = meta[:object_data] do
+      Map.put_new(data, "context", object["context"])
+    else
+      data
+    end
+  end
+
+  defp fix_addressing(data, meta) do
+    if object = meta[:object_data] do
+      data
+      |> Map.put_new("to", object["to"] || [])
+      |> Map.put_new("cc", object["cc"] || [])
+    else
+      data
+    end
+  end
+
+  defp fix(data, meta) do
+    data
+    |> fix_context(meta)
+    |> fix_addressing(meta)
+    |> CommonFixes.fix_actor()
+  end
+
+  defp validate_data(cng, meta) do
     cng
     |> validate_required([:actor, :type, :object])
     |> validate_inclusion(:type, ["Create"])
-    |> validate_actor_is_active()
-    |> validate_any_presence([:to, :cc])
+    |> CommonValidations.validate_actor_presence()
+    |> CommonValidations.validate_any_presence([:to, :cc])
     |> validate_actors_match(meta)
+    |> validate_context_match(meta)
     |> validate_object_nonexistence()
     |> validate_object_containment()
   end
@@ -98,4 +130,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
       end
     end)
   end
+
+  def validate_context_match(cng, %{object_data: %{"context" => object_context}}) do
+    cng
+    |> validate_change(:context, fn :context, context ->
+      if context == object_context do
+        []
+      else
+        [{:context, "context field not matching between Create and object (#{object_context})"}]
+      end
+    end)
+  end
+
+  def validate_context_match(cng, _), do: cng
 end