fix(workers): avoid dynamic publisher atoms

This commit is contained in:
Lain Soykaf 2026-07-24 16:01:24 +04:00
commit 08c8571c59
No known key found for this signature in database
3 changed files with 45 additions and 5 deletions

View file

@ -0,0 +1 @@
Avoid creating atoms from serialized PublisherWorker parameters.

View file

@ -9,6 +9,13 @@ defmodule Pleroma.Workers.PublisherWorker do
use Oban.Worker, queue: :federator_outgoing, max_attempts: 13 use Oban.Worker, queue: :federator_outgoing, max_attempts: 13
@publish_one_param_keys %{
"activity_id" => :activity_id,
"cc" => :cc,
"inbox" => :inbox,
"unreachable_since" => :unreachable_since
}
@impl true @impl true
def perform(%Job{args: %{"op" => "publish", "activity_id" => activity_id}}) do def perform(%Job{args: %{"op" => "publish", "activity_id" => activity_id}}) do
activity = Activity.get_by_id(activity_id) activity = Activity.get_by_id(activity_id)
@ -16,7 +23,13 @@ defmodule Pleroma.Workers.PublisherWorker do
end end
def perform(%Job{args: %{"op" => "publish_one", "params" => params}} = job) do def perform(%Job{args: %{"op" => "publish_one", "params" => params}} = job) do
params = Map.new(params, fn {k, v} -> {String.to_atom(k), v} end) params =
Enum.reduce(params, %{}, fn {key, value}, acc ->
case @publish_one_param_keys do
%{^key => atom_key} -> Map.put(acc, atom_key, value)
_ -> acc
end
end)
# Cancel / skip the job if this server believed to be unreachable now # Cancel / skip the job if this server believed to be unreachable now
if not Instances.reachable?(params.inbox) do if not Instances.reachable?(params.inbox) do

View file

@ -11,6 +11,7 @@ defmodule Pleroma.Workers.PublisherWorkerTest do
alias Pleroma.Instances alias Pleroma.Instances
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Workers.PublisherWorker
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
@ -70,12 +71,12 @@ defmodule Pleroma.Workers.PublisherWorkerTest do
max_attempts: 5 max_attempts: 5
} }
assert {:error, :connection_error} = Pleroma.Workers.PublisherWorker.perform(job) assert {:error, :connection_error} = PublisherWorker.perform(job)
assert Instances.reachable?("https://example.com/inbox") assert Instances.reachable?("https://example.com/inbox")
# Final attempt # Final attempt
job = %{job | attempt: 5} job = %{job | attempt: 5}
assert {:error, :connection_error} = Pleroma.Workers.PublisherWorker.perform(job) assert {:error, :connection_error} = PublisherWorker.perform(job)
refute Instances.reachable?("https://example.com/inbox") refute Instances.reachable?("https://example.com/inbox")
end end
end end
@ -95,11 +96,36 @@ defmodule Pleroma.Workers.PublisherWorkerTest do
max_attempts: 5 max_attempts: 5
} }
assert :ok = Pleroma.Workers.PublisherWorker.perform(job) assert :ok = PublisherWorker.perform(job)
assert Instances.reachable?("https://example.com/inbox") assert Instances.reachable?("https://example.com/inbox")
end end
end end
test "does not create atoms from unexpected job params", %{activity: activity} do
unknown_key = "unknown_#{System.unique_integer([:positive])}"
assert_raise ArgumentError, fn -> String.to_existing_atom(unknown_key) end
with_mock Pleroma.Web.Federator,
perform: fn :publish_one, _params -> {:ok, %{status: 200}} end do
job = %Oban.Job{
args: %{
"op" => "publish_one",
"params" => %{
"inbox" => "https://example.com/inbox",
"activity_id" => activity.id,
unknown_key => "ignored"
}
},
attempt: 1,
max_attempts: 5
}
assert :ok = PublisherWorker.perform(job)
assert_raise ArgumentError, fn -> String.to_existing_atom(unknown_key) end
end
end
test "cancels job if server is unreachable", %{activity: activity} do test "cancels job if server is unreachable", %{activity: activity} do
# First mark the server as unreachable # First mark the server as unreachable
Instances.set_unreachable("https://example.com/inbox") Instances.set_unreachable("https://example.com/inbox")
@ -117,7 +143,7 @@ defmodule Pleroma.Workers.PublisherWorkerTest do
max_attempts: 5 max_attempts: 5
} }
assert {:cancel, :unreachable} = Pleroma.Workers.PublisherWorker.perform(job) assert {:cancel, :unreachable} = PublisherWorker.perform(job)
end end
end end
end end