* Remove Connect
* Remove more Connect specs
* Remove a lot more Connect code
* 🚮
* It all has to go
* Explicitly add httpclient
* Update application layout
* Remove messages association from User
* Start fixing specs
* reintroduce util function and refactor references
* Remove Connect Cypress test
* Fix more specs
* Remove Connect from listings
* Ignore contact_via_connect column on listings
* Remove contact_via_connect usages
* Ignore mod_chat_channel_id on tags
* Drop Connect tables
* Remove email_connect_messages from user notification settings
* Re-add httpclient 2.8.3
This was mistakenly removed as a merge conflict
* Don't need to exclude removed chat channel file
* Remove unneeded style for chat channels
* Remove unneeded channel list prop type
* Remove chat channels index/connect-link from getPageEntries
* Re-add comment from httpclient in Gemfile
* Remove connect references from mailers
Tag Moderators no longer have a chat channel
No longer will users be notified about new messages (there won't be
any)
No longer will users be notified about channel invites (you can't
invite anyone anymore)
* Don't configure Pusher and remove PUSHER_* from .env_sample
since it's removed from gemfile, the Pusher constant will not resolve, if this is
configured in the environment variables we'll fail to boot.
Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
Co-authored-by: Dan Uber <dan@forem.com>
134 lines
5.8 KiB
Ruby
134 lines
5.8 KiB
Ruby
require "rails_helper"
|
|
|
|
describe Rack::Attack, type: :request, throttle: true do
|
|
before do
|
|
cache_db = ActiveSupport::Cache.lookup_store(:redis_cache_store)
|
|
allow(Rails).to receive(:cache) { cache_db }
|
|
cache_db.redis.flushdb
|
|
allow(Honeycomb).to receive(:add_field)
|
|
end
|
|
|
|
describe "search_throttle" do
|
|
it "throttles /search endpoints based on IP" do
|
|
Timecop.freeze do
|
|
allow(Search::Username).to receive(:search_documents).and_return({})
|
|
|
|
valid_responses = Array.new(5).map do
|
|
get "/search/usernames", headers: { "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" }
|
|
end
|
|
throttled_response = get "/search/usernames", headers: { "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" }
|
|
new_ip_response = get "/search/usernames", headers: { "HTTP_FASTLY_CLIENT_IP" => "1.1.1.1" }
|
|
|
|
valid_responses.each { |r| expect(r).not_to eq(429) }
|
|
expect(throttled_response).to eq(429)
|
|
expect(new_ip_response).not_to eq(429)
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "5.6.7.8").exactly(11).times
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "1.1.1.1").exactly(2).times
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "api_throttle" do
|
|
it "throttles api get endpoints based on IP" do
|
|
Timecop.freeze do
|
|
valid_responses = Array.new(3).map do
|
|
get api_articles_path, headers: { "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" }
|
|
end
|
|
throttled_response = get api_articles_path, headers: { "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" }
|
|
new_ip_response = get api_articles_path, headers: { "HTTP_FASTLY_CLIENT_IP" => "1.1.1.1" }
|
|
|
|
valid_responses.each { |r| expect(r).not_to eq(429) }
|
|
expect(throttled_response).to eq(429)
|
|
expect(new_ip_response).not_to eq(429)
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "5.6.7.8").exactly(7).times
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "1.1.1.1").exactly(2).times
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "api_write_throttle" do
|
|
let(:api_secret) { create(:api_secret) }
|
|
let(:another_api_secret) { create(:api_secret) }
|
|
let(:headers) do
|
|
{ "api-key" => api_secret.secret, "content-type" => "application/json", "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" }
|
|
end
|
|
let(:dif_headers) do
|
|
{
|
|
"api-key" => another_api_secret.secret,
|
|
"content-type" => "application/json",
|
|
"HTTP_FASTLY_CLIENT_IP" => "5.6.7.8"
|
|
}
|
|
end
|
|
|
|
it "throttles api write endpoints based on IP and API key" do
|
|
params = { article: { body_markdown: "", title: Faker::Book.title } }.to_json
|
|
|
|
Timecop.freeze do
|
|
valid_response = post api_articles_path, params: params, headers: headers
|
|
throttled_response = post api_articles_path, params: params, headers: headers
|
|
new_api_response = post api_articles_path, params: params, headers: dif_headers
|
|
|
|
expect(valid_response).not_to eq(429)
|
|
expect(throttled_response).to eq(429)
|
|
expect(new_api_response).not_to eq(429)
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "5.6.7.8").exactly(5).times
|
|
expect(Honeycomb).to have_received(:add_field).with("user_api_key", api_secret.secret).exactly(2).times
|
|
expect(Honeycomb).to have_received(:add_field).with("user_api_key", another_api_secret.secret)
|
|
end
|
|
end
|
|
|
|
it "throttles api write endpoints based on IP if API key not present" do
|
|
headers = { "content-type" => "application/json", "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" }
|
|
dif_headers = { "content-type" => "application/json", "HTTP_FASTLY_CLIENT_IP" => "1.1.1.1" }
|
|
params = { article: { body_markdown: "", title: Faker::Book.title } }.to_json
|
|
|
|
Timecop.freeze do
|
|
valid_response = post api_articles_path, params: params, headers: headers
|
|
throttled_response = post api_articles_path, params: params, headers: headers
|
|
new_api_response = post api_articles_path, params: params, headers: dif_headers
|
|
|
|
expect(valid_response).not_to eq(429)
|
|
expect(throttled_response).to eq(429)
|
|
expect(new_api_response).not_to eq(429)
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "5.6.7.8").exactly(3).times
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "1.1.1.1").exactly(2).times
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "tag_throttle" do
|
|
let(:user) { create(:user) }
|
|
let(:headers) { { "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" } }
|
|
let(:dif_headers) { { "HTTP_FASTLY_CLIENT_IP" => "1.1.1.1" } }
|
|
|
|
before do
|
|
sign_in user
|
|
end
|
|
|
|
# rubocop:disable RSpec/AnyInstance, RSpec/ExampleLength
|
|
it "throttles viewing tags", :aggregate_failures do
|
|
allow_any_instance_of(Stories::TaggedArticlesController).to receive(:tagged_count).and_return(0)
|
|
allow_any_instance_of(Stories::TaggedArticlesController).to receive(:stories_by_timeframe)
|
|
.and_return(Article.none)
|
|
allow(Articles::Feeds::Tag).to receive(:call).and_return(Article.none)
|
|
tag_path = "/t/#{create(:tag).name}"
|
|
|
|
get tag_path, headers: headers # warm up the slow endpoint
|
|
|
|
Timecop.freeze do
|
|
valid_responses = Array.new(2).map do
|
|
get tag_path, headers: headers
|
|
end
|
|
throttled_response = get tag_path, headers: headers
|
|
new_response = get tag_path, headers: dif_headers
|
|
|
|
expect(valid_responses.first).not_to eq(429)
|
|
expect(throttled_response).to eq(429)
|
|
expect(new_response).not_to eq(429)
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "5.6.7.8").exactly(8).times
|
|
expect(Honeycomb).to have_received(:add_field).with("fastly_client_ip", "1.1.1.1").exactly(2).times
|
|
end
|
|
end
|
|
# rubocop:enable RSpec/AnyInstance, RSpec/ExampleLength
|
|
end
|
|
end
|