Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-12-22 06:09:39 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-12-22 06:09:39 +0300
commitf8edcff7e9aff93f8ac605c19e542204b0ed9ba2 (patch)
treefe45e8bc69f5c68c6d4ee7505a4d61c4fdb70299 /lib
parentd61d19da54b0fb8fd54df4007fa95cd39db17e57 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib')
-rw-r--r--lib/api/helpers.rb10
-rw-r--r--lib/api/helpers/rate_limiter.rb17
-rw-r--r--lib/api/issues.rb6
-rw-r--r--lib/api/merge_requests.rb3
-rw-r--r--lib/gitlab/application_rate_limiter.rb32
5 files changed, 54 insertions, 14 deletions
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 0b5a471ea12..95c81c14bf9 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -695,6 +695,16 @@ module API
unprocessable_entity!('User must be authenticated to use search')
end
+ def validate_search_rate_limit!
+ return unless Feature.enabled?(:rate_limit_issuable_searches)
+
+ if current_user
+ check_rate_limit!(:search_rate_limit, scope: [current_user])
+ else
+ check_rate_limit!(:search_rate_limit_unauthenticated, scope: [ip_address])
+ end
+ end
+
private
# rubocop:disable Gitlab/ModuleWithInstanceVariables
diff --git a/lib/api/helpers/rate_limiter.rb b/lib/api/helpers/rate_limiter.rb
index 03f3cd649b1..be92277c25a 100644
--- a/lib/api/helpers/rate_limiter.rb
+++ b/lib/api/helpers/rate_limiter.rb
@@ -10,25 +10,14 @@ module API
# See app/controllers/concerns/check_rate_limit.rb for Rails controllers version
module RateLimiter
def check_rate_limit!(key, scope:, **options)
- return if bypass_header_set?
- return unless rate_limiter.throttled?(key, scope: scope, **options)
-
- rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
+ return unless Gitlab::ApplicationRateLimiter.throttled_request?(
+ request, current_user, key, scope: scope, **options
+ )
return yield if block_given?
render_api_error!({ error: _('This endpoint has been requested too many times. Try again later.') }, 429)
end
-
- private
-
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
-
- def bypass_header_set?
- ::Gitlab::Throttle.bypass_header.present? && request.get_header(Gitlab::Throttle.bypass_header) == '1'
- end
end
end
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index b08819e34e3..7b6306938cf 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -116,6 +116,7 @@ module API
get '/issues_statistics' do
authenticate! unless params[:scope] == 'all'
validate_anonymous_search_access! if params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
present issues_statistics, with: Grape::Presenters::Presenter
end
@@ -134,6 +135,7 @@ module API
get do
authenticate! unless params[:scope] == 'all'
validate_anonymous_search_access! if params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
issues = paginate(find_issues)
options = {
@@ -173,6 +175,7 @@ module API
end
get ":id/issues" do
validate_anonymous_search_access! if declared_params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
issues = paginate(find_issues(group_id: user_group.id, include_subgroups: true))
options = {
@@ -192,6 +195,7 @@ module API
end
get ":id/issues_statistics" do
validate_anonymous_search_access! if declared_params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
present issues_statistics(group_id: user_group.id, include_subgroups: true), with: Grape::Presenters::Presenter
end
@@ -211,6 +215,7 @@ module API
end
get ":id/issues" do
validate_anonymous_search_access! if declared_params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
issues = paginate(find_issues(project_id: user_project.id))
options = {
@@ -230,6 +235,7 @@ module API
end
get ":id/issues_statistics" do
validate_anonymous_search_access! if declared_params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
present issues_statistics(project_id: user_project.id), with: Grape::Presenters::Presenter
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index a9572cf7ce6..8a665b71bdb 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -149,6 +149,7 @@ module API
get feature_category: :code_review, urgency: :low do
authenticate! unless params[:scope] == 'all'
validate_anonymous_search_access! if params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
merge_requests = find_merge_requests
present merge_requests, serializer_options_for(merge_requests)
@@ -177,6 +178,7 @@ module API
end
get ":id/merge_requests", feature_category: :code_review, urgency: :low do
validate_anonymous_search_access! if declared_params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
merge_requests = find_merge_requests(group_id: user_group.id, include_subgroups: true)
present merge_requests, serializer_options_for(merge_requests).merge(group: user_group)
@@ -244,6 +246,7 @@ module API
get ":id/merge_requests", feature_category: :code_review, urgency: :low do
authorize! :read_merge_request, user_project
validate_anonymous_search_access! if declared_params[:search].present?
+ validate_search_rate_limit! if declared_params[:search].present?
merge_requests = find_merge_requests(project_id: user_project.id)
diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb
index 5b1bf99e297..a788586ebec 100644
--- a/lib/gitlab/application_rate_limiter.rb
+++ b/lib/gitlab/application_rate_limiter.rb
@@ -115,6 +115,38 @@ module Gitlab
value > threshold_value
end
+ # Similar to #throttled? above but checks for the bypass header in the request and logs the request when it is over the rate limit
+ #
+ # @param request [Http::Request] - Web request used to check the header and log
+ # @param current_user [User] Current user of the request, it can be nil
+ # @param key [Symbol] Key attribute registered in `.rate_limits`
+ # @param scope [Array<ActiveRecord>] Array of ActiveRecord models, Strings
+ # or Symbols to scope throttling to a specific request (e.g. per user
+ # per project)
+ # @param resource [ActiveRecord] An ActiveRecord model to count an action
+ # for (e.g. limit unique project (resource) downloads (action) to five
+ # per user (scope))
+ # @param threshold [Integer] Optional threshold value to override default
+ # one registered in `.rate_limits`
+ # @param interval [Integer] Optional interval value to override default
+ # one registered in `.rate_limits`
+ # @param users_allowlist [Array<String>] Optional list of usernames to
+ # exclude from the limit. This param will only be functional if Scope
+ # includes a current user.
+ # @param peek [Boolean] Optional. When true the key will not be
+ # incremented but the current throttled state will be returned.
+ #
+ # @return [Boolean] Whether or not a request should be throttled
+ def throttled_request?(request, current_user, key, scope:, **options)
+ if ::Gitlab::Throttle.bypass_header.present? && request.get_header(Gitlab::Throttle.bypass_header) == '1'
+ return false
+ end
+
+ throttled?(key, scope: scope, **options).tap do |throttled|
+ log_request(request, "#{key}_request_limit".to_sym, current_user) if throttled
+ end
+ end
+
# Returns the current rate limited state without incrementing the count.
#
# @param key [Symbol] Key attribute registered in `.rate_limits`