akkoma/test/pleroma/web/federator_test.exs
Oneric b0a46c1e2e Normalise public adressing to fix federation
Due to JSON-LD compaction the full address of public scope
may also occur in shorter forms and the spec requires us to treat them
all equivalently. To save us the pain of repeatedly checking for all
variants internally, normalise inbound data to just one form.
See note at: https://www.w3.org/TR/activitypub/#public-addressing

This needs to happen very early, even before the other addressing fixes
else an earlier validator will reject the object. This in turn required
to move the list-tpye normalisation earlier as well, but since I was
unsure about putting empty lists into the data when no such field
existed before, I excluded this case and thus the later fixing had to be
kept as well.

Fixes: https://akkoma.dev/AkkomaGang/akkoma/issues/670
2024-04-25 18:45:16 +02:00

207 lines
6.4 KiB
Elixir

# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.FederatorTest do
alias Pleroma.Instances
alias Pleroma.Tests.ObanHelpers
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Federator
alias Pleroma.Workers.PublisherWorker
use Pleroma.DataCase, async: false
@moduletag :mocked
use Oban.Testing, repo: Pleroma.Repo
import Pleroma.Factory
import Mock
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
setup_all do: clear_config([:instance, :federating], true)
setup do: clear_config([:instance, :allow_relay], true)
setup do: clear_config([:mrf, :policies])
setup do: clear_config([:mrf_keyword])
describe "Publish an activity" do
setup do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{status: "HI"})
relay_mock = {
Pleroma.Web.ActivityPub.Relay,
[],
[publish: fn _activity -> send(self(), :relay_publish) end]
}
%{activity: activity, relay_mock: relay_mock}
end
test "with relays active, it publishes to the relay", %{
activity: activity,
relay_mock: relay_mock
} do
with_mocks([relay_mock]) do
Federator.publish(activity)
ObanHelpers.perform(all_enqueued(worker: PublisherWorker))
end
assert_receive :relay_publish
end
test "with relays deactivated, it does not publish to the relay", %{
activity: activity,
relay_mock: relay_mock
} do
clear_config([:instance, :allow_relay], false)
with_mocks([relay_mock]) do
Federator.publish(activity)
ObanHelpers.perform(all_enqueued(worker: PublisherWorker))
end
refute_received :relay_publish
end
end
describe "Targets reachability filtering in `publish`" do
test "it federates only to reachable instances via AP" do
user = insert(:user)
{inbox1, inbox2} =
{"https://domain.com/users/nick1/inbox", "https://domain2.com/users/nick2/inbox"}
insert(:user, %{
local: false,
nickname: "nick1@domain.com",
ap_id: "https://domain.com/users/nick1",
inbox: inbox1,
ap_enabled: true
})
insert(:user, %{
local: false,
nickname: "nick2@domain2.com",
ap_id: "https://domain2.com/users/nick2",
inbox: inbox2,
ap_enabled: true
})
dt = NaiveDateTime.utc_now()
Instances.set_unreachable(inbox1, dt)
Instances.set_consistently_unreachable(URI.parse(inbox2).host)
{:ok, _activity} =
CommonAPI.post(user, %{status: "HI @nick1@domain.com, @nick2@domain2.com!"})
expected_dt = NaiveDateTime.to_iso8601(dt)
ObanHelpers.perform(all_enqueued(worker: PublisherWorker))
assert ObanHelpers.member?(
%{
"op" => "publish_one",
"params" => %{"inbox" => inbox1, "unreachable_since" => expected_dt}
},
all_enqueued(worker: PublisherWorker)
)
end
end
describe "Receive an activity" do
test "successfully processes incoming AP docs with correct origin" do
params = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"actor" => "http://mastodon.example.org/users/admin",
"type" => "Create",
"id" => "http://mastodon.example.org/users/admin/activities/1",
"object" => %{
"type" => "Note",
"content" => "hi world!",
"id" => "http://mastodon.example.org/users/admin/objects/1",
"attributedTo" => "http://mastodon.example.org/users/admin",
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
},
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
}
assert {:ok, job} = Federator.incoming_ap_doc(params)
assert {:ok, _activity} = ObanHelpers.perform(job)
assert {:ok, job} = Federator.incoming_ap_doc(params)
assert {:error, :already_present} = ObanHelpers.perform(job)
end
test "successfully normalises public scope descriptors" do
params = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"actor" => "http://mastodon.example.org/users/admin",
"type" => "Create",
"id" => "http://mastodon.example.org/users/admin/activities/1",
"object" => %{
"type" => "Note",
"content" => "hi world!",
"id" => "http://mastodon.example.org/users/admin/objects/1",
"attributedTo" => "http://mastodon.example.org/users/admin",
"to" => ["Public"]
},
"to" => ["as:Public"]
}
assert {:ok, job} = Federator.incoming_ap_doc(params)
assert {:ok, activity} = ObanHelpers.perform(job)
assert activity.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
object =
from(
object in Pleroma.Object,
where: fragment("(?)->>'id' = ?", object.data, ^activity.data["object"]),
limit: 1
)
|> Repo.one()
assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
end
test "rejects incoming AP docs with incorrect origin" do
params = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"actor" => "https://niu.moe/users/rye",
"type" => "Create",
"id" => "http://mastodon.example.org/users/admin/activities/1",
"object" => %{
"type" => "Note",
"content" => "hi world!",
"id" => "http://mastodon.example.org/users/admin/objects/1",
"attributedTo" => "http://mastodon.example.org/users/admin",
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
},
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
}
assert {:ok, job} = Federator.incoming_ap_doc(params)
assert {:discard, :origin_containment_failed} = ObanHelpers.perform(job)
end
test "it does not crash if MRF rejects the post" do
clear_config([:mrf_keyword, :reject], ["lain"])
clear_config(
[:mrf, :policies],
Pleroma.Web.ActivityPub.MRF.KeywordPolicy
)
params =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Jason.decode!()
assert {:ok, job} = Federator.incoming_ap_doc(params)
assert {:discard, _} = ObanHelpers.perform(job)
end
end
end