diff options
Diffstat (limited to 'app/controllers')
79 files changed, 594 insertions, 258 deletions
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 7c6a444ce7a..646a6dffd10 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -11,11 +11,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController # https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30233 before_action :set_application_setting, except: :integrations - before_action :whitelist_query_limiting, only: [:usage_data] - - before_action only: [:ci_cd] do - push_frontend_feature_flag(:ci_instance_variables_ui, default_enabled: true) - end + before_action :disable_query_limiting, only: [:usage_data] feature_category :not_owned, [ :general, :reporting, :metrics_and_profiling, :network, @@ -194,8 +190,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController @plans = Plan.all end - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/63107') + def disable_query_limiting + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/29418') end def application_setting_params diff --git a/app/controllers/admin/clusters/integrations_controller.rb b/app/controllers/admin/clusters/integrations_controller.rb new file mode 100644 index 00000000000..d163ae7368d --- /dev/null +++ b/app/controllers/admin/clusters/integrations_controller.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class Admin::Clusters::IntegrationsController < Clusters::IntegrationsController + include EnforcesAdminAuthentication + + private + + def clusterable + @clusterable ||= InstanceClusterablePresenter.fabricate(Clusters::Instance.new, current_user: current_user) + end +end diff --git a/app/controllers/admin/dev_ops_report_controller.rb b/app/controllers/admin/dev_ops_report_controller.rb index 4ebc643be33..4178e51fb13 100644 --- a/app/controllers/admin/dev_ops_report_controller.rb +++ b/app/controllers/admin/dev_ops_report_controller.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true class Admin::DevOpsReportController < Admin::ApplicationController - include Analytics::UniqueVisitsHelper + include RedisTracking helper_method :show_adoption? - track_unique_visits :show, target_id: 'i_analytics_dev_ops_score' + track_redis_hll_event :show, name: 'i_analytics_dev_ops_score', if: -> { should_track_devops_score? } feature_category :devops_reports @@ -18,6 +18,10 @@ class Admin::DevOpsReportController < Admin::ApplicationController def show_adoption? false end + + def should_track_devops_score? + true + end end Admin::DevOpsReportController.prepend_if_ee('EE::Admin::DevOpsReportController') diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 0a1c85eef3f..e14cfc236cf 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -30,9 +30,11 @@ class Admin::GroupsController < Admin::ApplicationController def new @group = Group.new + @group.build_admin_note end def edit + @group.build_admin_note unless @group.admin_note end def create @@ -49,6 +51,8 @@ class Admin::GroupsController < Admin::ApplicationController end def update + @group.build_admin_note unless @group.admin_note + if @group.update(group_params) redirect_to [:admin, @group], notice: _('Group was successfully updated.') else @@ -58,7 +62,7 @@ class Admin::GroupsController < Admin::ApplicationController def members_update member_params = params.permit(:user_ids, :access_level, :expires_at) - result = Members::CreateService.new(current_user, member_params.merge(limit: -1)).execute(@group) + result = Members::CreateService.new(current_user, member_params.merge(limit: -1, source: @group)).execute if result[:status] == :success redirect_to [:admin, @group], notice: _('Users were successfully added.') @@ -105,7 +109,10 @@ class Admin::GroupsController < Admin::ApplicationController :require_two_factor_authentication, :two_factor_grace_period, :project_creation_level, - :subgroup_creation_level + :subgroup_creation_level, + admin_note_attributes: [ + :note + ] ] end end diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb index 379e74bb249..9f951e838c8 100644 --- a/app/controllers/admin/services_controller.rb +++ b/app/controllers/admin/services_controller.rb @@ -4,12 +4,12 @@ class Admin::ServicesController < Admin::ApplicationController include ServiceParams before_action :service, only: [:edit, :update] - before_action :whitelist_query_limiting, only: [:index] + before_action :disable_query_limiting, only: [:index] feature_category :integrations def index - @services = Service.find_or_create_templates.sort_by(&:title) + @activated_services = Service.for_template.active.sort_by(&:title) @existing_instance_types = Service.for_instance.pluck(:type) # rubocop: disable CodeReuse/ActiveRecord end @@ -39,7 +39,7 @@ class Admin::ServicesController < Admin::ApplicationController end # rubocop: enable CodeReuse/ActiveRecord - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/220357') + 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 d0761083c8b..8a090c8ef10 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -13,7 +13,7 @@ class Admin::UsersController < Admin::ApplicationController def index @users = User.filter_items(params[:filter]).order_name_asc @users = @users.search_with_secondary_emails(params[:search_query]) if params[:search_query].present? - @users = @users.includes(:authorized_projects) # rubocop: disable CodeReuse/ActiveRecord + @users = users_with_included_associations(@users) @users = @users.sort_by_attribute(@sort = params[:sort]) @users = @users.page(params[:page]) @@ -228,6 +228,10 @@ class Admin::UsersController < Admin::ApplicationController protected + def users_with_included_associations(users) + users.includes(:authorized_projects) # rubocop: disable CodeReuse/ActiveRecord + end + def admin_making_changes_for_another_user? user != current_user end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 379da90827a..607f3435394 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -16,7 +16,6 @@ class ApplicationController < ActionController::Base include SessionlessAuthentication include SessionsHelper include ConfirmEmailWarning - include Gitlab::Tracking::ControllerConcern include Gitlab::Experimentation::ControllerConcern include InitializesCurrentUserMode include Impersonation @@ -463,7 +462,7 @@ class ApplicationController < ActionController::Base feature_category: feature_category) do yield ensure - @current_context = Labkit::Context.current.to_h + @current_context = Gitlab::ApplicationContext.current end end @@ -483,7 +482,7 @@ class ApplicationController < ActionController::Base end def set_current_admin(&block) - return yield unless Feature.enabled?(:user_mode_in_session) + return yield unless Gitlab::CurrentSettings.admin_mode return yield unless current_user Gitlab::Auth::CurrentUserMode.with_current_admin(current_user, &block) diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb index f5a9b9b61db..347bf1f4fa8 100644 --- a/app/controllers/boards/issues_controller.rb +++ b/app/controllers/boards/issues_controller.rb @@ -13,7 +13,7 @@ module Boards requires_cross_project_access if: -> { board&.group_board? } - before_action :whitelist_query_limiting, only: [:bulk_move] + before_action :disable_query_limiting, only: [:bulk_move] before_action :authorize_read_issue, only: [:index] before_action :authorize_create_issue, only: [:create] before_action :authorize_update_issue, only: [:update] @@ -147,8 +147,8 @@ module Boards serializer.represent(resource, opts) end - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/35174') + def disable_query_limiting + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/issues/35174') end def validate_id_list diff --git a/app/controllers/chaos_controller.rb b/app/controllers/chaos_controller.rb index 0ec6a2cb38a..1cfcd2905f2 100644 --- a/app/controllers/chaos_controller.rb +++ b/app/controllers/chaos_controller.rb @@ -20,7 +20,11 @@ class ChaosController < ActionController::Base end def kill - do_chaos :kill, Chaos::KillWorker + do_chaos :kill, Chaos::KillWorker, 'KILL' + end + + def quit + do_chaos :kill, Chaos::KillWorker, 'QUIT' end def gc diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index 9800d94964d..c64301f72ba 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -60,6 +60,9 @@ class Clusters::ClustersController < Clusters::BaseController end def show + if params[:tab] == 'integrations' + @prometheus_integration = Clusters::IntegrationPresenter.new(@cluster.find_or_build_integration_prometheus) + end end def update @@ -305,7 +308,8 @@ class Clusters::ClustersController < Clusters::BaseController def proxy_variable_substitution_service @empty_service ||= Class.new(BaseService) do def initialize(proxyable, params) - @proxyable, @params = proxyable, params + @proxyable = proxyable + @params = params end def execute diff --git a/app/controllers/clusters/integrations_controller.rb b/app/controllers/clusters/integrations_controller.rb new file mode 100644 index 00000000000..a8c7eb10136 --- /dev/null +++ b/app/controllers/clusters/integrations_controller.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Clusters + class IntegrationsController < ::Clusters::BaseController + before_action :cluster + before_action :authorize_admin_cluster!, only: [:create_or_update] + + def create_or_update + service_response = Clusters::Integrations::CreateService + .new(container: clusterable, cluster: cluster, current_user: current_user, params: cluster_integration_params) + .execute + + if service_response.success? + redirect_to cluster.show_path(params: { tab: 'integrations' }), notice: service_response.message + else + redirect_to cluster.show_path(params: { tab: 'integrations' }), alert: service_response.message + end + end + + private + + def clusterable + raise NotImplementedError + end + + def cluster_integration_params + params.require(:integration).permit(:application_type, :enabled) + end + + def cluster + @cluster ||= clusterable.clusters.find(params[:cluster_id]).present(current_user: current_user) + end + end +end diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb index 5c74d79951f..87555a28eb8 100644 --- a/app/controllers/concerns/authenticates_with_two_factor.rb +++ b/app/controllers/concerns/authenticates_with_two_factor.rb @@ -70,7 +70,7 @@ module AuthenticatesWithTwoFactor elsif !user.confirmed? I18n.t('devise.failure.unconfirmed') else - _('Invalid Login or password') + _('Invalid login or password') end end diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index e8e681ce649..7bfcda67aa2 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -5,19 +5,23 @@ module CreatesCommit include Gitlab::Utils::StrongMemoize # rubocop:disable Gitlab/ModuleWithInstanceVariables - def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil) - if user_access(@project).can_push_to_branch?(branch_name_or_ref) - @project_to_commit_into = @project + def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil, target_project: nil) + target_project ||= @project + + if user_access(target_project).can_push_to_branch?(branch_name_or_ref) + @project_to_commit_into = target_project @branch_name ||= @ref else - @project_to_commit_into = current_user.fork_of(@project) + @project_to_commit_into = current_user.fork_of(target_project) @branch_name ||= @project_to_commit_into.repository.next_branch('patch') end @start_branch ||= @ref || @branch_name + start_project = Feature.enabled?(:pick_into_project, @project, default_enabled: :yaml) ? @project_to_commit_into : @project + commit_params = @commit_params.merge( - start_project: @project, + start_project: start_project, start_branch: @start_branch, branch_name: @branch_name ) @@ -27,7 +31,7 @@ module CreatesCommit if result[:status] == :success update_flash_notice(success_notice) - success_path = final_success_path(success_path) + success_path = final_success_path(success_path, target_project) respond_to do |format| format.html { redirect_to success_path } @@ -79,9 +83,9 @@ module CreatesCommit end end - def final_success_path(success_path) + def final_success_path(success_path, target_project) if create_merge_request? - merge_request_exists? ? existing_merge_request_path : new_merge_request_path + merge_request_exists? ? existing_merge_request_path : new_merge_request_path(target_project) else success_path = success_path.call if success_path.respond_to?(:call) @@ -90,12 +94,12 @@ module CreatesCommit end # rubocop:disable Gitlab/ModuleWithInstanceVariables - def new_merge_request_path + def new_merge_request_path(target_project) project_new_merge_request_path( @project_to_commit_into, merge_request: { source_project_id: @project_to_commit_into.id, - target_project_id: @project.id, + target_project_id: target_project.id, source_branch: @branch_name, target_branch: @start_branch } diff --git a/app/controllers/concerns/enforces_admin_authentication.rb b/app/controllers/concerns/enforces_admin_authentication.rb index 527759de0bb..94c0e98c91a 100644 --- a/app/controllers/concerns/enforces_admin_authentication.rb +++ b/app/controllers/concerns/enforces_admin_authentication.rb @@ -15,7 +15,7 @@ module EnforcesAdminAuthentication def authenticate_admin! return render_404 unless current_user.admin? - return unless Feature.enabled?(:user_mode_in_session) + return unless Gitlab::CurrentSettings.admin_mode unless current_user_mode.admin_mode? current_user_mode.request_admin_mode! diff --git a/app/controllers/concerns/labels_as_hash.rb b/app/controllers/concerns/labels_as_hash.rb index 1171aa9cf44..e428520f709 100644 --- a/app/controllers/concerns/labels_as_hash.rb +++ b/app/controllers/concerns/labels_as_hash.rb @@ -11,7 +11,7 @@ module LabelsAsHash label_hashes = available_labels.as_json(only: [:title, :color]) - if target&.respond_to?(:labels) + if target.respond_to?(:labels) already_set_labels = available_labels & target.labels if already_set_labels.present? titles = already_set_labels.map(&:title) diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb index 9e3625d1b36..7bbee8ba79e 100644 --- a/app/controllers/concerns/membership_actions.rb +++ b/app/controllers/concerns/membership_actions.rb @@ -6,7 +6,7 @@ module MembershipActions def create create_params = params.permit(:user_ids, :access_level, :expires_at) - result = Members::CreateService.new(current_user, create_params).execute(membershipable) + result = Members::CreateService.new(current_user, create_params.merge({ source: membershipable })).execute if result[:status] == :success redirect_to members_page_url, notice: _('Users were successfully added.') @@ -43,10 +43,11 @@ module MembershipActions def destroy member = membershipable.members_and_requesters.find(params[:id]) + skip_subresources = !ActiveRecord::Type::Boolean.new.cast(params.delete(:remove_sub_memberships)) # !! is used in case unassign_issuables contains empty string which would result in nil unassign_issuables = !!ActiveRecord::Type::Boolean.new.cast(params.delete(:unassign_issuables)) - Members::DestroyService.new(current_user).execute(member, unassign_issuables: unassign_issuables) + Members::DestroyService.new(current_user).execute(member, skip_subresources: skip_subresources, unassign_issuables: unassign_issuables) respond_to do |format| format.html do @@ -54,7 +55,11 @@ module MembershipActions begin case membershipable when Namespace - _("User was successfully removed from group and any subresources.") + if skip_subresources + _("User was successfully removed from group.") + else + _("User was successfully removed from group and any subgroups and projects.") + end else _("User was successfully removed from project.") end diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb index 6470c75dfbd..0a859bd3af9 100644 --- a/app/controllers/concerns/milestone_actions.rb +++ b/app/controllers/concerns/milestone_actions.rb @@ -20,7 +20,7 @@ module MilestoneActions format.html { redirect_to milestone_redirect_path } format.json do render json: tabs_json("shared/milestones/_merge_requests_tab", { - merge_requests: @milestone.sorted_merge_requests(current_user), # rubocop:disable Gitlab/ModuleWithInstanceVariables + merge_requests: @milestone.sorted_merge_requests(current_user).preload_milestoneish_associations, # rubocop:disable Gitlab/ModuleWithInstanceVariables show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name]) }) end diff --git a/app/controllers/concerns/redis_tracking.rb b/app/controllers/concerns/redis_tracking.rb index a7e75f802a8..3155208f47c 100644 --- a/app/controllers/concerns/redis_tracking.rb +++ b/app/controllers/concerns/redis_tracking.rb @@ -10,26 +10,31 @@ # track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score' # # You can also pass custom conditions using `if:`, using the same format as with Rails callbacks. +# You can also pass an optional block that calculates and returns a custom id to track. module RedisTracking extend ActiveSupport::Concern class_methods do - def track_redis_hll_event(*controller_actions, name:, if: nil) + def track_redis_hll_event(*controller_actions, name:, if: nil, &block) custom_conditions = Array.wrap(binding.local_variable_get('if')) conditions = [:trackable_request?, *custom_conditions] after_action only: controller_actions, if: conditions do - track_unique_redis_hll_event(name) + track_unique_redis_hll_event(name, &block) end end end private - def track_unique_redis_hll_event(event_name) - return unless visitor_id + def track_unique_redis_hll_event(event_name, &block) + custom_id = block_given? ? yield(self) : nil - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: visitor_id) + unique_id = custom_id || visitor_id + + return unless unique_id + + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: unique_id) end def trackable_request? diff --git a/app/controllers/concerns/renders_commits.rb b/app/controllers/concerns/renders_commits.rb index 826fae834fa..4ea07c814ef 100644 --- a/app/controllers/concerns/renders_commits.rb +++ b/app/controllers/concerns/renders_commits.rb @@ -17,12 +17,13 @@ module RendersCommits def set_commits_for_rendering(commits, commits_count: nil) @total_commit_count = commits_count || commits.size limited, @hidden_commit_count = limited_commits(commits, @total_commit_count) - commits.each(&:lazy_author) # preload authors prepare_commits_for_rendering(limited) end # rubocop: enable Gitlab/ModuleWithInstanceVariables def prepare_commits_for_rendering(commits) + commits.each(&:lazy_author) # preload commits' authors + Banzai::CommitRenderer.render(commits, @project, current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables commits diff --git a/app/controllers/concerns/runner_setup_scripts.rb b/app/controllers/concerns/runner_setup_scripts.rb index c0e657a32d1..ccae15b824f 100644 --- a/app/controllers/concerns/runner_setup_scripts.rb +++ b/app/controllers/concerns/runner_setup_scripts.rb @@ -5,8 +5,8 @@ module RunnerSetupScripts private - def private_runner_setup_scripts(**kwargs) - instructions = Gitlab::Ci::RunnerInstructions.new(current_user: current_user, os: script_params[:os], arch: script_params[:arch], **kwargs) + def private_runner_setup_scripts + instructions = Gitlab::Ci::RunnerInstructions.new(os: script_params[:os], arch: script_params[:arch]) output = { install: instructions.install_script, register: instructions.register_command diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb index 3cab198c1f9..7c57d321c80 100644 --- a/app/controllers/concerns/service_params.rb +++ b/app/controllers/concerns/service_params.rb @@ -44,6 +44,8 @@ module ServiceParams # make those event names plural as special case. :issues_events, :issues_url, + :jenkins_url, + :jira_issue_transition_automatic, :jira_issue_transition_id, :manual_configuration, :merge_requests_events, @@ -55,6 +57,7 @@ module ServiceParams :password, :priority, :project_key, + :project_name, :project_url, :recipients, :restrict_to_branch, diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb index a9ef33bf3b9..882fef7a342 100644 --- a/app/controllers/concerns/sessionless_authentication.rb +++ b/app/controllers/concerns/sessionless_authentication.rb @@ -27,7 +27,7 @@ module SessionlessAuthentication end def sessionless_bypass_admin_mode!(&block) - return yield unless Feature.enabled?(:user_mode_in_session) + return yield unless Gitlab::CurrentSettings.admin_mode Gitlab::Auth::CurrentUserMode.bypass_session!(current_user.id, &block) end diff --git a/app/controllers/customers_dot/proxy_controller.rb b/app/controllers/customers_dot/proxy_controller.rb new file mode 100644 index 00000000000..5abf8a487c6 --- /dev/null +++ b/app/controllers/customers_dot/proxy_controller.rb @@ -0,0 +1,21 @@ +# 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/graphql_controller.rb b/app/controllers/graphql_controller.rb index 53064041ab8..a13ec1daddb 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -4,7 +4,8 @@ class GraphqlController < ApplicationController # Unauthenticated users have access to the API for public data skip_before_action :authenticate_user! - WHITELIST_HEADER = 'HTTP_X_GITLAB_QUERY_WHITELIST_ISSUE' + # Header can be passed by tests to disable SQL query limits. + DISABLE_SQL_QUERY_LIMIT_HEADER = 'HTTP_X_GITLAB_DISABLE_SQL_QUERY_LIMIT' # If a user is using their session to access GraphQL, we need to have session # storage, since the admin-mode check is session wide. @@ -23,7 +24,7 @@ class GraphqlController < ApplicationController before_action(only: [:execute]) { authenticate_sessionless_user!(:api) } before_action :set_user_last_activity before_action :track_vs_code_usage - before_action :whitelist_query! + before_action :disable_query_limiting # Since we deactivate authentication from the main ApplicationController and # defer it to :authorize_access_api!, we need to override the bypass session @@ -34,7 +35,6 @@ class GraphqlController < ApplicationController def execute result = multiplex? ? execute_multiplex : execute_query - render json: result end @@ -62,12 +62,14 @@ class GraphqlController < ApplicationController private - # Tests may mark some queries as exempt from query limits - def whitelist_query! - whitelist_issue = request.headers[WHITELIST_HEADER] - return unless whitelist_issue + # Tests may mark some GraphQL queries as exempt from SQL query limits + def disable_query_limiting + return unless Gitlab::QueryLimiting.enabled_for_env? + + disable_issue = request.headers[DISABLE_SQL_QUERY_LIMIT_HEADER] + return unless disable_issue - Gitlab::QueryLimiting.whitelist(whitelist_issue) + Gitlab::QueryLimiting.disable!(disable_issue) end def set_user_last_activity @@ -144,8 +146,7 @@ class GraphqlController < ApplicationController end def logs - RequestStore.store[:graphql_logs].to_h - .except(:duration_s, :query_string) - .merge(operation_name: params[:operationName]) + RequestStore.store[:graphql_logs].to_a + .map { |log| log.except(:duration_s, :query_string) } end end diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index 3354c0a5c9f..be38fe25842 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -9,7 +9,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(:boards_filtered_search, group) + push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml) end feature_category :boards diff --git a/app/controllers/groups/clusters/integrations_controller.rb b/app/controllers/groups/clusters/integrations_controller.rb new file mode 100644 index 00000000000..e8c8a14c164 --- /dev/null +++ b/app/controllers/groups/clusters/integrations_controller.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class Groups::Clusters::IntegrationsController < Clusters::IntegrationsController + 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]) + end +end diff --git a/app/controllers/groups/email_campaigns_controller.rb b/app/controllers/groups/email_campaigns_controller.rb index cbb0176ea7b..4ce7d86be3c 100644 --- a/app/controllers/groups/email_campaigns_controller.rb +++ b/app/controllers/groups/email_campaigns_controller.rb @@ -2,7 +2,6 @@ class Groups::EmailCampaignsController < Groups::ApplicationController include InProductMarketingHelper - include Gitlab::Tracking::ControllerConcern EMAIL_CAMPAIGNS_SCHEMA_URL = 'iglu:com.gitlab/email_campaigns/jsonschema/1-0-0' @@ -18,14 +17,19 @@ class Groups::EmailCampaignsController < Groups::ApplicationController private def track_click - data = { - namespace_id: group.id, - track: @track, - series: @series, - subject_line: subject_line(@track, @series) - } - - track_self_describing_event(EMAIL_CAMPAIGNS_SCHEMA_URL, data: data) + if Gitlab.com? + data = { + namespace_id: group.id, + track: @track.to_s, + series: @series, + subject_line: subject_line(@track, @series) + } + context = SnowplowTracker::SelfDescribingJson.new(EMAIL_CAMPAIGNS_SCHEMA_URL, data) + + ::Gitlab::Tracking.event(self.class.name, 'click', context: [context]) + else + ::Users::InProductMarketingEmail.save_cta_click(current_user, @track, @series) + end end def redirect_link diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb index c5dd3e1df35..86dde454cbc 100644 --- a/app/controllers/groups/labels_controller.rb +++ b/app/controllers/groups/labels_controller.rb @@ -16,7 +16,8 @@ class Groups::LabelsController < Groups::ApplicationController format.html do # at group level we do not want to list project labels, # we only want `only_group_labels = false` when pulling labels for label filter dropdowns, fetched through json - @labels = available_labels(params.merge(only_group_labels: true)).page(params[:page]) + @labels = available_labels(params.merge(only_group_labels: true)).page(params[:page]) # rubocop: disable CodeReuse/ActiveRecord + Preloaders::LabelsPreloader.new(@labels, current_user).preload_all end format.json do render json: LabelSerializer.new.represent_appearance(available_labels) diff --git a/app/controllers/groups/settings/applications_controller.rb b/app/controllers/groups/settings/applications_controller.rb new file mode 100644 index 00000000000..cefb5425867 --- /dev/null +++ b/app/controllers/groups/settings/applications_controller.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +module Groups + module Settings + class ApplicationsController < Groups::ApplicationController + include OauthApplications + + prepend_before_action :authorize_admin_group! + before_action :set_application, only: [:show, :edit, :update, :destroy] + before_action :load_scopes, only: [:index, :create, :edit, :update] + + feature_category :authentication_and_authorization + + def index + set_index_vars + end + + def show + end + + def edit + end + + def create + @application = Applications::CreateService.new(current_user, application_params).execute(request) + + if @application.persisted? + flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) + + redirect_to group_settings_application_url(@group, @application) + else + set_index_vars + render :index + end + end + + def update + if @application.update(application_params) + redirect_to group_settings_application_path(@group, @application), notice: _('Application was successfully updated.') + else + render :edit + end + end + + def destroy + @application.destroy + redirect_to group_settings_applications_url(@group), status: :found, notice: _('Application was successfully destroyed.') + end + + private + + def set_index_vars + # TODO: Remove limit(100) and implement pagination + # https://gitlab.com/gitlab-org/gitlab/-/issues/324187 + @applications = @group.oauth_applications.limit(100) + + # Don't overwrite a value possibly set by `create` + @application ||= Doorkeeper::Application.new + end + + def set_application + @application = @group.oauth_applications.find(params[:id]) + end + + def application_params + params + .require(:doorkeeper_application) + .permit(:name, :redirect_uri, :scopes, :confidential) + .tap do |params| + params[:owner] = @group + end + end + end + end +end diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index 723edc4b7e9..f1a6bcbe825 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -5,10 +5,12 @@ module Groups class CiCdController < Groups::ApplicationController include RunnerSetupScripts + layout 'group_settings' skip_cross_project_access_check :show before_action :authorize_admin_group! before_action :authorize_update_max_artifacts_size!, only: [:update] before_action :define_variables, only: [:show] + before_action :push_licensed_features, only: [:show] feature_category :continuous_integration @@ -51,7 +53,7 @@ module Groups end def runner_setup_scripts - private_runner_setup_scripts(group: group) + private_runner_setup_scripts end private @@ -90,6 +92,12 @@ module Groups def update_group_params params.require(:group).permit(:max_artifacts_size) end + + # Overridden in EE + def push_licensed_features + end end end end + +Groups::Settings::CiCdController.prepend_if_ee('EE::Groups::Settings::CiCdController') diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb index 8903feaff04..c3c93fe238a 100644 --- a/app/controllers/groups/settings/integrations_controller.rb +++ b/app/controllers/groups/settings/integrations_controller.rb @@ -9,6 +9,8 @@ module Groups feature_category :integrations + layout 'group_settings' + def index @integrations = Service.find_or_initialize_all_non_project_specific(Service.for_group(group)).sort_by(&:title) end diff --git a/app/controllers/groups/settings/packages_and_registries_controller.rb b/app/controllers/groups/settings/packages_and_registries_controller.rb index 0135c03026c..90fb6497e20 100644 --- a/app/controllers/groups/settings/packages_and_registries_controller.rb +++ b/app/controllers/groups/settings/packages_and_registries_controller.rb @@ -3,6 +3,7 @@ module Groups module Settings class PackagesAndRegistriesController < Groups::ApplicationController + layout 'group_settings' before_action :authorize_admin_group! before_action :verify_packages_enabled! diff --git a/app/controllers/groups/settings/repository_controller.rb b/app/controllers/groups/settings/repository_controller.rb index ccc1fa12458..7404075985b 100644 --- a/app/controllers/groups/settings/repository_controller.rb +++ b/app/controllers/groups/settings/repository_controller.rb @@ -3,6 +3,7 @@ module Groups module Settings class RepositoryController < Groups::ApplicationController + layout 'group_settings' skip_cross_project_access_check :show before_action :authorize_create_deploy_token! before_action :define_deploy_token_variables diff --git a/app/controllers/groups/shared_projects_controller.rb b/app/controllers/groups/shared_projects_controller.rb index 90ec64d4768..7acdacc2d46 100644 --- a/app/controllers/groups/shared_projects_controller.rb +++ b/app/controllers/groups/shared_projects_controller.rb @@ -25,13 +25,13 @@ module Groups def finder_params @finder_params ||= begin - # Make the `search` param consistent for the frontend, - # which will be using `filter`. - params[:search] ||= params[:filter] if params[:filter] - # Don't show archived projects - params[:non_archived] = true - params.permit(:sort, :search, :non_archived) - end + # Make the `search` param consistent for the frontend, + # which will be using `filter`. + params[:search] ||= params[:filter] if params[:filter] + # Don't show archived projects + params[:non_archived] = true + params.permit(:sort, :search, :non_archived) + end end end end diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb index a2289b540ec..75bb6975c6e 100644 --- a/app/controllers/groups/variables_controller.rb +++ b/app/controllers/groups/variables_controller.rb @@ -56,3 +56,5 @@ module Groups end end end + +Groups::VariablesController.prepend_if_ee('EE::Groups::VariablesController') diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 5de207857bb..63f138aa462 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -8,6 +8,7 @@ class GroupsController < Groups::ApplicationController include RecordUserLastActivity include SendFileUpload include FiltersEvents + include Recaptcha::Verify extend ::Gitlab::Utils::Override respond_to :html @@ -15,6 +16,7 @@ class GroupsController < Groups::ApplicationController prepend_before_action(only: [:show, :issues]) { authenticate_sessionless_user!(:rss) } prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) } prepend_before_action :ensure_export_enabled, only: [:export, :download_export] + prepend_before_action :check_captcha, only: :create, if: -> { captcha_enabled? } before_action :authenticate_user!, only: [:new, :create] before_action :group, except: [:index, :new, :create] @@ -22,6 +24,7 @@ class GroupsController < Groups::ApplicationController # Authorize before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects, :transfer, :export, :download_export] before_action :authorize_create_group!, only: [:new] + before_action :load_recaptcha, only: [:new], if: -> { captcha_required? } before_action :group_projects, only: [:projects, :activity, :issues, :merge_requests] before_action :event_filter, only: [:activity] @@ -38,6 +41,8 @@ class GroupsController < Groups::ApplicationController before_action :export_rate_limit, only: [:export, :download_export] + helper_method :captcha_required? + skip_cross_project_access_check :index, :new, :create, :edit, :update, :destroy, :projects # When loading show as an atom feed, we render events that could leak cross @@ -263,7 +268,8 @@ class GroupsController < Groups::ApplicationController :subgroup_creation_level, :default_branch_protection, :default_branch_name, - :allow_mfa_for_subgroups + :allow_mfa_for_subgroups, + :resource_access_token_creation_allowed ] end @@ -319,6 +325,23 @@ class GroupsController < Groups::ApplicationController private + def load_recaptcha + Gitlab::Recaptcha.load_configurations! + end + + def check_captcha + return if group_params[:parent_id].present? # Only require for top-level groups + + load_recaptcha + + return if verify_recaptcha + + flash[:alert] = _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.') + flash.delete :recaptcha_error + @group = Group.new(group_params) + render action: 'new' + end + def successful_creation_hooks; end def groups @@ -336,6 +359,14 @@ class GroupsController < Groups::ApplicationController def has_project_list? %w(details show index).include?(action_name) end + + def captcha_enabled? + Gitlab::Recaptcha.enabled? && Feature.enabled?(:recaptcha_on_top_level_group_creation, type: :ops) + end + + def captcha_required? + captcha_enabled? && !params[:parent_id] + end end GroupsController.prepend_if_ee('EE::GroupsController') diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb index ea67c76a8bc..4c7a91ee602 100644 --- a/app/controllers/ide_controller.rb +++ b/app/controllers/ide_controller.rb @@ -10,6 +10,7 @@ class IdeController < ApplicationController before_action do push_frontend_feature_flag(:build_service_proxy) push_frontend_feature_flag(:schema_linting) + push_frontend_feature_flag(:reject_unsigned_commits_by_gitlab, default_enabled: :yaml) define_index_vars end @@ -27,9 +28,20 @@ class IdeController < ApplicationController @branch = params[:branch] @path = params[:path] @merge_request = params[:merge_request_id] + @fork_info = fork_info(project, @branch) + end + + def fork_info(project, branch) + return if can?(current_user, :push_code, project) + + existing_fork = current_user.fork_of(project) - unless can?(current_user, :push_code, project) - @forked_project = ForkProjectsFinder.new(project, current_user: current_user).execute.first + if existing_fork + path = helpers.ide_edit_path(existing_fork, branch, '') + { ide_path: path } + elsif can?(current_user, :fork_project, project) + path = helpers.ide_fork_and_edit_path(project, branch, '', with_notice: false) + { fork_path: path } end end diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index 0e6b0af6baf..8de270e9d25 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -3,7 +3,7 @@ class Import::GitlabProjectsController < Import::BaseController include WorkhorseAuthorization - before_action :whitelist_query_limiting, only: [:create] + before_action :disable_query_limiting, only: [:create] before_action :verify_gitlab_project_import_enabled def new @@ -42,8 +42,8 @@ class Import::GitlabProjectsController < Import::BaseController ) end - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42437') + def disable_query_limiting + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20823') end def uploader_class diff --git a/app/controllers/import/manifest_controller.rb b/app/controllers/import/manifest_controller.rb index fdca6da95c5..8497e15c07c 100644 --- a/app/controllers/import/manifest_controller.rb +++ b/app/controllers/import/manifest_controller.rb @@ -3,7 +3,7 @@ class Import::ManifestController < Import::BaseController extend ::Gitlab::Utils::Override - before_action :whitelist_query_limiting, only: [:create] + before_action :disable_query_limiting, only: [:create] before_action :verify_import_enabled before_action :ensure_import_vars, only: [:create, :status] @@ -115,7 +115,7 @@ class Import::ManifestController < Import::BaseController render_404 unless manifest_import_enabled? end - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/48939') + def disable_query_limiting + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/23147') end end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 08a23dc8927..0eb08d2d0ad 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -91,15 +91,29 @@ class InvitesController < ApplicationController def authenticate_user! return if current_user - notice = ["To accept this invitation, sign in"] - notice << "or create an account" if Gitlab::CurrentSettings.allow_signup? - notice = notice.join(' ') + "." + store_location_for :user, request.fullpath - redirect_params = member ? { invite_email: member.invite_email } : {} + if user_sign_up? + redirect_to new_user_registration_path(invite_email: member.invite_email), notice: _("To accept this invitation, create an account or sign in.") + else + redirect_to new_user_session_path(sign_in_redirect_params), notice: sign_in_notice + end + end - store_location_for :user, request.fullpath + def sign_in_redirect_params + member ? { invite_email: member.invite_email } : {} + end + + def user_sign_up? + Gitlab::CurrentSettings.allow_signup? && member && !User.find_by_any_email(member.invite_email) + end - redirect_to new_user_session_path(redirect_params), notice: notice + def sign_in_notice + if Gitlab::CurrentSettings.allow_signup? + _("To accept this invitation, sign in or create an account.") + else + _("To accept this invitation, sign in.") + end end def invite_details diff --git a/app/controllers/ldap/omniauth_callbacks_controller.rb b/app/controllers/ldap/omniauth_callbacks_controller.rb index 4b6339c21cd..ebc35448964 100644 --- a/app/controllers/ldap/omniauth_callbacks_controller.rb +++ b/app/controllers/ldap/omniauth_callbacks_controller.rb @@ -16,7 +16,7 @@ class Ldap::OmniauthCallbacksController < OmniauthCallbacksController def ldap return unless Gitlab::Auth::Ldap::Config.sign_in_enabled? - if Feature.enabled?(:user_mode_in_session) + if Gitlab::CurrentSettings.admin_mode return admin_mode_flow(Gitlab::Auth::Ldap::User) if current_user_mode.admin_mode_requested? end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index c9791703413..af502c083d7 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -95,7 +95,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController end def after_omniauth_failure_path_for(scope) - if Feature.enabled?(:user_mode_in_session) + if Gitlab::CurrentSettings.admin_mode return new_admin_session_path if current_user_mode.admin_mode_requested? end @@ -112,7 +112,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController log_audit_event(current_user, with: oauth['provider']) - if Feature.enabled?(:user_mode_in_session) + if Gitlab::CurrentSettings.admin_mode return admin_mode_flow(auth_module::User) if current_user_mode.admin_mode_requested? end diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb index 0a73239709a..6ef0ed6d365 100644 --- a/app/controllers/profiles/notifications_controller.rb +++ b/app/controllers/profiles/notifications_controller.rb @@ -3,18 +3,13 @@ class Profiles::NotificationsController < Profiles::ApplicationController feature_category :users - # rubocop: disable CodeReuse/ActiveRecord def show @user = current_user @user_groups = user_groups @group_notifications = UserGroupNotificationSettingsFinder.new(current_user, user_groups).execute - - @project_notifications = current_user.notification_settings.for_projects.order(:id) - .preload_source_route - .select { |notification| current_user.can?(:read_project, notification.source) } + @project_notifications = project_notifications_with_preloaded_associations @global_notification_setting = current_user.global_notification_setting end - # rubocop: enable CodeReuse/ActiveRecord def update result = Users::UpdateService.new(current_user, user_params.merge(user: current_user)).execute @@ -37,4 +32,20 @@ class Profiles::NotificationsController < Profiles::ApplicationController def user_groups GroupsFinder.new(current_user, all_available: false).execute.order_name_asc.page(params[:page]) end + + # rubocop: disable CodeReuse/ActiveRecord + def project_notifications_with_preloaded_associations + project_notifications = current_user + .notification_settings + .for_projects + .order_by_id_asc + .preload_source_route + + projects = project_notifications.map(&:source) + ActiveRecord::Associations::Preloader.new.preload(projects, { namespace: [:route, :owner], group: [] }) + Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute + + project_notifications.select { |notification| current_user.can?(:read_project, notification.source) } + end + # rubocop: enable CodeReuse/ActiveRecord end diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb index d5de0d38152..2c7c49b4250 100644 --- a/app/controllers/projects/blame_controller.rb +++ b/app/controllers/projects/blame_controller.rb @@ -20,7 +20,7 @@ class Projects::BlameController < Projects::ApplicationController environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit } environment_params[:find_latest] = true - @environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last + @environment = EnvironmentsByDeploymentsFinder.new(@project, current_user, environment_params).execute.last @blame = Gitlab::Blame.new(@blob, @commit) @blame = Gitlab::View::Presenter::Factory.new(@blame, project: @project, path: @path).fabricate! diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 0080ae1a5be..a398fc56a35 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -214,7 +214,7 @@ class Projects::BlobController < Projects::ApplicationController def show_html environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit } environment_params[:find_latest] = true - @environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last + @environment = EnvironmentsByDeploymentsFinder.new(@project, current_user, environment_params).execute.last @last_commit = @repository.last_commit_for_path(@commit.id, @blob.path, literal_pathspec: true) @code_navigation_path = Gitlab::CodeNavigationPath.new(@project, @blob.commit_id).full_json_path_for(@blob.path) diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 418f2ee1592..349649c7b35 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -8,7 +8,8 @@ class Projects::BoardsController < Projects::ApplicationController before_action :authorize_read_board!, only: [:index, :show] before_action :assign_endpoint_vars before_action do - push_frontend_feature_flag(:add_issues_button) + push_frontend_feature_flag(:swimlanes_buffered_rendering, project, default_enabled: :yaml) + push_frontend_feature_flag(:graphql_board_lists, project, default_enabled: :yaml) end feature_category :boards diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 6f3c96fa654..f522dffdf3e 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -49,7 +49,7 @@ class Projects::BranchesController < Projects::ApplicationController branches = BranchesFinder.new(repository, params.permit(names: [])).execute Gitlab::GitalyClient.allow_n_plus_1_calls do - render json: branches.map { |branch| [branch.name, service.call(branch)] }.to_h + render json: branches.to_h { |branch| [branch.name, service.call(branch)] } end end end diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb index 4d491b33aa0..754e2ccf4f9 100644 --- a/app/controllers/projects/ci/pipeline_editor_controller.rb +++ b/app/controllers/projects/ci/pipeline_editor_controller.rb @@ -7,6 +7,7 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController push_frontend_feature_flag(:ci_config_merged_tab, @project, default_enabled: :yaml) push_frontend_feature_flag(:pipeline_status_for_pipeline_editor, @project, default_enabled: :yaml) push_frontend_feature_flag(:pipeline_editor_empty_state_action, @project, default_enabled: :yaml) + push_frontend_feature_flag(:pipeline_editor_branch_switcher, @project, default_enabled: :yaml) end feature_category :pipeline_authoring diff --git a/app/controllers/projects/clusters/integrations_controller.rb b/app/controllers/projects/clusters/integrations_controller.rb new file mode 100644 index 00000000000..94b8dd653e6 --- /dev/null +++ b/app/controllers/projects/clusters/integrations_controller.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class Projects::Clusters::IntegrationsController < ::Clusters::IntegrationsController + 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])) + end +end diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 8154128da29..0c3ff07bc76 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -19,13 +19,8 @@ class Projects::CommitController < Projects::ApplicationController before_action :define_commit_box_vars, only: [:show, :pipelines] before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files] before_action :authorize_edit_tree!, only: [:revert, :cherry_pick] - - before_action only: [:show, :pipelines] do - push_frontend_feature_flag(:ci_commit_pipeline_mini_graph_vue, @project, default_enabled: :yaml) - end - before_action do - push_frontend_feature_flag(:pick_into_project) + push_frontend_feature_flag(:pick_into_project, @project, default_enabled: :yaml) end BRANCH_SEARCH_LIMIT = 1000 @@ -59,8 +54,6 @@ class Projects::CommitController < Projects::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def pipelines - set_pipeline_feature_flag - @pipelines = @commit.pipelines.order(id: :desc) @pipelines = @pipelines.where(ref: params[:ref]).page(params[:page]).per(30) if params[:ref] @@ -119,7 +112,7 @@ class Projects::CommitController < Projects::ApplicationController @branch_name = create_new_branch? ? @commit.revert_branch_name : @start_branch create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title(current_user)} has been successfully reverted.", - success_path: -> { successful_change_path }, failure_path: failed_change_path) + success_path: -> { successful_change_path(@project) }, failure_path: failed_change_path) end def cherry_pick @@ -127,24 +120,25 @@ class Projects::CommitController < Projects::ApplicationController return render_404 if @start_branch.blank? + target_project = find_cherry_pick_target_project + return render_404 unless target_project + @branch_name = create_new_branch? ? @commit.cherry_pick_branch_name : @start_branch create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title(current_user)} has been successfully cherry-picked into #{@branch_name}.", - success_path: -> { successful_change_path }, failure_path: failed_change_path) + success_path: -> { successful_change_path(target_project) }, + failure_path: failed_change_path, + target_project: target_project) end private - def set_pipeline_feature_flag - push_frontend_feature_flag(:new_pipelines_table, @project, default_enabled: :yaml) - end - def create_new_branch? params[:create_merge_request].present? || !can?(current_user, :push_code, @project) end - def successful_change_path - referenced_merge_request_url || project_commits_url(@project, @branch_name) + def successful_change_path(target_project) + referenced_merge_request_url || project_commits_url(target_project, @branch_name) end def failed_change_path @@ -173,7 +167,7 @@ class Projects::CommitController < Projects::ApplicationController @diffs = commit.diffs(opts) @notes_count = commit.notes.count - @environment = EnvironmentsFinder.new(@project, current_user, commit: @commit, find_latest: true).execute.last + @environment = EnvironmentsByDeploymentsFinder.new(@project, current_user, commit: @commit, find_latest: true).execute.last end # rubocop: disable CodeReuse/ActiveRecord @@ -214,7 +208,6 @@ class Projects::CommitController < Projects::ApplicationController def define_commit_box_vars @last_pipeline = @commit.last_pipeline - return unless ::Gitlab::Ci::Features.ci_commit_pipeline_mini_graph_vue_enabled?(@project) return unless @commit.last_pipeline @last_pipeline_stages = StageSerializer.new(project: @project, current_user: @current_user).represent(@last_pipeline.stages) @@ -224,4 +217,14 @@ class Projects::CommitController < Projects::ApplicationController @start_branch = params[:start_branch] @commit_params = { commit: @commit } end + + def find_cherry_pick_target_project + return @project if params[:target_project_id].blank? + return @project unless Feature.enabled?(:pick_into_project, @project, default_enabled: :yaml) + + MergeRequestTargetProjectFinder + .new(current_user: current_user, source_project: @project, project_feature: :repository) + .execute + .find_by_id(params[:target_project_id]) + end end diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index d267ab732f9..9ca917841e9 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -8,7 +8,6 @@ class Projects::CommitsController < Projects::ApplicationController prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } around_action :allow_gitaly_ref_name_caching - before_action :whitelist_query_limiting, except: :commits_root before_action :require_non_empty_project before_action :assign_ref_vars, except: :commits_root before_action :authorize_download_code! @@ -64,7 +63,8 @@ class Projects::CommitsController < Projects::ApplicationController def set_commits render_404 unless @path.empty? || request.format == :atom || @repository.blob_at(@commit.id, @path) || @repository.tree(@commit.id, @path).entries.present? - @limit, @offset = (params[:limit] || 40).to_i, (params[:offset] || 0).to_i + @limit = (params[:limit] || 40).to_i + @offset = (params[:offset] || 0).to_i search = params[:search] author = params[:author] @@ -82,8 +82,4 @@ class Projects::CommitsController < Projects::ApplicationController @commits = @commits.with_latest_pipeline(@ref) @commits = set_commits_for_rendering(@commits) end - - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42330') - end end diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 81f80d37662..221bc16e256 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -132,7 +132,7 @@ class Projects::CompareController < Projects::ApplicationController if compare environment_params = source_project.repository.branch_exists?(head_ref) ? { ref: head_ref } : { commit: compare.commit } environment_params[:find_latest] = true - @environment = EnvironmentsFinder.new(source_project, current_user, environment_params).execute.last + @environment = EnvironmentsByDeploymentsFinder.new(source_project, current_user, environment_params).execute.last end end diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 33f046f414f..9fc8e8c063b 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -7,7 +7,7 @@ class Projects::ForksController < Projects::ApplicationController include Gitlab::Utils::StrongMemoize # Authorize - before_action :whitelist_query_limiting, only: [:create] + before_action :disable_query_limiting, only: [:create] before_action :require_non_empty_project before_action :authorize_download_code! before_action :authenticate_user!, only: [:new, :create] @@ -44,13 +44,17 @@ class Projects::ForksController < Projects::ApplicationController def new respond_to do |format| format.html do - @own_namespace = current_user.namespace if fork_service.valid_fork_targets.include?(current_user.namespace) + @own_namespace = current_user.namespace if can_fork_to?(current_user.namespace) @project = project end format.json do namespaces = load_namespaces_with_associations - [project.namespace] + namespaces = [current_user.namespace] + namespaces if + Feature.enabled?(:fork_project_form, project, default_enabled: :yaml) && + can_fork_to?(current_user.namespace) + render json: { namespaces: ForkNamespaceSerializer.new.represent(namespaces, project: project, current_user: current_user, memberships: memberships_hash) } @@ -78,6 +82,10 @@ class Projects::ForksController < Projects::ApplicationController private + def can_fork_to?(namespace) + ForkTargetsFinder.new(@project, current_user).execute.id_in(current_user.namespace).any? + end + def load_forks forks = ForkProjectsFinder.new( project, @@ -110,8 +118,8 @@ class Projects::ForksController < Projects::ApplicationController access_denied! unless fork_namespace && fork_service.valid_fork_target? end - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42335') + def disable_query_limiting + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20783') end def load_namespaces_with_associations diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index c454ae6eaf4..cae5cc411bc 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -18,7 +18,7 @@ class Projects::IssuesController < Projects::ApplicationController prepend_before_action :authenticate_user!, only: [:new, :export_csv] prepend_before_action :store_uri, only: [:new, :show, :designs] - before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update] + before_action :disable_query_limiting, only: [:create_merge_request, :move, :bulk_update] before_action :check_issues_available! before_action :issue, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) } after_action :log_issue_show, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) } @@ -45,6 +45,7 @@ class Projects::IssuesController < Projects::ApplicationController push_frontend_feature_flag(:vue_issuables_list, project) push_frontend_feature_flag(:usage_data_design_action, project, default_enabled: true) push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml) + push_frontend_feature_flag(:vue_issues_list, project) end before_action only: :show do @@ -53,15 +54,22 @@ class Projects::IssuesController < Projects::ApplicationController push_to_gon_attributes(:features, real_time_feature_flag, real_time_enabled) push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml) + push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml) record_experiment_user(:invite_members_version_b) + + experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance| + experiment_instance.exclude! unless helpers.can_import_members? + + experiment_instance.use {} + experiment_instance.try(:invite_member_link) {} + + experiment_instance.track(:view, property: @project.root_ancestor.id.to_s) + end end around_action :allow_gitaly_ref_name_caching, only: [:discussions] - before_action :run_null_hypothesis_experiment, - only: [:index, :new, :create] - respond_to :html alias_method :designs, :show @@ -344,13 +352,13 @@ class Projects::IssuesController < Projects::ApplicationController IssuesFinder end - def whitelist_query_limiting + def disable_query_limiting # Also see the following issues: # - # 1. https://gitlab.com/gitlab-org/gitlab-foss/issues/42423 - # 2. https://gitlab.com/gitlab-org/gitlab-foss/issues/42424 - # 3. https://gitlab.com/gitlab-org/gitlab-foss/issues/42426 - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42422') + # 1. https://gitlab.com/gitlab-org/gitlab/-/issues/20815 + # 2. https://gitlab.com/gitlab-org/gitlab/-/issues/20816 + # 3. https://gitlab.com/gitlab-org/gitlab/-/issues/21068 + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20814') end private @@ -390,14 +398,6 @@ class Projects::IssuesController < Projects::ApplicationController action_name == 'service_desk' end - def run_null_hypothesis_experiment - experiment(:null_hypothesis, project: project) do |e| - e.use { } # define the control - e.try { } # define the candidate - e.track(action_name) # track the action so we can build a funnel - end - end - # Overridden in EE def create_vulnerability_issue_feedback(issue); end end diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index f19a86209fc..92442fd4e28 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -15,6 +15,7 @@ class Projects::JobsController < Projects::ApplicationController before_action :verify_api_request!, only: :terminal_websocket_authorize before_action :authorize_create_proxy_build!, only: :proxy_websocket_authorize before_action :verify_proxy_request!, only: :proxy_websocket_authorize + before_action :push_jobs_table_vue, only: [:index] layout 'project' @@ -256,4 +257,8 @@ class Projects::JobsController < Projects::ApplicationController ::Gitlab::Workhorse.channel_websocket(service) end + + def push_jobs_table_vue + push_frontend_feature_flag(:jobs_table_vue, @project, default_enabled: :yaml) + end end diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 3992165d07c..6bf3885fb7a 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -17,11 +17,14 @@ class Projects::LabelsController < Projects::ApplicationController feature_category :issue_tracking def index - @prioritized_labels = @available_labels.prioritized(@project) - @labels = @available_labels.unprioritized(@project).page(params[:page]) - respond_to do |format| - format.html + format.html do + @prioritized_labels = @available_labels.prioritized(@project) + @labels = @available_labels.unprioritized(@project).page(params[:page]) + # preload group, project, and subscription data + Preloaders::LabelsPreloader.new(@prioritized_labels, current_user, @project).preload_all + Preloaders::LabelsPreloader.new(@labels, current_user, @project).preload_all + end format.json do render json: LabelSerializer.new.represent_appearance(@available_labels) end diff --git a/app/controllers/projects/logs_controller.rb b/app/controllers/projects/logs_controller.rb index b9aa9bfc947..f9b8091a419 100644 --- a/app/controllers/projects/logs_controller.rb +++ b/app/controllers/projects/logs_controller.rb @@ -58,7 +58,7 @@ module Projects def environment strong_memoize(:environment) do if cluster_params.key?(:environment_name) - EnvironmentsFinder.new(project, current_user, name: cluster_params[:environment_name]).find.first + EnvironmentsFinder.new(project, current_user, name: cluster_params[:environment_name]).execute.first else project.default_environment end diff --git a/app/controllers/projects/merge_requests/content_controller.rb b/app/controllers/projects/merge_requests/content_controller.rb index 399745151b1..dfc060c9204 100644 --- a/app/controllers/projects/merge_requests/content_controller.rb +++ b/app/controllers/projects/merge_requests/content_controller.rb @@ -14,6 +14,8 @@ class Projects::MergeRequests::ContentController < Projects::MergeRequests::Appl SLOW_POLLING_INTERVAL = 5.minutes.in_milliseconds def widget + check_mergeability_async! + respond_to do |format| format.json do render json: serializer(MergeRequestPollWidgetEntity) @@ -38,6 +40,13 @@ class Projects::MergeRequests::ContentController < Projects::MergeRequests::Appl def serializer(entity) serializer = MergeRequestSerializer.new(current_user: current_user, project: merge_request.project) - serializer.represent(merge_request, {}, entity) + serializer.represent(merge_request, { async_mergeability_check: params[:async_mergeability_check] }, entity) + end + + def check_mergeability_async! + return unless Feature.enabled?(:check_mergeability_async_in_widget, merge_request.project, default_enabled: :yaml) + return if params[:async_mergeability_check].blank? + + merge_request.check_mergeability(async: true) end end diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index e79c19c3b67..dc77b5e09c8 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -6,7 +6,6 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap include RendersCommits skip_before_action :merge_request - before_action :whitelist_query_limiting, only: [:create] before_action :authorize_create_merge_request_from! before_action :apply_diff_view_cookie!, only: [:diffs, :diff_for_path] before_action :build_merge_request, except: [:create] @@ -122,24 +121,24 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap # rubocop: disable CodeReuse/ActiveRecord def selected_target_project - if @project.id.to_s == params[:target_project_id] || !@project.forked? - @project - elsif params[:target_project_id].present? + return @project unless @project.forked? + + if params[:target_project_id].present? + return @project if @project.id.to_s == params[:target_project_id] + MergeRequestTargetProjectFinder.new(current_user: current_user, source_project: @project) .find_by(id: params[:target_project_id]) else - @project.forked_from_project + @project.default_merge_request_target end end # rubocop: enable CodeReuse/ActiveRecord - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42384') - end - def incr_count_webide_merge_request return if params[:nav_source] != 'webide' Gitlab::UsageDataCounters::WebIdeCounter.increment_merge_requests_count end end + +Projects::MergeRequests::CreationsController.prepend_ee_mod diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 2c6d5f62b4e..4e409b5f28f 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -14,7 +14,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv] before_action :apply_diff_view_cookie!, only: [:show] - before_action :whitelist_query_limiting, only: [:assign_related_issues, :update] + before_action :disable_query_limiting, only: [:assign_related_issues, :update] before_action :authorize_update_issuable!, only: [:close, :edit, :update, :remove_wip, :sort] before_action :authorize_read_actual_head_pipeline!, only: [ :test_reports, @@ -30,21 +30,32 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action :check_user_can_push_to_source_branch!, only: [:rebase] before_action only: [:show] do push_frontend_feature_flag(:file_identifier_hash) - push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true) push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true) push_frontend_feature_flag(:merge_request_widget_graphql, @project, default_enabled: :yaml) push_frontend_feature_flag(:drag_comment_selection, @project, default_enabled: true) push_frontend_feature_flag(:unified_diff_components, @project, default_enabled: true) push_frontend_feature_flag(:default_merge_ref_for_diffs, @project, default_enabled: :yaml) push_frontend_feature_flag(:core_security_mr_widget_counts, @project) - push_frontend_feature_flag(:remove_resolve_note, @project, default_enabled: true) push_frontend_feature_flag(:diffs_gradual_load, @project, default_enabled: true) - push_frontend_feature_flag(:codequality_backend_comparison, @project, default_enabled: :yaml) push_frontend_feature_flag(:local_file_reviews, default_enabled: :yaml) push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml) - push_frontend_feature_flag(:new_pipelines_table, @project, default_enabled: :yaml) + push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml) + push_frontend_feature_flag(:usage_data_i_testing_summary_widget_total, @project, default_enabled: :yaml) + push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml) + + # Usage data feature flags + push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml) record_experiment_user(:invite_members_version_b) + + experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance| + experiment_instance.exclude! unless helpers.can_import_members? + + experiment_instance.use {} + experiment_instance.try(:invite_member_link) {} + + experiment_instance.track(:view, property: @project.root_ancestor.id.to_s) + end end before_action do @@ -57,16 +68,19 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo feature_category :code_review, [ :assign_related_issues, :bulk_update, :cancel_auto_merge, - :ci_environments_status, :commit_change_content, :commits, - :context_commits, :destroy, :diff_for_path, :discussions, - :edit, :exposed_artifacts, :index, :merge, - :pipeline_status, :pipelines, :rebase, :remove_wip, :show, - :toggle_award_emoji, :toggle_subscription, :update + :commit_change_content, :commits, :context_commits, :destroy, + :discussions, :edit, :index, :merge, :rebase, :remove_wip, + :show, :toggle_award_emoji, :toggle_subscription, :update + ] + + feature_category :code_testing, [ + :test_reports, :coverage_reports, :codequality_reports, + :codequality_mr_diff_reports ] - feature_category :code_testing, [:test_reports, :coverage_reports, :codequality_mr_diff_reports] feature_category :accessibility_testing, [:accessibility_reports] feature_category :infrastructure_as_code, [:terraform_reports] + feature_category :continuous_integration, [:pipeline_status, :pipelines, :exposed_artifacts] def index @merge_requests = @issuables @@ -83,7 +97,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo def show close_merge_request_if_no_source_project - @merge_request.check_mergeability(async: true) + + if Feature.disabled?(:check_mergeability_async_in_widget, @project, default_enabled: :yaml) + @merge_request.check_mergeability(async: true) + end respond_to do |format| format.html do @@ -102,6 +119,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs @file_by_file_default = current_user&.view_diffs_file_by_file @coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports? + @update_current_user_path = expose_path(api_v4_user_preferences_path) @endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request) set_pipeline_variables @@ -459,9 +477,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo access_denied! unless @merge_request.can_be_merged_by?(current_user) end - def whitelist_query_limiting - # Also see https://gitlab.com/gitlab-org/gitlab-foss/issues/42441 - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42438') + def disable_query_limiting + # Also see https://gitlab.com/gitlab-org/gitlab/-/issues/20827 + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20824') end def reports_response(report_comparison, pipeline = nil) diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index 89b679fc033..f3a7bc7913e 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -4,7 +4,6 @@ class Projects::NetworkController < Projects::ApplicationController include ExtractsPath include ApplicationHelper - before_action :whitelist_query_limiting before_action :require_non_empty_project before_action :assign_ref_vars before_action :authorize_download_code! @@ -41,8 +40,4 @@ class Projects::NetworkController < Projects::ApplicationController @commit = @repo.commit(@options[:extended_sha1]) end - - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42333') - end end diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 77fd7688caf..e7e6aed8ec8 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -6,7 +6,7 @@ class Projects::NotesController < Projects::ApplicationController include NotesHelper include ToggleAwardEmoji - before_action :whitelist_query_limiting, only: [:create, :update] + before_action :disable_query_limiting, only: [:create, :update] before_action :authorize_read_note! before_action :authorize_create_note!, only: [:create] before_action :authorize_resolve_note!, only: [:resolve, :unresolve] @@ -87,7 +87,7 @@ class Projects::NotesController < Projects::ApplicationController access_denied! unless can?(current_user, :create_note, noteable) end - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42383') + def disable_query_limiting + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20800') end end diff --git a/app/controllers/projects/packages/infrastructure_registry_controller.rb b/app/controllers/projects/packages/infrastructure_registry_controller.rb new file mode 100644 index 00000000000..22ae1d65013 --- /dev/null +++ b/app/controllers/projects/packages/infrastructure_registry_controller.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Projects + module Packages + class InfrastructureRegistryController < Projects::ApplicationController + feature_category :infrastructure_as_code + end + end +end diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 9b5f5871c41..ee1e10221ec 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -4,7 +4,7 @@ class Projects::PipelinesController < Projects::ApplicationController include ::Gitlab::Utils::StrongMemoize include Analytics::UniqueVisitsHelper - before_action :whitelist_query_limiting, only: [:create, :retry] + before_action :disable_query_limiting, only: [:create, :retry] before_action :pipeline, except: [:index, :new, :create, :charts, :config_variables] before_action :set_pipeline_path, only: [:show] before_action :authorize_read_pipeline! @@ -14,10 +14,11 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action do push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: :yaml) + push_frontend_feature_flag(:pipeline_graph_layers_view, project, type: :development, default_enabled: :yaml) + push_frontend_feature_flag(:pipeline_filter_jobs, project, 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(:jira_for_vulnerabilities, project, type: :development, default_enabled: :yaml) - push_frontend_feature_flag(:new_pipelines_table, project, default_enabled: :yaml) end before_action :ensure_pipeline, only: [:show] @@ -44,7 +45,17 @@ class Projects::PipelinesController < Projects::ApplicationController @pipelines_count = limited_pipelines_count(project) respond_to do |format| - format.html + format.html do + experiment(:pipeline_empty_state_templates, actor: current_user) do |e| + e.exclude! unless current_user + e.exclude! if @pipelines_count.to_i > 0 + e.exclude! if helpers.has_gitlab_ci?(project) + + e.use {} + e.try {} + e.track(:view, value: project.namespace_id) + end + end format.json do Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL) @@ -92,10 +103,10 @@ class Projects::PipelinesController < Projects::ApplicationController end def show - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/26657') + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/26657') respond_to do |format| - format.html + format.html { render_show } format.json do Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL) @@ -150,15 +161,6 @@ class Projects::PipelinesController < Projects::ApplicationController .represent(@stage, details: true, retried: params[:retried]) end - # TODO: This endpoint is used by mini-pipeline-graph - # TODO: This endpoint should be migrated to `stage.json` - def stage_ajax - @stage = pipeline.legacy_stage(params[:stage]) - return not_found unless @stage - - render json: { html: view_to_html_string('projects/pipelines/_stage') } - end - def retry pipeline.retry_failed(current_user) @@ -185,10 +187,7 @@ class Projects::PipelinesController < Projects::ApplicationController def test_report respond_to do |format| - format.html do - render 'show' - end - + format.html { render_show } format.json do render json: TestReportSerializer .new(current_user: @current_user) @@ -217,6 +216,8 @@ class Projects::PipelinesController < Projects::ApplicationController end def render_show + @stages = @pipeline.stages.with_latest_and_retried_statuses + respond_to do |format| format.html do render 'show' @@ -269,9 +270,9 @@ class Projects::PipelinesController < Projects::ApplicationController &.present(current_user: current_user) end - def whitelist_query_limiting - # Also see https://gitlab.com/gitlab-org/gitlab-foss/issues/42343 - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42339') + def disable_query_limiting + # Also see https://gitlab.com/gitlab-org/gitlab/-/issues/20785 + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20784') end def authorize_update_pipeline! diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb index 28a86ecc9f0..8acebd89033 100644 --- a/app/controllers/projects/registry/repositories_controller.rb +++ b/app/controllers/projects/registry/repositories_controller.rb @@ -6,22 +6,11 @@ module Projects include PackagesHelper before_action :authorize_update_container_image!, only: [:destroy] - before_action :ensure_root_container_repository!, only: [:index] def index respond_to do |format| - format.html - format.json do - @images = ContainerRepositoriesFinder.new(user: current_user, subject: project, params: params.slice(:name)) - .execute - - track_package_event(:list_repositories, :container) - - serializer = ContainerRepositoriesSerializer - .new(project: project, current_user: current_user) - - render json: serializer.with_pagination(request, response).represent(@images) - end + format.html { ensure_root_container_repository! } + format.json { render_404 } end end diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index 614bada09ed..26382856761 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -12,7 +12,6 @@ class Projects::ReleasesController < Projects::ApplicationController push_frontend_feature_flag(:graphql_release_data, project, default_enabled: true) push_frontend_feature_flag(:graphql_milestone_stats, project, default_enabled: true) push_frontend_feature_flag(:graphql_releases_page, project, default_enabled: true) - push_frontend_feature_flag(:graphql_individual_release_page, project, default_enabled: true) end before_action :authorize_update_release!, only: %i[edit update] before_action :authorize_create_release!, only: :new diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 554eb01defe..ccb8b393bfe 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -71,7 +71,7 @@ class Projects::ServicesController < Projects::ApplicationController end result[:data].presence || {} - rescue Gitlab::HTTP::BlockedUrlError => e + rescue *Gitlab::HTTP::HTTP_ERRORS => e { error: true, message: s_('Integrations|Connection failed. Please check your settings.'), service_response: e.message, test_failed: true } end diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb index 74350147825..e3bb8c616df 100644 --- a/app/controllers/projects/settings/access_tokens_controller.rb +++ b/app/controllers/projects/settings/access_tokens_controller.rb @@ -5,7 +5,10 @@ module Projects class AccessTokensController < Projects::ApplicationController include ProjectsHelper - before_action :check_feature_availability + layout 'project_settings' + before_action -> { check_permission(:read_resource_access_tokens) }, only: [:index] + before_action -> { check_permission(:destroy_resource_access_tokens) }, only: [:revoke] + before_action -> { check_permission(:create_resource_access_tokens) }, only: [:create] feature_category :authentication_and_authorization @@ -42,8 +45,8 @@ module Projects private - def check_feature_availability - render_404 unless project_access_token_available?(@project) + def check_permission(action) + render_404 unless can?(current_user, action, @project) end def create_params diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 34b11c456b9..1a465406660 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -7,6 +7,7 @@ module Projects NUMBER_OF_RUNNERS_PER_PAGE = 20 + layout 'project_settings' before_action :authorize_admin_pipeline! before_action :define_variables before_action do @@ -61,7 +62,7 @@ module Projects end def runner_setup_scripts - private_runner_setup_scripts(project: @project) + private_runner_setup_scripts end private diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index c407b15e29f..a05793a0283 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -3,6 +3,7 @@ module Projects module Settings class OperationsController < Projects::ApplicationController + layout 'project_settings' before_action :authorize_admin_operations! before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token] diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 821560e32ba..bb5ad8e9aea 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -3,6 +3,7 @@ module Projects module Settings class RepositoryController < Projects::ApplicationController + layout 'project_settings' before_action :authorize_admin_project! before_action :define_variables, only: [:create_deploy_token] before_action do diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 94b0473e1f3..3bf9988ca22 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -9,6 +9,9 @@ class Projects::TagsController < Projects::ApplicationController before_action :require_non_empty_project before_action :authorize_download_code! before_action :authorize_admin_tag!, only: [:new, :create, :destroy] + before_action do + push_frontend_feature_flag(:gldropdown_tags, default_enabled: :yaml) + end feature_category :source_code_management, [:index, :show, :new, :destroy] feature_category :release_evidence, [:create] diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index bc48ebd1c74..7c9d6daad02 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -14,7 +14,7 @@ class ProjectsController < Projects::ApplicationController around_action :allow_gitaly_ref_name_caching, only: [:index, :show] - before_action :whitelist_query_limiting, only: [:show, :create] + before_action :disable_query_limiting, only: [:show, :create] before_action :authenticate_user!, except: [:index, :show, :activity, :refs, :resolve, :unfoldered_environment_names] before_action :redirect_git_extension, only: [:show] before_action :project, except: [:index, :new, :create, :resolve] @@ -35,6 +35,10 @@ class ProjectsController < Projects::ApplicationController push_frontend_feature_flag(:allow_editing_commit_messages, @project) end + before_action do + push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml) + end + layout :determine_layout feature_category :projects, [ @@ -70,6 +74,7 @@ class ProjectsController < Projects::ApplicationController @project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute if @project.saved? + experiment(:new_repo, user: current_user).track(:project_created) experiment(:new_project_readme, actor: current_user).track( :created, property: active_new_project_tab, @@ -399,6 +404,7 @@ class ProjectsController < Projects::ApplicationController show_default_award_emojis squash_option allow_editing_commit_messages + mr_default_target_self ] end @@ -510,8 +516,8 @@ class ProjectsController < Projects::ApplicationController redirect_to(request.original_url.sub(%r{\.git/?\Z}, '')) end - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/20826') + def disable_query_limiting + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20826') end def present_project diff --git a/app/controllers/registrations/experience_levels_controller.rb b/app/controllers/registrations/experience_levels_controller.rb index b6ed0366177..3a721823d89 100644 --- a/app/controllers/registrations/experience_levels_controller.rb +++ b/app/controllers/registrations/experience_levels_controller.rb @@ -6,7 +6,7 @@ module Registrations before_action :ensure_namespace_path_param - feature_category :navigation + feature_category :onboarding def update current_user.experience_level = params[:experience_level] diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb index a1a6a057171..62ec03206c4 100644 --- a/app/controllers/registrations/welcome_controller.rb +++ b/app/controllers/registrations/welcome_controller.rb @@ -35,7 +35,7 @@ module Registrations end def update_params - params.require(:user).permit(:role, :other_role, :setup_for_company) + params.require(:user).permit(:role, :other_role, :setup_for_company, :email_opted_in) end def requires_confirmation?(user) diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 44c08863dd6..61218a95add 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -9,7 +9,7 @@ class RegistrationsController < Devise::RegistrationsController layout 'devise' prepend_before_action :check_captcha, only: :create - before_action :whitelist_query_limiting, :ensure_destroy_prerequisites_met, only: [:destroy] + before_action :ensure_destroy_prerequisites_met, only: [:destroy] before_action :load_recaptcha, only: :new before_action :set_invite_params, only: :new @@ -162,10 +162,6 @@ class RegistrationsController < Devise::RegistrationsController @devise_mapping ||= Devise.mappings[:user] end - def whitelist_query_limiting - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42380') - end - def load_recaptcha Gitlab::Recaptcha.load_configurations! end diff --git a/app/controllers/root_controller.rb b/app/controllers/root_controller.rb index dab2f3bd67a..672a03ad11d 100644 --- a/app/controllers/root_controller.rb +++ b/app/controllers/root_controller.rb @@ -13,7 +13,6 @@ class RootController < Dashboard::ProjectsController before_action :redirect_unlogged_user, if: -> { current_user.nil? } before_action :redirect_logged_user, if: -> { current_user.present? } - before_action :customize_homepage, only: :index, if: -> { current_user.present? } # We only need to load the projects when the user is logged in but did not # configure a dashboard. In which case we render projects. We can do that straight # from the #index action. @@ -69,10 +68,6 @@ class RootController < Dashboard::ProjectsController root_urls.exclude?(home_page_url) end - - def customize_homepage - @customize_homepage = Feature.enabled?(:customize_homepage, default_enabled: :yaml) - end end RootController.prepend_if_ee('EE::RootController') diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 45c1c35a655..3b218822395 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -47,7 +47,11 @@ class SearchController < ApplicationController params.require([:search, :scope]) scope = search_service.scope - count = search_service.search_results.formatted_count(scope) + + count = 0 + ApplicationRecord.with_fast_read_statement_timeout do + count = search_service.search_results.formatted_count(scope) + end # Users switching tabs will keep fetching the same tab counts so it's a # good idea to cache in their browser just for a short time. They can still diff --git a/app/controllers/whats_new_controller.rb b/app/controllers/whats_new_controller.rb index 12a52f30bd0..e24b0bbc7bb 100644 --- a/app/controllers/whats_new_controller.rb +++ b/app/controllers/whats_new_controller.rb @@ -5,7 +5,7 @@ class WhatsNewController < ApplicationController skip_before_action :authenticate_user! - before_action :check_valid_page_param, :set_pagination_headers, unless: -> { has_version_param? } + before_action :check_valid_page_param, :set_pagination_headers feature_category :navigation @@ -29,19 +29,11 @@ class WhatsNewController < ApplicationController def highlights strong_memoize(:highlights) do - if has_version_param? - ReleaseHighlight.for_version(version: params[:version]) - else - ReleaseHighlight.paginated(page: current_page) - end + ReleaseHighlight.paginated(page: current_page) end end def set_pagination_headers response.set_header('X-Next-Page', highlights.next_page) end - - def has_version_param? - params[:version].present? - end end |