71 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			71 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| module Gitlab
 | |
|   module WebHooks
 | |
|     class RateLimiter
 | |
|       include Gitlab::Utils::StrongMemoize
 | |
| 
 | |
|       LIMIT_NAME = :web_hook_calls
 | |
|       NO_LIMIT = 0
 | |
|       # SystemHooks (instance admin hooks) and ServiceHooks (integration hooks)
 | |
|       # are not rate-limited.
 | |
|       EXCLUDED_HOOK_TYPES = %w(SystemHook ServiceHook).freeze
 | |
| 
 | |
|       def initialize(hook)
 | |
|         @hook = hook
 | |
|         @parent = hook.parent
 | |
|       end
 | |
| 
 | |
|       # Increments the rate-limit counter.
 | |
|       # Returns true if the hook should be rate-limited.
 | |
|       def rate_limit!
 | |
|         return false if no_limit?
 | |
| 
 | |
|         ::Gitlab::ApplicationRateLimiter.throttled?(
 | |
|           limit_name,
 | |
|           scope: [root_namespace],
 | |
|           threshold: limit
 | |
|         )
 | |
|       end
 | |
| 
 | |
|       # Returns true if the hook is currently over its rate-limit.
 | |
|       # It does not increment the rate-limit counter.
 | |
|       def rate_limited?
 | |
|         return false if no_limit?
 | |
| 
 | |
|         Gitlab::ApplicationRateLimiter.peek(
 | |
|           limit_name,
 | |
|           scope: [root_namespace],
 | |
|           threshold: limit
 | |
|         )
 | |
|       end
 | |
| 
 | |
|       def limit
 | |
|         strong_memoize(:limit) do
 | |
|           next NO_LIMIT if hook.class.name.in?(EXCLUDED_HOOK_TYPES)
 | |
| 
 | |
|           root_namespace.actual_limits.limit_for(limit_name) || NO_LIMIT
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       private
 | |
| 
 | |
|       attr_reader :hook, :parent
 | |
| 
 | |
|       def no_limit?
 | |
|         limit == NO_LIMIT
 | |
|       end
 | |
| 
 | |
|       def root_namespace
 | |
|         @root_namespace ||= parent.root_ancestor
 | |
|       end
 | |
| 
 | |
|       def limit_name
 | |
|         LIMIT_NAME
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 | |
| 
 | |
| Gitlab::WebHooks::RateLimiter.prepend_mod
 |