commit: 1d366c01382b1da635cd8c828f1b3faf6b55c593
parent d19b992417fe55729e331c77fbce9e30e8923844
Author: lain <lain@soykaf.club>
Date: Mon, 22 Dec 2025 07:39:44 +0000
Merge branch 'transmogrifier/handle-as-public' into 'develop'
Transmogrifier: convert "as:Public" to full w3 URL
See merge request pleroma/pleroma!4394
Diffstat:
6 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/changelog.d/transmogrifier-aspublic.fix b/changelog.d/transmogrifier-aspublic.fix
@@ -0,0 +1 @@
+Transmogrifier: convert "as:Public" to full w3 URL
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
@@ -20,7 +20,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
require Pleroma.Constants
def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do
- {:ok, data} = ObjectValidators.Recipients.cast(message[field] || field_fallback)
+ # Fix as:Public/Public before ObjectID casting drops it, but keep `field_fallback`
+ # semantics (only used when the field is missing).
+ recipients =
+ %{field => message[field] || field_fallback}
+ |> Transmogrifier.fix_addressing_list(field)
+ |> Transmogrifier.fix_addressing_public(field)
+ |> Map.fetch!(field)
+
+ {:ok, data} = ObjectValidators.Recipients.cast(recipients)
data =
Enum.reject(data, fn x ->
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -104,6 +104,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
+ @doc """
+ Bovine compatibility
+ https://codeberg.org/bovine/bovine/issues/53
+ """
+ def fix_addressing_public(map, field) do
+ addrs = Map.get(map, field, []) |> List.wrap()
+
+ Map.put(
+ map,
+ field,
+ Enum.map(addrs, fn
+ "Public" -> Pleroma.Constants.as_public()
+ "as:Public" -> Pleroma.Constants.as_public()
+ x -> x
+ end)
+ )
+ end
+
# if directMessage flag is set to true, leave the addressing alone
def fix_explicit_addressing(%{"directMessage" => true} = object, _follower_collection),
do: object
@@ -161,6 +179,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> fix_addressing_list("cc")
|> fix_addressing_list("bto")
|> fix_addressing_list("bcc")
+ |> fix_addressing_public("to")
+ |> fix_addressing_public("cc")
+ |> fix_addressing_public("bto")
+ |> fix_addressing_public("bcc")
|> fix_explicit_addressing(follower_collection)
|> fix_implicit_addressing(follower_collection)
end
diff --git a/test/fixtures/bovine-bogus-public-note.json b/test/fixtures/bovine-bogus-public-note.json
@@ -0,0 +1,34 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ "https://www.w3.org/ns/did/v1",
+ "https://w3id.org/security/multikey/v1",
+ {
+ "Hashtag": "as:Hashtag"
+ }
+ ],
+ "attributedTo": "https://mymath.rocks/endpoints/SYn3cl_N4HAPfPHgo2x37XunLEmhV9LnxCggcYwyec0",
+ "cc": [
+ "https://mymath.rocks/endpoints/30zoCe7haKBEFolH4rbAmKj-t9_bG0c2X2kMQkJk5qY",
+ "https://mastodon.social/users/nikclayton"
+ ],
+ "content": "<blockquote class=\"h-quote\">\n<p>I note that mymath.rocks does not provide this information.</p>\n</blockquote>\n<p>I'm a big believer in "Do as I say, not as I <strong>did</strong>".</p>\n<p>I could give a long list of technical reasons, which boil down to: nodeinfo is pretty nonsensical with the way I write stuff.</p>\n<p>I think the above statement also addresses a main failure of the Fediverse. People, e.g. me, would love to fix stuff. Unfortunately, we lack the focus to address a lot of issues, e.g. nodeinfo sucks. So stuff gets done in a broken way.</p>\n<p>I think the main challenge the Fediverse has faced, and failed at, is avoiding the above situation. To continue the example, there is no way for somebody to say: Let's fix nodeinfo and people will follow their ideas.</p>\n",
+ "id": "https://mymath.rocks/objects/2b89e564-30cf-4eeb-97ca-7e638a154026",
+ "inReplyTo": "https://mastodon.social/users/nikclayton/statuses/115496665258618127",
+ "likes": "https://mymath.rocks/objects/2b89e564-30cf-4eeb-97ca-7e638a154026/likes",
+ "published": "2025-11-06T08:21:17.790Z",
+ "replies": "https://mymath.rocks/objects/2b89e564-30cf-4eeb-97ca-7e638a154026/replies",
+ "shares": "https://mymath.rocks/objects/2b89e564-30cf-4eeb-97ca-7e638a154026/shares",
+ "source": {
+ "content": "> I note that mymath.rocks does not provide this information.\n\nI'm a big believer in \"Do as I say, not as I __did__\".\n\nI could give a long list of technical reasons, which boil down to: nodeinfo is pretty nonsensical with the way I write stuff.\n\nI think the above statement also addresses a main failure of the Fediverse. People, e.g. me, would love to fix stuff. Unfortunately, we lack the focus to address a lot of issues, e.g. nodeinfo sucks. So stuff gets done in a broken way.\n\nI think the main challenge the Fediverse has faced, and failed at, is avoiding the above situation. To continue the example, there is no way for somebody to say: Let's fix nodeinfo and people will follow their ideas.",
+ "mediaType": "text/markdown"
+ },
+ "tag": {
+ "href": "https://mastodon.social/users/nikclayton",
+ "name": "https://mastodon.social/users/nikclayton",
+ "type": "Mention"
+ },
+ "to": "as:Public",
+ "type": "Note"
+}
diff --git a/test/pleroma/web/activity_pub/object_validators/create_generic_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/create_generic_validator_test.exs
@@ -59,4 +59,37 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidatorTest do
assert validated.valid?
assert {:context, note["context"]} in validated.changes
end
+
+ test "a Create/Note without addressing falls back to the Note's recipients" do
+ user = insert(:user)
+
+ note = %{
+ "id" => Utils.generate_object_id(),
+ "type" => "Note",
+ "actor" => user.ap_id,
+ "to" => [user.follower_address],
+ "cc" => [],
+ "content" => "Hello world",
+ "context" => Utils.generate_context_id()
+ }
+
+ note_activity = %{
+ "id" => Utils.generate_activity_id(),
+ "type" => "Create",
+ "actor" => note["actor"],
+ "object" => note,
+ "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
+ "context" => Utils.generate_context_id()
+ }
+
+ # Build metadata
+ {:ok, object_data} = ObjectValidator.cast_and_apply(note_activity["object"])
+ meta = [object_data: ObjectValidator.stringify_keys(object_data)]
+
+ validated = CreateGenericValidator.cast_and_validate(note_activity, meta)
+
+ assert validated.valid?
+ assert Ecto.Changeset.get_field(validated, :to) == note["to"]
+ assert Ecto.Changeset.get_field(validated, :cc) == note["cc"]
+ end
end
diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs
@@ -123,6 +123,30 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert activity.data["context"] == object.data["context"]
end
+ test "it fixes the public scope addressing" do
+ insert(:user,
+ ap_id: "https://mymath.rocks/endpoints/SYn3cl_N4HAPfPHgo2x37XunLEmhV9LnxCggcYwyec0"
+ )
+
+ object =
+ "test/fixtures/bovine-bogus-public-note.json"
+ |> File.read!()
+ |> Jason.decode!()
+
+ message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "type" => "Create",
+ "actor" => "https://mymath.rocks/endpoints/SYn3cl_N4HAPfPHgo2x37XunLEmhV9LnxCggcYwyec0",
+ "object" => object
+ }
+
+ assert {:ok, activity} = Transmogrifier.handle_incoming(message)
+
+ object = Object.normalize(activity, fetch: false)
+ assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
+ assert "https://www.w3.org/ns/activitystreams#Public" in object.data["to"]
+ end
+
test "it keeps link tags" do
insert(:user, ap_id: "https://example.org/users/alice")