commit: 62340b50b57eeab0b7ab4093e07d05080991bfc4
parent edc8689d9176e0134dc9d3a45dae5b530f8950e9
Author: marcin mikołajczak <git@mkljczk.pl>
Date: Sat, 19 Aug 2023 19:03:25 +0200
Move maybe_add_content_map out of Transmogrifier, use code from tusooa's branch for MapOfString
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
Diffstat:
9 files changed, 194 insertions(+), 71 deletions(-)
diff --git a/lib/pleroma/ecto_type/activity_pub/object_validators/map_of_string.ex b/lib/pleroma/ecto_type/activity_pub/object_validators/map_of_string.ex
@@ -0,0 +1,48 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.MapOfString do
+ use Ecto.Type
+
+ import Pleroma.Web.CommonAPI.Utils, only: [is_good_locale_code?: 1]
+
+ def type, do: :map
+
+ def cast(%{} = object) do
+ with {status, %{} = data} when status in [:modified, :ok] <- validate_map(object) do
+ {:ok, data}
+ else
+ {_, nil} -> {:ok, nil}
+ {:error, _} -> :error
+ end
+ end
+
+ def cast(_), do: :error
+
+ def dump(data), do: {:ok, data}
+
+ def load(data), do: {:ok, data}
+
+ defp validate_map(%{} = object) do
+ {status, data} =
+ object
+ |> Enum.reduce({:ok, %{}}, fn
+ {lang, value}, {status, acc} when is_binary(lang) and is_binary(value) ->
+ if is_good_locale_code?(lang) do
+ {status, Map.put(acc, lang, value)}
+ else
+ {:modified, acc}
+ end
+
+ _, {_status, acc} ->
+ {:modified, acc}
+ end)
+
+ if data == %{} do
+ {status, nil}
+ else
+ {status, data}
+ end
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
@@ -87,6 +87,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
|> Transmogrifier.fix_emoji()
|> Transmogrifier.fix_content_map()
|> CommonFixes.maybe_add_language(meta)
+ |> CommonFixes.maybe_add_content_map()
end
def changeset(struct, data, meta \\ []) do
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
@@ -31,6 +31,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
defmacro object_fields do
quote bind_quoted: binding() do
field(:content, :string)
+ field(:contentMap, ObjectValidators.MapOfString)
field(:published, ObjectValidators.DateTime)
field(:updated, ObjectValidators.DateTime)
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
@@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
alias Pleroma.Web.ActivityPub.Utils
import Pleroma.Web.CommonAPI.Utils, only: [is_good_locale_code?: 1]
+ import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do
{:ok, data} = ObjectValidators.Recipients.cast(message[field] || field_fallback)
@@ -118,4 +119,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
end
defp get_language_from_content_map(_), do: nil
+
+ def maybe_add_content_map(%{"language" => language, "content" => content} = object)
+ when not_empty_string(language) do
+ Map.put(object, "contentMap", Map.put(%{}, language, content))
+ end
+
+ def maybe_add_content_map(object), do: object
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex
@@ -26,32 +26,34 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do
end
end
- def cast_and_apply(data) do
+ def cast_and_apply(data, meta \\ []) do
data
- |> cast_data
+ |> cast_data(meta)
|> apply_action(:insert)
end
- def cast_and_validate(data) do
+ def cast_and_validate(data, meta \\ []) do
data
- |> cast_data()
+ |> cast_data(meta)
|> validate_data()
end
- def cast_data(data) do
+ def cast_data(data, meta \\ []) do
%__MODULE__{}
- |> changeset(data)
+ |> changeset(data, meta)
end
- defp fix(data) do
+ defp fix(data, meta) do
data
|> CommonFixes.fix_actor()
|> CommonFixes.fix_object_defaults()
|> Transmogrifier.fix_emoji()
+ |> CommonFixes.maybe_add_language(meta)
+ |> CommonFixes.maybe_add_content_map()
end
- def changeset(struct, data) do
- data = fix(data)
+ def changeset(struct, data, meta \\ []) do
+ data = fix(data, meta)
struct
|> cast(data, __schema__(:fields) -- [:attachment, :tag])
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -682,7 +682,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> add_mention_tags
|> add_emoji_tags
|> add_attributed_to
- |> maybe_add_content_map
|> prepare_attachments
|> set_conversation
|> set_reply_to_uri
@@ -956,11 +955,4 @@ 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 maybe_add_content_map(%{"language" => language, "content" => content} = object)
- when not_empty_string(language) do
- Map.put(object, "contentMap", Map.put(%{}, language, content))
- end
-
- defp maybe_add_content_map(object), do: object
end
diff --git a/test/pleroma/ecto_type/activity_pub/object_validators/map_of_string_test.exs b/test/pleroma/ecto_type/activity_pub/object_validators/map_of_string_test.exs
@@ -0,0 +1,55 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.MapOfStringTest do
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.MapOfString
+ use Pleroma.DataCase, async: true
+
+ test "it validates" do
+ data = %{
+ "en-US" => "mew mew",
+ "en-GB" => "meow meow"
+ }
+
+ assert {:ok, ^data} = MapOfString.cast(data)
+ end
+
+ test "it validates empty strings" do
+ data = %{
+ "en-US" => "mew mew",
+ "en-GB" => ""
+ }
+
+ assert {:ok, ^data} = MapOfString.cast(data)
+ end
+
+ test "it ignores non-strings within the map" do
+ data = %{
+ "en-US" => "mew mew",
+ "en-GB" => 123
+ }
+
+ assert {:ok, validated_data} = MapOfString.cast(data)
+
+ assert validated_data == %{"en-US" => "mew mew"}
+ end
+
+ test "it ignores bad locale codes" do
+ data = %{
+ "en-US" => "mew mew",
+ "en_GB" => "meow meow",
+ "en<<#@!$#!@%!GB" => "meow meow"
+ }
+
+ assert {:ok, validated_data} = MapOfString.cast(data)
+
+ assert validated_data == %{"en-US" => "mew mew"}
+ end
+
+ test "it complains with non-map data" do
+ assert :error = MapOfString.cast("mew")
+ assert :error = MapOfString.cast(["mew"])
+ assert :error = MapOfString.cast([%{"en-US" => "mew"}])
+ end
+end
diff --git a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
@@ -116,4 +116,74 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
end
+
+ describe "Note language" do
+ test "it detects language from context" do
+ user = insert(:user)
+
+ note_activity = %{
+ "@context" => ["https://www.w3.org/ns/activitystreams", %{"@language" => "pl"}],
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "type" => "Create",
+ "object" => %{
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "id" => Utils.generate_object_id(),
+ "type" => "Note",
+ "content" => "Szczęść Boże",
+ "attributedTo" => user.ap_id
+ },
+ "actor" => user.ap_id
+ }
+
+ {:ok, object} =
+ ArticleNotePageValidator.cast_and_apply(note_activity["object"],
+ activity_data: note_activity
+ )
+
+ assert object.language == "pl"
+ end
+
+ test "it detects language from contentMap" do
+ user = insert(:user)
+
+ note = %{
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "id" => Utils.generate_object_id(),
+ "type" => "Note",
+ "content" => "Szczęść Boże",
+ "contentMap" => %{
+ "de" => "Gott segne",
+ "pl" => "Szczęść Boże"
+ },
+ "attributedTo" => user.ap_id
+ }
+
+ {:ok, object} = ArticleNotePageValidator.cast_and_apply(note)
+
+ assert object.language == "pl"
+ end
+
+ test "it adds contentMap if language is specified" do
+ user = insert(:user)
+
+ note = %{
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "id" => Utils.generate_object_id(),
+ "type" => "Note",
+ "content" => "тест",
+ "language" => "uk",
+ "attributedTo" => user.ap_id
+ }
+
+ {:ok, object} = ArticleNotePageValidator.cast_and_apply(note)
+
+ assert object.contentMap == %{
+ "uk" => "тест"
+ }
+ end
+ end
end
diff --git a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs
@@ -388,60 +388,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
end
end
- test "it detects language from context" do
- user = insert(:user)
-
- message = %{
- "@context" => ["https://www.w3.org/ns/activitystreams", %{"@language" => "pl"}],
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [],
- "type" => "Create",
- "object" => %{
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "cc" => [],
- "id" => Utils.generate_object_id(),
- "type" => "Note",
- "content" => "Szczęść Boże",
- "attributedTo" => user.ap_id
- },
- "actor" => user.ap_id
- }
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(message)
- object = Object.normalize(data["object"], fetch: false)
-
- assert object.data["language"] == "pl"
- end
-
- test "it detects language from contentMap" 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" => [],
- "id" => Utils.generate_object_id(),
- "type" => "Note",
- "content" => "Szczęść Boże",
- "contentMap" => %{
- "de" => "Gott segne",
- "pl" => "Szczęść Boże"
- },
- "attributedTo" => user.ap_id
- },
- "actor" => user.ap_id
- }
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(message)
- object = Object.normalize(data["object"], fetch: false)
-
- assert object.data["language"] == "pl"
- 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])