Initial commit on Forgejo
Fresh repository history for elektrine/tarakan hosted at https://git.elektrine.com/elektrine/tarakan.
This commit is contained in:
commit
af6077b9c3
455 changed files with 78366 additions and 0 deletions
85
test/tarakan_web/plugs/api_rate_limit_test.exs
Normal file
85
test/tarakan_web/plugs/api_rate_limit_test.exs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
defmodule TarakanWeb.Plugs.ApiRateLimitTest do
|
||||
use Tarakan.DataCase, async: true
|
||||
|
||||
import Plug.Conn
|
||||
import Plug.Test
|
||||
|
||||
alias Tarakan.Accounts.Scope
|
||||
alias TarakanWeb.Plugs.ApiRateLimit
|
||||
|
||||
defp call_ip(conn, opts) do
|
||||
ApiRateLimit.call(conn, ApiRateLimit.init([mode: :ip] ++ opts))
|
||||
end
|
||||
|
||||
defp call_actor(conn, scope, opts) do
|
||||
conn
|
||||
|> assign(:current_scope, scope)
|
||||
|> ApiRateLimit.call(ApiRateLimit.init([mode: :actor] ++ opts))
|
||||
end
|
||||
|
||||
defp credential_scope(account, token_id) do
|
||||
Scope.for_account(account, token_id: token_id, authentication_method: :api_credential)
|
||||
end
|
||||
|
||||
test "requests carrying a Bearer token count against the IP bucket" do
|
||||
opts = [request_limit: 2, mutation_limit: 2, window_seconds: 60]
|
||||
|
||||
for _ <- 1..2 do
|
||||
conn =
|
||||
conn(:get, "/api/repositories")
|
||||
|> put_req_header("authorization", "Bearer garbage-token")
|
||||
|> call_ip(opts)
|
||||
|
||||
refute conn.halted
|
||||
end
|
||||
|
||||
conn =
|
||||
conn(:get, "/api/repositories")
|
||||
|> put_req_header("authorization", "Bearer garbage-token")
|
||||
|> call_ip(opts)
|
||||
|
||||
assert conn.halted
|
||||
assert conn.status == 429
|
||||
assert Jason.decode!(conn.resp_body)["error"] == "rate limit exceeded"
|
||||
end
|
||||
|
||||
test "IPv6 clients in the same /64 share one IP bucket" do
|
||||
opts = [request_limit: 1, mutation_limit: 1, window_seconds: 60]
|
||||
|
||||
first =
|
||||
conn(:get, "/api/repositories")
|
||||
|> Map.put(:remote_ip, {0x2001, 0x0DB8, 0, 0, 0, 0, 0, 1})
|
||||
|> call_ip(opts)
|
||||
|
||||
refute first.halted
|
||||
|
||||
second =
|
||||
conn(:get, "/api/repositories")
|
||||
|> Map.put(:remote_ip, {0x2001, 0x0DB8, 0, 0, 0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD})
|
||||
|> call_ip(opts)
|
||||
|
||||
assert second.halted
|
||||
assert second.status == 429
|
||||
end
|
||||
|
||||
test "plain requests still count against the IP bucket" do
|
||||
opts = [request_limit: 1, mutation_limit: 1, window_seconds: 60]
|
||||
|
||||
refute conn(:get, "/api/repositories") |> call_ip(opts) |> Map.fetch!(:halted)
|
||||
assert conn(:get, "/api/repositories") |> call_ip(opts) |> Map.fetch!(:halted)
|
||||
end
|
||||
|
||||
test "authenticated actors get the multiplied actor budget" do
|
||||
opts = [request_limit: 2, mutation_limit: 2, window_seconds: 60]
|
||||
scope = credential_scope(account_fixture(), 11_001)
|
||||
|
||||
# 2 × @actor_multiplier (4) = 8 requests fit; the 9th is rejected.
|
||||
for _ <- 1..8 do
|
||||
refute conn(:get, "/api/jobs") |> call_actor(scope, opts) |> Map.fetch!(:halted)
|
||||
end
|
||||
|
||||
limited = conn(:get, "/api/jobs") |> call_actor(scope, opts)
|
||||
assert limited.halted
|
||||
assert limited.status == 429
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue