akkoma/test/pleroma/web/federator_test.exs
Oneric 2fee79e1f5 Use apropriate cancellation type for oban jobs
:discard marks jobs as "discarded", i.e. jobs which permanently failed
due to e.g. exhausting all retries or explicitly being discared due to a
fatal error.
:cancel marks jobs as "cancelled" which does not imply failure.

While neither method counts as a job "exception" in the set of
telemetries we currently export via Prometheus, the different state
is visible in the (not-exported) metadata of oban job telemetry.
We can use handlers of those events to build bespoke statistics.

Ideally we'd like to distinguish in the receiver worker between
"invalid" and "already present or delete of unknown" documents,
but this is cumbersome to get get right with a list of
free-form, human-readable descriptions oof the violated constraints.
For now, just count both as an fatal error.
        # but that is cumbersome to get right with a list of string error descriptions
2025-04-15 19:40:26 +02:00

205 lines
6.3 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
})
insert(:user, %{
local: false,
nickname: "nick2@domain2.com",
ap_id: "https://domain2.com/users/nick2",
inbox: inbox2
})
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 {:cancel, :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 {:cancel, _} = ObanHelpers.perform(job)
end
end
end