diff options
Diffstat (limited to 'app/models/hooks')
-rw-r--r-- | app/models/hooks/project_hook.rb | 5 | ||||
-rw-r--r-- | app/models/hooks/web_hook.rb | 52 | ||||
-rw-r--r-- | app/models/hooks/web_hook_log.rb | 13 |
3 files changed, 55 insertions, 15 deletions
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb index 9f45160d3a8..b7ace34141e 100644 --- a/app/models/hooks/project_hook.rb +++ b/app/models/hooks/project_hook.rb @@ -31,11 +31,6 @@ class ProjectHook < WebHook _('Webhooks') end - override :rate_limit - def rate_limit - project.actual_limits.limit_for(:web_hook_calls) - end - override :application_context def application_context super.merge(project: project) diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 88941df691c..37fd612e652 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -19,6 +19,15 @@ class WebHook < ApplicationRecord algorithm: 'aes-256-gcm', key: Settings.attr_encrypted_db_key_base_32 + attr_encrypted :url_variables, + mode: :per_attribute_iv, + key: Settings.attr_encrypted_db_key_base_32, + algorithm: 'aes-256-gcm', + marshal: true, + marshaler: ::Gitlab::Json, + encode: false, + encode_iv: false + has_many :web_hook_logs validates :url, presence: true @@ -26,6 +35,9 @@ class WebHook < ApplicationRecord validates :token, format: { without: /\n/ } validates :push_events_branch_filter, branch_filter: true + validates :url_variables, json_schema: { filename: 'web_hooks_url_variables' } + + after_initialize :initialize_url_variables scope :executable, -> do next all unless Feature.enabled?(:web_hooks_disable_failed) @@ -115,19 +127,12 @@ class WebHook < ApplicationRecord # @return [Boolean] Whether or not the WebHook is currently throttled. def rate_limited? - return false unless rate_limit - - Gitlab::ApplicationRateLimiter.peek( - :web_hook_calls, - scope: [self], - threshold: rate_limit - ) + rate_limiter.rate_limited? end - # Threshold for the rate-limit. - # Overridden in ProjectHook and GroupHook, other WebHooks are not rate-limited. + # @return [Integer] The rate limit for the WebHook. `0` for no limit. def rate_limit - nil + rate_limiter.limit end # Returns the associated Project or Group for the WebHook if one exists. @@ -140,9 +145,36 @@ class WebHook < ApplicationRecord { related_class: type } end + def alert_status + if temporarily_disabled? + :temporarily_disabled + elsif permanently_disabled? + :disabled + else + :executable + end + end + + # Exclude binary columns by default - they have no sensible JSON encoding + def serializable_hash(options = nil) + options = options.try(:dup) || {} + options[:except] = Array(options[:except]).dup + options[:except].concat [:encrypted_url_variables, :encrypted_url_variables_iv] + + super(options) + end + private def web_hooks_disable_failed? Feature.enabled?(:web_hooks_disable_failed) end + + def initialize_url_variables + self.url_variables = {} if encrypted_url_variables.nil? + end + + def rate_limiter + @rate_limiter ||= Gitlab::WebHooks::RateLimiter.new(self) + end end diff --git a/app/models/hooks/web_hook_log.rb b/app/models/hooks/web_hook_log.rb index 8c0565e4a38..2f03b3591cf 100644 --- a/app/models/hooks/web_hook_log.rb +++ b/app/models/hooks/web_hook_log.rb @@ -7,6 +7,8 @@ class WebHookLog < ApplicationRecord include CreatedAtFilterable include PartitionedTable + OVERSIZE_REQUEST_DATA = { 'oversize' => true }.freeze + self.primary_key = :id partitioned_by :created_at, strategy: :monthly, retain_for: 3.months @@ -26,6 +28,13 @@ class WebHookLog < ApplicationRecord .order(created_at: :desc) end + # Delete a batch of log records. Returns true if there may be more remaining. + def self.delete_batch_for(web_hook, batch_size:) + raise ArgumentError, 'batch_size is too small' if batch_size < 1 + + where(web_hook: web_hook).limit(batch_size).delete_all == batch_size + end + def success? response_status =~ /^2/ end @@ -34,6 +43,10 @@ class WebHookLog < ApplicationRecord response_status == WebHookService::InternalErrorResponse::ERROR_MESSAGE end + def oversize? + request_data == OVERSIZE_REQUEST_DATA + end + private def obfuscate_basic_auth |