diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-20 17:22:11 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-20 17:22:11 +0300 |
commit | 0c872e02b2c822e3397515ec324051ff540f0cd5 (patch) | |
tree | ce2fb6ce7030e4dad0f4118d21ab6453e5938cdd /app/controllers | |
parent | f7e05a6853b12f02911494c4b3fe53d9540d74fc (diff) |
Add latest changes from gitlab-org/gitlab@15-7-stable-eev15.7.0-rc42
Diffstat (limited to 'app/controllers')
136 files changed, 1082 insertions, 798 deletions
diff --git a/app/controllers/abuse_reports_controller.rb b/app/controllers/abuse_reports_controller.rb index 0de2115d4d6..80aca7e21ce 100644 --- a/app/controllers/abuse_reports_controller.rb +++ b/app/controllers/abuse_reports_controller.rb @@ -3,7 +3,7 @@ class AbuseReportsController < ApplicationController before_action :set_user, only: [:new] - feature_category :users + feature_category :insider_threat def new @abuse_report = AbuseReport.new diff --git a/app/controllers/admin/abuse_reports_controller.rb b/app/controllers/admin/abuse_reports_controller.rb index 6f80ed3c172..5357558434e 100644 --- a/app/controllers/admin/abuse_reports_controller.rb +++ b/app/controllers/admin/abuse_reports_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Admin::AbuseReportsController < Admin::ApplicationController - feature_category :users + feature_category :insider_threat def index @abuse_reports = AbuseReportsFinder.new(params).execute diff --git a/app/controllers/admin/application_settings/appearances_controller.rb b/app/controllers/admin/application_settings/appearances_controller.rb index cf765c96a8f..1a8447185a7 100644 --- a/app/controllers/admin/application_settings/appearances_controller.rb +++ b/app/controllers/admin/application_settings/appearances_controller.rb @@ -68,6 +68,7 @@ class Admin::ApplicationSettings::AppearancesController < Admin::ApplicationCont def allowed_appearance_params %i[ title + short_title description logo logo_cache diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index ec9441c2b9b..b8c1bc266f7 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -40,9 +40,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController feature_category :pages, [:lets_encrypt_terms_of_service] feature_category :error_tracking, [:reset_error_tracking_access_token] - VALID_SETTING_PANELS = %w(general repository + VALID_SETTING_PANELS = %w[general repository ci_cd reporting metrics_and_profiling - network preferences).freeze + network preferences].freeze # The current size of a sidekiq job's jid is 24 characters. The size of the # jid is an internal detail of Sidekiq, and they do not guarantee that it'll @@ -150,9 +150,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController } end - if @application_setting.self_monitoring_project_id.present? - return render status: :ok, json: self_monitoring_data - end + return render status: :ok, json: self_monitoring_data if @application_setting.self_monitoring_project_id.present? render status: :bad_request, json: { message: _('Self-monitoring project does not exist. Please check logs ' \ @@ -236,7 +234,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController params[:application_setting][:restricted_visibility_levels]&.delete("") if params[:application_setting].key?(:required_instance_ci_template) - params[:application_setting][:required_instance_ci_template] = nil if params[:application_setting][:required_instance_ci_template].empty? + if params[:application_setting][:required_instance_ci_template].empty? + params[:application_setting][:required_instance_ci_template] = nil + end end remove_blank_params_for!(:elasticsearch_aws_secret_access_key, :eks_secret_access_key) @@ -290,9 +290,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController .new(@application_setting, current_user, application_setting_params) .execute - if recheck_user_consent? - session[:ask_for_usage_stats_consent] = current_user.requires_usage_stats_consent? - end + session[:ask_for_usage_stats_consent] = current_user.requires_usage_stats_consent? if recheck_user_consent? redirect_path = referer_path(request) || general_admin_application_settings_path diff --git a/app/controllers/admin/background_jobs_controller.rb b/app/controllers/admin/background_jobs_controller.rb index 4eda35d66f6..43d2c983823 100644 --- a/app/controllers/admin/background_jobs_controller.rb +++ b/app/controllers/admin/background_jobs_controller.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true -class Admin::BackgroundJobsController < Admin::ApplicationController - feature_category :not_owned # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned +module Admin + class BackgroundJobsController < ApplicationController + feature_category :not_owned # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned + end end diff --git a/app/controllers/admin/background_migrations_controller.rb b/app/controllers/admin/background_migrations_controller.rb index c6c9e0ced22..b904196c5ab 100644 --- a/app/controllers/admin/background_migrations_controller.rb +++ b/app/controllers/admin/background_migrations_controller.rb @@ -1,66 +1,68 @@ # frozen_string_literal: true -class Admin::BackgroundMigrationsController < Admin::ApplicationController - feature_category :database - urgency :low - - around_action :support_multiple_databases - - def index - @relations_by_tab = { - 'queued' => batched_migration_class.queued.queue_order, - 'failed' => batched_migration_class.with_status(:failed).queue_order, - 'finished' => batched_migration_class.with_status(:finished).queue_order.reverse_order - } - - @current_tab = @relations_by_tab.key?(params[:tab]) ? params[:tab] : 'queued' - @migrations = @relations_by_tab[@current_tab].page(params[:page]) - @successful_rows_counts = batched_migration_class.successful_rows_counts(@migrations.map(&:id)) - @databases = Gitlab::Database.db_config_names - end +module Admin + class BackgroundMigrationsController < ApplicationController + feature_category :database + urgency :low + + around_action :support_multiple_databases + + def index + @relations_by_tab = { + 'queued' => batched_migration_class.queued.queue_order, + 'failed' => batched_migration_class.with_status(:failed).queue_order, + 'finished' => batched_migration_class.with_status(:finished).queue_order.reverse_order + } + + @current_tab = @relations_by_tab.key?(params[:tab]) ? params[:tab] : 'queued' + @migrations = @relations_by_tab[@current_tab].page(params[:page]) + @successful_rows_counts = batched_migration_class.successful_rows_counts(@migrations.map(&:id)) + @databases = Gitlab::Database.db_config_names + end - def show - @migration = batched_migration_class.find(params[:id]) + def show + @migration = batched_migration_class.find(params[:id]) - @failed_jobs = @migration.batched_jobs.with_status(:failed).page(params[:page]) - end + @failed_jobs = @migration.batched_jobs.with_status(:failed).page(params[:page]) + end - def pause - migration = batched_migration_class.find(params[:id]) - migration.pause! + def pause + migration = batched_migration_class.find(params[:id]) + migration.pause! - redirect_back fallback_location: { action: 'index' } - end + redirect_back fallback_location: { action: 'index' } + end - def resume - migration = batched_migration_class.find(params[:id]) - migration.execute! + def resume + migration = batched_migration_class.find(params[:id]) + migration.execute! - redirect_back fallback_location: { action: 'index' } - end + redirect_back fallback_location: { action: 'index' } + end - def retry - migration = batched_migration_class.find(params[:id]) - migration.retry_failed_jobs! if migration.failed? + def retry + migration = batched_migration_class.find(params[:id]) + migration.retry_failed_jobs! if migration.failed? - redirect_back fallback_location: { action: 'index' } - end + redirect_back fallback_location: { action: 'index' } + end - private + private - def support_multiple_databases - Gitlab::Database::SharedModel.using_connection(base_model.connection) do - yield + def support_multiple_databases + Gitlab::Database::SharedModel.using_connection(base_model.connection) do + yield + end end - end - def base_model - @selected_database = params[:database] || Gitlab::Database::MAIN_DATABASE_NAME + def base_model + @selected_database = params[:database] || Gitlab::Database::MAIN_DATABASE_NAME - Gitlab::Database.database_base_models[@selected_database] - end + Gitlab::Database.database_base_models[@selected_database] + end - def batched_migration_class - @batched_migration_class ||= Gitlab::Database::BackgroundMigration::BatchedMigration + def batched_migration_class + @batched_migration_class ||= Gitlab::Database::BackgroundMigration::BatchedMigration + end end end diff --git a/app/controllers/admin/batched_jobs_controller.rb b/app/controllers/admin/batched_jobs_controller.rb index 0a00ba13dc8..10b5f68d630 100644 --- a/app/controllers/admin/batched_jobs_controller.rb +++ b/app/controllers/admin/batched_jobs_controller.rb @@ -1,28 +1,30 @@ # frozen_string_literal: true -class Admin::BatchedJobsController < Admin::ApplicationController - feature_category :database - urgency :low +module Admin + class BatchedJobsController < ApplicationController + feature_category :database + urgency :low - around_action :support_multiple_databases + around_action :support_multiple_databases - def show - @job = Gitlab::Database::BackgroundMigration::BatchedJob.find(params[:id]) + def show + @job = Gitlab::Database::BackgroundMigration::BatchedJob.find(params[:id]) - @transition_logs = @job.batched_job_transition_logs - end + @transition_logs = @job.batched_job_transition_logs + end - private + private - def support_multiple_databases - Gitlab::Database::SharedModel.using_connection(base_model.connection) do - yield + def support_multiple_databases + Gitlab::Database::SharedModel.using_connection(base_model.connection) do + yield + end end - end - def base_model - @selected_database = params[:database] || Gitlab::Database::MAIN_DATABASE_NAME + def base_model + @selected_database = params[:database] || Gitlab::Database::MAIN_DATABASE_NAME - Gitlab::Database.database_base_models[@selected_database] + Gitlab::Database.database_base_models[@selected_database] + end end end diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb index bdf0c6aedb9..093c5667a24 100644 --- a/app/controllers/admin/broadcast_messages_controller.rb +++ b/app/controllers/admin/broadcast_messages_controller.rb @@ -1,104 +1,106 @@ # frozen_string_literal: true -class Admin::BroadcastMessagesController < Admin::ApplicationController - include BroadcastMessagesHelper +module Admin + class BroadcastMessagesController < ApplicationController + include BroadcastMessagesHelper - before_action :find_broadcast_message, only: [:edit, :update, :destroy] - before_action :find_broadcast_messages, only: [:index, :create] - before_action :push_features, only: [:index, :edit] + before_action :find_broadcast_message, only: [:edit, :update, :destroy] + before_action :find_broadcast_messages, only: [:index, :create] + before_action :push_features, only: [:index, :edit] - feature_category :onboarding - urgency :low + feature_category :onboarding + urgency :low - def index - @broadcast_message = BroadcastMessage.new - end - - def edit - end + def index + @broadcast_message = BroadcastMessage.new + end - def create - @broadcast_message = BroadcastMessage.new(broadcast_message_params) - success = @broadcast_message.save + def edit + end - respond_to do |format| - format.json do - if success - render json: @broadcast_message, status: :ok - else - render json: { errors: @broadcast_message.errors.full_messages }, status: :bad_request + def create + @broadcast_message = BroadcastMessage.new(broadcast_message_params) + success = @broadcast_message.save + + respond_to do |format| + format.json do + if success + render json: @broadcast_message, status: :ok + else + render json: { errors: @broadcast_message.errors.full_messages }, status: :bad_request + end end - end - format.html do - if success - redirect_to admin_broadcast_messages_path, notice: _('Broadcast Message was successfully created.') - else - render :index + format.html do + if success + redirect_to admin_broadcast_messages_path, notice: _('Broadcast Message was successfully created.') + else + render :index + end end end end - end - def update - success = @broadcast_message.update(broadcast_message_params) + def update + success = @broadcast_message.update(broadcast_message_params) - respond_to do |format| - format.json do - if success - render json: @broadcast_message, status: :ok - else - render json: { errors: @broadcast_message.errors.full_messages }, status: :bad_request + respond_to do |format| + format.json do + if success + render json: @broadcast_message, status: :ok + else + render json: { errors: @broadcast_message.errors.full_messages }, status: :bad_request + end end - end - format.html do - if success - redirect_to admin_broadcast_messages_path, notice: _('Broadcast Message was successfully updated.') - else - render :edit + format.html do + if success + redirect_to admin_broadcast_messages_path, notice: _('Broadcast Message was successfully updated.') + else + render :edit + end end end end - end - def destroy - @broadcast_message.destroy + def destroy + @broadcast_message.destroy - respond_to do |format| - format.html { redirect_back_or_default(default: { action: 'index' }) } - format.js { head :ok } + respond_to do |format| + format.html { redirect_back_or_default(default: { action: 'index' }) } + format.js { head :ok } + end end - end - def preview - @broadcast_message = BroadcastMessage.new(broadcast_message_params) - render partial: 'admin/broadcast_messages/preview' - end + def preview + @broadcast_message = BroadcastMessage.new(broadcast_message_params) + render partial: 'admin/broadcast_messages/preview' + end - protected + protected - def find_broadcast_message - @broadcast_message = BroadcastMessage.find(params[:id]) - end + def find_broadcast_message + @broadcast_message = BroadcastMessage.find(params[:id]) + end - def find_broadcast_messages - @broadcast_messages = BroadcastMessage.order(ends_at: :desc).page(params[:page]) # rubocop: disable CodeReuse/ActiveRecord - end + def find_broadcast_messages + @broadcast_messages = BroadcastMessage.order(ends_at: :desc).page(params[:page]) # rubocop: disable CodeReuse/ActiveRecord + end - def broadcast_message_params - params.require(:broadcast_message) - .permit(%i( - theme - ends_at - message - starts_at - target_path - broadcast_type - dismissable - ), target_access_levels: []).reverse_merge!(target_access_levels: []) - end + def broadcast_message_params + params.require(:broadcast_message) + .permit(%i[ + theme + ends_at + message + starts_at + target_path + broadcast_type + dismissable + ], target_access_levels: []).reverse_merge!(target_access_levels: []) + end - def push_features - push_frontend_feature_flag(:vue_broadcast_messages, current_user) - push_frontend_feature_flag(:role_targeted_broadcast_messages, current_user) + def push_features + push_frontend_feature_flag(:vue_broadcast_messages, current_user) + push_frontend_feature_flag(:role_targeted_broadcast_messages, current_user) + end end end diff --git a/app/controllers/admin/ci/variables_controller.rb b/app/controllers/admin/ci/variables_controller.rb index 7d643435ddb..ef50d7362c4 100644 --- a/app/controllers/admin/ci/variables_controller.rb +++ b/app/controllers/admin/ci/variables_controller.rb @@ -1,50 +1,54 @@ # frozen_string_literal: true -class Admin::Ci::VariablesController < Admin::ApplicationController - feature_category :pipeline_authoring - - def show - respond_to do |format| - format.json { render_instance_variables } - end - end - - def update - service = Ci::UpdateInstanceVariablesService.new(variables_params) - - if service.execute - respond_to do |format| - format.json { render_instance_variables } +module Admin + module Ci + class VariablesController < ApplicationController + feature_category :pipeline_authoring + + def show + respond_to do |format| + format.json { render_instance_variables } + end end - else - respond_to do |format| - format.json { render_error(service.errors) } + + def update + service = ::Ci::UpdateInstanceVariablesService.new(variables_params) + + if service.execute + respond_to do |format| + format.json { render_instance_variables } + end + else + respond_to do |format| + format.json { render_error(service.errors) } + end + end end - end - end - private + private - def variables - @variables ||= Ci::InstanceVariable.all - end + def variables + @variables ||= ::Ci::InstanceVariable.all + end - def render_instance_variables - render status: :ok, - json: { - variables: Ci::InstanceVariableSerializer.new.represent(variables) - } - end + def render_instance_variables + render status: :ok, + json: { + variables: ::Ci::InstanceVariableSerializer.new.represent(variables) + } + end - def render_error(errors) - render status: :bad_request, json: errors - end + def render_error(errors) + render status: :bad_request, json: errors + end - def variables_params - params.permit(variables_attributes: Array(variable_params_attributes)) - end + def variables_params + params.permit(variables_attributes: Array(variable_params_attributes)) + end - def variable_params_attributes - %i[id variable_type key secret_value protected masked _destroy] + def variable_params_attributes + %i[id variable_type key secret_value protected masked raw _destroy] + end + end end end diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 1395d4bb3b7..8005babe19e 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -51,6 +51,10 @@ class Admin::GroupsController < Admin::ApplicationController @group.build_admin_note unless @group.admin_note if @group.update(group_params) + unless Gitlab::Utils.to_boolean(group_params['runner_registration_enabled']) + Ci::Runners::ResetRegistrationTokenService.new(@group, current_user).execute + end + redirect_to [:admin, @group], notice: _('Group was successfully updated.') else render "edit" @@ -91,6 +95,7 @@ class Admin::GroupsController < Admin::ApplicationController :name, :path, :request_access_enabled, + :runner_registration_enabled, :visibility_level, :require_two_factor_authentication, :two_factor_grace_period, diff --git a/app/controllers/admin/plan_limits_controller.rb b/app/controllers/admin/plan_limits_controller.rb index 2cebc059830..ea52198432c 100644 --- a/app/controllers/admin/plan_limits_controller.rb +++ b/app/controllers/admin/plan_limits_controller.rb @@ -47,6 +47,7 @@ class Admin::PlanLimitsController < Admin::ApplicationController ci_needs_size_limit ci_registered_group_runners ci_registered_project_runners + pipeline_hierarchy_size ]) end end diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 3f3c3581555..9e841487508 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -13,9 +13,7 @@ class Admin::ProjectsController < Admin::ApplicationController params[:sort] ||= 'latest_activity_desc' @sort = params[:sort] - if params[:last_repository_check_failed].present? && params[:archived].nil? - params[:archived] = true - end + params[:archived] = true if params[:last_repository_check_failed].present? && params[:archived].nil? @projects = Admin::ProjectsFinder.new(params: params, current_user: current_user).execute @@ -57,9 +55,7 @@ class Admin::ProjectsController < Admin::ApplicationController namespace = Namespace.find_by(id: params[:new_namespace_id]) ::Projects::TransferService.new(@project, current_user, params.dup).execute(namespace) - if @project.errors[:new_namespace].present? - flash[:alert] = @project.errors[:new_namespace].first - end + flash[:alert] = @project.errors[:new_namespace].first if @project.errors[:new_namespace].present? @project.reset redirect_to admin_project_path(@project) diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb index 3a55fc4b951..180f4634136 100644 --- a/app/controllers/admin/spam_logs_controller.rb +++ b/app/controllers/admin/spam_logs_controller.rb @@ -5,7 +5,7 @@ class Admin::SpamLogsController < Admin::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def index - @spam_logs = SpamLog.order(id: :desc).page(params[:page]) + @spam_logs = SpamLog.includes(:user).order(id: :desc).page(params[:page]) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/controllers/admin/system_info_controller.rb b/app/controllers/admin/system_info_controller.rb index 41f95addc66..96fb73cedfe 100644 --- a/app/controllers/admin/system_info_controller.rb +++ b/app/controllers/admin/system_info_controller.rb @@ -59,11 +59,11 @@ class Admin::SystemInfoController < Admin::ApplicationController begin disk = Sys::Filesystem.stat(mount.mount_point) @disks.push({ - bytes_total: disk.bytes_total, - bytes_used: disk.bytes_used, - disk_name: mount.name, - mount_path: disk.path - }) + bytes_total: disk.bytes_total, + bytes_used: disk.bytes_used, + disk_name: mount.name, + mount_path: disk.path + }) rescue Sys::Filesystem::Error end end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 2c8b4888d5d..5f6e3f0062f 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -88,17 +88,25 @@ class Admin::UsersController < Admin::ApplicationController end def activate - return redirect_back_or_admin_user(notice: _("Error occurred. A blocked user must be unblocked to be activated")) if user.blocked? + if user.blocked? + return redirect_back_or_admin_user(notice: _("Error occurred. A blocked user must be unblocked to be activated")) + end user.activate redirect_back_or_admin_user(notice: _("Successfully activated")) end def deactivate - return redirect_back_or_admin_user(notice: _("Error occurred. A blocked user cannot be deactivated")) if user.blocked? + if user.blocked? + return redirect_back_or_admin_user(notice: _("Error occurred. A blocked user cannot be deactivated")) + end + return redirect_back_or_admin_user(notice: _("Successfully deactivated")) if user.deactivated? return redirect_back_or_admin_user(notice: _("Internal users cannot be deactivated")) if user.internal? - return redirect_back_or_admin_user(notice: _("The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated") % { minimum_inactive_days: Gitlab::CurrentSettings.deactivate_dormant_users_period }) unless user.can_be_deactivated? + + unless user.can_be_deactivated? + return redirect_back_or_admin_user(notice: _("The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated") % { minimum_inactive_days: Gitlab::CurrentSettings.deactivate_dormant_users_period }) + end user.deactivate redirect_back_or_admin_user(notice: _("Successfully deactivated")) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4de6b5de42a..e64d3110c3a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -158,7 +158,7 @@ class ApplicationController < ActionController::Base protected def workhorse_excluded_content_types - @workhorse_excluded_content_types ||= %w(text/html application/json) + @workhorse_excluded_content_types ||= %w[text/html application/json] end def append_info_to_payload(payload) @@ -179,9 +179,7 @@ class ApplicationController < ActionController::Base payload[:queue_duration_s] = request.env[::Gitlab::Middleware::RailsQueueDuration::GITLAB_RAILS_QUEUE_DURATION_KEY] - if Feature.enabled?(:log_response_length) - payload[:response_bytes] = response.body_parts.sum(&:bytesize) - end + payload[:response_bytes] = response.body_parts.sum(&:bytesize) if Feature.enabled?(:log_response_length) store_cloudflare_headers!(payload, request) end @@ -349,9 +347,7 @@ class ApplicationController < ActionController::Base def check_password_expiration return if session[:impersonator_id] || !current_user&.allow_password_authentication? - if current_user&.password_expired? - redirect_to new_profile_password_path - end + redirect_to new_profile_password_path if current_user&.password_expired? end def active_user_check @@ -426,8 +422,8 @@ class ApplicationController < ActionController::Base # accepting the terms. redirect_path = if request.get? request.fullpath - else - URI(request.referer).path if request.referer + elsif request.referer + URI(request.referer).path end flash[:notice] = message @@ -529,7 +525,7 @@ class ApplicationController < ActionController::Base end def set_page_title_header - # Per https://tools.ietf.org/html/rfc5987, headers need to be ISO-8859-1, not UTF-8 + # Per https://www.rfc-editor.org/rfc/rfc5987, headers need to be ISO-8859-1, not UTF-8 response.headers['Page-Title'] = Addressable::URI.encode_component(page_title('GitLab')) end @@ -565,9 +561,7 @@ class ApplicationController < ActionController::Base session[:ask_for_usage_stats_consent] = current_user.requires_usage_stats_consent? - if session[:ask_for_usage_stats_consent] - disable_usage_stats - end + disable_usage_stats if session[:ask_for_usage_stats_consent] end def disable_usage_stats diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb index 817f82085e6..b4a36b7db22 100644 --- a/app/controllers/concerns/authenticates_with_two_factor.rb +++ b/app/controllers/concerns/authenticates_with_two_factor.rb @@ -23,6 +23,8 @@ module AuthenticatesWithTwoFactor session[:otp_user_id] = user.id session[:user_password_hash] = Digest::SHA256.hexdigest(user.encrypted_password) + + add_gon_variables push_frontend_feature_flag(:webauthn) if Feature.enabled?(:webauthn) diff --git a/app/controllers/concerns/controller_with_cross_project_access_check.rb b/app/controllers/concerns/controller_with_cross_project_access_check.rb index 3f72f092683..eace8e9464b 100644 --- a/app/controllers/concerns/controller_with_cross_project_access_check.rb +++ b/app/controllers/concerns/controller_with_cross_project_access_check.rb @@ -9,9 +9,7 @@ module ControllerWithCrossProjectAccessCheck end def cross_project_check - if Gitlab::CrossProjectAccess.find_check(self)&.should_run?(self) - authorize_cross_project_page! - end + authorize_cross_project_page! if Gitlab::CrossProjectAccess.find_check(self)&.should_run?(self) end def authorize_cross_project_page! diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index b6ba1b13cc3..53bb11090c8 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -78,7 +78,7 @@ module CreatesCommit _("You can now submit a merge request to get this change into the original branch.") end - flash[:notice] += " " + mr_message + flash[:notice] += " #{mr_message}" end end end diff --git a/app/controllers/concerns/cycle_analytics_params.rb b/app/controllers/concerns/cycle_analytics_params.rb index 70bcefe339c..5199d879595 100644 --- a/app/controllers/concerns/cycle_analytics_params.rb +++ b/app/controllers/concerns/cycle_analytics_params.rb @@ -23,7 +23,10 @@ module CycleAnalyticsParams opts[:from] = params[:from] || start_date(params) opts[:to] = params[:to] if params[:to] opts[:end_event_filter] = params[:end_event_filter] if params[:end_event_filter] - opts[:use_aggregated_data_collector] = params[:use_aggregated_data_collector] if params[:use_aggregated_data_collector] + if params[:use_aggregated_data_collector] + opts[:use_aggregated_data_collector] = params[:use_aggregated_data_collector] + end + opts.merge!(params.slice(*::Gitlab::Analytics::CycleAnalytics::RequestParams::FINDER_PARAM_NAMES)) opts.merge!(date_range(params)) end diff --git a/app/controllers/concerns/enforces_two_factor_authentication.rb b/app/controllers/concerns/enforces_two_factor_authentication.rb index b1b6e21644e..c8de041d5bd 100644 --- a/app/controllers/concerns/enforces_two_factor_authentication.rb +++ b/app/controllers/concerns/enforces_two_factor_authentication.rb @@ -10,19 +10,12 @@ module EnforcesTwoFactorAuthentication extend ActiveSupport::Concern - MFA_HELP_PAGE = Rails.application.routes.url_helpers.help_page_url( - 'user/profile/account/two_factor_authentication.html', - anchor: 'enable-two-factor-authentication' - ) - included do before_action :check_two_factor_requirement, except: [:route_not_found] # to include this in controllers inheriting from `ActionController::Metal` # we need to add this block - if respond_to?(:helper_method) - helper_method :two_factor_grace_period_expired?, :two_factor_skippable? - end + helper_method :two_factor_grace_period_expired?, :two_factor_skippable? if respond_to?(:helper_method) end def check_two_factor_requirement @@ -33,7 +26,7 @@ module EnforcesTwoFactorAuthentication when GraphqlController render_error( _("Authentication error: enable 2FA in your profile settings to continue using GitLab: %{mfa_help_page}") % - { mfa_help_page: MFA_HELP_PAGE }, + { mfa_help_page: mfa_help_page_url }, status: :unauthorized ) else @@ -84,6 +77,13 @@ module EnforcesTwoFactorAuthentication def two_factor_verifier @two_factor_verifier ||= Gitlab::Auth::TwoFactorAuthVerifier.new(current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables end + + def mfa_help_page_url + Rails.application.routes.url_helpers.help_page_url( + 'user/profile/account/two_factor_authentication.html', + anchor: 'enable-two-factor-authentication' + ) + end end EnforcesTwoFactorAuthentication.prepend_mod_with('EnforcesTwoFactorAuthentication') diff --git a/app/controllers/concerns/impersonation.rb b/app/controllers/concerns/impersonation.rb index 539dd9ad69d..e562cf5dbe4 100644 --- a/app/controllers/concerns/impersonation.rb +++ b/app/controllers/concerns/impersonation.rb @@ -3,11 +3,11 @@ module Impersonation include Gitlab::Utils::StrongMemoize - SESSION_KEYS_TO_DELETE = %w( + SESSION_KEYS_TO_DELETE = %w[ github_access_token gitea_access_token gitlab_access_token bitbucket_token bitbucket_refresh_token bitbucket_server_personal_access_token bulk_import_gitlab_access_token fogbugz_token - ).freeze + ].freeze def current_user user = super diff --git a/app/controllers/concerns/import/github_oauth.rb b/app/controllers/concerns/import/github_oauth.rb index d53022aabf2..c233f5d09fa 100644 --- a/app/controllers/concerns/import/github_oauth.rb +++ b/app/controllers/concerns/import/github_oauth.rb @@ -53,6 +53,7 @@ module Import def authorize_url state = SecureRandom.base64(64) session[auth_state_key] = state + session[:auth_on_failure_path] = "#{new_project_path}#import_project" if Feature.enabled?(:remove_legacy_github_client) oauth_client.auth_code.authorize_url( redirect_uri: callback_import_url, diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb index 30de4a86bec..74d998503b7 100644 --- a/app/controllers/concerns/integrations/params.rb +++ b/app/controllers/concerns/integrations/params.rb @@ -88,7 +88,9 @@ module Integrations param_values = return_value[:integration] if param_values.is_a?(ActionController::Parameters) - if action_name == 'update' && integration.chat? && param_values['webhook'] == BaseChatNotification::SECRET_MASK + if %w[update test].include?(action_name) && integration.chat? && + param_values['webhook'] == BaseChatNotification::SECRET_MASK + param_values.delete('webhook') end diff --git a/app/controllers/concerns/invisible_captcha_on_signup.rb b/app/controllers/concerns/invisible_captcha_on_signup.rb index c7fd6d08744..b78869e02d0 100644 --- a/app/controllers/concerns/invisible_captcha_on_signup.rb +++ b/app/controllers/concerns/invisible_captcha_on_signup.rb @@ -13,7 +13,7 @@ module InvisibleCaptchaOnSignup invisible_captcha_honeypot_counter.increment log_request('Invisible_Captcha_Honeypot_Request') - head(200) + head(:ok) end def on_timestamp_spam_callback diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index bea184e44b9..0669f051457 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -146,13 +146,17 @@ module IssuableActions finder = Issuable::DiscussionsListService.new(current_user, issuable, finder_params_for_issuable) discussion_notes = finder.execute - response.headers['X-Next-Page-Cursor'] = finder.paginator.cursor_for_next_page if finder.paginator.present? && finder.paginator.has_next_page? + if finder.paginator.present? && finder.paginator.has_next_page? + response.headers['X-Next-Page-Cursor'] = finder.paginator.cursor_for_next_page + end case issuable when MergeRequest render_mr_discussions(discussion_notes, discussion_serializer, discussion_cache_context) when Issue - render json: discussion_serializer.represent(discussion_notes, context: self) if stale?(etag: [discussion_cache_context, discussion_notes]) + if stale?(etag: [discussion_cache_context, discussion_notes]) + render json: discussion_serializer.represent(discussion_notes, context: self) + end else render json: discussion_serializer.represent(discussion_notes, context: self) end @@ -173,7 +177,7 @@ module IssuableActions def render_cached_discussions(discussions, serializer, cache_context) render_cached(discussions, with: serializer, - cache_context: -> (_) { cache_context }, + cache_context: ->(_) { cache_context }, context: self) end @@ -230,15 +234,11 @@ module IssuableActions end def authorize_destroy_issuable! - unless can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable) - access_denied! - end + access_denied! unless can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable) end def authorize_admin_issuable! - unless can?(current_user, :"admin_#{resource_name}", parent) - access_denied! - end + access_denied! unless can?(current_user, :"admin_#{resource_name}", parent) end def authorize_update_issuable! diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index de38d26e3fe..7b0d8cf8dcb 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -14,7 +14,9 @@ module IssuableCollections private def show_alert_if_search_is_disabled - return if current_user || params[:search].blank? || !html_request? || Feature.disabled?(:disable_anonymous_search, type: :ops) + if current_user || params[:search].blank? || !html_request? || Feature.disabled?(:disable_anonymous_search, type: :ops) + return + end flash.now[:notice] = _('You must sign in to search for specific terms.') end diff --git a/app/controllers/concerns/issues_calendar.rb b/app/controllers/concerns/issues_calendar.rb index 51d6d3cf05a..692ac5e700b 100644 --- a/app/controllers/concerns/issues_calendar.rb +++ b/app/controllers/concerns/issues_calendar.rb @@ -16,9 +16,7 @@ module IssuesCalendar # the content as a file (even ignoring the Content-Disposition # header). We want to display the content inline when accessed # from GitLab, similarly to the RSS feed. - if request.referer&.start_with?(::Settings.gitlab.base_url) - response.headers['Content-Type'] = 'text/plain' - end + response.headers['Content-Type'] = 'text/plain' if request.referer&.start_with?(::Settings.gitlab.base_url) end end end diff --git a/app/controllers/concerns/labels_as_hash.rb b/app/controllers/concerns/labels_as_hash.rb index e428520f709..601d3bf50eb 100644 --- a/app/controllers/concerns/labels_as_hash.rb +++ b/app/controllers/concerns/labels_as_hash.rb @@ -16,9 +16,7 @@ module LabelsAsHash if already_set_labels.present? titles = already_set_labels.map(&:title) label_hashes.each do |hash| - if titles.include?(hash['title']) - hash[:set] = true - end + hash[:set] = true if titles.include?(hash['title']) end end end diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb index 97df3c7caea..1653b40bad5 100644 --- a/app/controllers/concerns/lfs_request.rb +++ b/app/controllers/concerns/lfs_request.rb @@ -78,25 +78,27 @@ module LfsRequest end def lfs_download_access? - strong_memoize(:lfs_download_access) do - ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? || deploy_token_can_download_code? - end + ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? || deploy_token_can_download_code? end + strong_memoize_attr :lfs_download_access?, :lfs_download_access def deploy_token_can_download_code? deploy_token.present? && - deploy_token.project == project && - deploy_token.active? && + deploy_token.has_access_to?(project) && deploy_token.read_repository? end def lfs_upload_access? - strong_memoize(:lfs_upload_access) do - next false unless has_authentication_ability?(:push_code) - next false if limit_exceeded? + return false unless has_authentication_ability?(:push_code) + return false if limit_exceeded? - lfs_deploy_token? || can?(user, :push_code, project) || can?(deploy_token, :push_code, project) - end + lfs_deploy_token? || can?(user, :push_code, +project) || can?(deploy_token, :push_code, project) || any_branch_allows_collaboration? + end + strong_memoize_attr :lfs_upload_access?, :lfs_upload_access + + def any_branch_allows_collaboration? + project.merge_requests_allowing_push_to_user(user).any? end def lfs_deploy_token? diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb index 8a67b62f28b..28d0af7a118 100644 --- a/app/controllers/concerns/membership_actions.rb +++ b/app/controllers/concerns/membership_actions.rb @@ -40,17 +40,15 @@ module MembershipActions respond_to do |format| format.html do message = - begin - case membershipable - when Namespace - if skip_subresources - _("User was successfully removed from group.") - else - _("User was successfully removed from group and any subgroups and projects.") - end + case membershipable + when Namespace + if skip_subresources + _("User was successfully removed from group.") else - _("User was successfully removed from project.") + _("User was successfully removed from group and any subgroups and projects.") end + else + _("User was successfully removed from project.") end redirect_to members_page_url, notice: message diff --git a/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb b/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb index 65237b552ca..ea9fd2de961 100644 --- a/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb +++ b/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb @@ -12,9 +12,7 @@ module Metrics::Dashboard::PrometheusApiProxy variable_substitution_result = proxy_variable_substitution_service.new(proxyable, permit_params).execute - if variable_substitution_result[:status] == :error - return error_response(variable_substitution_result) - end + return error_response(variable_substitution_result) if variable_substitution_result[:status] == :error prometheus_result = ::Prometheus::ProxyService.new( proxyable, diff --git a/app/controllers/concerns/metrics_dashboard.rb b/app/controllers/concerns/metrics_dashboard.rb index 28d0692d748..d4e8e95e016 100644 --- a/app/controllers/concerns/metrics_dashboard.rb +++ b/app/controllers/concerns/metrics_dashboard.rb @@ -118,9 +118,7 @@ module MetricsDashboard def decoded_params params = metrics_dashboard_params - if params[:dashboard_path] - params[:dashboard_path] = CGI.unescape(params[:dashboard_path]) - end + params[:dashboard_path] = CGI.unescape(params[:dashboard_path]) if params[:dashboard_path] params end diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb index 0a859bd3af9..e1967c50d70 100644 --- a/app/controllers/concerns/milestone_actions.rb +++ b/app/controllers/concerns/milestone_actions.rb @@ -8,9 +8,9 @@ module MilestoneActions format.html { redirect_to milestone_redirect_path } format.json do render json: tabs_json("shared/milestones/_issues_tab", { - issues: @milestone.sorted_issues(current_user), # rubocop:disable Gitlab/ModuleWithInstanceVariables - show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name]) - }) + issues: @milestone.sorted_issues(current_user), # rubocop:disable Gitlab/ModuleWithInstanceVariables + show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name]) + }) end end end @@ -20,9 +20,9 @@ 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).preload_milestoneish_associations, # rubocop:disable Gitlab/ModuleWithInstanceVariables - show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name]) - }) + 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 end end @@ -32,8 +32,8 @@ module MilestoneActions format.html { redirect_to milestone_redirect_path } format.json do render json: tabs_json("shared/milestones/_participants_tab", { - users: @milestone.issue_participants_visible_by_user(current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables - }) + users: @milestone.issue_participants_visible_by_user(current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables + }) end end end @@ -46,10 +46,10 @@ module MilestoneActions milestone_labels = @milestone.issue_labels_visible_by_user(current_user) render json: tabs_json("shared/milestones/_labels_tab", { - labels: milestone_labels.map do |label| - label.present(issuable_subject: @milestone.resource_parent) - end - }) + labels: milestone_labels.map do |label| + label.present(issuable_subject: @milestone.resource_parent) + end + }) end end end diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index b595c3c6790..a41e2d840ac 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -89,9 +89,7 @@ module NotesActions # rubocop:enable Gitlab/ModuleWithInstanceVariables def destroy - if note.editable? - Notes::DestroyService.new(project, current_user).execute(note) - end + Notes::DestroyService.new(project, current_user).execute(note) if note.editable? respond_to do |format| format.js { head :ok } @@ -258,15 +256,14 @@ module NotesActions end def last_fetched_at - strong_memoize(:last_fetched_at) do - microseconds = request.headers['X-Last-Fetched-At'].to_i + microseconds = request.headers['X-Last-Fetched-At'].to_i - seconds = microseconds / MICROSECOND - frac = microseconds % MICROSECOND + seconds = microseconds / MICROSECOND + frac = microseconds % MICROSECOND - Time.zone.at(seconds, frac) - end + Time.zone.at(seconds, frac) end + strong_memoize_attr :last_fetched_at def notes_filter current_user&.notes_filter_for(params[:target_type]) @@ -285,23 +282,22 @@ module NotesActions end def note_project - strong_memoize(:note_project) do - next nil unless project + return unless project - note_project_id = params[:note_project_id] + note_project_id = params[:note_project_id] - the_project = - if note_project_id.present? - Project.find(note_project_id) - else - project - end + the_project = + if note_project_id.present? + Project.find(note_project_id) + else + project + end - next access_denied! unless can?(current_user, :create_note, the_project) + return access_denied! unless can?(current_user, :create_note, the_project) - the_project - end + the_project end + strong_memoize_attr :note_project def return_discussion? Gitlab::Utils.to_boolean(params[:return_discussion]) diff --git a/app/controllers/concerns/oauth_applications.rb b/app/controllers/concerns/oauth_applications.rb index 8e63cc391ff..5b6fe933fda 100644 --- a/app/controllers/concerns/oauth_applications.rb +++ b/app/controllers/concerns/oauth_applications.rb @@ -12,9 +12,7 @@ module OauthApplications def prepare_scopes scopes = params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil) - if scopes - params[:doorkeeper_application][:scopes] = scopes.join(' ') - end + params[:doorkeeper_application][:scopes] = scopes.join(' ') if scopes end def set_created_session @@ -30,7 +28,7 @@ module OauthApplications end def permitted_params - %i{name redirect_uri scopes confidential} + %i[name redirect_uri scopes confidential] end def application_params diff --git a/app/controllers/concerns/observability/content_security_policy.rb b/app/controllers/concerns/observability/content_security_policy.rb new file mode 100644 index 00000000000..eccd1e1e3ef --- /dev/null +++ b/app/controllers/concerns/observability/content_security_policy.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Observability + module ContentSecurityPolicy + extend ActiveSupport::Concern + + included do + content_security_policy do |p| + next if p.directives.blank? || Gitlab::Observability.observability_url.blank? + + default_frame_src = p.directives['frame-src'] || p.directives['default-src'] + + # When ObservabilityUI is not authenticated, it needs to be able + # to redirect to the GL sign-in page, hence '/users/sign_in' and '/oauth/authorize' + frame_src_values = Array.wrap(default_frame_src) | [Gitlab::Observability.observability_url, + Gitlab::Utils.append_path(Gitlab.config.gitlab.url, +'/users/sign_in'), + Gitlab::Utils.append_path(Gitlab.config.gitlab.url, +'/oauth/authorize')] + + p.frame_src(*frame_src_values) + end + end + end +end diff --git a/app/controllers/concerns/page_limiter.rb b/app/controllers/concerns/page_limiter.rb index 362b02e5856..1d044a41899 100644 --- a/app/controllers/concerns/page_limiter.rb +++ b/app/controllers/concerns/page_limiter.rb @@ -44,10 +44,11 @@ module PageLimiter raise PageLimitNotANumberError unless max_page_number.is_a?(Integer) raise PageLimitNotSensibleError unless max_page_number > 0 - if params[:page].present? && params[:page].to_i > max_page_number - record_page_limit_interception - raise PageOutOfBoundsError, max_page_number - end + return if params[:page].blank? + return if params[:page].to_i <= max_page_number + + record_page_limit_interception + raise PageOutOfBoundsError, max_page_number end # By default just return a HTTP status code and an empty response diff --git a/app/controllers/concerns/paginated_collection.rb b/app/controllers/concerns/paginated_collection.rb index fcee4493314..94a52dd0f89 100644 --- a/app/controllers/concerns/paginated_collection.rb +++ b/app/controllers/concerns/paginated_collection.rb @@ -10,9 +10,7 @@ module PaginatedCollection out_of_range = collection.current_page > total_pages - if out_of_range - redirect_to(url_for(safe_params.merge(page: total_pages, only_path: true))) - end + redirect_to(url_for(safe_params.merge(page: total_pages, only_path: true))) if out_of_range out_of_range end diff --git a/app/controllers/concerns/preferred_language_switcher.rb b/app/controllers/concerns/preferred_language_switcher.rb index 9711e57cf7a..00cd0f9d1d5 100644 --- a/app/controllers/concerns/preferred_language_switcher.rb +++ b/app/controllers/concerns/preferred_language_switcher.rb @@ -16,3 +16,5 @@ module PreferredLanguageSwitcher Gitlab::CurrentSettings.default_preferred_language end end + +PreferredLanguageSwitcher.prepend_mod diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb index 7af114313a1..a7655efe7a9 100644 --- a/app/controllers/concerns/preview_markdown.rb +++ b/app/controllers/concerns/preview_markdown.rb @@ -45,7 +45,13 @@ module PreviewMarkdown when 'projects' then projects_filter_params when 'timeline_events' then timeline_events_filter_params else {} - end.merge(requested_path: params[:path], ref: params[:ref]) + end.merge( + requested_path: params[:path], + ref: params[:ref], + # Disable comments in markdown for IE browsers because comments in IE + # could allow script execution. + allow_comments: !browser.ie? + ) end # rubocop:enable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb index dfa159ccfd7..b01320ce3ec 100644 --- a/app/controllers/concerns/product_analytics_tracking.rb +++ b/app/controllers/concerns/product_analytics_tracking.rb @@ -16,7 +16,7 @@ module ProductAnalyticsTracking end end - def track_custom_event(*controller_actions, name:, conditions: nil, action:, label:, destinations: [:redis_hll], &block) + def track_custom_event(*controller_actions, name:, action:, label:, conditions: nil, destinations: [:redis_hll], &block) custom_conditions = [:trackable_html_request?, *conditions] after_action only: controller_actions, if: custom_conditions do @@ -30,15 +30,15 @@ module ProductAnalyticsTracking def route_events_to(destinations, name, &block) track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll) - if destinations.include?(:snowplow) && event_enabled?(name) - Gitlab::Tracking.event( - self.class.to_s, - name, - namespace: tracking_namespace_source, - user: current_user, - context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context] - ) - end + return unless destinations.include?(:snowplow) && event_enabled?(name) + + Gitlab::Tracking.event( + self.class.to_s, + name, + namespace: tracking_namespace_source, + user: current_user, + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context] + ) end def route_custom_events_to(destinations, name, action, label, &block) @@ -64,30 +64,32 @@ module ProductAnalyticsTracking def event_enabled?(event) events_to_ff = { - g_analytics_valuestream: :route_hll_to_snowplow, - - i_search_paid: :route_hll_to_snowplow_phase2, - i_search_total: :route_hll_to_snowplow_phase2, - i_search_advanced: :route_hll_to_snowplow_phase2, - i_ecosystem_jira_service_list_issues: :route_hll_to_snowplow_phase2, - users_viewing_analytics_group_devops_adoption: :route_hll_to_snowplow_phase2, - i_analytics_dev_ops_adoption: :route_hll_to_snowplow_phase2, - i_analytics_dev_ops_score: :route_hll_to_snowplow_phase2, - p_analytics_merge_request: :route_hll_to_snowplow_phase2, - i_analytics_instance_statistics: :route_hll_to_snowplow_phase2, - g_analytics_contribution: :route_hll_to_snowplow_phase2, - p_analytics_pipelines: :route_hll_to_snowplow_phase2, - p_analytics_code_reviews: :route_hll_to_snowplow_phase2, - p_analytics_valuestream: :route_hll_to_snowplow_phase2, - p_analytics_insights: :route_hll_to_snowplow_phase2, - p_analytics_issues: :route_hll_to_snowplow_phase2, - p_analytics_repo: :route_hll_to_snowplow_phase2, - g_analytics_insights: :route_hll_to_snowplow_phase2, - g_analytics_issues: :route_hll_to_snowplow_phase2, - g_analytics_productivity: :route_hll_to_snowplow_phase2, - i_analytics_cohorts: :route_hll_to_snowplow_phase2 + g_analytics_valuestream: '', + + i_search_paid: :_phase2, + i_search_total: :_phase2, + i_search_advanced: :_phase2, + i_ecosystem_jira_service_list_issues: :_phase2, + users_viewing_analytics_group_devops_adoption: :_phase2, + i_analytics_dev_ops_adoption: :_phase2, + i_analytics_dev_ops_score: :_phase2, + p_analytics_merge_request: :_phase2, + i_analytics_instance_statistics: :_phase2, + g_analytics_contribution: :_phase2, + p_analytics_pipelines: :_phase2, + p_analytics_code_reviews: :_phase2, + p_analytics_valuestream: :_phase2, + p_analytics_insights: :_phase2, + p_analytics_issues: :_phase2, + p_analytics_repo: :_phase2, + g_analytics_insights: :_phase2, + g_analytics_issues: :_phase2, + g_analytics_productivity: :_phase2, + i_analytics_cohorts: :_phase2, + + g_compliance_dashboard: :_phase4 } - Feature.enabled?(events_to_ff[event.to_sym], tracking_namespace_source) + Feature.enabled?("route_hll_to_snowplow#{events_to_ff[event.to_sym]}", tracking_namespace_source) end end diff --git a/app/controllers/concerns/record_user_last_activity.rb b/app/controllers/concerns/record_user_last_activity.rb index 29164df4516..6ac87d8f27b 100644 --- a/app/controllers/concerns/record_user_last_activity.rb +++ b/app/controllers/concerns/record_user_last_activity.rb @@ -18,9 +18,8 @@ module RecordUserLastActivity def set_user_last_activity return unless request.get? return if Gitlab::Database.read_only? + return unless current_user && current_user.last_activity_on != Date.today - if current_user && current_user.last_activity_on != Date.today - Users::ActivityService.new(current_user).execute - end + Users::ActivityService.new(current_user).execute end end diff --git a/app/controllers/concerns/render_service_results.rb b/app/controllers/concerns/render_service_results.rb index 0149a71d9f5..83b880096be 100644 --- a/app/controllers/concerns/render_service_results.rb +++ b/app/controllers/concerns/render_service_results.rb @@ -5,25 +5,25 @@ module RenderServiceResults def success_response(result) render({ - status: result[:http_status], - json: result[:body] - }) + status: result[:http_status], + json: result[:body] + }) end def continue_polling_response render({ - status: :no_content, - json: { - status: _('processing'), - message: _('Not ready yet. Try again later.') - } - }) + status: :no_content, + json: { + status: _('processing'), + message: _('Not ready yet. Try again later.') + } + }) end def error_response(result) render({ - status: result[:http_status] || :bad_request, - json: { status: result[:status], message: result[:message] } - }) + status: result[:http_status] || :bad_request, + json: { status: result[:status], message: result[:message] } + }) end end diff --git a/app/controllers/concerns/renders_ldap_servers.rb b/app/controllers/concerns/renders_ldap_servers.rb index cc83ff47048..8c3d9fd4d5c 100644 --- a/app/controllers/concerns/renders_ldap_servers.rb +++ b/app/controllers/concerns/renders_ldap_servers.rb @@ -8,12 +8,10 @@ module RendersLdapServers end def ldap_servers - @ldap_servers ||= begin - if Gitlab::Auth::Ldap::Config.sign_in_enabled? - Gitlab::Auth::Ldap::Config.available_servers - else - [] - end - end + @ldap_servers ||= if Gitlab::Auth::Ldap::Config.sign_in_enabled? + Gitlab::Auth::Ldap::Config.available_servers + else + [] + end end end diff --git a/app/controllers/concerns/routable_actions.rb b/app/controllers/concerns/routable_actions.rb index e34d6b09c24..28e1fa473b3 100644 --- a/app/controllers/concerns/routable_actions.rb +++ b/app/controllers/concerns/routable_actions.rb @@ -46,13 +46,13 @@ module RoutableActions return unless request.get? canonical_path = routable.full_path - if canonical_path != routable_full_path - if !request.xhr? && request.format.html? && canonical_path.casecmp(routable_full_path) != 0 - flash[:notice] = "#{routable.class.to_s.titleize} '#{routable_full_path}' was moved to '#{canonical_path}'. Please update any links and bookmarks that may still have the old path." - end + return unless canonical_path != routable_full_path - redirect_to build_canonical_path(routable), status: :moved_permanently + if !request.xhr? && request.format.html? && canonical_path.casecmp(routable_full_path) != 0 + flash[:notice] = "#{routable.class.to_s.titleize} '#{routable_full_path}' was moved to '#{canonical_path}'. Please update any links and bookmarks that may still have the old path." end + + redirect_to build_canonical_path(routable), status: :moved_permanently end end diff --git a/app/controllers/concerns/snippets/blobs_actions.rb b/app/controllers/concerns/snippets/blobs_actions.rb index b510594ad63..2a0491b4df8 100644 --- a/app/controllers/concerns/snippets/blobs_actions.rb +++ b/app/controllers/concerns/snippets/blobs_actions.rb @@ -25,14 +25,13 @@ module Snippets::BlobsActions # rubocop:disable Gitlab/ModuleWithInstanceVariables def blob - strong_memoize(:blob) do - assign_ref_vars + assign_ref_vars - next unless @commit + return unless @commit - @repo.blob_at(@commit.id, @path) - end + @repo.blob_at(@commit.id, @path) end + strong_memoize_attr :blob # rubocop:enable Gitlab/ModuleWithInstanceVariables def ensure_blob @@ -40,11 +39,11 @@ module Snippets::BlobsActions end def ensure_repository - unless snippet.repo_exists? - Gitlab::AppLogger.error(message: "Snippet raw blob attempt with no repo", snippet: snippet.id) + return if snippet.repo_exists? - respond_422 - end + Gitlab::AppLogger.error(message: "Snippet raw blob attempt with no repo", snippet: snippet.id) + + respond_422 end def snippet_id diff --git a/app/controllers/concerns/sorting_preference.rb b/app/controllers/concerns/sorting_preference.rb index 6278b489028..300c1d6d779 100644 --- a/app/controllers/concerns/sorting_preference.rb +++ b/app/controllers/concerns/sorting_preference.rb @@ -45,9 +45,7 @@ module SortingPreference return sort_param if Gitlab::Database.read_only? - if user_preference[field] != sort_param - user_preference.update(field => sort_param) - end + user_preference.update(field => sort_param) if user_preference[field] != sort_param sort_param end diff --git a/app/controllers/concerns/sourcegraph_decorator.rb b/app/controllers/concerns/sourcegraph_decorator.rb index 061990a4361..4aeace1ca67 100644 --- a/app/controllers/concerns/sourcegraph_decorator.rb +++ b/app/controllers/concerns/sourcegraph_decorator.rb @@ -22,8 +22,8 @@ module SourcegraphDecorator return unless sourcegraph_enabled? gon.push({ - sourcegraph: { url: Gitlab::CurrentSettings.sourcegraph_url } - }) + sourcegraph: { url: Gitlab::CurrentSettings.sourcegraph_url } + }) end def sourcegraph_enabled? diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb index e98d36854f1..0ba13896631 100644 --- a/app/controllers/concerns/uploads_actions.rb +++ b/app/controllers/concerns/uploads_actions.rb @@ -5,7 +5,7 @@ module UploadsActions include Gitlab::Utils::StrongMemoize include SendFileUpload - UPLOAD_MOUNTS = %w(avatar attachment file logo header_logo favicon).freeze + UPLOAD_MOUNTS = %w[avatar attachment file logo header_logo favicon].freeze included do prepend_before_action :set_request_format_from_path_extension @@ -73,11 +73,11 @@ module UploadsActions def set_request_format_from_path_extension path = request.headers['action_dispatch.original_path'] || request.headers['PATH_INFO'] - if match = path&.match(/\.(\w+)\z/) - format = Mime[match.captures.first] + return unless match = path&.match(/\.(\w+)\z/) - request.format = format.symbol if format - end + format = Mime[match.captures.first] + + request.format = format.symbol if format end def content_disposition @@ -102,14 +102,13 @@ module UploadsActions end def uploader - strong_memoize(:uploader) do - if uploader_mounted? - model.public_send(upload_mount) # rubocop:disable GitlabSecurity/PublicSend - else - build_uploader_from_upload || build_uploader_from_params - end + if uploader_mounted? + model.public_send(upload_mount) # rubocop:disable GitlabSecurity/PublicSend + else + build_uploader_from_upload || build_uploader_from_params end end + strong_memoize_attr :uploader # rubocop: disable CodeReuse/ActiveRecord def build_uploader_from_upload @@ -163,8 +162,9 @@ module UploadsActions end def model - strong_memoize(:model) { find_model } + find_model end + strong_memoize_attr :model def workhorse_authorize_request? action_name == 'authorize' diff --git a/app/controllers/concerns/verifies_with_email.rb b/app/controllers/concerns/verifies_with_email.rb index ac1475597ff..3cada24a81a 100644 --- a/app/controllers/concerns/verifies_with_email.rb +++ b/app/controllers/concerns/verifies_with_email.rb @@ -28,7 +28,7 @@ module VerifiesWithEmail if user.unlock_token # Prompt for the token if it already has been set prompt_for_email_verification(user) - elsif user.access_locked? || !AuthenticationEvent.initial_login_or_known_ip_address?(user, request.ip) + elsif user.access_locked? || !trusted_ip_address?(user) # require email verification if: # - their account has been locked because of too many failed login attempts, or # - they have logged in before, but never from the current ip address @@ -68,7 +68,7 @@ module VerifiesWithEmail # After successful verification and calling sign_in, devise redirects the # user to this path. Override it to show the successful verified page. def after_sign_in_path_for(resource) - if action_name == 'create' && session[:verification_user_id] + if action_name == 'create' && session[:verification_user_id] == resource.id return users_successful_verification_path end @@ -133,6 +133,12 @@ module VerifiesWithEmail sign_in(user) end + def trusted_ip_address?(user) + return true if Feature.disabled?(:check_ip_address_for_email_verification) + + AuthenticationEvent.initial_login_or_known_ip_address?(user, request.ip) + end + def prompt_for_email_verification(user) session[:verification_user_id] = user.id self.resource = user diff --git a/app/controllers/concerns/vscode_cdn_csp.rb b/app/controllers/concerns/vscode_cdn_csp.rb new file mode 100644 index 00000000000..dc8cea966e5 --- /dev/null +++ b/app/controllers/concerns/vscode_cdn_csp.rb @@ -0,0 +1,17 @@ +# rubocop:disable Naming/FileName +# frozen_string_literal: true + +module VSCodeCDNCSP + extend ActiveSupport::Concern + + included do + content_security_policy do |policy| + next if policy.directives.blank? + + default_src = Array(policy.directives['default-src'] || []) + policy.directives['frame-src'] ||= default_src + policy.directives['frame-src'].concat(['https://*.vscode-cdn.net/']) + end + end +end +# rubocop:enable Naming/FileName diff --git a/app/controllers/concerns/web_hooks/hook_actions.rb b/app/controllers/concerns/web_hooks/hook_actions.rb index 75065ef9d24..f61600af951 100644 --- a/app/controllers/concerns/web_hooks/hook_actions.rb +++ b/app/controllers/concerns/web_hooks/hook_actions.rb @@ -18,7 +18,9 @@ module WebHooks self.hook = relation.new(hook_params) hook.save - unless hook.valid? + if hook.valid? + flash[:notice] = _('Webhook was created') + else self.hooks = relation.select(&:persisted?) flash[:alert] = hook.errors.full_messages.to_sentence.html_safe end @@ -28,8 +30,8 @@ module WebHooks def update if hook.update(hook_params) - flash[:notice] = _('Hook was successfully updated.') - redirect_to action: :index + flash[:notice] = _('Webhook was updated') + redirect_to action: :edit else render 'edit' end @@ -66,21 +68,14 @@ module WebHooks end def hook_param_names - param_names = %i[enable_ssl_verification token url push_events_branch_filter] - param_names.push(:branch_filter_strategy) if Feature.enabled?(:enhanced_webhook_support_regex) - param_names + %i[enable_ssl_verification token url push_events_branch_filter branch_filter_strategy] end def destroy_hook(hook) result = WebHooks::DestroyService.new(current_user).execute(hook) if result[:status] == :success - flash[:notice] = - if result[:async] - format(_("%{hook_type} was scheduled for deletion"), hook_type: hook.model_name.human) - else - format(_("%{hook_type} was deleted"), hook_type: hook.model_name.human) - end + flash[:notice] = result[:async] ? _('Webhook was scheduled for deletion') : _('Webhook was deleted') else flash[:alert] = result[:message] end diff --git a/app/controllers/dashboard/snippets_controller.rb b/app/controllers/dashboard/snippets_controller.rb index 5a885349467..d72a5e44b9f 100644 --- a/app/controllers/dashboard/snippets_controller.rb +++ b/app/controllers/dashboard/snippets_controller.rb @@ -7,7 +7,7 @@ class Dashboard::SnippetsController < Dashboard::ApplicationController skip_cross_project_access_check :index - feature_category :snippets + feature_category :source_code_management def index @snippet_counts = Snippets::CountService diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index d2434d4b0ba..3005d19f8ed 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -3,6 +3,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController include ActionView::Helpers::NumberHelper include PaginatedCollection + include Gitlab::Utils::StrongMemoize before_action :authorize_read_project!, only: :index before_action :authorize_read_group!, only: :index @@ -64,19 +65,19 @@ class Dashboard::TodosController < Dashboard::ApplicationController def authorize_read_project! project_id = params[:project_id] - if project_id.present? - project = Project.find(project_id) - render_404 unless can?(current_user, :read_project, project) - end + return unless project_id.present? + + project = Project.find(project_id) + render_404 unless can?(current_user, :read_project, project) end def authorize_read_group! group_id = params[:group_id] - if group_id.present? - group = Group.find(group_id) - render_404 unless can?(current_user, :read_group, group) - end + return unless group_id.present? + + group = Group.find(group_id) + render_404 unless can?(current_user, :read_group, group) end def find_todos @@ -99,14 +100,28 @@ class Dashboard::TodosController < Dashboard::ApplicationController end def todo_params - aliased_action_id( + aliased_params( params.permit(:action_id, :author_id, :project_id, :type, :sort, :state, :group_id) ) end + strong_memoize_attr :todo_params + + def aliased_params(original_params) + alias_issue_type(original_params) + alias_action_id(original_params) + + original_params + end + + def alias_issue_type(original_params) + return unless original_params[:type] == Issue.name + + original_params[:type] = [Issue.name, WorkItem.name] + end - def aliased_action_id(original_params) - return original_params unless original_params[:action_id].to_i == ::Todo::MENTIONED + def alias_action_id(original_params) + return unless original_params[:action_id].to_i == ::Todo::MENTIONED - original_params.merge(action_id: [::Todo::MENTIONED, ::Todo::DIRECTLY_ADDRESSED]) + original_params[:action_id] = [::Todo::MENTIONED, ::Todo::DIRECTLY_ADDRESSED] end end diff --git a/app/controllers/explore/snippets_controller.rb b/app/controllers/explore/snippets_controller.rb index 617cc2e7f3d..dee94b53cc1 100644 --- a/app/controllers/explore/snippets_controller.rb +++ b/app/controllers/explore/snippets_controller.rb @@ -3,7 +3,7 @@ class Explore::SnippetsController < Explore::ApplicationController include Gitlab::NoteableMetadata - feature_category :snippets + feature_category :source_code_management def index @snippets = SnippetsFinder.new(current_user, explore: true) diff --git a/app/controllers/google_api/authorizations_controller.rb b/app/controllers/google_api/authorizations_controller.rb index 5080ee5fbbe..536c5e347e7 100644 --- a/app/controllers/google_api/authorizations_controller.rb +++ b/app/controllers/google_api/authorizations_controller.rb @@ -48,14 +48,13 @@ module GoogleApi end def redirect_uri_from_session - strong_memoize(:redirect_uri_from_session) do - if params[:state].present? - session[session_key_for_redirect_uri(params[:state])] - else - nil - end + if params[:state].present? + session[session_key_for_redirect_uri(params[:state])] + else + nil end end + strong_memoize_attr :redirect_uri_from_session def session_key_for_redirect_uri(state) GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(state) diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 5ffd525c170..942cb9beed4 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -70,6 +70,12 @@ class GraphqlController < ApplicationController end end + rescue_from Gitlab::Auth::TooManyIps do |exception| + log_exception(exception) + + render_error(exception.message, status: :forbidden) + end + rescue_from Gitlab::Graphql::Variables::Invalid do |exception| render_error(exception.message, status: :unprocessable_entity) end diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index f8cfa996447..5440908aee7 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -96,6 +96,28 @@ class Groups::ApplicationController < ApplicationController def validate_root_group! render_404 unless group.root? end + + def authorize_action!(action) + access_denied! unless can?(current_user, action, group) + end + + def respond_to_missing?(method, *args) + case method.to_s + when /\Aauthorize_(.*)!\z/ + true + else + super + end + end + + def method_missing(method_sym, *arguments, &block) + case method_sym.to_s + when /\Aauthorize_(.*)!\z/ + authorize_action!(Regexp.last_match(1).to_sym) + else + super + end + end end Groups::ApplicationController.prepend_mod_with('Groups::ApplicationController') diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index e1ba86220c7..6bb807be1c4 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -20,16 +20,14 @@ class Groups::BoardsController < Groups::ApplicationController private def board_finder - strong_memoize :board_finder do - Boards::BoardsFinder.new(parent, current_user, board_id: params[:id]) - end + Boards::BoardsFinder.new(parent, current_user, board_id: params[:id]) end + strong_memoize_attr :board_finder def board_create_service - strong_memoize :board_create_service do - Boards::CreateService.new(parent, current_user) - end + Boards::CreateService.new(parent, current_user) end + strong_memoize_attr :board_create_service def authorize_read_board! access_denied! unless can?(current_user, :read_issue_board, group) diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb index 2e9e0b12d2f..427df9a7129 100644 --- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb +++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb @@ -117,7 +117,7 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy end def blob_file_name - @blob_file_name ||= params[:sha].sub('sha256:', '') + '.gz' + @blob_file_name ||= "#{params[:sha].sub('sha256:', '')}.gz" end def manifest_file_name diff --git a/app/controllers/groups/observability_controller.rb b/app/controllers/groups/observability_controller.rb index 4b1f2b582ce..3baa5e830ff 100644 --- a/app/controllers/groups/observability_controller.rb +++ b/app/controllers/groups/observability_controller.rb @@ -1,18 +1,9 @@ # frozen_string_literal: true module Groups class ObservabilityController < Groups::ApplicationController - feature_category :tracing - - content_security_policy do |p| - next if p.directives.blank? - - default_frame_src = p.directives['frame-src'] || p.directives['default-src'] + include ::Observability::ContentSecurityPolicy - # When ObservabilityUI is not authenticated, it needs to be able to redirect to the GL sign-in page, hence 'self' - frame_src_values = Array.wrap(default_frame_src) | [observability_url, "'self'"] - - p.frame_src(*frame_src_values) - end + feature_category :tracing before_action :check_observability_allowed @@ -34,16 +25,8 @@ module Groups render 'observability', layout: 'group', locals: { base_layout: 'layouts/fullscreen' } end - def self.observability_url - Gitlab::Observability.observability_url - end - - def observability_url - self.class.observability_url - end - def check_observability_allowed - return render_404 unless observability_url.present? + return render_404 unless Gitlab::Observability.observability_url.present? render_404 unless can?(current_user, :read_observability, @group) end diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index b1afac1f1c7..1dfa8cdf133 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -15,6 +15,8 @@ module Groups urgency :low def show + @entity = :group + @variable_limit = ::Plan.default.actual_limits.group_ci_variables end def update diff --git a/app/controllers/groups/usage_quotas_controller.rb b/app/controllers/groups/usage_quotas_controller.rb new file mode 100644 index 00000000000..29878f0001d --- /dev/null +++ b/app/controllers/groups/usage_quotas_controller.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Groups + class UsageQuotasController < Groups::ApplicationController + before_action :authorize_read_usage_quotas! + before_action :verify_usage_quotas_enabled! + + feature_category :subscription_cost_management + urgency :low + + def index + # To be used in ee/app/controllers/ee/groups/usage_quotas_controller.rb + @seat_count_data = seat_count_data + end + + private + + def verify_usage_quotas_enabled! + render_404 unless Feature.enabled?(:usage_quotas_for_all_editions, group) + render_404 if group.has_parent? + end + + # To be overriden in ee/app/controllers/ee/groups/usage_quotas_controller.rb + def seat_count_data; end + end +end + +Groups::UsageQuotasController.prepend_mod diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb index 220b0b4509c..9ddf6c80c70 100644 --- a/app/controllers/groups/variables_controller.rb +++ b/app/controllers/groups/variables_controller.rb @@ -50,7 +50,7 @@ module Groups end def variable_params_attributes - %i[id variable_type key secret_value protected masked _destroy] + %i[id variable_type key secret_value protected masked raw _destroy] end def authorize_admin_build! diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 3f516c24a69..0a487bb2508 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -386,7 +386,7 @@ class GroupsController < Groups::ApplicationController override :has_project_list? def has_project_list? - %w(details show index).include?(action_name) + %w[details show index].include?(action_name) end def captcha_enabled? diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb index fcf6871d137..8a8c41e65b9 100644 --- a/app/controllers/ide_controller.rb +++ b/app/controllers/ide_controller.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class IdeController < ApplicationController + include VSCodeCDNCSP include ClientsidePreviewCSP include StaticObjectExternalStorageCSP include Gitlab::Utils::StrongMemoize diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 75193309a4e..1d05cee02d4 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -49,6 +49,14 @@ class Import::BitbucketController < Import::BaseController namespace_path = params[:new_namespace].presence || repo_owner target_namespace = find_or_create_namespace(namespace_path, current_user) + Gitlab::Tracking.event( + self.class.name, + 'create', + label: 'import_access_level', + user: current_user, + extra: { user_role: user_role(current_user, target_namespace), import_type: 'bitbucket' } + ) + if current_user.can?(:create_projects, target_namespace) # The token in a session can be expired, we need to get most recent one because # Bitbucket::Connection class refreshes it. @@ -89,6 +97,21 @@ class Import::BitbucketController < Import::BaseController private + def user_role(user, namespace) + if current_user.id == namespace&.owner_id + Gitlab::Access.options_with_owner.key(Gitlab::Access::OWNER) + else + access_level = current_user&.group_members&.find_by(source_id: namespace&.id)&.access_level + + case access_level + when nil + 'Not a member' + else + Gitlab::Access.human_access(access_level) + end + end + end + def oauth_client @oauth_client ||= OAuth2::Client.new(provider.app_id, provider.app_secret, options) end diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb index 655fc7854fe..9a7118ce498 100644 --- a/app/controllers/import/bulk_imports_controller.rb +++ b/app/controllers/import/bulk_imports_controller.rb @@ -135,7 +135,7 @@ class Import::BulkImportsController < ApplicationController session[url_key], allow_localhost: allow_local_requests?, allow_local_network: allow_local_requests?, - schemes: %w(http https) + schemes: %w[http https] ) rescue Gitlab::UrlBlocker::BlockedUrlError => e clear_session_data diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb index 7b580234227..77043e174b4 100644 --- a/app/controllers/import/fogbugz_controller.rb +++ b/app/controllers/import/fogbugz_controller.rb @@ -114,7 +114,7 @@ class Import::FogbugzController < Import::BaseController end def user_map_params - params.permit(users: %w(name email gitlab_user)) + params.permit(users: %w[name email gitlab_user]) end def verify_fogbugz_import_enabled @@ -126,7 +126,7 @@ class Import::FogbugzController < Import::BaseController params[:uri], allow_localhost: allow_local_requests?, allow_local_network: allow_local_requests?, - schemes: %w(http https) + schemes: %w[http https] ) rescue Gitlab::UrlBlocker::BlockedUrlError => e redirect_to new_import_fogbugz_url, alert: _('Specified URL cannot be used: "%{reason}"') % { reason: e.message } diff --git a/app/controllers/import/gitea_controller.rb b/app/controllers/import/gitea_controller.rb index 4b4ac07b389..61e32650db3 100644 --- a/app/controllers/import/gitea_controller.rb +++ b/app/controllers/import/gitea_controller.rb @@ -16,12 +16,27 @@ class Import::GiteaController < Import::GithubController super end - # We need to re-expose controller's internal method 'status' as action. - # rubocop:disable Lint/UselessMethodDefinition def status - super + # Request repos to display error page if provider token is invalid + # Improving in https://gitlab.com/gitlab-org/gitlab/-/issues/25859 + client_repos + + respond_to do |format| + format.json do + render json: { imported_projects: serialized_imported_projects, + provider_repos: serialized_provider_repos, + incompatible_repos: serialized_incompatible_repos } + end + + format.html do + if params[:namespace_id].present? + @namespace = Namespace.find_by_id(params[:namespace_id]) + + render_404 unless current_user.can?(:create_projects, @namespace) + end + end + end end - # rubocop:enable Lint/UselessMethodDefinition protected @@ -61,7 +76,6 @@ class Import::GiteaController < Import::GithubController @client_repos ||= filtered(client.repos) end - override :client def client @client ||= Gitlab::LegacyGithubImport::Client.new(session[access_token_key], **client_options) end @@ -78,7 +92,7 @@ class Import::GiteaController < Import::GithubController provider_url, allow_localhost: allow_local_requests?, allow_local_network: allow_local_requests?, - schemes: %w(http https) + schemes: %w[http https] ) rescue Gitlab::UrlBlocker::BlockedUrlError => e session[access_token_key] = nil diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb index 92763e09ba3..cb58b5974ca 100644 --- a/app/controllers/import/github_controller.rb +++ b/app/controllers/import/github_controller.rb @@ -15,6 +15,8 @@ class Import::GithubController < Import::BaseController rescue_from Octokit::TooManyRequests, with: :provider_rate_limit rescue_from Gitlab::GithubImport::RateLimitError, with: :rate_limit_threshold_exceeded + delegate :client, to: :client_proxy, private: true + PAGE_LENGTH = 25 def new @@ -46,7 +48,22 @@ class Import::GithubController < Import::BaseController # Improving in https://gitlab.com/gitlab-org/gitlab-foss/issues/55585 client_repos - super + respond_to do |format| + format.json do + render json: { imported_projects: serialized_imported_projects, + provider_repos: serialized_provider_repos, + incompatible_repos: serialized_incompatible_repos, + page_info: client_repos_response[:page_info] } + end + + format.html do + if params[:namespace_id].present? + @namespace = Namespace.find_by_id(params[:namespace_id]) + + render_404 unless current_user.can?(:create_projects, @namespace) + end + end + end end def create @@ -126,24 +143,18 @@ class Import::GithubController < Import::BaseController end end - def client - @client ||= if Feature.enabled?(:remove_legacy_github_client) - Gitlab::GithubImport::Client.new(session[access_token_key]) - else - Gitlab::LegacyGithubImport::Client.new(session[access_token_key], **client_options) - end + def client_proxy + @client_proxy ||= Gitlab::GithubImport::Clients::Proxy.new( + session[access_token_key], client_options + ) + end + + def client_repos_response + @client_repos_response ||= client_proxy.repos(sanitized_filter_param, pagination_options) end def client_repos - @client_repos ||= if Feature.enabled?(:remove_legacy_github_client) - if sanitized_filter_param - client.search_repos_by_name(sanitized_filter_param, pagination_options)[:items] - else - client.repos(pagination_options) - end - else - filtered(client.repos) - end + client_repos_response[:repos] end def sanitized_filter_param @@ -213,6 +224,11 @@ class Import::GithubController < Import::BaseController def pagination_options { + before: params[:before].presence, + after: params[:after].presence, + first: PAGE_LENGTH, + # TODO: remove after rollout FF github_client_fetch_repos_via_graphql + # https://gitlab.com/gitlab-org/gitlab/-/issues/385649 page: [1, params[:page].to_i].max, per_page: PAGE_LENGTH } diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb index 16bd73f5ab6..3c50d54fa10 100644 --- a/app/controllers/jira_connect/app_descriptor_controller.rb +++ b/app/controllers/jira_connect/app_descriptor_controller.rb @@ -28,7 +28,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController type: 'jwt' }, modules: modules, - scopes: %w(READ WRITE DELETE), + scopes: %w[READ WRITE DELETE], apiVersion: 1, apiMigrations: { 'context-qsh': true, @@ -76,7 +76,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController jiraDevelopmentTool: { actions: { createBranch: { - templateUrl: new_jira_connect_branch_url + '?issue_key={issue.key}&issue_summary={issue.summary}' + templateUrl: "#{new_jira_connect_branch_url}?issue_key={issue.key}&issue_summary={issue.summary}" } }, key: 'gitlab-development-tool', @@ -84,7 +84,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController name: { value: 'GitLab' }, url: HOME_URL, logoUrl: logo_url, - capabilities: %w(branch commit pull_request) + capabilities: %w[branch commit pull_request] } } end diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb index b9f0ea795e1..e26d69314cd 100644 --- a/app/controllers/jira_connect/application_controller.rb +++ b/app/controllers/jira_connect/application_controller.rb @@ -3,11 +3,6 @@ class JiraConnect::ApplicationController < ApplicationController include Gitlab::Utils::StrongMemoize - CORS_ALLOWED_METHODS = { - '/-/jira_connect/oauth_application_id' => %i[GET OPTIONS], - '/-/jira_connect/subscriptions/*' => %i[DELETE OPTIONS] - }.freeze - skip_before_action :authenticate_user! skip_before_action :verify_authenticity_token before_action :verify_atlassian_jwt! @@ -65,25 +60,4 @@ class JiraConnect::ApplicationController < ApplicationController def auth_token params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last end - - def cors_allowed_methods - CORS_ALLOWED_METHODS[resource] - end - - def resource - request.path.gsub(%r{/\d+$}, '/*') - end - - def set_cors_headers - return unless allow_cors_request? - - response.set_header('Access-Control-Allow-Origin', Gitlab::CurrentSettings.jira_connect_proxy_url) - response.set_header('Access-Control-Allow-Methods', cors_allowed_methods.join(', ')) - end - - def allow_cors_request? - return false if cors_allowed_methods.nil? - - !Gitlab.com? && Gitlab::CurrentSettings.jira_connect_proxy_url.present? - end end diff --git a/app/controllers/jira_connect/cors_preflight_checks_controller.rb b/app/controllers/jira_connect/cors_preflight_checks_controller.rb deleted file mode 100644 index 3f30c1e04df..00000000000 --- a/app/controllers/jira_connect/cors_preflight_checks_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -module JiraConnect - class CorsPreflightChecksController < ApplicationController - feature_category :integrations - - skip_before_action :verify_atlassian_jwt! - before_action :set_cors_headers - - def index - return render_404 unless allow_cors_request? - - render plain: '', content_type: 'text/plain' - end - end -end diff --git a/app/controllers/jira_connect/events_controller.rb b/app/controllers/jira_connect/events_controller.rb index 394fdc9b2f6..fa1e1f505eb 100644 --- a/app/controllers/jira_connect/events_controller.rb +++ b/app/controllers/jira_connect/events_controller.rb @@ -31,7 +31,10 @@ class JiraConnect::EventsController < JiraConnect::ApplicationController end def update_installation - current_jira_installation.update(update_params) + JiraConnectInstallations::UpdateService.execute( + current_jira_installation, + update_params + ).success? end def create_params @@ -56,7 +59,7 @@ class JiraConnect::EventsController < JiraConnect::ApplicationController def jwt_verification_claims { - aud: jira_connect_base_url(protocol: 'https'), + aud: Gitlab.config.jira_connect.enforce_jira_base_url_https ? jira_connect_base_url(protocol: 'https') : jira_connect_base_url, iss: transformed_params[:client_key], qsh: Atlassian::Jwt.create_query_string_hash(request.url, request.method, jira_connect_base_url) } diff --git a/app/controllers/jira_connect/installations_controller.rb b/app/controllers/jira_connect/installations_controller.rb index 401bc4f9c87..44dbf90f5fb 100644 --- a/app/controllers/jira_connect/installations_controller.rb +++ b/app/controllers/jira_connect/installations_controller.rb @@ -6,11 +6,12 @@ class JiraConnect::InstallationsController < JiraConnect::ApplicationController end def update - if current_jira_installation.update(installation_params) + result = update_installation + if result.success? render json: installation_json(current_jira_installation) else render( - json: { errors: current_jira_installation.errors }, + json: { errors: result.message }, status: :unprocessable_entity ) end @@ -18,6 +19,13 @@ class JiraConnect::InstallationsController < JiraConnect::ApplicationController private + def update_installation + JiraConnectInstallations::UpdateService.execute( + current_jira_installation, + installation_params + ) + end + def installation_json(installation) { gitlab_com: installation.instance_url.blank?, diff --git a/app/controllers/jira_connect/oauth_application_ids_controller.rb b/app/controllers/jira_connect/oauth_application_ids_controller.rb index 3e788e2282e..de520337af3 100644 --- a/app/controllers/jira_connect/oauth_application_ids_controller.rb +++ b/app/controllers/jira_connect/oauth_application_ids_controller.rb @@ -5,7 +5,6 @@ module JiraConnect feature_category :integrations skip_before_action :verify_atlassian_jwt! - before_action :set_cors_headers def show if show_application_id? @@ -20,7 +19,7 @@ module JiraConnect def show_application_id? return if Gitlab.com? - Feature.enabled?(:jira_connect_oauth_self_managed) && jira_connect_application_key.present? + jira_connect_application_key.present? end def jira_connect_application_key diff --git a/app/controllers/jira_connect/public_keys_controller.rb b/app/controllers/jira_connect/public_keys_controller.rb index b3144993edb..09003f8478f 100644 --- a/app/controllers/jira_connect/public_keys_controller.rb +++ b/app/controllers/jira_connect/public_keys_controller.rb @@ -10,7 +10,9 @@ module JiraConnect skip_before_action :authenticate_user! def show - return render_404 if Feature.disabled?(:jira_connect_oauth_self_managed) || !Gitlab.com? + if Feature.disabled?(:jira_connect_oauth_self_managed) || !Gitlab.config.jira_connect.enable_public_keys_storage + return render_404 + end render plain: public_key.key end diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb index 9a732cadd94..ff7477a94d6 100644 --- a/app/controllers/jira_connect/subscriptions_controller.rb +++ b/app/controllers/jira_connect/subscriptions_controller.rb @@ -1,19 +1,20 @@ # frozen_string_literal: true class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController + ALLOWED_IFRAME_ANCESTORS = [:self, 'https://*.atlassian.net', 'https://*.jira.com'].freeze layout 'jira_connect' content_security_policy do |p| next if p.directives.blank? # rubocop: disable Lint/PercentStringArray - script_src_values = Array.wrap(p.directives['script-src']) | %w('self' https://connect-cdn.atl-paas.net) - style_src_values = Array.wrap(p.directives['style-src']) | %w('self' 'unsafe-inline') + script_src_values = Array.wrap(p.directives['script-src']) | %w['self' https://connect-cdn.atl-paas.net] + style_src_values = Array.wrap(p.directives['style-src']) | %w['self' 'unsafe-inline'] # rubocop: enable Lint/PercentStringArray # *.jira.com is needed for some legacy Jira Cloud instances, new ones will use *.atlassian.net # https://support.atlassian.com/organization-administration/docs/ip-addresses-and-domains-for-atlassian-cloud-products/ - p.frame_ancestors :self, 'https://*.atlassian.net', 'https://*.jira.com' + p.frame_ancestors(*(ALLOWED_IFRAME_ANCESTORS + Gitlab.config.jira_connect.additional_iframe_ancestors)) p.script_src(*script_src_values) p.style_src(*style_src_values) end @@ -27,7 +28,6 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController before_action :verify_qsh_claim!, only: :index before_action :allow_self_managed_content_security_policy, only: :index before_action :authenticate_user!, only: :create - before_action :set_cors_headers def index @subscriptions = current_jira_installation.subscriptions.preload_namespace_route @@ -65,8 +65,6 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController private def allow_self_managed_content_security_policy - return unless Feature.enabled?(:jira_connect_oauth_self_managed_setting) - return unless current_jira_installation.instance_url? request.content_security_policy.directives['connect-src'] ||= [] diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index f3f0ddd968a..8650b6cbc6f 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -119,6 +119,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController identity_linker ||= auth_module::IdentityLinker.new(current_user, oauth, session) link_identity(identity_linker) + set_remember_me(current_user) if identity_linker.changed? redirect_identity_linked @@ -169,6 +170,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController # available in the logs for this request. Gitlab::ApplicationContext.push(user: user) log_audit_event(user, with: oauth['provider']) + Gitlab::Tracking.event(self.class.name, "#{oauth['provider']}_sso", user: user) if new_user set_remember_me(user) diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index 1216353be36..38cdb16c350 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -58,8 +58,8 @@ class PasswordsController < Devise::PasswordsController def check_password_authentication_available if resource return if resource.allow_password_authentication? - else - return if Gitlab::CurrentSettings.password_authentication_enabled? + elsif Gitlab::CurrentSettings.password_authentication_enabled? + return end redirect_to after_sending_reset_password_instructions_path_for(resource_name), diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb index 90d5f945d78..39e8f6c500d 100644 --- a/app/controllers/profiles/keys_controller.rb +++ b/app/controllers/profiles/keys_controller.rb @@ -37,6 +37,6 @@ class Profiles::KeysController < Profiles::ApplicationController private def key_params - params.require(:key).permit(:title, :key, :expires_at) + params.require(:key).permit(:title, :key, :usage_type, :expires_at) end end diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb index a57c87bf691..974e7104c07 100644 --- a/app/controllers/profiles/preferences_controller.rb +++ b/app/controllers/profiles/preferences_controller.rb @@ -57,7 +57,8 @@ class Profiles::PreferencesController < Profiles::ApplicationController :render_whitespace_in_code, :markdown_surround_selection, :markdown_automatic_lists, - :use_legacy_web_ide + :use_legacy_web_ide, + :use_new_navigation ] end end diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb index 0933f2bb7ea..03b7cc9f892 100644 --- a/app/controllers/profiles/two_factor_auths_controller.rb +++ b/app/controllers/profiles/two_factor_auths_controller.rb @@ -97,7 +97,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController def skip if two_factor_grace_period_expired? - redirect_to new_profile_two_factor_auth_path, alert: s_('Cannot skip two factor authentication setup') + redirect_to new_profile_two_factor_auth_path, alert: _('Cannot skip two factor authentication setup') else session[:skip_two_factor] = current_user.otp_grace_period_started_at + two_factor_grace_period.hours redirect_to root_path @@ -186,9 +186,9 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController def u2f_registrations current_user.u2f_registrations.map do |u2f_registration| { - name: u2f_registration.name, - created_at: u2f_registration.created_at, - delete_path: profile_u2f_registration_path(u2f_registration) + name: u2f_registration.name, + created_at: u2f_registration.created_at, + delete_path: profile_u2f_registration_path(u2f_registration) } end end @@ -196,9 +196,9 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController def webauthn_registrations current_user.webauthn_registrations.map do |webauthn_registration| { - name: webauthn_registration.name, - created_at: webauthn_registration.created_at, - delete_path: profile_webauthn_registration_path(webauthn_registration) + name: webauthn_registration.name, + created_at: webauthn_registration.created_at, + delete_path: profile_webauthn_registration_path(webauthn_registration) } end end @@ -216,7 +216,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController group_links = groups.map { |group| view_context.link_to group.full_name, group_path(group) }.to_sentence leave_group_links = groups.map { |group| view_context.link_to (s_("leave %{group_name}") % { group_name: group.full_name }), leave_group_members_path(group), remote: false, method: :delete }.to_sentence - s_(%{The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}.}) + s_(%(The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}.)) .html_safe % { group_links: group_links.html_safe, leave_group_links: leave_group_links.html_safe } end diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb index 7755effe1da..ef20c71cd77 100644 --- a/app/controllers/projects/autocomplete_sources_controller.rb +++ b/app/controllers/projects/autocomplete_sources_controller.rb @@ -7,7 +7,7 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController feature_category :team_planning, [:issues, :labels, :milestones, :commands, :contacts] feature_category :code_review, [:merge_requests] feature_category :users, [:members] - feature_category :snippets, [:snippets] + feature_category :source_code_management, [:snippets] urgency :low, [:merge_requests, :members] urgency :low, [:issues, :labels, :milestones, :commands, :contacts] diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb index 42bd87e1c01..dbbffc4c283 100644 --- a/app/controllers/projects/badges_controller.rb +++ b/app/controllers/projects/badges_controller.rb @@ -13,10 +13,10 @@ class Projects::BadgesController < Projects::ApplicationController def pipeline pipeline_status = Gitlab::Ci::Badge::Pipeline::Status .new(project, params[:ref], opts: { - ignore_skipped: params[:ignore_skipped], - key_text: params[:key_text], - key_width: params[:key_width] - }) + ignore_skipped: params[:ignore_skipped], + key_text: params[:key_text], + key_width: params[:key_width] + }) render_badge pipeline_status end @@ -24,13 +24,13 @@ class Projects::BadgesController < Projects::ApplicationController def coverage coverage_report = Gitlab::Ci::Badge::Coverage::Report .new(project, params[:ref], opts: { - job: params[:job], - key_text: params[:key_text], - key_width: params[:key_width], - min_good: params[:min_good], - min_acceptable: params[:min_acceptable], - min_medium: params[:min_medium] - }) + job: params[:job], + key_text: params[:key_text], + key_width: params[:key_width], + min_good: params[:min_good], + min_acceptable: params[:min_acceptable], + min_medium: params[:min_medium] + }) render_badge coverage_report end @@ -38,10 +38,10 @@ class Projects::BadgesController < Projects::ApplicationController def release latest_release = Gitlab::Ci::Badge::Release::LatestRelease .new(project, current_user, opts: { - key_text: params[:key_text], - key_width: params[:key_width], - order_by: params[:order_by] - }) + key_text: params[:key_text], + key_width: params[:key_width], + order_by: params[:order_by] + }) render_badge latest_release end diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb index 01ed5473b41..cfff281604e 100644 --- a/app/controllers/projects/blame_controller.rb +++ b/app/controllers/projects/blame_controller.rb @@ -7,7 +7,7 @@ class Projects::BlameController < Projects::ApplicationController before_action :require_non_empty_project before_action :assign_ref_vars - before_action :authorize_download_code! + before_action :authorize_read_code! feature_category :source_code_management urgency :low, [:show] diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index f5188e28b81..4eda76f4f21 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -18,7 +18,8 @@ class Projects::BlobController < Projects::ApplicationController around_action :allow_gitaly_ref_name_caching, only: [:show] before_action :require_non_empty_project, except: [:new, :create] - before_action :authorize_download_code! + before_action :authorize_download_code!, except: [:show] + before_action :authorize_read_code!, only: [:show] # We need to assign the blob vars before `authorize_edit_tree!` so we can # validate access to a specific ref. diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 27969cb1a75..7b01e4db42a 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -6,7 +6,7 @@ class Projects::BranchesController < Projects::ApplicationController # Authorize before_action :require_non_empty_project, except: :create - before_action :authorize_download_code! + before_action :authorize_read_code! before_action :authorize_push_code!, only: [:new, :create, :destroy, :destroy_all_merged] # Support legacy URLs diff --git a/app/controllers/projects/ci/daily_build_group_report_results_controller.rb b/app/controllers/projects/ci/daily_build_group_report_results_controller.rb index b2b5e096105..37138afc719 100644 --- a/app/controllers/projects/ci/daily_build_group_report_results_controller.rb +++ b/app/controllers/projects/ci/daily_build_group_report_results_controller.rb @@ -25,7 +25,7 @@ class Projects::Ci::DailyBuildGroupReportResultsController < Projects::Applicati { date: 'date', group_name: 'group_name', - param_type => -> (record) { record.data[param_type] } + param_type => ->(record) { record.data[param_type] } } ).render end diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb index 30d001d0ac5..b781365b3c3 100644 --- a/app/controllers/projects/clusters_controller.rb +++ b/app/controllers/projects/clusters_controller.rb @@ -5,7 +5,6 @@ class Projects::ClustersController < Clusters::ClustersController before_action :repository before_action do - push_frontend_feature_flag(:prometheus_computed_alerts) push_frontend_feature_flag(:show_gitlab_agent_feedback, type: :ops) end diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 870320a79d9..583b572d4b1 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -12,7 +12,7 @@ class Projects::CommitController < Projects::ApplicationController # Authorize before_action :require_non_empty_project - before_action :authorize_download_code! + before_action :authorize_read_code! before_action :authorize_read_pipeline!, only: [:pipelines] before_action :commit before_action :define_commit_vars, only: [:show, :diff_for_path, :diff_files, :pipelines, :merge_requests] diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index f4125fd0a15..c006d56ae81 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -12,7 +12,7 @@ class Projects::CommitsController < Projects::ApplicationController around_action :allow_gitaly_ref_name_caching before_action :require_non_empty_project before_action :assign_ref_vars, except: :commits_root - before_action :authorize_download_code! + before_action :authorize_read_code! before_action :validate_ref!, except: :commits_root before_action :set_commits, except: :commits_root @@ -28,6 +28,8 @@ class Projects::CommitsController < Projects::ApplicationController @merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened .find_by(source_project: @project, source_branch: @ref, target_branch: @repository.root_ref) + @ref_type = ref_type + respond_to do |format| format.html format.atom { render layout: 'xml' } @@ -73,18 +75,20 @@ class Projects::CommitsController < Projects::ApplicationController search = permitted_params[:search] author = permitted_params[:author] + # fully_qualified_ref is available in some situations when the use_ref_type_parameter FF is enabled + ref = @fully_qualified_ref || @ref @commits = if search.present? - @repository.find_commits_by_message(search, @ref, @path, @limit, @offset) + @repository.find_commits_by_message(search, ref, @path, @limit, @offset) elsif author.present? - @repository.commits(@ref, author: author, path: @path, limit: @limit, offset: @offset) + @repository.commits(ref, author: author, path: @path, limit: @limit, offset: @offset) else - @repository.commits(@ref, path: @path, limit: @limit, offset: @offset) + @repository.commits(ref, path: @path, limit: @limit, offset: @offset) end @commits.each(&:lazy_author) # preload authors - @commits = @commits.with_markdown_cache.with_latest_pipeline(@ref) + @commits = @commits.with_markdown_cache.with_latest_pipeline(ref) @commits = set_commits_for_rendering(@commits) end diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 61308f24412..266edd506d5 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -10,7 +10,7 @@ class Projects::CompareController < Projects::ApplicationController # Authorize before_action :require_non_empty_project - before_action :authorize_download_code! + before_action :authorize_read_code! # Defining ivars before_action :define_diffs, only: [:show, :diff_for_path] before_action :define_environment, only: [:show] @@ -95,7 +95,7 @@ class Projects::CompareController < Projects::ApplicationController target_project = target_projects(source_project).find_by_id(compare_params[:from_project_id]) # Just ignore the field if it points at a non-existent or hidden project - next source_project unless target_project && can?(current_user, :download_code, target_project) + next source_project unless target_project && can?(current_user, :read_code, target_project) target_project end diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 67f2f85ce65..537fd3854c4 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -14,11 +14,11 @@ class Projects::EnvironmentsController < Projects::ApplicationController before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do authorize_metrics_dashboard! - - push_frontend_feature_flag(:prometheus_computed_alerts) - push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate) end + before_action only: [:show] do + push_frontend_feature_flag(:environment_details_vue, @project) + end before_action :authorize_read_environment!, except: [:metrics, :additional_metrics, :metrics_dashboard, :metrics_redirect] before_action :authorize_create_environment!, only: [:new, :create] before_action :authorize_stop_environment!, only: [:stop] diff --git a/app/controllers/projects/find_file_controller.rb b/app/controllers/projects/find_file_controller.rb index c6bc115e737..b5099d555ae 100644 --- a/app/controllers/projects/find_file_controller.rb +++ b/app/controllers/projects/find_file_controller.rb @@ -8,7 +8,7 @@ class Projects::FindFileController < Projects::ApplicationController before_action :require_non_empty_project before_action :assign_ref_vars - before_action :authorize_download_code! + before_action :authorize_read_code! feature_category :source_code_management urgency :low, [:show, :list] diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 3208a5076e7..ff3dc71b6cc 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -9,9 +9,9 @@ class Projects::ForksController < Projects::ApplicationController # Authorize before_action :disable_query_limiting, only: [:create] before_action :require_non_empty_project - before_action :authorize_download_code! + before_action :authorize_read_code! before_action :authenticate_user!, only: [:new, :create] - before_action :authorize_fork_project!, only: [:new, :create] + before_action :authorize_fork_project!, except: [:index] before_action :authorize_fork_namespace!, only: [:create] feature_category :source_code_management diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index 6da70b5e157..d072381933a 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -21,11 +21,24 @@ class Projects::GraphsController < Projects::ApplicationController feature_category :continuous_integration, [:ci] urgency :low, [:ci] + MAX_COMMITS = 6000 + def show + @ref_type = ref_type + respond_to do |format| format.html format.json do - fetch_graph + commits = @project.repository.commits(ref, limit: MAX_COMMITS, skip_merges: true) + log = commits.map do |commit| + { + author_name: commit.author_name, + author_email: commit.author_email, + date: commit.committed_date.strftime("%Y-%m-%d") + } + end + + render json: Gitlab::Json.dump(log) end end end @@ -50,9 +63,13 @@ class Projects::GraphsController < Projects::ApplicationController private + def ref + @fully_qualified_ref || @ref + end + def get_commits @commits_limit = 2000 - @commits = @project.repository.commits(@ref, limit: @commits_limit, skip_merges: true) + @commits = @project.repository.commits(ref, limit: @commits_limit, skip_merges: true) @commits_graph = Gitlab::Graphs::Commits.new(@commits) @commits_per_week_days = @commits_graph.commits_per_week_days @commits_per_time = @commits_graph.commits_per_time @@ -76,7 +93,7 @@ class Projects::GraphsController < Projects::ApplicationController base_params: { start_date: date_today - report_window, end_date: date_today, - ref_path: @project.repository.expand_ref(@ref), + ref_path: @project.repository.expand_ref(ref), param_type: 'coverage' }, download_path: namespace_project_ci_daily_build_group_report_results_path( @@ -92,21 +109,6 @@ class Projects::GraphsController < Projects::ApplicationController } end - def fetch_graph - @commits = @project.repository.commits(@ref, limit: 6000, skip_merges: true) - @log = [] - - @commits.each do |commit| - @log << { - author_name: commit.author_name, - author_email: commit.author_email, - date: commit.committed_date.strftime("%Y-%m-%d") - } - end - - render json: Gitlab::Json.dump(@log) - end - def tracking_namespace_source project.namespace end diff --git a/app/controllers/projects/incidents_controller.rb b/app/controllers/projects/incidents_controller.rb index 599505dcb6d..3842a88d15b 100644 --- a/app/controllers/projects/incidents_controller.rb +++ b/app/controllers/projects/incidents_controller.rb @@ -8,6 +8,7 @@ class Projects::IncidentsController < Projects::ApplicationController before_action :load_incident, only: [:show] before_action do push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?) + push_force_frontend_feature_flag(:work_items_mvc, @project&.work_items_mvc_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?) end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index ee845cd001e..631e697dd2f 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -7,6 +7,7 @@ class Projects::IssuesController < Projects::ApplicationController include IssuableCollections include IssuesCalendar include RecordUserLastActivity + include ::Observability::ContentSecurityPolicy ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze @@ -19,7 +20,7 @@ class Projects::IssuesController < Projects::ApplicationController 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) } - before_action :redirect_if_task, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) } + before_action :redirect_if_work_item, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) } after_action :log_issue_show, only: :show @@ -37,7 +38,7 @@ class Projects::IssuesController < Projects::ApplicationController before_action :authorize_create_merge_request_from!, only: [:create_merge_request] before_action :authorize_import_issues!, only: [:import_csv] - before_action :authorize_download_code!, only: [:related_branches] + before_action :authorize_read_code!, only: [:related_branches] before_action do push_frontend_feature_flag(:preserve_unchanged_markdown, project) @@ -55,8 +56,10 @@ class Projects::IssuesController < Projects::ApplicationController before_action only: :show do push_frontend_feature_flag(:issue_assignees_widget, project) push_frontend_feature_flag(:work_items_mvc, project&.group) + push_force_frontend_feature_flag(:work_items_mvc, project&.work_items_mvc_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_mvc_2, project&.work_items_mvc_2_feature_flag_enabled?) push_frontend_feature_flag(:epic_widget_edit_confirmation, project) + push_frontend_feature_flag(:use_iid_in_work_items_path, project) push_force_frontend_feature_flag(:work_items_create_from_markdown, project&.work_items_create_from_markdown_feature_flag_enabled?) end @@ -432,8 +435,8 @@ class Projects::IssuesController < Projects::ApplicationController # Overridden in EE def create_vulnerability_issue_feedback(issue); end - def redirect_if_task - return unless issue.task? + def redirect_if_work_item + return unless allowed_work_item? if Feature.enabled?(:use_iid_in_work_items_path, project.group) redirect_to project_work_items_path(project, issue.iid, params: request.query_parameters.merge(iid_path: true)) @@ -441,6 +444,10 @@ class Projects::IssuesController < Projects::ApplicationController redirect_to project_work_items_path(project, issue.id, params: request.query_parameters) end end + + def allowed_work_item? + issue.task? + end end Projects::IssuesController.prepend_mod_with('Projects::IssuesController') diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index 557ac566733..c6d442a6f27 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -20,9 +20,6 @@ class Projects::JobsController < Projects::ApplicationController before_action :verify_proxy_request!, only: :proxy_websocket_authorize before_action :push_job_log_jump_to_failures, only: [:show] before_action :reject_if_build_artifacts_size_refreshing!, only: [:erase] - before_action do - push_frontend_feature_flag(:graphql_job_app, project, type: :development) - end layout 'project' diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index 93e2298ca98..cba0056ccd5 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -4,6 +4,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap include DiffForPath include DiffHelper include RendersCommits + include ::Observability::ContentSecurityPolicy skip_before_action :merge_request before_action :authorize_create_merge_request_from! @@ -19,6 +20,10 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap :branch_to ] + before_action do + push_frontend_feature_flag(:mr_compare_dropdowns, project) + end + def new define_new_vars end @@ -89,6 +94,14 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap render layout: false end + def target_projects + projects = MergeRequestTargetProjectFinder + .new(current_user: current_user, source_project: @project, project_feature: :repository) + .execute(include_routes: true).limit(20).search(params[:search]) + + render json: ProjectSerializer.new.represent(projects) + end + private def build_merge_request diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index c88dbc70ed5..83377f67723 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -60,17 +60,11 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic options[:merge_conflicts_in_diff] ] - if Feature.enabled?(:check_etags_diffs_batch_before_write_cache, merge_request.project) && !stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs]) - return - end + return unless stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs]) diffs.unfold_diff_files(unfoldable_positions) diffs.write_cache - if Feature.disabled?(:check_etags_diffs_batch_before_write_cache, merge_request.project) && !stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs]) - return - end - render json: PaginatedDiffSerializer.new(current_user: current_user).represent(diffs, options) end # rubocop: enable Metrics/AbcSize diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 4ba79d43f27..3ab1f7d1d32 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -11,10 +11,11 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo include SourcegraphDecorator include DiffHelper include Gitlab::Cache::Helpers + include ::Observability::ContentSecurityPolicy prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv] - before_action :apply_diff_view_cookie!, only: [:show] + before_action :apply_diff_view_cookie!, only: [:show, :diffs] 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: [ @@ -30,7 +31,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action :authenticate_user!, only: [:assign_related_issues] before_action :check_user_can_push_to_source_branch!, only: [:rebase] - before_action only: [:show] do + before_action only: [:show, :diffs] do push_frontend_feature_flag(:core_security_mr_widget_counts, project) push_frontend_feature_flag(:issue_assignees_widget, @project) push_frontend_feature_flag(:refactor_security_extension, @project) @@ -40,21 +41,22 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:mr_review_submit_comment, project) push_frontend_feature_flag(:mr_experience_survey, project) push_frontend_feature_flag(:realtime_reviewers, project) + push_frontend_feature_flag(:realtime_mr_status_change, project) end before_action do push_frontend_feature_flag(:permit_all_shared_groups_for_approval, @project) end - around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions] + around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :diffs, :discussions] - after_action :log_merge_request_show, only: [:show] + after_action :log_merge_request_show, only: [:show, :diffs] feature_category :code_review, [ :assign_related_issues, :bulk_update, :cancel_auto_merge, :commit_change_content, :commits, :context_commits, :destroy, :discussions, :edit, :index, :merge, :rebase, :remove_wip, - :show, :toggle_award_emoji, :toggle_subscription, :update + :show, :diffs, :toggle_award_emoji, :toggle_subscription, :update ] feature_category :code_testing, [:test_reports, :coverage_reports] @@ -67,6 +69,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo urgency :low, [ :index, :show, + :diffs, :commits, :bulk_update, :edit, @@ -100,74 +103,13 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo end end - # rubocop:disable Metrics/AbcSize def show - close_merge_request_if_no_source_project - @merge_request.check_mergeability(async: true) - - respond_to do |format| - format.html do - # use next to appease Rubocop - next render('invalid') if target_branch_missing? - - preload_assignees_for_render(@merge_request) - - # Build a note object for comment form - @note = @project.notes.new(noteable: @merge_request) - - @noteable = @merge_request - @commits_count = @merge_request.commits_count + @merge_request.context_commits_count - @diffs_count = get_diffs_count - @issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar') - @current_user_data = Gitlab::Json.dump(UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestCurrentUserEntity)) - @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) - @endpoint_diff_batch_url = endpoint_diff_batch_url(@project, @merge_request) - - set_pipeline_variables - - @number_of_pipelines = @pipelines.size - - render - end - - format.json do - Gitlab::PollingInterval.set_header(response, interval: 10_000) - - if params[:serializer] == 'sidebar_extras' - cache_context = [ - params[:serializer], - current_user&.cache_key, - @merge_request.merge_request_assignees.map(&:cache_key), - @merge_request.merge_request_reviewers.map(&:cache_key) - ] - - render_cached(@merge_request, - with: serializer, - cache_context: -> (_) { [Digest::SHA256.hexdigest(cache_context.to_s)] }, - serializer: params[:serializer]) - else - render json: serializer.represent(@merge_request, serializer: params[:serializer]) - end - end - - format.patch do - break render_404 unless @merge_request.diff_refs - - send_git_patch @project.repository, @merge_request.diff_refs - end - - format.diff do - break render_404 unless @merge_request.diff_refs + show_merge_request + end - send_git_diff @project.repository, @merge_request.diff_refs - end - end + def diffs + show_merge_request end - # rubocop:enable Metrics/AbcSize def commits # Get context commits from repository @@ -412,6 +354,77 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo private + def show_merge_request + close_merge_request_if_no_source_project + @merge_request.check_mergeability(async: true) + + respond_to do |format| + format.html do + # use next to appease Rubocop + next render('invalid') if target_branch_missing? + + render_html_page + end + + format.json do + Gitlab::PollingInterval.set_header(response, interval: 10_000) + + if params[:serializer] == 'sidebar_extras' + cache_context = [ + params[:serializer], + current_user&.cache_key, + @merge_request.merge_request_assignees.map(&:cache_key), + @merge_request.merge_request_reviewers.map(&:cache_key) + ] + + render_cached(@merge_request, + with: serializer, + cache_context: ->(_) { [Digest::SHA256.hexdigest(cache_context.to_s)] }, + serializer: params[:serializer]) + else + render json: serializer.represent(@merge_request, serializer: params[:serializer]) + end + end + + format.patch do + break render_404 unless @merge_request.diff_refs + + send_git_patch @project.repository, @merge_request.diff_refs + end + + format.diff do + break render_404 unless @merge_request.diff_refs + + send_git_diff @project.repository, @merge_request.diff_refs + end + end + end + + def render_html_page + preload_assignees_for_render(@merge_request) + + # Build a note object for comment form + @note = @project.notes.new(noteable: @merge_request) + + @noteable = @merge_request + @commits_count = @merge_request.commits_count + @merge_request.context_commits_count + @diffs_count = get_diffs_count + @issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar') + @current_user_data = Gitlab::Json.dump(UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestCurrentUserEntity)) + @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) + @endpoint_diff_batch_url = endpoint_diff_batch_url(@project, @merge_request) + + set_pipeline_variables + + @number_of_pipelines = @pipelines.size + + render + end + def get_diffs_count if show_only_context_commits? @merge_request.context_commits_diff.raw_diffs.size diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb index b78ee6ca917..08757d11912 100644 --- a/app/controllers/projects/metrics_dashboard_controller.rb +++ b/app/controllers/projects/metrics_dashboard_controller.rb @@ -9,10 +9,6 @@ module Projects include Gitlab::Utils::StrongMemoize before_action :authorize_metrics_dashboard! - before_action do - push_frontend_feature_flag(:prometheus_computed_alerts) - push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate) - end feature_category :metrics urgency :low diff --git a/app/controllers/projects/ml/candidates_controller.rb b/app/controllers/projects/ml/candidates_controller.rb new file mode 100644 index 00000000000..b702edb858e --- /dev/null +++ b/app/controllers/projects/ml/candidates_controller.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Projects + module Ml + class CandidatesController < ApplicationController + before_action :check_feature_flag + + feature_category :mlops + + def show + @candidate = ::Ml::Candidate.with_project_id_and_iid(@project.id, params['iid']) + + render_404 unless @candidate.present? + end + + private + + def check_feature_flag + render_404 unless Feature.enabled?(:ml_experiment_tracking, @project) + end + end + end +end diff --git a/app/controllers/projects/ml/experiments_controller.rb b/app/controllers/projects/ml/experiments_controller.rb index 749586791ac..c82a959d612 100644 --- a/app/controllers/projects/ml/experiments_controller.rb +++ b/app/controllers/projects/ml/experiments_controller.rb @@ -3,7 +3,6 @@ module Projects module Ml class ExperimentsController < ::Projects::ApplicationController - include Projects::Ml::ExperimentsHelper before_action :check_feature_flag feature_category :mlops diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index 84ac9fb01fd..aa0838752e2 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -6,7 +6,7 @@ class Projects::NetworkController < Projects::ApplicationController before_action :require_non_empty_project before_action :assign_ref_vars - before_action :authorize_download_code! + before_action :authorize_read_code! before_action :assign_options before_action :assign_commit @@ -14,7 +14,13 @@ class Projects::NetworkController < Projects::ApplicationController urgency :low, [:show] def show - @url = project_network_path(@project, @ref, @options.merge(format: :json)) + @url = if Feature.enabled?(:use_ref_type_parameter, @project) + project_network_path(@project, @ref, @options.merge(format: :json, ref_type: ref_type)) + else + project_network_path(@project, @ref, @options.merge(format: :json)) + end + + @ref_type = ref_type @commit_url = project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s") respond_to do |format| diff --git a/app/controllers/projects/performance_monitoring/dashboards_controller.rb b/app/controllers/projects/performance_monitoring/dashboards_controller.rb index 8acbc17aef3..d043f8d0b9f 100644 --- a/app/controllers/projects/performance_monitoring/dashboards_controller.rb +++ b/app/controllers/projects/performance_monitoring/dashboards_controller.rb @@ -70,7 +70,7 @@ module Projects end def validate_required_params! - params.require(%i(branch file_name dashboard commit_message)) + params.require(%i[branch file_name dashboard commit_message]) end def redirect_safe_branch_name @@ -78,7 +78,7 @@ module Projects end def dashboard_params - params.permit(%i(branch file_name dashboard commit_message)).to_h + params.permit(%i[branch file_name dashboard commit_message]).to_h end def file_content_params diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 7d1a75ae449..db77127cb0a 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -24,11 +24,6 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :ensure_pipeline, only: [:show, :downloadable_artifacts] before_action :reject_if_build_artifacts_size_refreshing!, only: [:destroy] - before_action do - push_frontend_feature_flag(:pipeline_tabs_vue, @project) - push_frontend_feature_flag(:run_pipeline_graphql, @project) - end - # Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596 before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? } diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb index 8c70ef446a2..baa4607dcb6 100644 --- a/app/controllers/projects/protected_branches_controller.rb +++ b/app/controllers/projects/protected_branches_controller.rb @@ -1,6 +1,12 @@ # frozen_string_literal: true class Projects::ProtectedBranchesController < Projects::ProtectedRefsController + def show + super + + render 'protected_branches/show' + end + protected def project_refs diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index 9707b70f26f..924de0ee7ea 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -12,7 +12,7 @@ class Projects::RawController < Projects::ApplicationController before_action :set_ref_and_path before_action :require_non_empty_project - before_action :authorize_download_code! + before_action :authorize_read_code! before_action :check_show_rate_limit!, only: [:show], unless: :external_storage_request? before_action :redirect_to_external_storage, only: :show, if: :static_objects_external_storage_enabled? @@ -21,7 +21,7 @@ class Projects::RawController < Projects::ApplicationController def show @blob = @repository.blob_at(@ref, @path, limit: Gitlab::Git::Blob::LFS_POINTER_MAX_SIZE) - send_blob(@repository, @blob, inline: (params[:inline] != 'false'), allow_caching: Guest.can?(:download_code, @project)) + send_blob(@repository, @blob, inline: (params[:inline] != 'false'), allow_caching: Guest.can?(:read_code, @project)) end private diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index 72af3280a39..8ac6d872aae 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -9,7 +9,7 @@ class Projects::RefsController < Projects::ApplicationController before_action :require_non_empty_project before_action :validate_ref_id before_action :assign_ref_vars - before_action :authorize_download_code! + before_action :authorize_read_code! feature_category :source_code_management urgency :low, [:switch, :logs_tree] @@ -24,9 +24,17 @@ class Projects::RefsController < Projects::ApplicationController when "blob" project_blob_path(@project, @id) when "graph" - project_network_path(@project, @id, @options) + if Feature.enabled?(:use_ref_type_parameter, @project) + project_network_path(@project, @id, ref_type: ref_type) + else + project_network_path(@project, @id, @options) + end when "graphs" - project_graph_path(@project, @id) + if Feature.enabled?(:use_ref_type_parameter, @project) + project_graph_path(@project, @id, ref_type: ref_type) + else + project_graph_path(@project, @id) + end when "find_file" project_find_file_path(@project, @id) when "graphs_commits" @@ -34,7 +42,11 @@ class Projects::RefsController < Projects::ApplicationController when "badges" project_settings_ci_cd_path(@project, ref: @id) else - project_commits_path(@project, @id) + if Feature.enabled?(:use_ref_type_parameter, @project) + project_commits_path(@project, @id, ref_type: ref_type) + else + project_commits_path(@project, @id) + end end redirect_to new_path diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb index ffe95bf4fee..6c663c4694a 100644 --- a/app/controllers/projects/registry/repositories_controller.rb +++ b/app/controllers/projects/registry/repositories_controller.rb @@ -23,10 +23,6 @@ module Projects def destroy image.delete_scheduled! - unless Feature.enabled?(:container_registry_delete_repository_with_cron_worker) - DeleteContainerRepositoryWorker.perform_async(current_user.id, image.id) # rubocop:disable CodeReuse/Worker - end - track_package_event(:delete_repository, :container) respond_to do |format| diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb index 5946c43b134..6f896244acb 100644 --- a/app/controllers/projects/runner_projects_controller.rb +++ b/app/controllers/projects/runner_projects_controller.rb @@ -11,7 +11,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController def create @runner = Ci::Runner.find(params[:runner_project][:runner_id]) - return head(403) unless can?(current_user, :assign_runner, @runner) + return head(:forbidden) unless can?(current_user, :assign_runner, @runner) path = project_runners_path(project) diff --git a/app/controllers/projects/service_desk_controller.rb b/app/controllers/projects/service_desk_controller.rb index aa0e70121df..8f576b8d72b 100644 --- a/app/controllers/projects/service_desk_controller.rb +++ b/app/controllers/projects/service_desk_controller.rb @@ -29,7 +29,7 @@ class Projects::ServiceDeskController < Projects::ApplicationController end def allowed_update_attributes - %i(issue_template_key outgoing_name project_key) + %i[issue_template_key outgoing_name project_key] end def service_desk_attributes diff --git a/app/controllers/projects/service_ping_controller.rb b/app/controllers/projects/service_ping_controller.rb index 43c249afd8e..cfc322b47e7 100644 --- a/app/controllers/projects/service_ping_controller.rb +++ b/app/controllers/projects/service_ping_controller.rb @@ -10,7 +10,7 @@ class Projects::ServicePingController < Projects::ApplicationController Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_count - head(200) + head(:ok) end def web_ide_clientside_preview_success @@ -20,12 +20,12 @@ class Projects::ServicePingController < Projects::ApplicationController Gitlab::UsageDataCounters::EditorUniqueCounter.track_live_preview_edit_action(author: current_user, project: project) - head(200) + head(:ok) end def web_ide_pipelines_count Gitlab::UsageDataCounters::WebIdeCounter.increment_pipelines_count - head(200) + head(:ok) end end diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 8aef1c3d24d..cf07de4dc29 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -18,6 +18,9 @@ module Projects urgency :low def show + @entity = :project + @variable_limit = ::Plan.default.actual_limits.project_ci_variables + if Feature.enabled?(:ci_pipeline_triggers_settings_vue_ui, @project) triggers = ::Ci::TriggerSerializer.new.represent( @project.triggers, current_user: current_user, project: @project @@ -122,11 +125,13 @@ module Projects .page(params[:specific_page]).per(NUMBER_OF_RUNNERS_PER_PAGE) .with_tags - @shared_runners = ::Ci::Runner.instance_type.active.with_tags - - @shared_runners_count = @shared_runners.count(:all) + active_shared_runners = ::Ci::Runner.instance_type.active + @shared_runners_count = active_shared_runners.count + @shared_runners = active_shared_runners.page(params[:shared_runners_page]).per(NUMBER_OF_RUNNERS_PER_PAGE).with_tags - @group_runners = ::Ci::Runner.belonging_to_parent_group_of_project(@project.id).with_tags + parent_group_runners = ::Ci::Runner.belonging_to_parent_group_of_project(@project.id) + @group_runners_count = parent_group_runners.count + @group_runners = parent_group_runners.page(params[:group_runners_page]).per(NUMBER_OF_RUNNERS_PER_PAGE).with_tags end def define_ci_variables diff --git a/app/controllers/projects/settings/integrations_controller.rb b/app/controllers/projects/settings/integrations_controller.rb index 2bbcd9fe20c..16c1373df2b 100644 --- a/app/controllers/projects/settings/integrations_controller.rb +++ b/app/controllers/projects/settings/integrations_controller.rb @@ -79,7 +79,7 @@ module Projects return { error: true, message: _('Validations failed.'), - service_response: integration.errors.full_messages.join(','), + service_response: integration.errors.full_messages.join(', '), test_failed: false } end @@ -90,7 +90,7 @@ module Projects return { error: true, message: s_('Integrations|Connection failed. Check your integration settings.'), - service_response: result[:message].to_s, + service_response: result[:result].to_s, test_failed: true } end diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 90988645d3a..6d099aa8b3d 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -95,6 +95,14 @@ module Projects @protected_tags_count = @protected_tags.reduce(0) { |sum, tag| sum + tag.matching(@project.repository.tag_names).size } + if Feature.enabled?(:group_protected_branches) + @protected_group_branches = if @project.root_namespace.is_a?(Group) + @project.root_namespace.protected_branches.order(:name).page(params[:page]) + else + [] + end + end + load_gon_index end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/controllers/projects/snippets/application_controller.rb b/app/controllers/projects/snippets/application_controller.rb index 8ee12bf3795..b8faf464531 100644 --- a/app/controllers/projects/snippets/application_controller.rb +++ b/app/controllers/projects/snippets/application_controller.rb @@ -4,7 +4,7 @@ class Projects::Snippets::ApplicationController < Projects::ApplicationControlle include FindSnippet include SnippetAuthorizations - feature_category :snippets + feature_category :source_code_management private diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 847b1baca10..3c1735c728c 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -7,7 +7,7 @@ class Projects::TagsController < Projects::ApplicationController # Authorize before_action :require_non_empty_project - before_action :authorize_download_code! + before_action :authorize_read_code! before_action :authorize_admin_tag!, only: [:new, :create, :destroy] feature_category :source_code_management diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index fea2689db14..737a6290431 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -13,11 +13,10 @@ class Projects::TreeController < Projects::ApplicationController before_action :require_non_empty_project, except: [:new, :create] before_action :assign_ref_vars before_action :assign_dir_vars, only: [:create_dir] - before_action :authorize_download_code! + before_action :authorize_read_code! before_action :authorize_edit_tree!, only: [:create_dir] before_action do - push_frontend_feature_flag(:lazy_load_commits, @project) push_frontend_feature_flag(:highlight_js, @project) push_frontend_feature_flag(:file_line_blame, @project) push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks) diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index a8f062bd7c1..a83ccccbeae 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -47,6 +47,6 @@ class Projects::VariablesController < Projects::ApplicationController end def variable_params_attributes - %i[id variable_type key secret_value protected masked environment_scope _destroy] + %i[id variable_type key secret_value protected masked raw environment_scope _destroy] end end diff --git a/app/controllers/projects/work_items_controller.rb b/app/controllers/projects/work_items_controller.rb index a7e59a28fb7..a118c6986f7 100644 --- a/app/controllers/projects/work_items_controller.rb +++ b/app/controllers/projects/work_items_controller.rb @@ -3,6 +3,7 @@ class Projects::WorkItemsController < Projects::ApplicationController before_action do push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?) + push_force_frontend_feature_flag(:work_items_mvc, project&.work_items_mvc_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_mvc_2, project&.work_items_mvc_2_feature_flag_enabled?) push_frontend_feature_flag(:use_iid_in_work_items_path, project) end @@ -10,3 +11,5 @@ class Projects::WorkItemsController < Projects::ApplicationController feature_category :team_planning urgency :low end + +Projects::WorkItemsController.prepend_mod diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a5dacbf7f2f..886819fe778 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -26,7 +26,7 @@ class ProjectsController < Projects::ApplicationController before_action :verify_git_import_enabled, only: [:create] before_action :project_export_enabled, only: [:export, :download_export, :remove_export, :generate_new_export] before_action :present_project, only: [:edit] - before_action :authorize_download_code!, only: [:refs] + before_action :authorize_read_code!, only: [:refs] # Authorize before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export] @@ -37,21 +37,17 @@ class ProjectsController < Projects::ApplicationController before_action :check_export_rate_limit!, only: [:export, :download_export, :generate_new_export] before_action do - push_frontend_feature_flag(:lazy_load_commits, @project) push_frontend_feature_flag(:highlight_js, @project) push_frontend_feature_flag(:file_line_blame, @project) push_frontend_feature_flag(:increase_page_size_exponentially, @project) push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks) push_licensed_feature(:security_orchestration_policies) if @project.present? && @project.licensed_feature_available?(:security_orchestration_policies) push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?) + push_force_frontend_feature_flag(:work_items_mvc, @project&.work_items_mvc_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?) push_frontend_feature_flag(:package_registry_access_level) end - before_action only: :edit do - push_frontend_feature_flag(:split_operations_visibility_permissions, @project) - end - layout :determine_layout feature_category :projects, [ @@ -369,7 +365,7 @@ class ProjectsController < Projects::ApplicationController def render_landing_page Gitlab::Tracking.event('project_overview', 'render', user: current_user, project: @project.project) - if can?(current_user, :download_code, @project) + if can?(current_user, :read_code, @project) return render 'projects/no_repo' unless @project.repository_exists? render 'projects/empty' if @project.empty_repo? @@ -433,17 +429,11 @@ class ProjectsController < Projects::ApplicationController security_and_compliance_access_level container_registry_access_level releases_access_level - ] + operations_feature_attributes - end - - def operations_feature_attributes - if Feature.enabled?(:split_operations_visibility_permissions, project) - %i[ - environments_access_level feature_flags_access_level monitor_access_level infrastructure_access_level - ] - else - %i[operations_access_level] - end + environments_access_level + feature_flags_access_level + monitor_access_level + infrastructure_access_level + ] end def project_setting_attributes @@ -520,14 +510,6 @@ class ProjectsController < Projects::ApplicationController false end - def project_view_files? - if current_user - current_user.project_view == 'files' - else - project_view_files_allowed? - end - end - # Override extract_ref from ExtractsPath, which returns the branch and file path # for the blob/tree, which in this case is just the root of the default branch. # This way we avoid to access the repository.ref_names. @@ -540,10 +522,6 @@ class ProjectsController < Projects::ApplicationController project.repository.root_ref end - def project_view_files_allowed? - !project.empty_repo? && can?(current_user, :download_code, project) - end - def build_canonical_path(project) params[:namespace_id] = project.namespace.to_param params[:id] = project.to_param diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb index a49b82319da..4a42632a980 100644 --- a/app/controllers/registrations/welcome_controller.rb +++ b/app/controllers/registrations/welcome_controller.rb @@ -14,12 +14,16 @@ module Registrations def show return redirect_to path_for_signed_in_user(current_user) if completed_welcome_step? + + track_event('render') end def update result = ::Users::SignupService.new(current_user, update_params).execute if result[:status] == :success + track_event('successfully_submitted_form') + return redirect_to issues_dashboard_path(assignee_username: current_user.username) if show_tasks_to_be_done? return redirect_to update_success_path if show_signup_onboarding? @@ -86,6 +90,10 @@ module Registrations # overridden in EE def update_success_path end + + # overridden in EE + def track_event(category) + end end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 995303a631a..11f9f1cf0c6 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -15,10 +15,10 @@ class RegistrationsController < Devise::RegistrationsController layout 'devise' prepend_before_action :check_captcha, only: :create + before_action :ensure_first_name_and_last_name_not_empty, only: :create before_action :ensure_destroy_prerequisites_met, only: [:destroy] before_action :init_preferred_language, only: :new before_action :load_recaptcha, only: :new - before_action :set_invite_params, only: :new before_action only: [:create] do check_rate_limit!(:user_sign_up, scope: request.ip) end @@ -32,11 +32,11 @@ class RegistrationsController < Devise::RegistrationsController def new @resource = build_resource + set_invite_params end def create - set_user_state - set_custom_confirmation_token + set_resource_fields super do |new_user| accept_pending_invitations if new_user.persisted? @@ -111,8 +111,11 @@ class RegistrationsController < Devise::RegistrationsController super end + # overridden by EE module def after_request_hook(user) - # overridden by EE module + return unless user.persisted? + + Gitlab::Tracking.event(self.class.name, 'successfully_submitted_form', user: user) end def after_sign_up_path_for(user) @@ -132,6 +135,7 @@ class RegistrationsController < Devise::RegistrationsController return identity_verification_redirect_path if custom_confirmation_enabled? + Gitlab::Tracking.event(self.class.name, 'render', user: resource) users_almost_there_path(email: resource.email) end @@ -172,6 +176,21 @@ class RegistrationsController < Devise::RegistrationsController render action: 'new' end + def ensure_first_name_and_last_name_not_empty + # The key here will be affected by feature flag 'arkose_labs_signup_challenge' + # When flag is disabled, the key will be 'user' because #check_captcha will remove 'new_' prefix + # When flag is enabled, #check_captcha will be skipped, so the key will have 'new_' prefix + first_name = params.dig(resource_name, :first_name) || params.dig("new_#{resource_name}", :first_name) + last_name = params.dig(resource_name, :last_name) || params.dig("new_#{resource_name}", :last_name) + + return if first_name.present? && last_name.present? + + resource.errors.add(_('First name'), _("cannot be blank")) if first_name.blank? + resource.errors.add(_('Last name'), _("cannot be blank")) if last_name.blank? + + render action: 'new' + end + def pending_approval? return false unless Gitlab::CurrentSettings.require_admin_approval_after_user_signup @@ -211,18 +230,22 @@ class RegistrationsController < Devise::RegistrationsController Gitlab::Recaptcha.load_configurations! end - def set_user_state + # overridden by EE module + def set_resource_fields return unless set_blocked_pending_approval? resource.state = User::BLOCKED_PENDING_APPROVAL_STATE end + # overridden by EE module def set_blocked_pending_approval? Gitlab::CurrentSettings.require_admin_approval_after_user_signup end def set_invite_params - @invite_email = ActionController::Base.helpers.sanitize(params[:invite_email]) + if resource.email.blank? && params[:invite_email].present? + resource.email = @invite_email = ActionController::Base.helpers.sanitize(params[:invite_email]) + end end def after_pending_invitations_hook @@ -251,10 +274,6 @@ class RegistrationsController < Devise::RegistrationsController # overridden by EE module end - def set_custom_confirmation_token - # overridden by EE module - end - def send_custom_confirmation_instructions # overridden by EE module end diff --git a/app/controllers/repositories/lfs_locks_api_controller.rb b/app/controllers/repositories/lfs_locks_api_controller.rb index f36126d67ff..ea858d63236 100644 --- a/app/controllers/repositories/lfs_locks_api_controller.rb +++ b/app/controllers/repositories/lfs_locks_api_controller.rb @@ -54,9 +54,9 @@ module Repositories def error_payload(message, custom_attrs = {}) custom_attrs.merge({ - message: message, - documentation_url: help_url - }) + message: message, + documentation_url: help_url + }) end def split_by_owner(locks) @@ -72,7 +72,7 @@ module Repositories end def upload_request? - %w(create unlock verify).include?(params[:action]) + %w[create unlock verify].include?(params[:action]) end def lfs_params diff --git a/app/controllers/repositories/lfs_storage_controller.rb b/app/controllers/repositories/lfs_storage_controller.rb index d54b51b463a..22f1a81b95b 100644 --- a/app/controllers/repositories/lfs_storage_controller.rb +++ b/app/controllers/repositories/lfs_storage_controller.rb @@ -49,7 +49,7 @@ module Repositories validate_uploaded_file! if store_file!(oid, size) - head 200, content_type: LfsRequest::CONTENT_TYPE + head :ok, content_type: LfsRequest::CONTENT_TYPE else render plain: 'Unprocessable entity', status: :unprocessable_entity end diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 5351e3e9e77..66968b34380 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -8,6 +8,7 @@ class SearchController < ApplicationController include SearchRateLimitable RESCUE_FROM_TIMEOUT_ACTIONS = [:count, :show, :autocomplete, :aggregations].freeze + CODE_SEARCH_LITERALS = %w[blob: extension: path: filename:].freeze track_custom_event :show, name: 'i_search_total', @@ -32,7 +33,10 @@ class SearchController < ApplicationController before_action only: :show do push_frontend_feature_flag(:search_page_vertical_nav, current_user) end - + before_action only: :show do + update_scope_for_code_search + end + before_action :elasticsearch_in_use, only: :show rescue_from ActiveRecord::QueryCanceled, with: :render_timeout layout 'search' @@ -43,6 +47,7 @@ class SearchController < ApplicationController def show @project = search_service.project @group = search_service.group + @search_service = Gitlab::View::Presenter::Factory.new(search_service, current_user: current_user).fabricate! return unless search_term_valid? @@ -51,15 +56,11 @@ class SearchController < ApplicationController @search_term = params[:search] @sort = params[:sort] || default_sort - @search_service = Gitlab::View::Presenter::Factory.new(search_service, current_user: current_user).fabricate! - @search_level = @search_service.level @search_type = search_type @global_search_duration_s = Benchmark.realtime do @scope = @search_service.scope - @without_count = @search_service.without_count? - @show_snippets = @search_service.show_snippets? @search_results = @search_service.search_results @search_objects = @search_service.search_objects @search_highlight = @search_service.search_highlight @@ -118,8 +119,22 @@ class SearchController < ApplicationController def opensearch end + def elasticsearch_in_use + search_service.respond_to?(:use_elasticsearch?) && search_service.use_elasticsearch? + end + strong_memoize_attr :elasticsearch_in_use + private + def update_scope_for_code_search + return if params[:scope] == 'blobs' + return unless params[:search].present? + + if CODE_SEARCH_LITERALS.any? { |literal| literal.in? params[:search] } + redirect_to search_path(safe_params.except(:controller, :action).merge(scope: 'blobs')) + end + end + # overridden in EE def default_sort 'created_desc' diff --git a/app/controllers/snippets/application_controller.rb b/app/controllers/snippets/application_controller.rb index f259f4569ef..64adc4e6611 100644 --- a/app/controllers/snippets/application_controller.rb +++ b/app/controllers/snippets/application_controller.rb @@ -4,7 +4,7 @@ class Snippets::ApplicationController < ApplicationController include FindSnippet include SnippetAuthorizations - feature_category :snippets + feature_category :source_code_management private diff --git a/app/controllers/snippets/notes_controller.rb b/app/controllers/snippets/notes_controller.rb index 8a4e8edbf3c..9e23eef4178 100644 --- a/app/controllers/snippets/notes_controller.rb +++ b/app/controllers/snippets/notes_controller.rb @@ -8,7 +8,7 @@ class Snippets::NotesController < ApplicationController before_action :authorize_read_snippet!, only: [:show, :index] before_action :authorize_create_note!, only: [:create] - feature_category :snippets + feature_category :source_code_management private diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 0f03333d793..f23e513e419 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -31,8 +31,7 @@ class UsersController < ApplicationController :followers, :following, :calendar, :calendar_activities, :exists, :activity, :follow, :unfollow, :ssh_keys] - feature_category :snippets, [:snippets] - feature_category :source_code_management, [:gpg_keys] + feature_category :source_code_management, [:snippets, :gpg_keys] # TODO: Set higher urgency after resolving https://gitlab.com/gitlab-org/gitlab/-/issues/357914 urgency :low, [:show, :calendar_activities, :contributed, :activity, :projects, :groups, :calendar, :snippets] diff --git a/app/controllers/web_ide/remote_ide_controller.rb b/app/controllers/web_ide/remote_ide_controller.rb new file mode 100644 index 00000000000..fe70e78b1e5 --- /dev/null +++ b/app/controllers/web_ide/remote_ide_controller.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'uri' + +module WebIde + class RemoteIdeController < ApplicationController + include VSCodeCDNCSP + + rescue_from URI::InvalidComponentError, with: :render_404 + + before_action :allow_remote_ide_content_security_policy + + feature_category :remote_development + + urgency :low + + def index + return render_404 unless Feature.enabled?(:vscode_web_ide, current_user) + + render layout: 'fullscreen', locals: { minimal: true, data: root_element_data } + end + + private + + def allow_remote_ide_content_security_policy + return if request.content_security_policy.directives.blank? + + default_src = Array(request.content_security_policy.directives['default-src'] || []) + + request.content_security_policy.directives['connect-src'] ||= default_src + request.content_security_policy.directives['connect-src'].concat(connect_src_urls) + end + + def connect_src_urls + # It's okay if "port" is null + host, port = params.require(:remote_host).split(':') + + # This could throw URI::InvalidComponentError. We go ahead and let it throw + # and let the controller recover with a bad_request response + %w[ws wss http https].map { |scheme| URI::Generic.build(scheme: scheme, host: host, port: port).to_s } + end + + def root_element_data + { + connection_token: params.fetch(:connection_token, ''), + remote_host: params.require(:remote_host), + remote_path: params.fetch(:remote_path, ''), + return_url: params.fetch(:return_url, ''), + csp_nonce: content_security_policy_nonce + } + end + end +end |