• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

AlyBadawy / Securial / 15660309064

15 Jun 2025 06:22AM UTC coverage: 98.458% (-0.2%) from 98.65%
15660309064

Pull #47

github

web-flow
Merge 6a153ba83 into e9fb9d184
Pull Request #47: Feat: Implement request rate limiting using Rack::Attack

205 of 210 branches covered (97.62%)

Branch coverage included in aggregate %.

64 of 66 new or added lines in 5 files covered. (96.97%)

1008 of 1022 relevant lines covered (98.63%)

54.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.59
/lib/securial/security/request_rate_limiter.rb
1
require "rack/attack"
1✔
2
require "securial/config"
1✔
3
require "securial/logger"
1✔
4

5
module Securial
1✔
6
  module Security
1✔
7
    module RequestRateLimiter
1✔
8
      module_function
1✔
9

10
      def apply! # rubocop:disable Metrics/MethodLength
1✔
11
        resp_status = Securial.configuration.rate_limit_response_status
1✔
12
        resp_message = Securial.configuration.rate_limit_response_message
1✔
13
        # Throttle login attempts by IP
14
        Rack::Attack.throttle("securial/logins/ip",
1✔
15
                              limit: ->(_req) { Securial.configuration.rate_limit_requests_per_minute },
3✔
16
                              period: 1.minute
17
        ) do |req|
18
          if req.path.include?("sessions/login") && req.post?
181✔
19
            req.ip
3✔
20
          end
21
        end
22

23
        # Throttle login attempts by username/email
24
        Rack::Attack.throttle("securial/logins/email",
1✔
25
                              limit: ->(_req) { Securial.configuration.rate_limit_requests_per_minute },
3✔
26
                              period: 1.minute
27
        ) do |req|
28
          if req.path.include?("sessions/login") && req.post?
181✔
29
            req.params["email_address"].to_s.downcase.strip
3✔
30
          end
31
        end
32

33
        # Throttle password reset requests by IP
34
        Rack::Attack.throttle("securial/password_resets/ip",
1✔
35
                              limit: ->(_req) { Securial.configuration.rate_limit_requests_per_minute },
3✔
36
                              period: 1.minute
37
        ) do |req|
38
          if req.path.include?("password/forgot") && req.post?
181✔
39
            req.ip
3✔
40
          end
41
        end
42

43
        # Throttle password reset requests by email
44
        Rack::Attack.throttle("securial/password_resets/email",
1✔
45
                              limit: ->(_req) { Securial.configuration.rate_limit_requests_per_minute },
3✔
46
                              period: 1.minute
47
        ) do |req|
48
          if req.path.include?("password/forgot") && req.post?
181✔
49
            req.params["email_address"].to_s.downcase.strip
3✔
50
          end
51
        end
52

53
        # Custom response for throttled requests
54
        Rack::Attack.throttled_responder = lambda do |request|
1✔
NEW
55
          retry_after = (request.env["rack.attack.match_data"] || {})[:period]
×
56
          [
NEW
57
            resp_status,
×
58
            {
59
              "Content-Type" => "application/json",
60
              "Retry-After" => retry_after.to_s,
61
            },
62
            [{ error: resp_message }.to_json]
63
          ]
64
        end
65
      end
66
    end
67
  end
68
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc