summaryrefslogtreecommitdiff
path: root/app/controllers
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 09:08:42 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 09:08:42 +0000
commitb76ae638462ab0f673e5915986070518dd3f9ad3 (patch)
treebdab0533383b52873be0ec0eb4d3c66598ff8b91 /app/controllers
parent434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff)
downloadgitlab-ce-b76ae638462ab0f673e5915986070518dd3f9ad3.tar.gz
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/admin/clusters/applications_controller.rb11
-rw-r--r--app/controllers/admin/integrations_controller.rb17
-rw-r--r--app/controllers/admin/runner_projects_controller.rb2
-rw-r--r--app/controllers/admin/runners_controller.rb8
-rw-r--r--app/controllers/admin/services_controller.rb47
-rw-r--r--app/controllers/admin/users_controller.rb11
-rw-r--r--app/controllers/clusters/applications_controller.rb56
-rw-r--r--app/controllers/concerns/analytics/cycle_analytics/stage_actions.rb96
-rw-r--r--app/controllers/concerns/cycle_analytics_params.rb34
-rw-r--r--app/controllers/concerns/dependency_proxy/auth.rb43
-rw-r--r--app/controllers/concerns/dependency_proxy/group_access.rb6
-rw-r--r--app/controllers/concerns/find_snippet.rb6
-rw-r--r--app/controllers/concerns/integrations_actions.rb3
-rw-r--r--app/controllers/concerns/issuable_actions.rb50
-rw-r--r--app/controllers/concerns/lfs_request.rb15
-rw-r--r--app/controllers/concerns/spammable_actions.rb73
-rw-r--r--app/controllers/concerns/spammable_actions/akismet_mark_as_spam_action.rb28
-rw-r--r--app/controllers/concerns/spammable_actions/attributes.rb13
-rw-r--r--app/controllers/concerns/spammable_actions/captcha_check/common.rb23
-rw-r--r--app/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support.rb35
-rw-r--r--app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb25
-rw-r--r--app/controllers/customers_dot/proxy_controller.rb21
-rw-r--r--app/controllers/dashboard/projects_controller.rb2
-rw-r--r--app/controllers/explore/projects_controller.rb2
-rw-r--r--app/controllers/groups/application_controller.rb8
-rw-r--r--app/controllers/groups/boards_controller.rb2
-rw-r--r--app/controllers/groups/clusters/applications_controller.rb18
-rw-r--r--app/controllers/groups/dependency_proxies_controller.rb2
-rw-r--r--app/controllers/groups/dependency_proxy/application_controller.rb66
-rw-r--r--app/controllers/groups/dependency_proxy_auth_controller.rb4
-rw-r--r--app/controllers/groups/dependency_proxy_for_containers_controller.rb27
-rw-r--r--app/controllers/groups/email_campaigns_controller.rb6
-rw-r--r--app/controllers/groups/group_members_controller.rb2
-rw-r--r--app/controllers/groups/runners_controller.rb13
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb5
-rw-r--r--app/controllers/groups/settings/integrations_controller.rb4
-rw-r--r--app/controllers/groups_controller.rb2
-rw-r--r--app/controllers/import/available_namespaces_controller.rb2
-rw-r--r--app/controllers/import/base_controller.rb11
-rw-r--r--app/controllers/invites_controller.rb12
-rw-r--r--app/controllers/jira_connect/app_descriptor_controller.rb40
-rw-r--r--app/controllers/jira_connect/branches_controller.rb29
-rw-r--r--app/controllers/jira_connect/subscriptions_controller.rb7
-rw-r--r--app/controllers/jwt_controller.rb7
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb4
-rw-r--r--app/controllers/profiles_controller.rb1
-rw-r--r--app/controllers/projects/analytics/cycle_analytics/stages_controller.rb37
-rw-r--r--app/controllers/projects/blob_controller.rb1
-rw-r--r--app/controllers/projects/clusters/applications_controller.rb15
-rw-r--r--app/controllers/projects/compare_controller.rb5
-rw-r--r--app/controllers/projects/environments_controller.rb8
-rw-r--r--app/controllers/projects/error_tracking_controller.rb10
-rw-r--r--app/controllers/projects/forks_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb13
-rw-r--r--app/controllers/projects/jobs_controller.rb26
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb4
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb38
-rw-r--r--app/controllers/projects/merge_requests_controller.rb23
-rw-r--r--app/controllers/projects/packages/infrastructure_registry_controller.rb9
-rw-r--r--app/controllers/projects/pipelines_controller.rb18
-rw-r--r--app/controllers/projects/project_members_controller.rb2
-rw-r--r--app/controllers/projects/raw_controller.rb2
-rw-r--r--app/controllers/projects/runner_projects_controller.rb2
-rw-r--r--app/controllers/projects/security/configuration_controller.rb4
-rw-r--r--app/controllers/projects/services_controller.rb25
-rw-r--r--app/controllers/projects/snippets_controller.rb8
-rw-r--r--app/controllers/projects/templates_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb11
-rw-r--r--app/controllers/registrations/welcome_controller.rb8
-rw-r--r--app/controllers/registrations_controller.rb4
-rw-r--r--app/controllers/repositories/git_http_client_controller.rb2
-rw-r--r--app/controllers/repositories/lfs_api_controller.rb6
-rw-r--r--app/controllers/repositories/lfs_locks_api_controller.rb4
-rw-r--r--app/controllers/repositories/lfs_storage_controller.rb4
-rw-r--r--app/controllers/runner_setup_controller.rb2
-rw-r--r--app/controllers/search_controller.rb16
-rw-r--r--app/controllers/snippets_controller.rb2
77 files changed, 697 insertions, 515 deletions
diff --git a/app/controllers/admin/clusters/applications_controller.rb b/app/controllers/admin/clusters/applications_controller.rb
deleted file mode 100644
index 7400cc16175..00000000000
--- a/app/controllers/admin/clusters/applications_controller.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class Admin::Clusters::ApplicationsController < Clusters::ApplicationsController
- include EnforcesAdminAuthentication
-
- private
-
- def clusterable
- @clusterable ||= InstanceClusterablePresenter.fabricate(Clusters::Instance.new, current_user: current_user)
- end
-end
diff --git a/app/controllers/admin/integrations_controller.rb b/app/controllers/admin/integrations_controller.rb
index 76c1c46e0e8..a3eb24b9b6f 100644
--- a/app/controllers/admin/integrations_controller.rb
+++ b/app/controllers/admin/integrations_controller.rb
@@ -2,19 +2,26 @@
class Admin::IntegrationsController < Admin::ApplicationController
include IntegrationsActions
- include IntegrationsHelper
before_action :not_found, unless: -> { instance_level_integrations? }
feature_category :integrations
+ def overrides
+ respond_to do |format|
+ format.json do
+ projects = Project.with_active_integration(integration.class).merge(::Integration.with_custom_settings)
+ serializer = ::Integrations::ProjectSerializer.new.with_pagination(request, response)
+
+ render json: serializer.represent(projects)
+ end
+ format.html { render 'shared/integrations/overrides' }
+ end
+ end
+
private
def find_or_initialize_non_project_specific_integration(name)
Integration.find_or_initialize_non_project_specific_integration(name, instance: true)
end
-
- def scoped_edit_integration_path(integration)
- edit_admin_application_settings_integration_path(integration)
- end
end
diff --git a/app/controllers/admin/runner_projects_controller.rb b/app/controllers/admin/runner_projects_controller.rb
index 7761ffaac84..3b408de5f01 100644
--- a/app/controllers/admin/runner_projects_controller.rb
+++ b/app/controllers/admin/runner_projects_controller.rb
@@ -3,7 +3,7 @@
class Admin::RunnerProjectsController < Admin::ApplicationController
before_action :project, only: [:create]
- feature_category :continuous_integration
+ feature_category :runner
def create
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index d1c91d9617f..8c74352a179 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -4,19 +4,11 @@ class Admin::RunnersController < Admin::ApplicationController
include RunnerSetupScripts
before_action :runner, except: [:index, :tag_list, :runner_setup_scripts]
- before_action only: [:index] do
- push_frontend_feature_flag(:runner_list_view_vue_ui, current_user, default_enabled: :yaml)
- end
feature_category :runner
- NUMBER_OF_RUNNERS_PER_PAGE = 30
-
def index
- finder = Ci::RunnersFinder.new(current_user: current_user, params: params)
- @runners = finder.execute.page(params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
@active_runners_count = Ci::Runner.online.count
- @sort = finder.sort_key
end
def show
diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb
deleted file mode 100644
index d34773ee4dc..00000000000
--- a/app/controllers/admin/services_controller.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class Admin::ServicesController < Admin::ApplicationController
- include Integrations::Params
-
- before_action :integration, only: [:edit, :update]
- before_action :disable_query_limiting, only: [:index]
-
- feature_category :integrations
-
- def index
- @activated_services = Integration.for_template.active.sort_by(&:title)
- @existing_instance_types = Integration.for_instance.pluck(:type) # rubocop: disable CodeReuse/ActiveRecord
- end
-
- def edit
- if integration.nil? || Integration.instance_exists_for?(integration.type)
- redirect_to admin_application_settings_services_path,
- alert: "Service is unknown or it doesn't exist"
- end
- end
-
- def update
- if integration.update(integration_params[:integration])
- PropagateServiceTemplateWorker.perform_async(integration.id) if integration.active? # rubocop:disable CodeReuse/Worker
-
- redirect_to admin_application_settings_services_path,
- notice: 'Application settings saved successfully'
- else
- render :edit
- end
- end
-
- private
-
- # rubocop: disable CodeReuse/ActiveRecord
- def integration
- @integration ||= Integration.find_by(id: params[:id], template: true)
- @service ||= @integration # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/329759
- end
- alias_method :service, :integration
- # rubocop: enable CodeReuse/ActiveRecord
-
- def disable_query_limiting
- Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/220357')
- end
-end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 145b4d10b16..3801906635f 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -26,9 +26,10 @@ class Admin::UsersController < Admin::ApplicationController
def show
end
+ # rubocop: disable CodeReuse/ActiveRecord
def projects
- @personal_projects = user.personal_projects
- @joined_projects = user.projects.joined(@user)
+ @personal_projects = user.personal_projects.includes(:topics)
+ @joined_projects = user.projects.joined(@user).includes(:topics)
end
def keys
@@ -136,7 +137,9 @@ class Admin::UsersController < Admin::ApplicationController
end
def unban
- if update_user { |user| user.activate }
+ result = Users::UnbanService.new(current_user).execute(user)
+
+ if result[:status] == :success
redirect_back_or_admin_user(notice: _("Successfully unbanned"))
else
redirect_back_or_admin_user(alert: _("Error occurred. User was not unbanned"))
@@ -145,7 +148,7 @@ class Admin::UsersController < Admin::ApplicationController
def unlock
if update_user { |user| user.unlock_access! }
- redirect_back_or_admin_user(alert: _("Successfully unlocked"))
+ redirect_back_or_admin_user(notice: _("Successfully unlocked"))
else
redirect_back_or_admin_user(alert: _("Error occurred. User was not unlocked"))
end
diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb
deleted file mode 100644
index 91003e9580d..00000000000
--- a/app/controllers/clusters/applications_controller.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-class Clusters::ApplicationsController < Clusters::BaseController
- before_action :cluster
- before_action :authorize_create_cluster!, only: [:create]
- before_action :authorize_update_cluster!, only: [:update]
- before_action :authorize_admin_cluster!, only: [:destroy]
-
- def create
- request_handler do
- Clusters::Applications::CreateService
- .new(@cluster, current_user, cluster_application_params)
- .execute(request)
- end
- end
-
- def update
- request_handler do
- Clusters::Applications::UpdateService
- .new(@cluster, current_user, cluster_application_params)
- .execute(request)
- end
- end
-
- def destroy
- request_handler do
- Clusters::Applications::DestroyService
- .new(@cluster, current_user, cluster_application_destroy_params)
- .execute(request)
- end
- end
-
- private
-
- def request_handler
- yield
-
- head :no_content
- rescue Clusters::Applications::BaseService::InvalidApplicationError
- render_404
- rescue StandardError
- head :bad_request
- end
-
- def cluster
- @cluster ||= clusterable.clusters.find(params[:id]) || render_404
- end
-
- def cluster_application_params
- params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :host, :port, :protocol)
- end
-
- def cluster_application_destroy_params
- params.permit(:application)
- end
-end
diff --git a/app/controllers/concerns/analytics/cycle_analytics/stage_actions.rb b/app/controllers/concerns/analytics/cycle_analytics/stage_actions.rb
new file mode 100644
index 00000000000..eebc40f33f4
--- /dev/null
+++ b/app/controllers/concerns/analytics/cycle_analytics/stage_actions.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+module Analytics
+ module CycleAnalytics
+ module StageActions
+ include Gitlab::Utils::StrongMemoize
+ extend ActiveSupport::Concern
+
+ included do
+ include CycleAnalyticsParams
+
+ before_action :validate_params, only: %i[median]
+ end
+
+ def index
+ result = list_service.execute
+
+ if result.success?
+ render json: cycle_analytics_configuration(result.payload[:stages])
+ else
+ render json: { message: result.message }, status: result.http_status
+ end
+ end
+
+ def median
+ render json: { value: data_collector.median.seconds }
+ end
+
+ def average
+ render json: { value: data_collector.average.seconds }
+ end
+
+ def records
+ serialized_records = data_collector.serialized_records do |relation|
+ add_pagination_headers(relation)
+ end
+
+ render json: serialized_records
+ end
+
+ def count
+ render json: { count: data_collector.count }
+ end
+
+ private
+
+ def parent
+ raise NotImplementedError
+ end
+
+ def value_stream_class
+ raise NotImplementedError
+ end
+
+ def add_pagination_headers(relation)
+ Gitlab::Pagination::OffsetHeaderBuilder.new(
+ request_context: self,
+ per_page: relation.limit_value,
+ page: relation.current_page,
+ next_page: relation.next_page,
+ prev_page: relation.prev_page,
+ params: permitted_cycle_analytics_params
+ ).execute(exclude_total_headers: true, data_without_counts: true)
+ end
+
+ def stage
+ @stage ||= ::Analytics::CycleAnalytics::StageFinder.new(parent: parent, stage_id: params[:id]).execute
+ end
+
+ def data_collector
+ @data_collector ||= Gitlab::Analytics::CycleAnalytics::DataCollector.new(
+ stage: stage,
+ params: request_params.to_data_collector_params
+ )
+ end
+
+ def value_stream
+ @value_stream ||= value_stream_class.build_default_value_stream(parent)
+ end
+
+ def list_params
+ { value_stream: value_stream }
+ end
+
+ def list_service
+ Analytics::CycleAnalytics::Stages::ListService.new(parent: parent, current_user: current_user, params: list_params)
+ end
+
+ def cycle_analytics_configuration(stages)
+ stage_presenters = stages.map { |s| ::Analytics::CycleAnalytics::StagePresenter.new(s) }
+
+ Analytics::CycleAnalytics::ConfigurationEntity.new(stages: stage_presenters)
+ end
+ end
+ end
+end
diff --git a/app/controllers/concerns/cycle_analytics_params.rb b/app/controllers/concerns/cycle_analytics_params.rb
index b74e343f90b..626093b4588 100644
--- a/app/controllers/concerns/cycle_analytics_params.rb
+++ b/app/controllers/concerns/cycle_analytics_params.rb
@@ -16,9 +16,20 @@ module CycleAnalyticsParams
end
def options(params)
- @options ||= { from: start_date(params), current_user: current_user }.merge(date_range(params))
+ @options ||= {}.tap do |opts|
+ opts[:current_user] = current_user
+ opts[:projects] = params[:project_ids] if params[:project_ids]
+ opts[:group] = params[:group_id] if params[:group_id]
+ opts[:from] = params[:from] || start_date(params)
+ opts[:to] = params[:to] if params[:to]
+ opts[:end_event_filter] = params[:end_event_filter] if params[:end_event_filter]
+ opts.merge!(params.slice(*::Gitlab::Analytics::CycleAnalytics::RequestParams::FINDER_PARAM_NAMES))
+ opts.merge!(date_range(params))
+ end
end
+ private
+
def start_date(params)
case params[:start_date]
when '7'
@@ -41,6 +52,27 @@ module CycleAnalyticsParams
date = field.is_a?(Date) || field.is_a?(Time) ? field : Date.parse(field)
date.to_time.utc
end
+
+ def permitted_cycle_analytics_params
+ params.permit(*::Gitlab::Analytics::CycleAnalytics::RequestParams::STRONG_PARAMS_DEFINITION)
+ end
+
+ def all_cycle_analytics_params
+ permitted_cycle_analytics_params.merge(current_user: current_user)
+ end
+
+ def request_params
+ @request_params ||= ::Gitlab::Analytics::CycleAnalytics::RequestParams.new(all_cycle_analytics_params)
+ end
+
+ def validate_params
+ if request_params.invalid?
+ render(
+ json: { message: 'Invalid parameters', errors: request_params.errors },
+ status: :unprocessable_entity
+ )
+ end
+ end
end
CycleAnalyticsParams.prepend_mod_with('CycleAnalyticsParams')
diff --git a/app/controllers/concerns/dependency_proxy/auth.rb b/app/controllers/concerns/dependency_proxy/auth.rb
deleted file mode 100644
index 1276feedba6..00000000000
--- a/app/controllers/concerns/dependency_proxy/auth.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-module DependencyProxy
- module Auth
- extend ActiveSupport::Concern
-
- included do
- # We disable `authenticate_user!` since the `DependencyProxy::Auth` performs auth using JWT token
- skip_before_action :authenticate_user!, raise: false
- prepend_before_action :authenticate_user_from_jwt_token!
- end
-
- def authenticate_user_from_jwt_token!
- return unless dependency_proxy_for_private_groups?
-
- authenticate_with_http_token do |token, _|
- user = user_from_token(token)
- sign_in(user) if user
- end
-
- request_bearer_token! unless current_user
- end
-
- private
-
- def dependency_proxy_for_private_groups?
- Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true)
- end
-
- def request_bearer_token!
- # unfortunately, we cannot use https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html#method-i-authentication_request
- response.headers['WWW-Authenticate'] = ::DependencyProxy::Registry.authenticate_header
- render plain: '', status: :unauthorized
- end
-
- def user_from_token(token)
- token_payload = DependencyProxy::AuthTokenService.decoded_token_payload(token)
- User.find(token_payload['user_id'])
- rescue JWT::DecodeError, JWT::ExpiredSignature, JWT::ImmatureSignature
- nil
- end
- end
-end
diff --git a/app/controllers/concerns/dependency_proxy/group_access.rb b/app/controllers/concerns/dependency_proxy/group_access.rb
index 2a923d02752..07aca72b22f 100644
--- a/app/controllers/concerns/dependency_proxy/group_access.rb
+++ b/app/controllers/concerns/dependency_proxy/group_access.rb
@@ -12,15 +12,15 @@ module DependencyProxy
private
def verify_dependency_proxy_enabled!
- render_404 unless group.dependency_proxy_feature_available?
+ render_404 unless group&.dependency_proxy_feature_available?
end
def authorize_read_dependency_proxy!
- access_denied! unless can?(current_user, :read_dependency_proxy, group)
+ access_denied! unless can?(auth_user, :read_dependency_proxy, group)
end
def authorize_admin_dependency_proxy!
- access_denied! unless can?(current_user, :admin_dependency_proxy, group)
+ access_denied! unless can?(auth_user, :admin_dependency_proxy, group)
end
end
end
diff --git a/app/controllers/concerns/find_snippet.rb b/app/controllers/concerns/find_snippet.rb
index d51f1a1b3ad..8a4adbb608f 100644
--- a/app/controllers/concerns/find_snippet.rb
+++ b/app/controllers/concerns/find_snippet.rb
@@ -9,7 +9,7 @@ module FindSnippet
# rubocop:disable CodeReuse/ActiveRecord
def snippet
strong_memoize(:snippet) do
- snippet_klass.inc_relations_for_view.find_by(id: snippet_id)
+ snippet_klass.inc_relations_for_view.find_by(snippet_find_params)
end
end
# rubocop:enable CodeReuse/ActiveRecord
@@ -21,4 +21,8 @@ module FindSnippet
def snippet_id
params[:id]
end
+
+ def snippet_find_params
+ { id: snippet_id }
+ end
end
diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb
index f1fa5c845e2..dd066cc1b02 100644
--- a/app/controllers/concerns/integrations_actions.rb
+++ b/app/controllers/concerns/integrations_actions.rb
@@ -5,8 +5,9 @@ module IntegrationsActions
included do
include Integrations::Params
+ include IntegrationsHelper
- before_action :integration, only: [:edit, :update, :test]
+ before_action :integration, only: [:edit, :update, :overrides, :test]
end
def edit
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index 2664a7b7151..7ee680db7f9 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -4,6 +4,9 @@ module IssuableActions
extend ActiveSupport::Concern
include Gitlab::Utils::StrongMemoize
include Gitlab::Cache::Helpers
+ include SpammableActions::AkismetMarkAsSpamAction
+ include SpammableActions::CaptchaCheck::HtmlFormatActionsSupport
+ include SpammableActions::CaptchaCheck::JsonFormatActionsSupport
included do
before_action :authorize_destroy_issuable!, only: :destroy
@@ -25,17 +28,42 @@ module IssuableActions
end
def update
- @issuable = update_service.execute(issuable) # rubocop:disable Gitlab/ModuleWithInstanceVariables
- respond_to do |format|
- format.html do
- recaptcha_check_if_spammable { render :edit }
+ updated_issuable = update_service.execute(issuable)
+ # NOTE: We only assign the instance variable on this line, and use the local variable
+ # everywhere else in the method, to avoid having to add multiple `rubocop:disable` comments.
+ @issuable = updated_issuable # rubocop:disable Gitlab/ModuleWithInstanceVariables
+
+ # NOTE: This check for `is_a?(Spammable)` is necessary because not all
+ # possible `issuable` types implement Spammable. Once they all implement Spammable,
+ # this check can be removed.
+ if updated_issuable.is_a?(Spammable)
+ respond_to do |format|
+ format.html do
+ # NOTE: This redirect is intentionally only performed in the case where the updated
+ # issuable is a spammable, and intentionally is not performed in the non-spammable case.
+ # This preserves the legacy behavior of this action.
+ if updated_issuable.valid?
+ redirect_to spammable_path
+ else
+ with_captcha_check_html_format { render :edit }
+ end
+ end
+
+ format.json do
+ with_captcha_check_json_format { render_entity_json }
+ end
end
-
- format.json do
- recaptcha_check_if_spammable(false) { render_entity_json }
+ else
+ respond_to do |format|
+ format.html do
+ render :edit
+ end
+
+ format.json do
+ render_entity_json
+ end
end
end
-
rescue ActiveRecord::StaleObjectError
render_conflict_response
end
@@ -171,12 +199,6 @@ module IssuableActions
DiscussionSerializer.new(project: project, noteable: issuable, current_user: current_user, note_entity: ProjectNoteEntity)
end
- def recaptcha_check_if_spammable(should_redirect = true, &block)
- return yield unless issuable.is_a? Spammable
-
- recaptcha_check_with_fallback(should_redirect, &block)
- end
-
def render_conflict_response
respond_to do |format|
format.html do
diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb
index 55e0ed8cd42..97df3c7caea 100644
--- a/app/controllers/concerns/lfs_request.rb
+++ b/app/controllers/concerns/lfs_request.rb
@@ -4,6 +4,7 @@
# - a `#container` accessor
# - a `#project` accessor
# - a `#user` accessor
+# - a `#deploy_token` accessor
# - a `#authentication_result` accessor
# - a `#can?(object, action, subject)` method
# - a `#ci?` method
@@ -83,26 +84,18 @@ module LfsRequest
end
def deploy_token_can_download_code?
- deploy_token_present? &&
+ deploy_token.present? &&
deploy_token.project == project &&
deploy_token.active? &&
deploy_token.read_repository?
end
- def deploy_token_present?
- user && user.is_a?(DeployToken)
- end
-
- def deploy_token
- user
- end
-
def lfs_upload_access?
strong_memoize(:lfs_upload_access) do
next false unless has_authentication_ability?(:push_code)
next false if limit_exceeded?
- lfs_deploy_token? || can?(user, :push_code, project)
+ lfs_deploy_token? || can?(user, :push_code, project) || can?(deploy_token, :push_code, project)
end
end
@@ -111,7 +104,7 @@ module LfsRequest
end
def user_can_download_code?
- has_authentication_ability?(:download_code) && can?(user, :download_code, project) && !deploy_token_present?
+ has_authentication_ability?(:download_code) && can?(user, :download_code, project)
end
def build_can_download_code?
diff --git a/app/controllers/concerns/spammable_actions.rb b/app/controllers/concerns/spammable_actions.rb
deleted file mode 100644
index eb1223f22a9..00000000000
--- a/app/controllers/concerns/spammable_actions.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module SpammableActions
- extend ActiveSupport::Concern
- include Spam::Concerns::HasSpamActionResponseFields
-
- included do
- before_action :authorize_submit_spammable!, only: :mark_as_spam
- end
-
- def mark_as_spam
- if Spam::MarkAsSpamService.new(target: spammable).execute
- redirect_to spammable_path, notice: _("%{spammable_titlecase} was submitted to Akismet successfully.") % { spammable_titlecase: spammable.spammable_entity_type.titlecase }
- else
- redirect_to spammable_path, alert: _('Error with Akismet. Please check the logs for more info.')
- end
- end
-
- private
-
- def recaptcha_check_with_fallback(should_redirect = true, &fallback)
- if should_redirect && spammable.valid?
- redirect_to spammable_path
- elsif spammable.render_recaptcha?
- Gitlab::Recaptcha.load_configurations!
-
- 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
- # 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
-
- # 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
- yield
- end
- end
-
- # TODO: This method is currently only needed for issue create, to convert spam/CAPTCHA values from
- # params, and instead be passed as headers, as the spam services now all expect. It can be removed
- # when issue create is is converted to a client/JS based approach instead of the legacy HAML
- # `_recaptcha_form.html.haml` which is rendered via the `projects/issues/verify` template.
- # In that case, which is based on the legacy reCAPTCHA implementation using the HTML/HAML form,
- # the 'g-recaptcha-response' field name comes from `Recaptcha::ClientHelper#recaptcha_tags` in the
- # recaptcha gem, which is called from the HAML `_recaptcha_form.html.haml` form.
- def extract_legacy_spam_params_to_headers
- request.headers['X-GitLab-Captcha-Response'] = params['g-recaptcha-response'] || params[:captcha_response]
- request.headers['X-GitLab-Spam-Log-Id'] = params[:spam_log_id]
- end
-
- def spammable
- raise NotImplementedError, "#{self.class} does not implement #{__method__}"
- end
-
- def spammable_path
- raise NotImplementedError, "#{self.class} does not implement #{__method__}"
- end
-
- def authorize_submit_spammable!
- access_denied! unless current_user.admin?
- end
-end
diff --git a/app/controllers/concerns/spammable_actions/akismet_mark_as_spam_action.rb b/app/controllers/concerns/spammable_actions/akismet_mark_as_spam_action.rb
new file mode 100644
index 00000000000..234c591ffb7
--- /dev/null
+++ b/app/controllers/concerns/spammable_actions/akismet_mark_as_spam_action.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module SpammableActions::AkismetMarkAsSpamAction
+ extend ActiveSupport::Concern
+ include SpammableActions::Attributes
+
+ included do
+ before_action :authorize_submit_spammable!, only: :mark_as_spam
+ end
+
+ def mark_as_spam
+ if Spam::AkismetMarkAsSpamService.new(target: spammable).execute
+ redirect_to spammable_path, notice: _("%{spammable_titlecase} was submitted to Akismet successfully.") % { spammable_titlecase: spammable.spammable_entity_type.titlecase }
+ else
+ redirect_to spammable_path, alert: _('Error with Akismet. Please check the logs for more info.')
+ end
+ end
+
+ private
+
+ def authorize_submit_spammable!
+ access_denied! unless current_user.can_admin_all_resources?
+ end
+
+ def spammable_path
+ raise NotImplementedError, "#{self.class} does not implement #{__method__}"
+ end
+end
diff --git a/app/controllers/concerns/spammable_actions/attributes.rb b/app/controllers/concerns/spammable_actions/attributes.rb
new file mode 100644
index 00000000000..d7060e47c07
--- /dev/null
+++ b/app/controllers/concerns/spammable_actions/attributes.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module SpammableActions
+ module Attributes
+ extend ActiveSupport::Concern
+
+ private
+
+ def spammable
+ raise NotImplementedError, "#{self.class} does not implement #{__method__}"
+ end
+ end
+end
diff --git a/app/controllers/concerns/spammable_actions/captcha_check/common.rb b/app/controllers/concerns/spammable_actions/captcha_check/common.rb
new file mode 100644
index 00000000000..7c047e02a1d
--- /dev/null
+++ b/app/controllers/concerns/spammable_actions/captcha_check/common.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module SpammableActions::CaptchaCheck
+ module Common
+ extend ActiveSupport::Concern
+
+ private
+
+ def with_captcha_check_common(captcha_render_lambda:, &block)
+ # If the Spammable indicates that CAPTCHA is not necessary (either due to it not being flagged
+ # as spam, or if spam/captcha is disabled for some reason), then we will go ahead and
+ # yield to the block containing the action's original behavior, then return.
+ return yield unless spammable.render_recaptcha?
+
+ # If we got here, we need to render the CAPTCHA instead of yielding to action's original
+ # behavior. We will present a CAPTCHA to be solved by executing the lambda which was passed
+ # as the `captcha_render_lambda:` argument. This lambda contains either the HTML-specific or
+ # JSON-specific behavior to cause the CAPTCHA modal to be rendered.
+ Gitlab::Recaptcha.load_configurations!
+ captcha_render_lambda.call
+ end
+ end
+end
diff --git a/app/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support.rb b/app/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support.rb
new file mode 100644
index 00000000000..f687c0fcf2d
--- /dev/null
+++ b/app/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+# This module should *ONLY* be included if needed to support forms submits with HTML MIME type.
+# In other words, forms handled by actions which use a `respond_to` of `format.html`.
+#
+# If the request is handled by actions via `format.json`, for example, for all Javascript based form
+# submissions and Vue components which use Apollo and Axios, then the corresponding module
+# which supports JSON format should be used instead.
+module SpammableActions::CaptchaCheck::HtmlFormatActionsSupport
+ extend ActiveSupport::Concern
+ include SpammableActions::Attributes
+ include SpammableActions::CaptchaCheck::Common
+
+ included do
+ before_action :convert_html_spam_params_to_headers, only: [:create, :update]
+ end
+
+ private
+
+ def with_captcha_check_html_format(&block)
+ captcha_render_lambda = -> { render :captcha_check }
+ with_captcha_check_common(captcha_render_lambda: captcha_render_lambda, &block)
+ end
+
+ # Convert spam/CAPTCHA values from form field params to headers, because all spam-related services
+ # expect these values to be passed as headers.
+ #
+ # The 'g-recaptcha-response' field name comes from `Recaptcha::ClientHelper#recaptcha_tags` in the
+ # recaptcha gem. This is a field which is automatically included by calling the
+ # `#recaptcha_tags` method within a HAML template's form.
+ def convert_html_spam_params_to_headers
+ request.headers['X-GitLab-Captcha-Response'] = params['g-recaptcha-response'] if params['g-recaptcha-response']
+ request.headers['X-GitLab-Spam-Log-Id'] = params[:spam_log_id] if params[:spam_log_id]
+ end
+end
diff --git a/app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb b/app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb
new file mode 100644
index 00000000000..0bfea05abc7
--- /dev/null
+++ b/app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# This module should be included to support forms submits with a 'js' or 'json' type of MIME type.
+# In other words, forms handled by actions which use a `respond_to` of `format.js` or `format.json`.
+#
+# For example, for all Javascript based form submissions and Vue components which use Apollo and Axios
+#
+# If the request is handled by actions via `format.html`, then the corresponding module which
+# supports HTML format should be used instead.
+module SpammableActions::CaptchaCheck::JsonFormatActionsSupport
+ extend ActiveSupport::Concern
+ include SpammableActions::Attributes
+ include SpammableActions::CaptchaCheck::Common
+ include Spam::Concerns::HasSpamActionResponseFields
+
+ private
+
+ def with_captcha_check_json_format(&block)
+ # 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.
+ # https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10
+ captcha_render_lambda = -> { render json: spam_action_response_fields(spammable), status: :conflict }
+ with_captcha_check_common(captcha_render_lambda: captcha_render_lambda, &block)
+ end
+end
diff --git a/app/controllers/customers_dot/proxy_controller.rb b/app/controllers/customers_dot/proxy_controller.rb
deleted file mode 100644
index 5abf8a487c6..00000000000
--- a/app/controllers/customers_dot/proxy_controller.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module CustomersDot
- class ProxyController < ApplicationController
- skip_before_action :authenticate_user!
- skip_before_action :verify_authenticity_token
-
- feature_category :purchase
-
- BASE_URL = Gitlab::SubscriptionPortal::SUBSCRIPTIONS_URL
-
- def graphql
- response = Gitlab::HTTP.post("#{BASE_URL}/graphql",
- body: request.raw_post,
- headers: { 'Content-Type' => 'application/json' }
- )
-
- render json: response.body, status: response.code
- end
- end
-end
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index 01bb930a51b..d861ef646f8 100644
--- a/app/controllers/dashboard/projects_controller.rb
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -81,7 +81,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(projects)
- projects.includes(:route, :creator, :group, namespace: [:route, :owner]).preload(:project_feature)
+ projects.includes(:route, :creator, :group, :topics, namespace: [:route, :owner]).preload(:project_feature)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index 5ef973e9bf3..e0973b0f3b4 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -87,7 +87,7 @@ class Explore::ProjectsController < Explore::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(projects)
- projects.includes(:route, :creator, :group, :project_feature, namespace: [:route, :owner])
+ projects.includes(:route, :creator, :group, :project_feature, :topics, namespace: [:route, :owner])
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index 69081835c4d..aa0d49902c3 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -13,16 +13,8 @@ class Groups::ApplicationController < ApplicationController
before_action :set_sorting
requires_cross_project_access
- helper_method :can_manage_members?
-
private
- def can_manage_members?(group = @group)
- strong_memoize(:can_manage_members) do
- can?(current_user, :admin_group_member, group)
- end
- end
-
def group
@group ||= find_routable!(Group, params[:group_id] || params[:id], request.path_info)
end
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 04b4d8ea9a7..96a3b38669d 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -7,7 +7,7 @@ class Groups::BoardsController < Groups::ApplicationController
before_action :assign_endpoint_vars
before_action do
- push_frontend_feature_flag(:graphql_board_lists, group, default_enabled: false)
+ push_frontend_feature_flag(:graphql_board_lists, group, default_enabled: :yaml)
push_frontend_feature_flag(:issue_boards_filtered_search, group, default_enabled: :yaml)
push_frontend_feature_flag(:board_multi_select, group, default_enabled: :yaml)
push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
diff --git a/app/controllers/groups/clusters/applications_controller.rb b/app/controllers/groups/clusters/applications_controller.rb
deleted file mode 100644
index ce6fda4143c..00000000000
--- a/app/controllers/groups/clusters/applications_controller.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class Groups::Clusters::ApplicationsController < Clusters::ApplicationsController
- include ControllerWithCrossProjectAccessCheck
-
- prepend_before_action :group
- requires_cross_project_access
-
- private
-
- def clusterable
- @clusterable ||= ClusterablePresenter.fabricate(group, current_user: current_user)
- end
-
- def group
- @group ||= find_routable!(Group, params[:group_id] || params[:id], request.path_info)
- end
-end
diff --git a/app/controllers/groups/dependency_proxies_controller.rb b/app/controllers/groups/dependency_proxies_controller.rb
index b896b240daf..b037aa52939 100644
--- a/app/controllers/groups/dependency_proxies_controller.rb
+++ b/app/controllers/groups/dependency_proxies_controller.rb
@@ -2,7 +2,7 @@
module Groups
class DependencyProxiesController < Groups::ApplicationController
- include DependencyProxy::GroupAccess
+ include ::DependencyProxy::GroupAccess
before_action :authorize_admin_dependency_proxy!, only: :update
before_action :dependency_proxy
diff --git a/app/controllers/groups/dependency_proxy/application_controller.rb b/app/controllers/groups/dependency_proxy/application_controller.rb
new file mode 100644
index 00000000000..fd9db41f748
--- /dev/null
+++ b/app/controllers/groups/dependency_proxy/application_controller.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Groups
+ module DependencyProxy
+ class ApplicationController < ::ApplicationController
+ EMPTY_AUTH_RESULT = Gitlab::Auth::Result.new(nil, nil, nil, nil).freeze
+
+ delegate :actor, to: :@authentication_result, allow_nil: true
+
+ # This allows auth_user to be set in the base ApplicationController
+ alias_method :authenticated_user, :actor
+
+ # We disable `authenticate_user!` since the `DependencyProxy::ApplicationController` performs auth using JWT token
+ skip_before_action :authenticate_user!, raise: false
+
+ prepend_before_action :authenticate_user_from_jwt_token!
+
+ def authenticate_user_from_jwt_token!
+ return unless dependency_proxy_for_private_groups?
+
+ authenticate_with_http_token do |token, _|
+ @authentication_result = EMPTY_AUTH_RESULT
+
+ found_user = user_from_token(token)
+ sign_in(found_user) if found_user.is_a?(User)
+ end
+
+ request_bearer_token! unless authenticated_user
+ end
+
+ private
+
+ def dependency_proxy_for_private_groups?
+ Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true)
+ end
+
+ def request_bearer_token!
+ # unfortunately, we cannot use https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html#method-i-authentication_request
+ response.headers['WWW-Authenticate'] = ::DependencyProxy::Registry.authenticate_header
+ render plain: '', status: :unauthorized
+ end
+
+ def user_from_token(token)
+ token_payload = ::DependencyProxy::AuthTokenService.decoded_token_payload(token)
+
+ if token_payload['user_id']
+ token_user = User.find(token_payload['user_id'])
+ return unless token_user
+
+ @authentication_result = Gitlab::Auth::Result.new(token_user, nil, :user, [])
+ return token_user
+ elsif token_payload['deploy_token']
+ deploy_token = DeployToken.active.find_by_token(token_payload['deploy_token'])
+ return unless deploy_token
+
+ @authentication_result = Gitlab::Auth::Result.new(deploy_token, nil, :deploy_token, [])
+ return deploy_token
+ end
+
+ nil
+ rescue JWT::DecodeError, JWT::ExpiredSignature, JWT::ImmatureSignature
+ nil
+ end
+ end
+ end
+end
diff --git a/app/controllers/groups/dependency_proxy_auth_controller.rb b/app/controllers/groups/dependency_proxy_auth_controller.rb
index e3e9bd88e24..60b2371fa9a 100644
--- a/app/controllers/groups/dependency_proxy_auth_controller.rb
+++ b/app/controllers/groups/dependency_proxy_auth_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-class Groups::DependencyProxyAuthController < ApplicationController
- include DependencyProxy::Auth
-
+class Groups::DependencyProxyAuthController < ::Groups::DependencyProxy::ApplicationController
feature_category :dependency_proxy
def authenticate
diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
index e2c104f88a4..f7dc552bd3e 100644
--- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb
+++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
-class Groups::DependencyProxyForContainersController < Groups::ApplicationController
- include DependencyProxy::Auth
+class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy::ApplicationController
+ include Gitlab::Utils::StrongMemoize
include DependencyProxy::GroupAccess
include SendFileUpload
+ include ::PackagesHelper # for event tracking
+ before_action :ensure_group
before_action :ensure_token_granted!
before_action :ensure_feature_enabled!
@@ -22,6 +24,8 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro
response.headers['Etag'] = "\"#{result[:manifest].digest}\""
content_type = result[:manifest].content_type
+ event_name = tracking_event_name(object_type: :manifest, from_cache: result[:from_cache])
+ track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user)
send_upload(
result[:manifest].file,
proxy: true,
@@ -38,6 +42,8 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro
.new(group, image, token, params[:sha]).execute
if result[:status] == :success
+ event_name = tracking_event_name(object_type: :blob, from_cache: result[:from_cache])
+ track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user)
send_upload(result[:blob].file)
else
head result[:http_status]
@@ -46,6 +52,12 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro
private
+ def group
+ strong_memoize(:group) do
+ Group.find_by_full_path(params[:group_id], follow_redirects: request.get?)
+ end
+ end
+
def image
params[:image]
end
@@ -54,11 +66,22 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro
params[:tag]
end
+ def tracking_event_name(object_type:, from_cache:)
+ event_name = "pull_#{object_type}"
+ event_name = "#{event_name}_from_cache" if from_cache
+
+ event_name
+ end
+
def dependency_proxy
@dependency_proxy ||=
group.dependency_proxy_setting || group.create_dependency_proxy_setting
end
+ def ensure_group
+ render_404 unless group
+ end
+
def ensure_feature_enabled!
render_404 unless dependency_proxy.enabled
end
diff --git a/app/controllers/groups/email_campaigns_controller.rb b/app/controllers/groups/email_campaigns_controller.rb
index d4c7b31c4b8..70c8a23d918 100644
--- a/app/controllers/groups/email_campaigns_controller.rb
+++ b/app/controllers/groups/email_campaigns_controller.rb
@@ -38,10 +38,12 @@ class Groups::EmailCampaignsController < Groups::ApplicationController
create_track_url
when :verify
project_pipelines_url(group.projects.first)
- when :trial
+ when :trial, :trial_short
'https://about.gitlab.com/free-trial/'
- when :team
+ when :team, :team_short
group_group_members_url(group)
+ when :admin_verify
+ project_settings_ci_cd_path(group.projects.first, ci_runner_templates: true, anchor: 'js-runners-settings')
end
end
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index d5e7653dea2..9b8d5cfe476 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -29,7 +29,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
.new(@group, current_user, params: filter_params)
.execute(include_relations: requested_relations)
- if can_manage_members?
+ if can?(current_user, :admin_group_member, @group)
@skip_groups = @group.related_group_ids
@invited_members = @members.invite
diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb
index 1cff658dd52..dbbfdd76fe8 100644
--- a/app/controllers/groups/runners_controller.rb
+++ b/app/controllers/groups/runners_controller.rb
@@ -1,14 +1,21 @@
# frozen_string_literal: true
class Groups::RunnersController < Groups::ApplicationController
- # Proper policies should be implemented per
- # https://gitlab.com/gitlab-org/gitlab-foss/issues/45894
+ # TODO Proper policies, such as `read_group_runners, should be implemented per
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/334802
before_action :authorize_admin_group!
-
+ before_action :runner_list_group_view_vue_ui_enabled, only: [:index]
before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show]
feature_category :runner
+ def index
+ end
+
+ def runner_list_group_view_vue_ui_enabled
+ return render_404 unless Feature.enabled?(:runner_list_group_view_vue_ui, group, default_enabled: :yaml)
+ end
+
def show
end
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index 88c709e3f53..0f40c9bfd2c 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -60,6 +60,7 @@ module Groups
def define_variables
define_ci_variables
+ define_view_variables
end
def define_ci_variables
@@ -69,6 +70,10 @@ module Groups
.map { |variable| variable.present(current_user: current_user) }
end
+ def define_view_variables
+ @content_class = 'limit-container-width' unless fluid_layout
+ end
+
def authorize_admin_group!
return render_404 unless can?(current_user, :admin_group, group)
end
diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb
index 8e3b2cb5d1b..a7a1de03224 100644
--- a/app/controllers/groups/settings/integrations_controller.rb
+++ b/app/controllers/groups/settings/integrations_controller.rb
@@ -26,10 +26,6 @@ module Groups
def find_or_initialize_non_project_specific_integration(name)
Integration.find_or_initialize_non_project_specific_integration(name, group_id: group.id)
end
-
- def scoped_edit_integration_path(integration)
- edit_group_settings_integration_path(group, integration)
- end
end
end
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 66816d4c587..2796760fbe1 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -206,8 +206,6 @@ class GroupsController < Groups::ApplicationController
protected
def render_show_html
- record_experiment_user(:invite_members_empty_group_version_a) if ::Gitlab.com?
-
render 'groups/show', locals: { trial: params[:trial] }
end
diff --git a/app/controllers/import/available_namespaces_controller.rb b/app/controllers/import/available_namespaces_controller.rb
index c6211b33d28..0c2af13d3f3 100644
--- a/app/controllers/import/available_namespaces_controller.rb
+++ b/app/controllers/import/available_namespaces_controller.rb
@@ -4,6 +4,6 @@ class Import::AvailableNamespacesController < ApplicationController
feature_category :importers
def index
- render json: NamespaceSerializer.new.represent(current_user.manageable_groups_with_routes)
+ render json: NamespaceSerializer.new.represent(current_user.manageable_groups_with_routes(include_groups_with_developer_maintainer_access: true))
end
end
diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb
index 1121ecfb65c..53856e4575b 100644
--- a/app/controllers/import/base_controller.rb
+++ b/app/controllers/import/base_controller.rb
@@ -11,8 +11,7 @@ class Import::BaseController < ApplicationController
format.json do
render json: { imported_projects: serialized_imported_projects,
provider_repos: serialized_provider_repos,
- incompatible_repos: serialized_incompatible_repos,
- namespaces: serialized_namespaces }
+ incompatible_repos: serialized_incompatible_repos }
end
format.html
end
@@ -74,14 +73,6 @@ class Import::BaseController < ApplicationController
@already_added_projects ||= filtered(find_already_added_projects(provider_name))
end
- def serialized_namespaces
- NamespaceSerializer.new.represent(namespaces)
- end
-
- def namespaces
- current_user.manageable_groups_with_routes
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def find_already_added_projects(import_type)
current_user.created_projects.where(import_type: import_type).with_import_state
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 3c81b698546..7f5750d2011 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -75,7 +75,10 @@ class InvitesController < ApplicationController
end
def track_invite_join_click
- experiment('members/invite_email', actor: member).track(:join_clicked) if member && Members::InviteEmailExperiment.initial_invite_email?(params[:invite_type])
+ return unless member && initial_invite_email?
+
+ experiment(:invite_email_preview_text, actor: member).track(:join_clicked) if params[:experiment_name] == 'invite_email_preview_text'
+ Gitlab::Tracking.event(self.class.name, 'join_clicked', label: 'invite_email', property: member.id.to_s)
end
def authenticate_user!
@@ -95,7 +98,12 @@ class InvitesController < ApplicationController
def set_session_invite_params
session[:invite_email] = member.invite_email
- session[:originating_member_id] = member.id if Members::InviteEmailExperiment.initial_invite_email?(params[:invite_type])
+ session[:originating_member_id] = member.id if initial_invite_email?
+ session[:invite_email_experiment_name] = params[:experiment_name] if initial_invite_email? && params[:experiment_name]
+ end
+
+ def initial_invite_email?
+ params[:invite_type] == Emails::Members::INITIAL_INVITE
end
def sign_in_redirect_params
diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb
index 0de42ad2452..a0f387631dd 100644
--- a/app/controllers/jira_connect/app_descriptor_controller.rb
+++ b/app/controllers/jira_connect/app_descriptor_controller.rb
@@ -44,27 +44,14 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
def modules
modules = {
- jiraDevelopmentTool: {
- key: 'gitlab-development-tool',
- application: {
- value: 'GitLab'
- },
- name: {
- value: 'GitLab'
- },
- url: HOME_URL,
- logoUrl: logo_url,
- capabilities: %w(branch commit pull_request)
- },
postInstallPage: {
key: 'gitlab-configuration',
- name: {
- value: 'GitLab Configuration'
- },
+ name: { value: 'GitLab Configuration' },
url: relative_to_base_path(jira_connect_subscriptions_path)
}
}
+ modules.merge!(development_tool_module)
modules.merge!(build_information_module)
modules.merge!(deployment_information_module)
modules.merge!(feature_flag_module)
@@ -76,6 +63,25 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
view_context.image_url('gitlab_logo.png')
end
+ # See https://developer.atlassian.com/cloud/jira/software/modules/development-tool/
+ def development_tool_module
+ {
+ jiraDevelopmentTool: {
+ actions: {
+ createBranch: {
+ templateUrl: new_jira_connect_branch_url + '?issue_key={issue.key}&issue_summary={issue.summary}'
+ }
+ },
+ key: 'gitlab-development-tool',
+ application: { value: 'GitLab' },
+ name: { value: 'GitLab' },
+ url: HOME_URL,
+ logoUrl: logo_url,
+ capabilities: %w(branch commit pull_request)
+ }
+ }
+ end
+
# See: https://developer.atlassian.com/cloud/jira/software/modules/deployment/
def deployment_information_module
{
@@ -92,9 +98,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
{
jiraFeatureFlagInfoProvider: common_module_properties.merge(
actions: {}, # TODO: create, link and list feature flags https://gitlab.com/gitlab-org/gitlab/-/issues/297386
- name: {
- value: 'GitLab Feature Flags'
- },
+ name: { value: 'GitLab Feature Flags' },
key: 'gitlab-feature-flags'
)
}
diff --git a/app/controllers/jira_connect/branches_controller.rb b/app/controllers/jira_connect/branches_controller.rb
new file mode 100644
index 00000000000..12ea6560e3a
--- /dev/null
+++ b/app/controllers/jira_connect/branches_controller.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+# NOTE: This controller does not inherit from JiraConnect::ApplicationController
+# because we don't receive a JWT for this action, so we rely on standard GitLab authentication.
+class JiraConnect::BranchesController < ApplicationController
+ feature_category :integrations
+
+ def new
+ @new_branch_data = new_branch_data
+ end
+
+ private
+
+ def initial_branch_name
+ return unless params[:issue_key].present?
+
+ Issue.to_branch_name(
+ params[:issue_key],
+ params[:issue_summary]
+ )
+ end
+
+ def new_branch_data
+ {
+ initial_branch_name: initial_branch_name,
+ success_state_svg_path: ActionController::Base.helpers.image_path('illustrations/merge_requests.svg')
+ }
+ end
+end
diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb
index 3ff12f29f10..a9c4dbf2b17 100644
--- a/app/controllers/jira_connect/subscriptions_controller.rb
+++ b/app/controllers/jira_connect/subscriptions_controller.rb
@@ -22,6 +22,13 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController
def index
@subscriptions = current_jira_installation.subscriptions.preload_namespace_route
+
+ respond_to do |format|
+ format.html
+ format.json do
+ render json: JiraConnect::AppDataSerializer.new(@subscriptions, !!current_user).as_json
+ end
+ end
end
def create
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index 85ee2204324..010b85e81bf 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -19,7 +19,7 @@ class JwtController < ApplicationController
service = SERVICES[params[:service]]
return head :not_found unless service
- result = service.new(@authentication_result.project, @authentication_result.actor, auth_params)
+ result = service.new(@authentication_result.project, auth_user, auth_params)
.execute(authentication_abilities: @authentication_result.authentication_abilities)
render json: result, status: result[:http_status]
@@ -67,7 +67,7 @@ class JwtController < ApplicationController
end
def additional_params
- { scopes: scopes_param }.compact
+ { scopes: scopes_param, deploy_token: @authentication_result.deploy_token }.compact
end
# We have to parse scope here, because Docker Client does not send an array of scopes,
@@ -83,8 +83,7 @@ class JwtController < ApplicationController
def auth_user
strong_memoize(:auth_user) do
- actor = @authentication_result&.actor
- actor.is_a?(User) ? actor : nil
+ @authentication_result.auth_user
end
end
end
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index e2f8baa8226..effd3514c1b 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -57,6 +57,8 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
@codes = user.generate_otp_backup_codes!
end
+ helpers.dismiss_account_recovery_regular_check
+
render 'create'
else
@error = _('Invalid pin code')
@@ -105,6 +107,8 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
def codes
Users::UpdateService.new(current_user, user: current_user).execute! do |user|
@codes = user.generate_otp_backup_codes!
+
+ helpers.dismiss_account_recovery_regular_check
end
end
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 505608779ec..6cc602fec88 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -128,6 +128,7 @@ class ProfilesController < Profiles::ApplicationController
:timezone,
:job_title,
:pronouns,
+ :pronunciation,
status: [:emoji, :message, :availability]
)
end
diff --git a/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb b/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb
index 7b4f6739a9b..2f9d70fede1 100644
--- a/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb
+++ b/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb
@@ -1,6 +1,9 @@
# frozen_string_literal: true
class Projects::Analytics::CycleAnalytics::StagesController < Projects::ApplicationController
+ include ::Analytics::CycleAnalytics::StageActions
+ extend ::Gitlab::Utils::Override
+
respond_to :json
feature_category :planning_analytics
@@ -8,37 +11,19 @@ class Projects::Analytics::CycleAnalytics::StagesController < Projects::Applicat
before_action :authorize_read_cycle_analytics!
before_action :only_default_value_stream_is_allowed!
- def index
- result = list_service.execute
-
- if result.success?
- render json: cycle_analytics_configuration(result.payload[:stages])
- else
- render json: { message: result.message }, status: result.http_status
- end
- end
-
private
- def only_default_value_stream_is_allowed!
- render_404 if params[:value_stream_id] != Analytics::CycleAnalytics::Stages::BaseService::DEFAULT_VALUE_STREAM_NAME
+ override :parent
+ def parent
+ @project
end
- def value_stream
- Analytics::CycleAnalytics::ProjectValueStream.build_default_value_stream(@project)
+ override :value_stream_class
+ def value_stream_class
+ Analytics::CycleAnalytics::ProjectValueStream
end
- def list_params
- { value_stream: value_stream }
- end
-
- def list_service
- Analytics::CycleAnalytics::Stages::ListService.new(parent: @project, current_user: current_user, params: list_params)
- end
-
- def cycle_analytics_configuration(stages)
- stage_presenters = stages.map { |s| ::Analytics::CycleAnalytics::StagePresenter.new(s) }
-
- Analytics::CycleAnalytics::ConfigurationEntity.new(stages: stage_presenters)
+ def only_default_value_stream_is_allowed!
+ render_404 if params[:value_stream_id] != Analytics::CycleAnalytics::Stages::BaseService::DEFAULT_VALUE_STREAM_NAME
end
end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 08066acb45c..acf6b6116b8 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -44,6 +44,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
push_frontend_feature_flag(:consolidated_edit_button, @project, default_enabled: :yaml)
+ push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
end
def new
diff --git a/app/controllers/projects/clusters/applications_controller.rb b/app/controllers/projects/clusters/applications_controller.rb
deleted file mode 100644
index 6c5778124e8..00000000000
--- a/app/controllers/projects/clusters/applications_controller.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class Projects::Clusters::ApplicationsController < Clusters::ApplicationsController
- prepend_before_action :project
-
- private
-
- def clusterable
- @clusterable ||= ClusterablePresenter.fabricate(project, current_user: current_user)
- end
-
- def project
- @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), request.path_info)
- end
-end
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index edf45e7063a..99f62c18593 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -20,10 +20,6 @@ class Projects::CompareController < Projects::ApplicationController
# Validation
before_action :validate_refs!
- before_action do
- push_frontend_feature_flag(:compare_repo_dropdown, source_project, default_enabled: :yaml)
- end
-
feature_category :source_code_management
# Diffs may be pretty chunky, the less is better in this endpoint.
@@ -91,7 +87,6 @@ class Projects::CompareController < Projects::ApplicationController
def target_project
strong_memoize(:target_project) do
next source_project unless params.key?(:from_project_id)
- next source_project unless Feature.enabled?(:compare_repo_dropdown, source_project, default_enabled: :yaml)
next source_project if params[:from_project_id].to_i == source_project.id
target_project = target_projects(source_project).find_by_id(params[:from_project_id])
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index 8519841ee16..cac0aa9d513 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -87,17 +87,17 @@ class Projects::EnvironmentsController < Projects::ApplicationController
@environment = project.environments.create(environment_params)
if @environment.persisted?
- redirect_to project_environment_path(project, @environment)
+ render json: { environment: @environment, path: project_environment_path(project, @environment) }
else
- render :new
+ render json: { message: @environment.errors.full_messages }, status: :bad_request
end
end
def update
if @environment.update(environment_params)
- redirect_to project_environment_path(project, @environment)
+ render json: { environment: @environment, path: project_environment_path(project, @environment) }
else
- render :edit
+ render json: { message: @environment.errors.full_messages }, status: :bad_request
end
end
diff --git a/app/controllers/projects/error_tracking_controller.rb b/app/controllers/projects/error_tracking_controller.rb
index b4b03e219ab..8700d3c2198 100644
--- a/app/controllers/projects/error_tracking_controller.rb
+++ b/app/controllers/projects/error_tracking_controller.rb
@@ -27,7 +27,7 @@ class Projects::ErrorTrackingController < Projects::ErrorTracking::BaseControlle
end
def update
- service = ErrorTracking::IssueUpdateService.new(project, current_user, issue_update_params)
+ service = ::ErrorTracking::IssueUpdateService.new(project, current_user, issue_update_params)
result = service.execute
return if render_errors(result)
@@ -40,7 +40,7 @@ class Projects::ErrorTrackingController < Projects::ErrorTracking::BaseControlle
private
def render_index_json
- service = ErrorTracking::ListIssuesService.new(
+ service = ::ErrorTracking::ListIssuesService.new(
project,
current_user,
list_issues_params
@@ -57,7 +57,7 @@ class Projects::ErrorTrackingController < Projects::ErrorTracking::BaseControlle
end
def render_issue_detail_json
- service = ErrorTracking::IssueDetailsService.new(project, current_user, issue_details_params)
+ service = ::ErrorTracking::IssueDetailsService.new(project, current_user, issue_details_params)
result = service.execute
return if render_errors(result)
@@ -91,13 +91,13 @@ class Projects::ErrorTrackingController < Projects::ErrorTracking::BaseControlle
end
def serialize_errors(errors)
- ErrorTracking::ErrorSerializer
+ ::ErrorTracking::ErrorSerializer
.new(project: project, user: current_user)
.represent(errors)
end
def serialize_detailed_error(error)
- ErrorTracking::DetailedErrorSerializer
+ ::ErrorTracking::DetailedErrorSerializer
.new(project: project, user: current_user)
.represent(error)
end
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 0f00fda4687..7135c0d959e 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -99,7 +99,7 @@ class Projects::ForksController < Projects::ApplicationController
current_user: current_user
).execute
- forks.includes(:route, :creator, :group, namespace: [:route, :owner])
+ forks.includes(:route, :creator, :group, :topics, namespace: [:route, :owner])
end
def fork_service
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 5d38e431c8a..bdfaaf2b143 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -7,7 +7,6 @@ class Projects::IssuesController < Projects::ApplicationController
include ToggleAwardEmoji
include IssuableCollections
include IssuesCalendar
- include SpammableActions
include RecordUserLastActivity
ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze
@@ -58,7 +57,7 @@ class Projects::IssuesController < Projects::ApplicationController
push_frontend_feature_flag(:labels_widget, @project, default_enabled: :yaml)
experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
- experiment_instance.exclude! unless helpers.can_import_members?
+ experiment_instance.exclude! unless helpers.can_admin_project_member?(@project)
experiment_instance.use {}
experiment_instance.try(:invite_member_link) {}
@@ -129,7 +128,6 @@ class Projects::IssuesController < Projects::ApplicationController
end
def create
- extract_legacy_spam_params_to_headers
create_params = issue_params.merge(
merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of],
discussion_to_resolve: params[:discussion_to_resolve]
@@ -149,10 +147,11 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
- respond_to do |format|
- format.html do
- recaptcha_check_with_fallback { render :new }
- end
+ if @issue.valid?
+ redirect_to project_issue_path(@project, @issue)
+ else
+ # NOTE: this CAPTCHA support method is indirectly included via IssuableActions
+ with_captcha_check_html_format { render :new }
end
end
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index 49687a50ff6..778623a05c6 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -9,7 +9,7 @@ class Projects::JobsController < Projects::ApplicationController
before_action :authorize_read_build_trace!, only: [:trace, :raw]
before_action :authorize_read_build!
before_action :authorize_update_build!,
- except: [:index, :show, :status, :raw, :trace, :erase]
+ except: [:index, :show, :status, :raw, :trace, :erase, :cancel, :unschedule]
before_action :authorize_erase_build!, only: [:erase]
before_action :authorize_use_build_terminal!, only: [:terminal, :terminal_websocket_authorize]
before_action :verify_api_request!, only: :terminal_websocket_authorize
@@ -93,22 +93,28 @@ class Projects::JobsController < Projects::ApplicationController
end
def cancel
- return respond_422 unless @build.cancelable?
+ service_response = Ci::BuildCancelService.new(@build, current_user).execute
- @build.cancel
-
- if continue_params[:to]
- redirect_to continue_params[:to]
+ if service_response.success?
+ destination = continue_params[:to].presence || builds_project_pipeline_path(@project, @build.pipeline.id)
+ redirect_to destination
+ elsif service_response.http_status == :forbidden
+ access_denied!
else
- redirect_to builds_project_pipeline_path(@project, @build.pipeline.id)
+ head service_response.http_status
end
end
def unschedule
- return respond_422 unless @build.scheduled?
+ service_response = Ci::BuildUnscheduleService.new(@build, current_user).execute
- @build.unschedule!
- redirect_to build_path(@build)
+ if service_response.success?
+ redirect_to build_path(@build)
+ elsif service_response.http_status == :forbidden
+ access_denied!
+ else
+ head service_response.http_status
+ end
end
def status
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index 9f1e2d8236a..ecc5ad1f84e 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -10,10 +10,6 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
before_action :apply_diff_view_cookie!, only: [:diffs, :diff_for_path]
before_action :build_merge_request, except: [:create]
- before_action do
- push_frontend_feature_flag(:mr_collapsed_approval_rules, @project)
- end
-
def new
define_new_vars
end
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index 88423bec915..8ccc658dfe7 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -27,10 +27,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
diff_options_hash[:paths] = params[:paths] if params[:paths]
diffs = @compare.diffs_in_batch(params[:page], params[:per_page], diff_options: diff_options_hash)
- positions = @merge_request.note_positions_for_paths(diffs.diff_file_paths, current_user)
+ unfoldable_positions = @merge_request.note_positions_for_paths(diffs.diff_file_paths, current_user).unfoldable
environment = @merge_request.environments_for(current_user, latest: true).last
- diffs.unfold_diff_files(positions.unfoldable)
+ diffs.unfold_diff_files(unfoldable_positions)
diffs.write_cache
options = {
@@ -38,14 +38,29 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
merge_request: @merge_request,
diff_view: diff_view,
merge_ref_head_diff: render_merge_ref_head_diff?,
- pagination_data: diffs.pagination_data
+ pagination_data: diffs.pagination_data,
+ allow_tree_conflicts: display_merge_conflicts_in_diff?
}
if diff_options_hash[:paths].blank? && Feature.enabled?(:diffs_batch_render_cached, project, default_enabled: :yaml)
+ # NOTE: Any variables that would affect the resulting json needs to be added to the cache_context to avoid stale cache issues.
+ cache_context = [
+ current_user&.cache_key,
+ environment&.cache_key,
+ unfoldable_positions.map(&:to_h),
+ diff_view,
+ params[:w],
+ params[:expanded],
+ params[:page],
+ params[:per_page],
+ options[:merge_ref_head_diff],
+ options[:allow_tree_conflicts]
+ ]
+
render_cached(
diffs,
with: PaginatedDiffSerializer.new(current_user: current_user),
- cache_context: -> (_) { [diff_view, params[:w], params[:expanded], params[:per_page], params[:page]] },
+ cache_context: -> (_) { [Digest::SHA256.hexdigest(cache_context.to_s)] },
**options
)
else
@@ -56,8 +71,14 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
def diffs_metadata
diffs = @compare.diffs(diff_options)
+ options = additional_attributes.merge(
+ only_context_commits: show_only_context_commits?,
+ merge_ref_head_diff: render_merge_ref_head_diff?,
+ allow_tree_conflicts: display_merge_conflicts_in_diff?
+ )
+
render json: DiffsMetadataSerializer.new(project: @merge_request.project, current_user: current_user)
- .represent(diffs, additional_attributes.merge(only_context_commits: show_only_context_commits?))
+ .represent(diffs, options)
end
private
@@ -82,7 +103,8 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
options = additional_attributes.merge(
diff_view: "inline",
- merge_ref_head_diff: render_merge_ref_head_diff?
+ merge_ref_head_diff: render_merge_ref_head_diff?,
+ allow_tree_conflicts: display_merge_conflicts_in_diff?
)
if @merge_request.project.context_commits_enabled?
@@ -213,4 +235,8 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
.track_mr_diffs_single_file_action(merge_request: @merge_request, user: current_user)
end
+
+ def display_merge_conflicts_in_diff?
+ Feature.enabled?(:display_merge_conflicts_in_diff, @merge_request.project)
+ end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index cfa64bbc16d..8b3f2df69df 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -11,6 +11,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
include RecordUserLastActivity
include SourcegraphDecorator
include DiffHelper
+ include Gitlab::Cache::Helpers
skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv]
before_action :apply_diff_view_cookie!, only: [:show]
@@ -43,9 +44,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
# Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
push_frontend_feature_flag(:diff_settings_usage_data, default_enabled: :yaml)
+ push_frontend_feature_flag(:diff_searching_usage_data, @project, default_enabled: :yaml)
experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
- experiment_instance.exclude! unless helpers.can_import_members?
+ experiment_instance.exclude! unless helpers.can_admin_project_member?(@project)
experiment_instance.use {}
experiment_instance.try(:invite_member_link) {}
@@ -55,7 +57,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
before_action do
- push_frontend_feature_flag(:mr_collapsed_approval_rules, @project)
push_frontend_feature_flag(:show_relevant_approval_rule_approvers, @project, default_enabled: :yaml)
end
@@ -92,6 +93,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
end
+ # rubocop:disable Metrics/AbcSize
def show
close_merge_request_if_no_source_project
@@ -128,7 +130,21 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
format.json do
Gitlab::PollingInterval.set_header(response, interval: 10_000)
- render json: serializer.represent(@merge_request, serializer: params[:serializer])
+ if params[:serializer] == 'sidebar_extras' && Feature.enabled?(:merge_request_show_render_cached, @project, default_enabled: :yaml)
+ cache_context = [
+ params[:serializer],
+ current_user&.cache_key,
+ @merge_request.assignees.map(&:cache_key),
+ @merge_request.reviewers.map(&:cache_key)
+ ]
+
+ render_cached(@merge_request,
+ with: serializer,
+ cache_context: -> (_) { [Digest::SHA256.hexdigest(cache_context.to_s)] },
+ serializer: params[:serializer])
+ else
+ render json: serializer.represent(@merge_request, serializer: params[:serializer])
+ end
end
format.patch do
@@ -144,6 +160,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
end
end
+ # rubocop:enable Metrics/AbcSize
def commits
# Get context commits from repository
diff --git a/app/controllers/projects/packages/infrastructure_registry_controller.rb b/app/controllers/projects/packages/infrastructure_registry_controller.rb
index ee04cbb0062..4506a83634a 100644
--- a/app/controllers/projects/packages/infrastructure_registry_controller.rb
+++ b/app/controllers/projects/packages/infrastructure_registry_controller.rb
@@ -3,19 +3,14 @@
module Projects
module Packages
class InfrastructureRegistryController < Projects::ApplicationController
- before_action :verify_feature_enabled!
+ include PackagesAccess
+
feature_category :infrastructure_as_code
def show
@package = project.packages.find(params[:id])
@package_files = @package.package_files.recent
end
-
- private
-
- def verify_feature_enabled!
- render_404 unless Feature.enabled?(:infrastructure_registry_page, default_enabled: :yaml)
- end
end
end
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index ba7c86434e0..a411264b350 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -12,12 +12,11 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_read_ci_cd_analytics!, only: [:charts]
before_action :authorize_create_pipeline!, only: [:new, :create, :config_variables]
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
+ before_action :ensure_pipeline, only: [:show, :downloadable_artifacts]
+
before_action do
- push_frontend_feature_flag(:pipeline_graph_layers_view, project, type: :development, default_enabled: :yaml)
- push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: :yaml)
- push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml)
+ push_frontend_feature_flag(:pipeline_source_filter, project, type: :development, default_enabled: :yaml)
end
- before_action :ensure_pipeline, only: [:show, :downloadable_artifacts]
# Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596
before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? }
@@ -32,10 +31,11 @@ class Projects::PipelinesController < Projects::ApplicationController
feature_category :continuous_integration, [
:charts, :show, :config_variables, :stage, :cancel, :retry,
- :builds, :dag, :failures, :status, :downloadable_artifacts,
+ :builds, :dag, :failures, :status,
:index, :create, :new, :destroy
]
feature_category :code_testing, [:test_report]
+ feature_category :build_artifacts, [:downloadable_artifacts]
def index
@pipelines = Ci::PipelinesFinder
@@ -68,20 +68,22 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def create
- @pipeline = Ci::CreatePipelineService
+ service_response = Ci::CreatePipelineService
.new(project, current_user, create_params)
.execute(:web, ignore_skip_ci: true, save_on_errors: false)
+ @pipeline = service_response.payload
+
respond_to do |format|
format.html do
- if @pipeline.created_successfully?
+ if service_response.success?
redirect_to project_pipeline_path(project, @pipeline)
else
render 'new', status: :bad_request
end
end
format.json do
- if @pipeline.created_successfully?
+ if service_response.success?
render json: PipelineSerializer
.new(project: project, current_user: current_user)
.represent(@pipeline),
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index 370cd2b02a1..d0987492d2d 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -23,7 +23,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
.new(@project, current_user, params: filter_params)
.execute(include_relations: requested_relations)
- if helpers.can_manage_project_members?(@project)
+ if can?(current_user, :admin_project_member, @project)
@invited_members = present_members(project_members.invite)
@requesters = present_members(AccessRequestsFinder.new(@project).execute(current_user))
end
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index 3fff93abe5c..e86d2490282 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -19,7 +19,7 @@ class Projects::RawController < Projects::ApplicationController
feature_category :source_code_management
def show
- @blob = @repository.blob_at(@ref, @path)
+ @blob = @repository.blob_at(@ref, @path, limit: Gitlab::Git::Blob::LFS_POINTER_MAX_SIZE)
send_blob(@repository, @blob, inline: (params[:inline] != 'false'), allow_caching: Guest.can?(:download_code, @project))
end
diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb
index fa6adc9431d..5da81045e02 100644
--- a/app/controllers/projects/runner_projects_controller.rb
+++ b/app/controllers/projects/runner_projects_controller.rb
@@ -5,7 +5,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController
layout 'project_settings'
- feature_category :continuous_integration
+ feature_category :runner
def create
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
diff --git a/app/controllers/projects/security/configuration_controller.rb b/app/controllers/projects/security/configuration_controller.rb
index 3a473bb67e0..19de157357a 100644
--- a/app/controllers/projects/security/configuration_controller.rb
+++ b/app/controllers/projects/security/configuration_controller.rb
@@ -7,10 +7,6 @@ module Projects
feature_category :static_application_security_testing
- before_action only: [:show] do
- push_frontend_feature_flag(:security_configuration_redesign, project, default_enabled: :yaml)
- end
-
def show
render_403 unless can?(current_user, :read_security_configuration, project)
end
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index ef6d96e8737..0dcaab7160b 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -8,6 +8,7 @@ class Projects::ServicesController < Projects::ApplicationController
before_action :authorize_admin_project!
before_action :ensure_service_enabled
before_action :integration
+ before_action :default_integration, only: [:edit, :update]
before_action :web_hook_logs, only: [:edit, :update]
before_action :set_deprecation_notice_for_prometheus_integration, only: [:edit, :update]
before_action :redirect_deprecated_prometheus_integration, only: [:update]
@@ -19,14 +20,22 @@ class Projects::ServicesController < Projects::ApplicationController
feature_category :integrations
def edit
- @default_integration = Integration.default_integration(service.type, project)
end
def update
- @integration.attributes = integration_params[:integration]
- @integration.inherit_from_id = nil if integration_params[:integration][:inherit_from_id].blank?
+ attributes = integration_params[:integration]
- saved = @integration.save(context: :manual_change)
+ if use_inherited_settings?(attributes)
+ @integration.inherit_from_id = default_integration.id
+
+ if saved = @integration.save(context: :manual_change)
+ BulkUpdateIntegrationService.new(default_integration, [@integration]).execute
+ end
+ else
+ attributes[:inherit_from_id] = nil
+ @integration.attributes = attributes
+ saved = @integration.save(context: :manual_change)
+ end
respond_to do |format|
format.html do
@@ -88,6 +97,10 @@ class Projects::ServicesController < Projects::ApplicationController
end
alias_method :service, :integration
+ def default_integration
+ @default_integration ||= Integration.default_integration(integration.type, project)
+ end
+
def web_hook_logs
return unless integration.service_hook.present?
@@ -115,4 +128,8 @@ class Projects::ServicesController < Projects::ApplicationController
message = s_('PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page have been deprecated.') % { operations_link_start: operations_link_start, operations_link_end: "</a>" }
flash.now[:alert] = message.html_safe
end
+
+ def use_inherited_settings?(attributes)
+ default_integration && attributes[:inherit_from_id] == default_integration.id.to_s
+ end
end
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index de2ab16b5b1..97f9c5814e2 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
class Projects::SnippetsController < Projects::Snippets::ApplicationController
+ extend ::Gitlab::Utils::Override
include SnippetsActions
include ToggleAwardEmoji
- include SpammableActions
+ include SpammableActions::AkismetMarkAsSpamAction
before_action :check_snippets_available!
@@ -45,4 +46,9 @@ class Projects::SnippetsController < Projects::Snippets::ApplicationController
def spammable_path
project_snippet_path(@project, @snippet)
end
+
+ override :snippet_find_params
+ def snippet_find_params
+ super.merge(project_id: project.id)
+ end
end
diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb
index df945a99c73..4bad6dc1b3d 100644
--- a/app/controllers/projects/templates_controller.rb
+++ b/app/controllers/projects/templates_controller.rb
@@ -5,7 +5,7 @@ class Projects::TemplatesController < Projects::ApplicationController
before_action :authorize_can_read_issuable!
before_action :get_template_class
- feature_category :templates
+ feature_category :source_code_management
def index
templates = @template_type.template_subsets(project)
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 0dbf7d40f87..bdb645e1934 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -31,10 +31,6 @@ class ProjectsController < Projects::ApplicationController
# Project Export Rate Limit
before_action :export_rate_limit, only: [:export, :download_export, :generate_new_export]
- before_action only: [:edit] do
- push_frontend_feature_flag(:allow_editing_commit_messages, @project)
- end
-
before_action do
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
push_frontend_feature_flag(:increase_page_size_exponentially, @project, default_enabled: :yaml)
@@ -74,11 +70,6 @@ class ProjectsController < Projects::ApplicationController
@project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute
if @project.saved?
- experiment(:new_project_readme, actor: current_user).track(
- :created,
- property: active_new_project_tab,
- value: project_params[:initialize_with_readme].to_i
- )
redirect_to(
project_path(@project, custom_import_params),
notice: _("Project '%{project_name}' was successfully created.") % { project_name: @project.name }
@@ -397,6 +388,7 @@ class ProjectsController < Projects::ApplicationController
analytics_access_level
operations_access_level
security_and_compliance_access_level
+ container_registry_access_level
]
end
@@ -404,7 +396,6 @@ class ProjectsController < Projects::ApplicationController
%i[
show_default_award_emojis
squash_option
- allow_editing_commit_messages
mr_default_target_self
]
end
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 303ee431a4d..ced21b8f291 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -16,7 +16,7 @@ module Registrations
result = ::Users::SignupService.new(current_user, update_params).execute
if result[:status] == :success
- return redirect_to new_users_sign_up_group_path if show_signup_onboarding?
+ return redirect_to new_users_sign_up_group_path(trial_params) if show_signup_onboarding?
members = current_user.members
@@ -41,7 +41,7 @@ module Registrations
end
def update_params
- params.require(:user).permit(:role, :other_role, :setup_for_company, :email_opted_in)
+ params.require(:user).permit(:role, :other_role, :setup_for_company)
end
def requires_confirmation?(user)
@@ -67,6 +67,10 @@ module Registrations
def show_signup_onboarding?
false
end
+
+ def trial_params
+ nil
+ end
end
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 7b1060eba8f..cc985e84542 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -199,7 +199,9 @@ class RegistrationsController < Devise::RegistrationsController
return unless member
- experiment('members/invite_email', actor: member).track(:accepted)
+ experiment_name = session.delete(:invite_email_experiment_name)
+ experiment(:invite_email_preview_text, actor: member).track(:accepted) if experiment_name == 'invite_email_preview_text'
+ Gitlab::Tracking.event(self.class.name, 'accepted', label: 'invite_email', property: member.id.to_s)
end
def context_user
diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb
index 76d9983d341..b3adda8c633 100644
--- a/app/controllers/repositories/git_http_client_controller.rb
+++ b/app/controllers/repositories/git_http_client_controller.rb
@@ -33,7 +33,7 @@ module Repositories
end
def authenticate_user
- @authentication_result = Gitlab::Auth::Result.new
+ @authentication_result = Gitlab::Auth::Result::EMPTY
if allow_basic_auth? && basic_auth_provided?
login, password = user_name_and_password(request)
diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb
index 4f2e02c78c3..a7719516cb6 100644
--- a/app/controllers/repositories/lfs_api_controller.rb
+++ b/app/controllers/repositories/lfs_api_controller.rb
@@ -10,6 +10,10 @@ module Repositories
skip_before_action :lfs_check_access!, only: [:deprecated]
before_action :lfs_check_batch_operation!, only: [:batch]
+ # added here as a part of the refactor, will be removed
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/328692
+ delegate :deploy_token, :user, to: :authentication_result, allow_nil: true
+
def batch
unless objects.present?
render_lfs_not_found
@@ -141,7 +145,7 @@ module Repositories
end
def lfs_auth_header
- return unless user.is_a?(User)
+ return unless user
Gitlab::LfsToken.new(user).basic_encoding
end
diff --git a/app/controllers/repositories/lfs_locks_api_controller.rb b/app/controllers/repositories/lfs_locks_api_controller.rb
index 19fc09ad4de..1d091a5bfcd 100644
--- a/app/controllers/repositories/lfs_locks_api_controller.rb
+++ b/app/controllers/repositories/lfs_locks_api_controller.rb
@@ -4,6 +4,10 @@ module Repositories
class LfsLocksApiController < Repositories::GitHttpClientController
include LfsRequest
+ # added here as a part of the refactor, will be removed
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/328692
+ delegate :deploy_token, :user, to: :authentication_result, allow_nil: true
+
def create
@result = Lfs::LockFileService.new(project, user, lfs_params).execute
diff --git a/app/controllers/repositories/lfs_storage_controller.rb b/app/controllers/repositories/lfs_storage_controller.rb
index 36912948b77..6ec63a0f939 100644
--- a/app/controllers/repositories/lfs_storage_controller.rb
+++ b/app/controllers/repositories/lfs_storage_controller.rb
@@ -8,6 +8,10 @@ module Repositories
skip_before_action :verify_workhorse_api!, only: :download
+ # added here as a part of the refactor, will be removed
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/328692
+ delegate :deploy_token, :user, to: :authentication_result, allow_nil: true
+
def download
lfs_object = LfsObject.find_by_oid(oid)
unless lfs_object && lfs_object.file.exists?
diff --git a/app/controllers/runner_setup_controller.rb b/app/controllers/runner_setup_controller.rb
index e0e9c5b7c23..89b635d5a6f 100644
--- a/app/controllers/runner_setup_controller.rb
+++ b/app/controllers/runner_setup_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class RunnerSetupController < ApplicationController
- feature_category :continuous_integration
+ feature_category :runner
def platforms
render json: Gitlab::Ci::RunnerInstructions::OS.merge(Gitlab::Ci::RunnerInstructions::OTHER_ENVIRONMENTS)
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 4160b528301..dbddb35d358 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -5,6 +5,8 @@ class SearchController < ApplicationController
include SearchHelper
include RedisTracking
+ RESCUE_FROM_TIMEOUT_ACTIONS = [:count, :show].freeze
+
track_redis_hll_event :show, name: 'i_search_total'
around_action :allow_gitaly_ref_name_caching
@@ -37,6 +39,7 @@ class SearchController < ApplicationController
@search_service = Gitlab::View::Presenter::Factory.new(search_service, current_user: current_user).fabricate!
@scope = @search_service.scope
+ @without_count = @search_service.without_count?
@show_snippets = @search_service.show_snippets?
@search_results = @search_service.search_results
@search_objects = @search_service.search_objects
@@ -154,12 +157,21 @@ class SearchController < ApplicationController
end
def render_timeout(exception)
- raise exception unless action_name.to_sym == :show
+ raise exception unless action_name.to_sym.in?(RESCUE_FROM_TIMEOUT_ACTIONS)
log_exception(exception)
@timeout = true
- render status: :request_timeout
+
+ if count_action_name?
+ render json: {}, status: :request_timeout
+ else
+ render status: :request_timeout
+ end
+ end
+
+ def count_action_name?
+ action_name.to_sym == :count
end
end
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index 1c6168dbc2c..e81868faa6e 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -4,7 +4,7 @@ class SnippetsController < Snippets::ApplicationController
include SnippetsActions
include PreviewMarkdown
include ToggleAwardEmoji
- include SpammableActions
+ include SpammableActions::AkismetMarkAsSpamAction
before_action :snippet, only: [:show, :edit, :raw, :toggle_award_emoji, :mark_as_spam]