fix(activitypub): rate limit C2S outbox posts

POST /users/:nickname/outbox had no rate limiter, so a client could send
unlimited activities through the C2S API. Apply :statuses_actions to
update_outbox. RateLimiter keys buckets by limiter name and user, so the
outbox shares one counter with the Mastodon API status actions and mixing
both APIs does not double the limit.
This commit is contained in:
Lain Soykaf 2026-10-30 10:20:06 +04:00
commit 44adf271c2
No known key found for this signature in database
2 changed files with 41 additions and 0 deletions

View file

@ -2685,6 +2685,43 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert result == "Character limit (5 characters) exceeded, contains 11 characters"
end
test "it is rate limited", %{conn: conn, activity: activity} do
clear_config([:rate_limit, :statuses_actions], {60_000, 2})
user = insert(:user)
conn =
conn
|> assign(:user, user)
|> put_req_header("content-type", "application/activity+json")
for _ <- 1..2 do
conn
|> post("/users/#{user.nickname}/outbox", activity)
|> json_response(201)
end
assert conn
|> post("/users/#{user.nickname}/outbox", activity)
|> json_response(429) == %{"error" => "Throttled"}
end
test "it shares the rate limit with the Mastodon API", %{activity: activity} do
clear_config([:rate_limit, :statuses_actions], {60_000, 2})
%{user: user, conn: conn} = oauth_access(["write"])
for _ <- 1..2 do
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses", %{status: "cofe"})
|> json_response(200)
end
assert conn
|> put_req_header("content-type", "application/activity+json")
|> post("/users/#{user.nickname}/outbox", activity)
|> json_response(429) == %{"error" => "Throttled"}
end
end
describe "/relay/followers" do