parent
f26013cf2e
commit
ad04d12de6
@ -1,36 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Plugs.RateLimitPlug do
|
|
||||||
import Phoenix.Controller, only: [json: 2]
|
|
||||||
import Plug.Conn
|
|
||||||
|
|
||||||
def init(opts), do: opts
|
|
||||||
|
|
||||||
def call(conn, opts) do
|
|
||||||
enabled? = Pleroma.Config.get([:app_account_creation, :enabled])
|
|
||||||
|
|
||||||
case check_rate(conn, Map.put(opts, :enabled, enabled?)) do
|
|
||||||
{:ok, _count} -> conn
|
|
||||||
{:error, _count} -> render_error(conn)
|
|
||||||
%Plug.Conn{} = conn -> conn
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp check_rate(conn, %{enabled: true} = opts) do
|
|
||||||
max_requests = opts[:max_requests]
|
|
||||||
bucket_name = conn.remote_ip |> Tuple.to_list() |> Enum.join(".")
|
|
||||||
|
|
||||||
ExRated.check_rate(bucket_name, opts[:interval] * 1000, max_requests)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp check_rate(conn, _), do: conn
|
|
||||||
|
|
||||||
defp render_error(conn) do
|
|
||||||
conn
|
|
||||||
|> put_status(:forbidden)
|
|
||||||
|> json(%{error: "Rate limit exceeded."})
|
|
||||||
|> halt()
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,50 +0,0 @@
|
|||||||
defmodule Pleroma.Plugs.RateLimitPlugTest do
|
|
||||||
use ExUnit.Case, async: true
|
|
||||||
use Plug.Test
|
|
||||||
|
|
||||||
alias Pleroma.Plugs.RateLimitPlug
|
|
||||||
|
|
||||||
@opts RateLimitPlug.init(%{max_requests: 5, interval: 1})
|
|
||||||
|
|
||||||
setup do
|
|
||||||
enabled = Pleroma.Config.get([:app_account_creation, :enabled])
|
|
||||||
|
|
||||||
Pleroma.Config.put([:app_account_creation, :enabled], true)
|
|
||||||
|
|
||||||
on_exit(fn ->
|
|
||||||
Pleroma.Config.put([:app_account_creation, :enabled], enabled)
|
|
||||||
end)
|
|
||||||
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
|
|
||||||
test "it restricts by opts" do
|
|
||||||
conn = conn(:get, "/")
|
|
||||||
bucket_name = conn.remote_ip |> Tuple.to_list() |> Enum.join(".")
|
|
||||||
ms = 1000
|
|
||||||
|
|
||||||
conn = RateLimitPlug.call(conn, @opts)
|
|
||||||
{1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
|
|
||||||
conn = RateLimitPlug.call(conn, @opts)
|
|
||||||
{2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
|
|
||||||
conn = RateLimitPlug.call(conn, @opts)
|
|
||||||
{3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
|
|
||||||
conn = RateLimitPlug.call(conn, @opts)
|
|
||||||
{4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
|
|
||||||
conn = RateLimitPlug.call(conn, @opts)
|
|
||||||
{5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
|
|
||||||
conn = RateLimitPlug.call(conn, @opts)
|
|
||||||
assert conn.status == 403
|
|
||||||
assert conn.halted
|
|
||||||
assert conn.resp_body == "{\"error\":\"Rate limit exceeded.\"}"
|
|
||||||
|
|
||||||
Process.sleep(to_reset)
|
|
||||||
|
|
||||||
conn = conn(:get, "/")
|
|
||||||
conn = RateLimitPlug.call(conn, @opts)
|
|
||||||
{1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
|
|
||||||
refute conn.status == 403
|
|
||||||
refute conn.halted
|
|
||||||
refute conn.resp_body
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in new issue