diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-23 15:08:38 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-23 15:08:38 +0300 |
commit | 5ad0cf26551baff8f08af8562a8d45e6ec14d71a (patch) | |
tree | 57f1a6bad31bcd11efacd3fdfb9cc92f88fb6a86 /app/controllers | |
parent | f47c768fad17d4c876e96524f83f8306f071db66 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/controllers')
-rw-r--r-- | app/controllers/concerns/page_limiter.rb | 68 | ||||
-rw-r--r-- | app/controllers/explore/projects_controller.rb | 33 | ||||
-rw-r--r-- | app/controllers/projects/snippets_controller.rb | 24 | ||||
-rw-r--r-- | app/controllers/snippets/notes_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/snippets_controller.rb | 8 | ||||
-rw-r--r-- | app/controllers/uploads_controller.rb | 2 |
6 files changed, 118 insertions, 19 deletions
diff --git a/app/controllers/concerns/page_limiter.rb b/app/controllers/concerns/page_limiter.rb new file mode 100644 index 00000000000..5b078d80fca --- /dev/null +++ b/app/controllers/concerns/page_limiter.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +# Include this in your controller and call `limit_pages` in order +# to configure the limiter. +# +# Examples: +# class MyController < ApplicationController +# include PageLimiter +# +# before_action only: [:index] do +# limit_pages(500) +# end +# +# # You can override the default response +# rescue_from PageOutOfBoundsError, with: :page_out_of_bounds +# +# def page_out_of_bounds(error) +# # Page limit number is available as error.message +# head :ok +# end +# + +module PageLimiter + extend ActiveSupport::Concern + + PageLimiterError = Class.new(StandardError) + PageLimitNotANumberError = Class.new(PageLimiterError) + PageLimitNotSensibleError = Class.new(PageLimiterError) + PageOutOfBoundsError = Class.new(PageLimiterError) + + included do + rescue_from PageOutOfBoundsError, with: :default_page_out_of_bounds_response + end + + def limit_pages(max_page_number) + check_page_number!(max_page_number) + end + + private + + # If the page exceeds the defined maximum, raise a PageOutOfBoundsError + # If the page doesn't exceed the limit, it does nothing. + def check_page_number!(max_page_number) + raise PageLimitNotANumberError unless max_page_number.is_a?(Integer) + raise PageLimitNotSensibleError unless max_page_number > 0 + + if params[:page].present? && params[:page].to_i > max_page_number + record_page_limit_interception + raise PageOutOfBoundsError.new(max_page_number) + end + end + + # By default just return a HTTP status code and an empty response + def default_page_out_of_bounds_response + head :bad_request + end + + # Record the page limit being hit in Prometheus + def record_page_limit_interception + dd = DeviceDetector.new(request.user_agent) + + Gitlab::Metrics.counter(:gitlab_page_out_of_bounds, + controller: params[:controller], + action: params[:action], + bot: dd.bot? + ) + end +end diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index 271f2b4b57d..a8a76b47bbe 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class Explore::ProjectsController < Explore::ApplicationController + include PageLimiter include ParamsBackwardCompatibility include RendersMemberAccess include SortingHelper @@ -9,6 +10,13 @@ class Explore::ProjectsController < Explore::ApplicationController before_action :set_non_archived_param before_action :set_sorting + # Limit taken from https://gitlab.com/gitlab-org/gitlab/issues/38357 + before_action only: [:index, :trending, :starred] do + limit_pages(200) + end + + rescue_from PageOutOfBoundsError, with: :page_out_of_bounds + def index @projects = load_projects @@ -53,10 +61,14 @@ class Explore::ProjectsController < Explore::ApplicationController private - # rubocop: disable CodeReuse/ActiveRecord - def load_projects + def load_project_counts @total_user_projects_count = ProjectsFinder.new(params: { non_public: true }, current_user: current_user).execute @total_starred_projects_count = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute + end + + # rubocop: disable CodeReuse/ActiveRecord + def load_projects + load_project_counts projects = ProjectsFinder.new(current_user: current_user, params: params) .execute @@ -80,4 +92,21 @@ class Explore::ProjectsController < Explore::ApplicationController def sorting_field Project::SORTING_PREFERENCE_FIELD end + + def page_out_of_bounds(error) + load_project_counts + @max_page_number = error.message + + respond_to do |format| + format.html do + render "page_out_of_bounds", status: :bad_request + end + + format.json do + render json: { + html: view_to_html_string("explore/projects/page_out_of_bounds") + }, status: :bad_request + end + end + end end diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index daddd9dd485..d7ae6d2cbb4 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -15,17 +15,17 @@ class Projects::SnippetsController < Projects::ApplicationController before_action :check_snippets_available! before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :toggle_award_emoji, :mark_as_spam] - # Allow read any snippet - before_action :authorize_read_project_snippet!, except: [:new, :create, :index] + # Allow create snippet + before_action :authorize_create_snippet!, only: [:new, :create] - # Allow write(create) snippet - before_action :authorize_create_project_snippet!, only: [:new, :create] + # Allow read any snippet + before_action :authorize_read_snippet!, except: [:new, :create, :index] # Allow modify snippet - before_action :authorize_update_project_snippet!, only: [:edit, :update] + before_action :authorize_update_snippet!, only: [:edit, :update] # Allow destroy snippet - before_action :authorize_admin_project_snippet!, only: [:destroy] + before_action :authorize_admin_snippet!, only: [:destroy] respond_to :html @@ -115,16 +115,16 @@ class Projects::SnippetsController < Projects::ApplicationController project_snippet_path(@project, @snippet) end - def authorize_read_project_snippet! - return render_404 unless can?(current_user, :read_project_snippet, @snippet) + def authorize_read_snippet! + return render_404 unless can?(current_user, :read_snippet, @snippet) end - def authorize_update_project_snippet! - return render_404 unless can?(current_user, :update_project_snippet, @snippet) + def authorize_update_snippet! + return render_404 unless can?(current_user, :update_snippet, @snippet) end - def authorize_admin_project_snippet! - return render_404 unless can?(current_user, :admin_project_snippet, @snippet) + def authorize_admin_snippet! + return render_404 unless can?(current_user, :admin_snippet, @snippet) end def snippet_params diff --git a/app/controllers/snippets/notes_controller.rb b/app/controllers/snippets/notes_controller.rb index 551b37cb3d3..a7e8ef0798b 100644 --- a/app/controllers/snippets/notes_controller.rb +++ b/app/controllers/snippets/notes_controller.rb @@ -33,7 +33,7 @@ class Snippets::NotesController < ApplicationController end def authorize_read_snippet! - return render_404 unless can?(current_user, :read_personal_snippet, snippet) + return render_404 unless can?(current_user, :read_snippet, snippet) end def authorize_create_note! diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index fc073e47368..b6ad5fd02b0 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -126,7 +126,7 @@ class SnippetsController < ApplicationController end def authorize_read_snippet! - return if can?(current_user, :read_personal_snippet, @snippet) + return if can?(current_user, :read_snippet, @snippet) if current_user render_404 @@ -136,15 +136,15 @@ class SnippetsController < ApplicationController end def authorize_update_snippet! - return render_404 unless can?(current_user, :update_personal_snippet, @snippet) + return render_404 unless can?(current_user, :update_snippet, @snippet) end def authorize_admin_snippet! - return render_404 unless can?(current_user, :admin_personal_snippet, @snippet) + return render_404 unless can?(current_user, :admin_snippet, @snippet) end def authorize_create_snippet! - return render_404 unless can?(current_user, :create_personal_snippet) + return render_404 unless can?(current_user, :create_snippet) end def snippet_params diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index 67d33648470..0b092d2622b 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -41,6 +41,8 @@ class UploadsController < ApplicationController case model when Note can?(current_user, :read_project, model.project) + when Snippet, ProjectSnippet + can?(current_user, :read_snippet, model) when User # We validate the current user has enough (writing) # access to itself when a secret is given. |