Merge pull request 'Rate limit C2S outbox posts and emoji reactions' (#8042) from lambadalambda/pleroma:fix/c2s-rate-limit into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8042
This commit is contained in:
commit
d3495ceead
5 changed files with 100 additions and 0 deletions
1
changelog.d/c2s-rate-limit.security
Normal file
1
changelog.d/c2s-rate-limit.security
Normal file
|
|
@ -0,0 +1 @@
|
|||
Rate limit ActivityPub C2S outbox posts and emoji reactions
|
||||
|
|
@ -26,6 +26,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
|||
alias Pleroma.Web.Plugs.EnsureAuthenticatedPlug
|
||||
alias Pleroma.Web.Plugs.FederatingPlug
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Web.Plugs.RateLimiter
|
||||
|
||||
require Logger
|
||||
|
||||
|
|
@ -66,6 +67,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
|||
when action in [:followers, :following]
|
||||
)
|
||||
|
||||
# Shares the per-user bucket with Mastodon API status actions and emoji reactions.
|
||||
plug(RateLimiter, [name: :statuses_actions] when action == :update_outbox)
|
||||
|
||||
plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:upload_media])
|
||||
|
||||
plug(
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
|
|||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Web.Plugs.RateLimiter
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action in [:create, :delete])
|
||||
|
|
@ -22,6 +23,14 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
|
|||
when action == :index
|
||||
)
|
||||
|
||||
plug(
|
||||
RateLimiter,
|
||||
[name: :status_id_action, bucket_name: "status_id_action:emoji_react", params: [:id]]
|
||||
when action in [:create, :delete]
|
||||
)
|
||||
|
||||
plug(RateLimiter, [name: :statuses_actions] when action in [:create, :delete])
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.EmojiReactionOperation
|
||||
|
||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||
|
|
|
|||
|
|
@ -2709,6 +2709,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
|
||||
|
|
|
|||
|
|
@ -477,4 +477,53 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionControllerTest do
|
|||
|> get("/api/v1/pleroma/statuses/#{activity_id}/reactions/🐈")
|
||||
|> json_response_and_validate_schema(404) == %{"error" => "Record not found"}
|
||||
end
|
||||
|
||||
describe "rate limiting" do
|
||||
test "PUT and DELETE share a per-status limit", %{conn: conn} do
|
||||
clear_config([:rate_limit, :status_id_action], {60_000, 2})
|
||||
user = insert(:user)
|
||||
%{id: activity_id} = insert(:note_activity)
|
||||
%{id: other_activity_id} = insert(:note_activity)
|
||||
conn = prepare_conn_of_user(conn, user)
|
||||
|
||||
conn
|
||||
|> put("/api/v1/pleroma/statuses/#{activity_id}/reactions/☕")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
conn
|
||||
|> delete("/api/v1/pleroma/statuses/#{activity_id}/reactions/☕")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert conn
|
||||
|> put("/api/v1/pleroma/statuses/#{activity_id}/reactions/🐈")
|
||||
|> json_response(429) == %{"error" => "Throttled"}
|
||||
|
||||
conn
|
||||
|> put("/api/v1/pleroma/statuses/#{other_activity_id}/reactions/🐈")
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "PUT and DELETE count against statuses_actions", %{conn: conn} do
|
||||
clear_config([:rate_limit, :statuses_actions], {60_000, 2})
|
||||
user = insert(:user)
|
||||
[first, second, third] = insert_list(3, :note_activity)
|
||||
conn = prepare_conn_of_user(conn, user)
|
||||
|
||||
conn
|
||||
|> put("/api/v1/pleroma/statuses/#{first.id}/reactions/☕")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
conn
|
||||
|> delete("/api/v1/pleroma/statuses/#{first.id}/reactions/☕")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert conn
|
||||
|> put("/api/v1/pleroma/statuses/#{second.id}/reactions/☕")
|
||||
|> json_response(429) == %{"error" => "Throttled"}
|
||||
|
||||
assert conn
|
||||
|> delete("/api/v1/pleroma/statuses/#{third.id}/reactions/☕")
|
||||
|> json_response(429) == %{"error" => "Throttled"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue