mirror of
https://github.com/discourse/discourse.git
synced 2024-12-02 21:05:12 +08:00
c9dab6fd08
It's very easy to forget to add `require 'rails_helper'` at the top of every core/plugin spec file, and omissions can cause some very confusing/sporadic errors. By setting this flag in `.rspec`, we can remove the need for `require 'rails_helper'` entirely.
141 lines
4.3 KiB
Ruby
141 lines
4.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
describe "RequestTracker in multisite", type: :multisite do
|
|
before do
|
|
global_setting :skip_per_ip_rate_limit_trust_level, 2
|
|
|
|
RateLimiter.enable
|
|
|
|
test_multisite_connection("default") do
|
|
RateLimiter.clear_all!
|
|
end
|
|
test_multisite_connection("second") do
|
|
RateLimiter.clear_all!
|
|
end
|
|
RateLimiter.clear_all_global!
|
|
end
|
|
|
|
def call(env, &block)
|
|
Middleware::RequestTracker.new(block).call(env)
|
|
end
|
|
|
|
def create_env(opts)
|
|
create_request_env.merge(opts)
|
|
end
|
|
|
|
shared_examples "ip rate limiters behavior" do |error_code, app_callback|
|
|
it "applies rate limits on an IP address across all sites" do
|
|
called = { default: 0, second: 0 }
|
|
test_multisite_connection("default") do
|
|
env = create_env("REMOTE_ADDR" => "123.10.71.4")
|
|
status, = call(env) do
|
|
called[:default] += 1
|
|
app_callback&.call(env)
|
|
[200, {}, ["OK"]]
|
|
end
|
|
expect(status).to eq(200)
|
|
|
|
env = create_env("REMOTE_ADDR" => "123.10.71.4")
|
|
status, headers = call(env) do
|
|
called[:default] += 1
|
|
app_callback&.call(env)
|
|
[200, {}, ["OK"]]
|
|
end
|
|
expect(status).to eq(429)
|
|
expect(headers["Discourse-Rate-Limit-Error-Code"]).to eq(error_code)
|
|
expect(called[:default]).to eq(1)
|
|
end
|
|
|
|
test_multisite_connection("second") do
|
|
env = create_env("REMOTE_ADDR" => "123.10.71.4")
|
|
status, headers = call(env) do
|
|
called[:second] += 1
|
|
app_callback&.call(env)
|
|
[200, {}, ["OK"]]
|
|
end
|
|
expect(status).to eq(429)
|
|
expect(headers["Discourse-Rate-Limit-Error-Code"]).to eq(error_code)
|
|
expect(called[:second]).to eq(0)
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "user id rate limiters behavior" do |error_code, app_callback|
|
|
it "does not leak rate limits for a user id to other sites" do
|
|
cookie = create_auth_cookie(
|
|
token: SecureRandom.hex,
|
|
user_id: 1,
|
|
trust_level: 2
|
|
)
|
|
called = { default: 0, second: 0 }
|
|
test_multisite_connection("default") do
|
|
env = create_env("REMOTE_ADDR" => "123.10.71.4", "HTTP_COOKIE" => "_t=#{cookie}")
|
|
status, = call(env) do
|
|
called[:default] += 1
|
|
app_callback&.call(env)
|
|
[200, {}, ["OK"]]
|
|
end
|
|
expect(status).to eq(200)
|
|
|
|
env = create_env("REMOTE_ADDR" => "123.10.71.4", "HTTP_COOKIE" => "_t=#{cookie}")
|
|
status, headers, = call(env) do
|
|
called[:default] += 1
|
|
app_callback&.call(env)
|
|
[200, {}, ["OK"]]
|
|
end
|
|
expect(status).to eq(429)
|
|
expect(headers["Discourse-Rate-Limit-Error-Code"]).to eq(error_code)
|
|
expect(called[:default]).to eq(1)
|
|
end
|
|
|
|
test_multisite_connection("second") do
|
|
env = create_env("REMOTE_ADDR" => "123.10.71.4", "HTTP_COOKIE" => "_t=#{cookie}")
|
|
status, = call(env) do
|
|
called[:second] += 1
|
|
app_callback&.call(env)
|
|
[200, {}, ["OK"]]
|
|
end
|
|
expect(status).to eq(200)
|
|
|
|
env = create_env("REMOTE_ADDR" => "123.10.71.4", "HTTP_COOKIE" => "_t=#{cookie}")
|
|
status, headers, = call(env) do
|
|
called[:second] += 1
|
|
app_callback&.call(env)
|
|
[200, {}, ["OK"]]
|
|
end
|
|
expect(status).to eq(429)
|
|
expect(headers["Discourse-Rate-Limit-Error-Code"]).to eq(error_code)
|
|
expect(called[:second]).to eq(1)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "10 seconds limiter" do
|
|
before do
|
|
global_setting :max_reqs_per_ip_per_10_seconds, 1
|
|
end
|
|
|
|
include_examples "ip rate limiters behavior", "ip_10_secs_limit"
|
|
include_examples "user id rate limiters behavior", "id_10_secs_limit"
|
|
end
|
|
|
|
context "60 seconds limiter" do
|
|
before do
|
|
global_setting :max_reqs_per_ip_per_minute, 1
|
|
end
|
|
|
|
include_examples "ip rate limiters behavior", "ip_60_secs_limit"
|
|
include_examples "user id rate limiters behavior", "id_60_secs_limit"
|
|
end
|
|
|
|
context "assets 10 seconds limiter" do
|
|
before do
|
|
global_setting :max_asset_reqs_per_ip_per_10_seconds, 1
|
|
end
|
|
|
|
app_callback = ->(env) { env["DISCOURSE_IS_ASSET_PATH"] = true }
|
|
include_examples "ip rate limiters behavior", "ip_assets_10_secs_limit", app_callback
|
|
include_examples "user id rate limiters behavior", "id_assets_10_secs_limit", app_callback
|
|
end
|
|
end
|