From f22caeff530b2b218b9e33a216c4828ef4fd2eac Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 27 Oct 2026 21:46:45 +0400 Subject: [PATCH] fix(user): update the known user when fetched from a display URL A fetch from a display URL (e.g. https://host/@user) returns the actor with its canonical id. make_user_from_ap_id looked the user up by the fetch URL, did not find it and tried to insert a duplicate. Look the user up by the fetched id. Based on Akkoma 48b3a3579. --- changelog.d/user-fetch-display-url.fix | 1 + lib/pleroma/web/activity_pub/activity_pub.ex | 5 ++-- .../web/activity_pub/activity_pub_test.exs | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 changelog.d/user-fetch-display-url.fix diff --git a/changelog.d/user-fetch-display-url.fix b/changelog.d/user-fetch-display-url.fix new file mode 100644 index 000000000..fcde4ecf4 --- /dev/null +++ b/changelog.d/user-fetch-display-url.fix @@ -0,0 +1 @@ +Update the known user instead of failing when an actor is fetched from a display URL diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 18cb2cadc..b997e7831 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -2055,11 +2055,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def enqueue_pin_fetches(_), do: nil def make_user_from_ap_id(ap_id, additional \\ []) do - user = User.get_cached_by_ap_id(ap_id) - with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, additional) do enqueue_pin_fetches(data) + # the fetched actor's id differs from ap_id when it was fetched from a display URL + user = User.get_cached_by_ap_id(data.ap_id) + if user do user |> User.remote_user_changeset(data) diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index 7294119b8..c118cd8f1 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -269,6 +269,33 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do refute User.get_by_ap_id(ap_id) end + test "updates the known user when fetched from a display URL" do + ap_id = "https://example.com/users/lain" + display_url = "https://example.com/@lain" + user = insert(:user, local: false, ap_id: ap_id, nickname: "lain@example.com") + + user_data = + "test/fixtures/users_mock/user.json" + |> File.read!() + |> String.replace("{{nickname}}", "lain") + |> Jason.decode!() + |> Map.merge(%{"featured" => nil, "name" => "new name"}) + |> Jason.encode!() + + Tesla.Mock.mock(fn %{method: :get, url: url} when url in [ap_id, display_url] -> + %Tesla.Env{ + status: 200, + body: user_data, + headers: [{"content-type", "application/activity+json"}] + } + end) + + assert {:ok, %User{id: id, name: "new name"}} = + ActivityPub.make_user_from_ap_id(display_url) + + assert id == user.id + end + test "fetches user featured collection" do ap_id = "https://example.com/users/lain"