Merge pull request 'Akkoma interop fixes: emoji reacts, personal inbox, markers, data: URLs' (#8050) from lambadalambda/pleroma:fix/akkoma-interop into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8050
This commit is contained in:
commit
4b08f7a553
15 changed files with 92 additions and 93 deletions
1
changelog.d/emoji-react-single-tag.fix
Normal file
1
changelog.d/emoji-react-single-tag.fix
Normal file
|
|
@ -0,0 +1 @@
|
|||
Accept incoming emoji reactions whose tag is a single object instead of an array
|
||||
1
changelog.d/marker-updated-at-format.fix
Normal file
1
changelog.d/marker-updated-at-format.fix
Normal file
|
|
@ -0,0 +1 @@
|
|||
Mastodon API: Use the Mastodon date format for marker updated_at
|
||||
1
changelog.d/media-proxy-data-urls.fix
Normal file
1
changelog.d/media-proxy-data-urls.fix
Normal file
|
|
@ -0,0 +1 @@
|
|||
MediaProxy: Do not proxy data: URLs
|
||||
1
changelog.d/personal-inbox-addressing.fix
Normal file
1
changelog.d/personal-inbox-addressing.fix
Normal file
|
|
@ -0,0 +1 @@
|
|||
Accept activities delivered to a personal inbox that do not address the inbox owner (fixes Bridgy Fed follows)
|
||||
|
|
@ -341,7 +341,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
|||
{:sender_exists, User.get_or_fetch_by_ap_id(params["actor"])},
|
||||
{:recipient_active, true} <- {:recipient_active, recipient.is_active},
|
||||
{:sender_active, true} <- {:sender_active, actor.is_active},
|
||||
true <- Utils.recipient_in_message(recipient, actor, params),
|
||||
params <- Utils.maybe_splice_recipient(recipient.ap_id, params) do
|
||||
Federator.incoming_ap_doc(params)
|
||||
json(conn, "ok")
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
|
|||
|> CommonFixes.fix_actor()
|
||||
|> CommonFixes.fix_activity_addressing()
|
||||
|
||||
data = Map.put_new(data, "tag", [])
|
||||
data = fix_tag(data)
|
||||
|
||||
case Object.normalize(data["object"]) do
|
||||
%Object{} = object ->
|
||||
|
|
@ -70,6 +70,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
|
|||
end
|
||||
end
|
||||
|
||||
# JSON-LD compaction turns a single-element array into a bare object
|
||||
defp fix_tag(%{"tag" => %{} = tag} = data), do: Map.put(data, "tag", [tag])
|
||||
defp fix_tag(data), do: Map.put_new(data, "tag", [])
|
||||
|
||||
defp fix_emoji_qualification(%{"content" => emoji} = data) do
|
||||
new_emoji = Pleroma.Emoji.fully_qualify_emoji(emoji)
|
||||
|
||||
|
|
|
|||
|
|
@ -78,22 +78,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
[params["to"], params["cc"], params["bto"], params["bcc"]]
|
||||
|> Enum.any?(&label_in_collection?(label, &1))
|
||||
|
||||
@spec unaddressed_message?(map()) :: boolean()
|
||||
def unaddressed_message?(params),
|
||||
do:
|
||||
[params["to"], params["cc"], params["bto"], params["bcc"]]
|
||||
|> Enum.all?(fn
|
||||
nil -> true
|
||||
[] -> true
|
||||
_ -> false
|
||||
end)
|
||||
|
||||
@spec recipient_in_message(User.t(), User.t(), map()) :: boolean()
|
||||
def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params),
|
||||
do:
|
||||
label_in_message?(ap_id, params) || unaddressed_message?(params) ||
|
||||
User.following?(recipient, actor)
|
||||
|
||||
defp extract_list(target) when is_binary(target), do: [target]
|
||||
defp extract_list(lst) when is_list(lst), do: lst
|
||||
defp extract_list(_), do: []
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.MarkerView do
|
||||
use Pleroma.Web, :view
|
||||
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
|
||||
def render("markers.json", %{markers: markers}) do
|
||||
Map.new(markers, fn m ->
|
||||
{m.timeline,
|
||||
%{
|
||||
last_read_id: m.last_read_id,
|
||||
version: m.lock_version,
|
||||
updated_at: NaiveDateTime.to_iso8601(m.updated_at),
|
||||
updated_at: Utils.to_masto_date(m.updated_at),
|
||||
pleroma: %{
|
||||
unread_count: m.unread_count
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
def url("/" <> _ = url), do: url
|
||||
|
||||
def url(url) do
|
||||
if enabled?() and url_proxiable?(url) do
|
||||
if enabled?() and not data_url?(url) and url_proxiable?(url) do
|
||||
encode_url(url)
|
||||
else
|
||||
url
|
||||
|
|
@ -61,7 +61,7 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
def preview_url("//" <> _ = url, pparams), do: preview_url("https:" <> url, pparams)
|
||||
|
||||
def preview_url(url, preview_params) do
|
||||
if preview_enabled?() do
|
||||
if preview_enabled?() and not data_url?(url) do
|
||||
encode_preview_url(url, preview_params)
|
||||
else
|
||||
url(url)
|
||||
|
|
@ -74,6 +74,8 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
# non-local non-whitelisted URLs through it and be sure that body size constraint is preserved.
|
||||
def preview_enabled?, do: enabled?() and !!Config.get([:media_preview_proxy, :enabled])
|
||||
|
||||
defp data_url?(url), do: url |> String.slice(0, 5) |> String.downcase() == "data:"
|
||||
|
||||
def local?(url), do: String.starts_with?(url, Endpoint.url())
|
||||
|
||||
def whitelisted?(url) do
|
||||
|
|
|
|||
|
|
@ -1872,6 +1872,30 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
|
||||
test "it accepts activities that do not address the inbox owner", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
actor = insert(:user, local: false)
|
||||
|
||||
data = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Follow",
|
||||
"id" => "#{actor.ap_id}/follows/1",
|
||||
"actor" => actor.ap_id,
|
||||
"object" => user.ap_id,
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign_valid_signature_for_actor(data["actor"])
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{user.nickname}/inbox", data)
|
||||
|
||||
assert "ok" == json_response(conn, 200)
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
|
||||
test "it returns an error when receiving an activity sent to a deactivated user", %{
|
||||
conn: conn,
|
||||
data: data
|
||||
|
|
|
|||
|
|
@ -86,6 +86,31 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do
|
|||
)
|
||||
end
|
||||
|
||||
test "it works for incoming custom emoji reactions with a single tag object" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/custom-emoji-reaction.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|> Map.put("actor", other_user.ap_id)
|
||||
|
||||
[tag] = data["tag"]
|
||||
data = Map.put(data, "tag", tag)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["content"] == ":hanapog:"
|
||||
assert [%{"name" => "hanapog"}] = data["tag"]
|
||||
|
||||
object = Object.get_by_ap_id(data["object"])
|
||||
url = tag["icon"]["url"]
|
||||
|
||||
assert match?([["hanapog", _, ^url]], object.data["reactions"])
|
||||
end
|
||||
|
||||
test "it works for incoming unqualified emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
|
|
|
|||
|
|
@ -406,74 +406,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "recipient_in_message/3" do
|
||||
test "returns true when recipient in `to`" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"to" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"to" => [recipient.ap_id], "cc" => ""}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns true when recipient in `cc`" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"cc" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"cc" => [recipient.ap_id], "to" => ""}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns true when recipient in `bto`" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"bto" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"bcc" => "", "bto" => [recipient.ap_id]}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns true when recipient in `bcc`" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"bcc" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"bto" => "", "bcc" => [recipient.ap_id]}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns true when message without addresses fields" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"bccc" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"btod" => "", "bccc" => [recipient.ap_id]}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns false" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
refute Utils.recipient_in_message(recipient, actor, %{"to" => "ap_id"})
|
||||
end
|
||||
end
|
||||
|
||||
describe "lazy_put_activity_defaults/2" do
|
||||
test "returns map with id and published data" do
|
||||
note_activity = insert(:note_activity)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
|
|||
alias Pleroma.Notification
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
|
|||
assert response == %{
|
||||
"notifications" => %{
|
||||
"last_read_id" => "69420",
|
||||
"updated_at" => NaiveDateTime.to_iso8601(marker.updated_at),
|
||||
"updated_at" => Utils.to_masto_date(marker.updated_at),
|
||||
"version" => 0,
|
||||
"pleroma" => %{"unread_count" => 7}
|
||||
}
|
||||
|
|
@ -107,7 +108,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
|
|||
assert response == %{
|
||||
"notifications" => %{
|
||||
"last_read_id" => "69888",
|
||||
"updated_at" => NaiveDateTime.to_iso8601(marker.updated_at),
|
||||
"updated_at" => Utils.to_masto_date(marker.updated_at),
|
||||
"version" => 0,
|
||||
"pleroma" => %{"unread_count" => 0}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.MastodonAPI.MarkerViewTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.MarkerView
|
||||
import Pleroma.Factory
|
||||
|
||||
|
|
@ -14,16 +15,25 @@ defmodule Pleroma.Web.MastodonAPI.MarkerViewTest do
|
|||
assert MarkerView.render("markers.json", %{markers: [marker1, marker2]}) == %{
|
||||
"home" => %{
|
||||
last_read_id: "42",
|
||||
updated_at: NaiveDateTime.to_iso8601(marker2.updated_at),
|
||||
updated_at: Utils.to_masto_date(marker2.updated_at),
|
||||
version: 0,
|
||||
pleroma: %{unread_count: 0}
|
||||
},
|
||||
"notifications" => %{
|
||||
last_read_id: "17",
|
||||
updated_at: NaiveDateTime.to_iso8601(marker1.updated_at),
|
||||
updated_at: Utils.to_masto_date(marker1.updated_at),
|
||||
version: 0,
|
||||
pleroma: %{unread_count: 5}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
test "renders updated_at in the Mastodon date format" do
|
||||
marker = insert(:marker, timeline: "home")
|
||||
|
||||
%{"home" => %{updated_at: updated_at}} =
|
||||
MarkerView.render("markers.json", %{markers: [marker]})
|
||||
|
||||
assert updated_at =~ ~r/\.\d{3}Z$/
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -45,6 +45,18 @@ defmodule Pleroma.Web.MediaProxyTest do
|
|||
assert MediaProxy.url(local_root) == local_root
|
||||
end
|
||||
|
||||
test "ignores data url" do
|
||||
assert MediaProxy.url("data:image/png;base64,AAAA") == "data:image/png;base64,AAAA"
|
||||
assert MediaProxy.url("DATA:image/png;base64,AAAA") == "DATA:image/png;base64,AAAA"
|
||||
end
|
||||
|
||||
test "preview_url ignores data url" do
|
||||
clear_config([:media_preview_proxy, :enabled], true)
|
||||
|
||||
assert MediaProxy.preview_url("data:image/png;base64,AAAA") ==
|
||||
"data:image/png;base64,AAAA"
|
||||
end
|
||||
|
||||
test "encodes and decodes URL" do
|
||||
url = "https://pleroma.soykaf.com/static/logo.png"
|
||||
encoded = MediaProxy.url(url)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue