diff options
Diffstat (limited to 'app/controllers/concerns')
-rw-r--r-- | app/controllers/concerns/boards_responses.rb | 4 | ||||
-rw-r--r-- | app/controllers/concerns/check_rate_limit.rb | 23 | ||||
-rw-r--r-- | app/controllers/concerns/comment_and_close_flag.rb | 11 | ||||
-rw-r--r-- | app/controllers/concerns/multiple_boards_actions.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/notes_actions.rb | 8 | ||||
-rw-r--r-- | app/controllers/concerns/security_and_compliance_permissions.rb | 15 | ||||
-rw-r--r-- | app/controllers/concerns/spammable_actions.rb | 15 | ||||
-rw-r--r-- | app/controllers/concerns/wiki_actions.rb | 3 |
8 files changed, 59 insertions, 22 deletions
diff --git a/app/controllers/concerns/boards_responses.rb b/app/controllers/concerns/boards_responses.rb index 6e6686f225c..7307b7b4f8f 100644 --- a/app/controllers/concerns/boards_responses.rb +++ b/app/controllers/concerns/boards_responses.rb @@ -35,7 +35,7 @@ module BoardsResponses end def authorize_read_list - authorize_action_for!(board, :read_list) + authorize_action_for!(board, :read_issue_board_list) end def authorize_read_issue @@ -54,7 +54,7 @@ module BoardsResponses end def authorize_admin_list - authorize_action_for!(board, :admin_list) + authorize_action_for!(board, :admin_issue_board_list) end def authorize_action_for!(resource, ability) diff --git a/app/controllers/concerns/check_rate_limit.rb b/app/controllers/concerns/check_rate_limit.rb new file mode 100644 index 00000000000..c4de3315e22 --- /dev/null +++ b/app/controllers/concerns/check_rate_limit.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +# == CheckRateLimit +# +# Controller concern that checks if the rate limit for a given action is throttled by calling the +# Gitlab::ApplicationRateLimiter class. If the action is throttled for the current user, the request +# will be logged and an error message will be rendered with a Too Many Requests response status. +module CheckRateLimit + def check_rate_limit(key) + return unless rate_limiter.throttled?(key, scope: current_user, users_allowlist: rate_limit_users_allowlist) + + rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user) + render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests + end + + def rate_limiter + ::Gitlab::ApplicationRateLimiter + end + + def rate_limit_users_allowlist + Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist + end +end diff --git a/app/controllers/concerns/comment_and_close_flag.rb b/app/controllers/concerns/comment_and_close_flag.rb deleted file mode 100644 index e2f3272abbc..00000000000 --- a/app/controllers/concerns/comment_and_close_flag.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -module CommentAndCloseFlag - extend ActiveSupport::Concern - - included do - before_action do - push_frontend_feature_flag(:remove_comment_close_reopen, @group) - end - end -end diff --git a/app/controllers/concerns/multiple_boards_actions.rb b/app/controllers/concerns/multiple_boards_actions.rb index 5206f5759d8..85bb73463db 100644 --- a/app/controllers/concerns/multiple_boards_actions.rb +++ b/app/controllers/concerns/multiple_boards_actions.rb @@ -80,7 +80,7 @@ module MultipleBoardsActions end def authorize_admin_board! - return render_404 unless can?(current_user, :admin_board, parent) + return render_404 unless can?(current_user, :admin_issue_board, parent) end def serializer diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index 036d95622ef..2d8168af2e3 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -3,6 +3,7 @@ module NotesActions include RendersNotes include Gitlab::Utils::StrongMemoize + include CheckRateLimit extend ActiveSupport::Concern # last_fetched_at is an integer number of microseconds, which is the same @@ -15,6 +16,7 @@ module NotesActions before_action :require_noteable!, only: [:index, :create] before_action :authorize_admin_note!, only: [:update, :destroy] before_action :note_project, only: [:create] + before_action -> { check_rate_limit(:notes_create) }, only: [:create] end def index @@ -31,9 +33,9 @@ module NotesActions # We know there's more data, so tell the frontend to poll again after 1ms set_polling_interval_header(interval: 1) if meta[:more] - # We might still want to investigate further adjusting ETag caching with paginated notes, but - # let's avoid ETag caching for now until we confirm the viability of paginated notes. - ::Gitlab::EtagCaching::Middleware.skip!(response) + # Only present an ETag for the empty response to ensure pagination works + # as expected + ::Gitlab::EtagCaching::Middleware.skip!(response) if notes.present? render json: meta.merge(notes: notes) end diff --git a/app/controllers/concerns/security_and_compliance_permissions.rb b/app/controllers/concerns/security_and_compliance_permissions.rb new file mode 100644 index 00000000000..104f3638bb7 --- /dev/null +++ b/app/controllers/concerns/security_and_compliance_permissions.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module SecurityAndCompliancePermissions + extend ActiveSupport::Concern + + included do + before_action :ensure_security_and_compliance_enabled! + end + + private + + def ensure_security_and_compliance_enabled! + render_404 unless can?(current_user, :access_security_and_compliance, project) + end +end diff --git a/app/controllers/concerns/spammable_actions.rb b/app/controllers/concerns/spammable_actions.rb index b285faee9bc..9e861d2859d 100644 --- a/app/controllers/concerns/spammable_actions.rb +++ b/app/controllers/concerns/spammable_actions.rb @@ -2,6 +2,7 @@ module SpammableActions extend ActiveSupport::Concern + include Spam::Concerns::HasSpamActionResponseFields included do before_action :authorize_submit_spammable!, only: :mark_as_spam @@ -25,14 +26,20 @@ module SpammableActions respond_to do |format| format.html do + # NOTE: format.html is still used by issue create, and uses the legacy HAML + # `_recaptcha_form.html.haml` rendered via the `projects/issues/verify` template. render :verify end format.json do - locals = { spammable: spammable, script: false, has_submit: false } - recaptcha_html = render_to_string(partial: 'shared/recaptcha_form', formats: :html, locals: locals) + # format.json is used by all new Vue-based CAPTCHA implementations, which + # handle all of the CAPTCHA form rendering on the client via the Pajamas-based + # app/assets/javascripts/captcha/captcha_modal.vue - render json: { recaptcha_html: recaptcha_html } + # NOTE: "409 - Conflict" seems to be the most appropriate HTTP status code for a response + # which requires a CAPTCHA to be solved in order for the request to be resubmitted. + # See https://stackoverflow.com/q/26547466/25192 + render json: spam_action_response_fields(spammable), status: :conflict end end else @@ -58,7 +65,7 @@ module SpammableActions # After this newer GraphQL/JS API process is fully supported by the backend, we can remove the # check for the 'g-recaptcha-response' field and other HTML/HAML form-specific support. - captcha_response = params['g-recaptcha-response'] + captcha_response = params['g-recaptcha-response'] || params[:captcha_response] { request: request, diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb index 4014e4f0024..60ff0a12d0c 100644 --- a/app/controllers/concerns/wiki_actions.rb +++ b/app/controllers/concerns/wiki_actions.rb @@ -112,10 +112,11 @@ module WikiActions wiki_page_path(wiki, page) ) else + @error = response.message render 'shared/wikis/edit' end rescue WikiPage::PageChangedError, WikiPage::PageRenameError => e - @error = e + @error = e.message render 'shared/wikis/edit' end # rubocop:enable Gitlab/ModuleWithInstanceVariables |