defmodule TarakanWeb.Plugs.CodeBrowserRateLimitTest do use Tarakan.DataCase, async: true import Plug.Conn import Plug.Test alias TarakanWeb.Plugs.CodeBrowserRateLimit test "allows requests under the per-IP budget" do opts = CodeBrowserRateLimit.init(limit: 2, window_seconds: 60) for path <- [ "/findings/55d5c681-240a-4e3a-a1f8-45933a30c4ef/code", "/github.com/openai/codex" ] do conn = conn(:get, path) |> CodeBrowserRateLimit.call(opts) refute conn.halted end end test "answers 429 once the per-IP budget is exceeded" do opts = CodeBrowserRateLimit.init(limit: 2, window_seconds: 60) for _ <- 1..2 do conn = conn(:get, "/github.com/openai/codex") |> CodeBrowserRateLimit.call(opts) refute conn.halted end conn = conn(:get, "/github.com/openai/codex") |> CodeBrowserRateLimit.call(opts) assert conn.halted assert conn.status == 429 assert [retry_after] = get_resp_header(conn, "retry-after") assert String.to_integer(retry_after) > 0 end test "IPv6 clients in the same /64 share one bucket" do opts = CodeBrowserRateLimit.init(limit: 1, window_seconds: 60) first = conn(:get, "/github.com/openai/codex") |> Map.put(:remote_ip, {0x2001, 0x0DB8, 0, 0, 0, 0, 0, 1}) |> CodeBrowserRateLimit.call(opts) refute first.halted second = conn(:get, "/github.com/openai/codex") |> Map.put(:remote_ip, {0x2001, 0x0DB8, 0, 0, 0xFFFF, 0xEEEE, 0xDDDD, 0xCCCC}) |> CodeBrowserRateLimit.call(opts) assert second.halted assert second.status == 429 end test "admins and moderators are exempt from the budget" do opts = CodeBrowserRateLimit.init(limit: 1, window_seconds: 60) for role <- ["admin", "moderator"], _ <- 1..3 do conn = conn(:get, "/github.com/openai/codex") |> assign(:current_scope, %{platform_role: role}) |> CodeBrowserRateLimit.call(opts) refute conn.halted end end end