diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-20 16:49:51 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-20 16:49:51 +0300 |
commit | 71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e (patch) | |
tree | 6a2d93ef3fb2d353bb7739e4b57e6541f51cdd71 /app/controllers/projects | |
parent | a7253423e3403b8c08f8a161e5937e1488f5f407 (diff) |
Add latest changes from gitlab-org/gitlab@15-9-stable-eev15.9.0-rc42
Diffstat (limited to 'app/controllers/projects')
35 files changed, 254 insertions, 206 deletions
diff --git a/app/controllers/projects/airflow/dags_controller.rb b/app/controllers/projects/airflow/dags_controller.rb new file mode 100644 index 00000000000..9d1f0b0d63b --- /dev/null +++ b/app/controllers/projects/airflow/dags_controller.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Projects + module Airflow + class DagsController < ::Projects::ApplicationController + before_action :check_feature_flag + before_action :authorize_read_airflow_dags! + + feature_category :dataops + + MAX_DAGS_PER_PAGE = 15 + def index + page = params[:page].to_i + page = 1 if page <= 0 + + @dags = ::Airflow::Dags.by_project_id(@project.id) + + return unless @dags.any? + + @dags = @dags.page(page).per(MAX_DAGS_PER_PAGE) + return redirect_to(url_for(page: @dags.total_pages)) if @dags.out_of_range? + + @pagination = { + page: page, + is_last_page: @dags.last_page?, + per_page: MAX_DAGS_PER_PAGE, + total_items: @dags.total_count + } + end + + private + + def check_feature_flag + render_404 unless Feature.enabled?(:airflow_dags, @project) + end + end + end +end diff --git a/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb b/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb index ab2cf3abdde..a61b774f9c8 100644 --- a/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb +++ b/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb @@ -3,7 +3,6 @@ class Projects::Analytics::CycleAnalytics::StagesController < Projects::ApplicationController include ::Analytics::CycleAnalytics::StageActions include Gitlab::Utils::StrongMemoize - extend ::Gitlab::Utils::Override respond_to :json @@ -11,20 +10,14 @@ class Projects::Analytics::CycleAnalytics::StagesController < Projects::Applicat before_action :authorize_read_cycle_analytics! before_action :only_default_value_stream_is_allowed! - before_action :authorize_stage!, only: [:median, :count, :average, :records] urgency :low private - override :parent - def parent - @project - end - - override :value_stream_class - def value_stream_class - Analytics::CycleAnalytics::ProjectValueStream + override :namespace + def namespace + @project.project_namespace end override :cycle_analytics_configuration @@ -33,7 +26,9 @@ class Projects::Analytics::CycleAnalytics::StagesController < Projects::Applicat end def only_default_value_stream_is_allowed! - render_404 if params[:value_stream_id] != Analytics::CycleAnalytics::Stages::BaseService::DEFAULT_VALUE_STREAM_NAME + return if requests_default_value_stream? + + render_403 end def permitted_stage?(stage) @@ -42,11 +37,20 @@ class Projects::Analytics::CycleAnalytics::StagesController < Projects::Applicat def permissions strong_memoize(:permissions) do - Gitlab::CycleAnalytics::Permissions.new(user: current_user, project: parent).get + Gitlab::CycleAnalytics::Permissions.new(user: current_user, project: @project).get end end - def authorize_stage! + def authorize_stage render_403 unless permitted_stage?(stage) end + + def requests_default_value_stream? + default_name = Analytics::CycleAnalytics::Stages::BaseService::DEFAULT_VALUE_STREAM_NAME + + params[:value_stream_id] == default_name + end end + +mod = 'Projects::Analytics::CycleAnalytics::StagesController' +Projects::Analytics::CycleAnalytics::StagesController.prepend_mod_with(mod) # rubocop: disable Cop/InjectEnterpriseEditionModule diff --git a/app/controllers/projects/analytics/cycle_analytics/value_streams_controller.rb b/app/controllers/projects/analytics/cycle_analytics/value_streams_controller.rb index 60bcd1d7238..f58730f1d33 100644 --- a/app/controllers/projects/analytics/cycle_analytics/value_streams_controller.rb +++ b/app/controllers/projects/analytics/cycle_analytics/value_streams_controller.rb @@ -1,17 +1,16 @@ # frozen_string_literal: true class Projects::Analytics::CycleAnalytics::ValueStreamsController < Projects::ApplicationController + include ::Analytics::CycleAnalytics::ValueStreamActions + respond_to :json feature_category :planning_analytics urgency :low - before_action :authorize_read_cycle_analytics! - - def index - # FOSS users can only see the default value stream - value_streams = [Analytics::CycleAnalytics::ProjectValueStream.build_default_value_stream(@project)] + private - render json: Analytics::CycleAnalytics::ValueStreamSerializer.new.represent(value_streams) + def namespace + project.project_namespace end end diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index 25b83aed78a..62233c8c3c9 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -32,21 +32,6 @@ class Projects::ApplicationController < ApplicationController ->(project) { !project.pending_delete? } end - def authorize_read_build_trace! - return if can?(current_user, :read_build_trace, build) - - if build.debug_mode? - access_denied!( - _('You must have developer or higher permissions in the associated project to view job logs when debug trace ' \ - "is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' and 'CI_DEBUG_SERVICES' variables to 'false' " \ - 'in your pipeline configuration or CI/CD settings. If you must view this job log, a project maintainer ' \ - 'or owner must add you to the project with developer permissions or higher.') - ) - else - access_denied!(_('The current user is not authorized to access the job log.')) - end - end - def build_canonical_path(project) params[:namespace_id] = project.namespace.to_param params[:project_id] = project.to_param diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 3201538a393..5f8060ad756 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class Projects::ArtifactsController < Projects::ApplicationController + include Ci::AuthBuildTrace include ExtractsPath include RendersBlob include SendFileUpload @@ -11,6 +12,7 @@ class Projects::ArtifactsController < Projects::ApplicationController layout 'project' before_action :authorize_read_build! before_action :authorize_read_build_trace!, only: [:download] + before_action :authorize_read_job_artifacts!, only: [:download] before_action :authorize_update_build!, only: [:keep] before_action :authorize_destroy_artifacts!, only: [:destroy] before_action :extract_ref_name_and_path @@ -40,10 +42,10 @@ class Projects::ArtifactsController < Projects::ApplicationController end def download - return render_404 unless artifacts_file + return render_404 unless artifact_file - log_artifacts_filesize(artifacts_file.model) - send_upload(artifacts_file, attachment: artifacts_file.filename, proxy: params[:proxy]) + log_artifacts_filesize(artifact_file.model) + send_upload(artifact_file, attachment: artifact_file.filename, proxy: params[:proxy]) end def browse @@ -82,11 +84,11 @@ class Projects::ArtifactsController < Projects::ApplicationController def raw return render_404 unless zip_artifact? - return render_404 unless artifacts_file + return render_404 unless artifact_file path = Gitlab::Ci::Build::Artifacts::Path.new(params[:path]) - send_artifacts_entry(artifacts_file, path) + send_artifacts_entry(artifact_file, path) end def keep @@ -153,8 +155,12 @@ class Projects::ArtifactsController < Projects::ApplicationController project.latest_successful_build_for_ref(params[:job], @ref_name) end - def artifacts_file - @artifacts_file ||= build&.artifacts_file_for_type(params[:file_type] || :archive) + def job_artifact + @job_artifact ||= build&.artifact_for_type(params[:file_type] || :archive) + end + + def artifact_file + @artifact_file ||= job_artifact&.file end def zip_artifact? @@ -175,4 +181,8 @@ class Projects::ArtifactsController < Projects::ApplicationController super end + + def authorize_read_job_artifacts! + return access_denied! unless can?(current_user, :read_job_artifacts, job_artifact) + end end diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb index 000203079cc..ffe6071ab3c 100644 --- a/app/controllers/projects/autocomplete_sources_controller.rb +++ b/app/controllers/projects/autocomplete_sources_controller.rb @@ -6,7 +6,7 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController feature_category :team_planning, [:issues, :labels, :milestones, :commands, :contacts] feature_category :code_review_workflow, [:merge_requests] - feature_category :users, [:members] + feature_category :user_profile, [:members] feature_category :source_code_management, [:snippets] urgency :low, [:merge_requests, :members] @@ -54,6 +54,8 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController # type_id is not required in general target_type = params.require(:type) + # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/388541 + # type_id is a misnomer. QuickActions::TargetService actually requires an iid. QuickActions::TargetService .new(project, current_user) .execute(target_type, params[:type_id]) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 4eda76f4f21..59cea00e26b 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -239,6 +239,8 @@ class Projects::BlobController < Projects::ApplicationController @last_commit = @repository.last_commit_for_path(@commit.id, @blob.path, literal_pathspec: true) @code_navigation_path = Gitlab::CodeNavigationPath.new(@project, @blob.commit_id).full_json_path_for(@blob.path) + allow_lfs_direct_download + render 'show' end @@ -282,6 +284,30 @@ class Projects::BlobController < Projects::ApplicationController def visitor_id current_user&.id end + + def allow_lfs_direct_download + return unless directly_downloading_lfs_object? && content_security_policy_enabled? + return unless (lfs_object = @project.lfs_objects.find_by_oid(@blob.lfs_oid)) + + request.content_security_policy.directives['connect-src'] ||= [] + request.content_security_policy.directives['connect-src'] << lfs_src(lfs_object) + end + + def directly_downloading_lfs_object? + Gitlab.config.lfs.enabled && + !Gitlab.config.lfs.object_store.proxy_download && + @blob&.stored_externally? + end + + def content_security_policy_enabled? + Gitlab.config.gitlab.content_security_policy.enabled + end + + def lfs_src(lfs_object) + file = lfs_object.file + file = file.cdn_enabled_url(request.remote_ip) if file.respond_to?(:cdn_enabled_url) + file.url + end end Projects::BlobController.prepend_mod diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 7b01e4db42a..f19f143816f 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -19,8 +19,10 @@ class Projects::BranchesController < Projects::ApplicationController def index respond_to do |format| format.html do - @mode = params[:state].presence || 'overview' - @sort = sort_value_for_mode + @mode = fetch_mode + next render_404 unless @mode + + @sort = sort_param || default_sort @overview_max_branches = 5 # Fetch branches for the specified mode @@ -128,11 +130,7 @@ class Projects::BranchesController < Projects::ApplicationController private - def sort_value_for_mode - custom_sort || default_sort - end - - def custom_sort + def sort_param sort = params[:sort].presence unless sort.in?(supported_sort_options) @@ -144,11 +142,11 @@ class Projects::BranchesController < Projects::ApplicationController end def default_sort - 'stale' == @mode ? sort_value_oldest_updated : sort_value_recently_updated + 'stale' == @mode ? SORT_UPDATED_OLDEST : SORT_UPDATED_RECENT end def supported_sort_options - [nil, sort_value_name, sort_value_oldest_updated, sort_value_recently_updated] + [nil, SORT_NAME, SORT_UPDATED_OLDEST, SORT_UPDATED_RECENT] end # It can be expensive to calculate the diverging counts for each @@ -206,15 +204,23 @@ class Projects::BranchesController < Projects::ApplicationController limit = @overview_max_branches + 1 @active_branches = - BranchesFinder.new(@repository, { per_page: limit, sort: sort_value_recently_updated }) + BranchesFinder.new(@repository, { per_page: limit, sort: SORT_UPDATED_RECENT }) .execute(gitaly_pagination: true).select(&:active?) @stale_branches = - BranchesFinder.new(@repository, { per_page: limit, sort: sort_value_oldest_updated }) + BranchesFinder.new(@repository, { per_page: limit, sort: SORT_UPDATED_OLDEST }) .execute(gitaly_pagination: true).select(&:stale?) @branches = @active_branches + @stale_branches end + def fetch_mode + state = params[:state].presence + + return 'overview' unless state + + state.presence_in(%w[active stale all overview]) + end + def confidential_issue_project return if params[:confidential_issue_project_id].blank? diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb index 1942a5fef7b..3a2bc445737 100644 --- a/app/controllers/projects/ci/pipeline_editor_controller.rb +++ b/app/controllers/projects/ci/pipeline_editor_controller.rb @@ -2,6 +2,9 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController before_action :check_can_collaborate! + before_action do + push_frontend_feature_flag(:ci_job_assistant_drawer, @project) + end feature_category :pipeline_authoring diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 583b572d4b1..252b203b38a 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -31,6 +31,7 @@ class Projects::CommitController < Projects::ApplicationController respond_to do |format| format.html do + @ref = params[:id] render locals: { pagination_params: params.permit(:page) } end format.diff do diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index c006d56ae81..3acc71d5dd3 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -75,7 +75,7 @@ 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 + # fully_qualified_ref is available in some situations from ExtractsRef ref = @fully_qualified_ref || @ref @commits = if search.present? diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb index 63c1378ad11..9fe44659250 100644 --- a/app/controllers/projects/cycle_analytics_controller.rb +++ b/app/controllers/projects/cycle_analytics_controller.rb @@ -48,7 +48,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController end def load_value_stream - @value_stream = Analytics::CycleAnalytics::ProjectValueStream.build_default_value_stream(@project) + @value_stream = Analytics::CycleAnalytics::ValueStream.build_default_value_stream(@project.project_namespace) end def cycle_analytics_json diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index ea1288c0b20..9a88a8160b6 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -19,6 +19,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController 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] @@ -57,6 +58,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController render json: { environments: serialize_environments(request, response, params[:nested]), review_app: serialize_review_app, + can_stop_stale_environments: can?(current_user, :stop_environment, @project), available_count: environments_count_by_state[:available], stopped_count: environments_count_by_state[:stopped] } diff --git a/app/controllers/projects/google_cloud/databases_controller.rb b/app/controllers/projects/google_cloud/databases_controller.rb index b511a85b0b8..9c20f10809c 100644 --- a/app/controllers/projects/google_cloud/databases_controller.rb +++ b/app/controllers/projects/google_cloud/databases_controller.rb @@ -51,7 +51,7 @@ module Projects if enable_response[:status] == :error track_event(:error_enable_cloudsql_services) - flash[:error] = error_message(enable_response[:message]) + flash[:alert] = error_message(enable_response[:message]) else create_response = ::GoogleCloud::CreateCloudsqlInstanceService .new(project, current_user, create_service_params) diff --git a/app/controllers/projects/google_cloud/deployments_controller.rb b/app/controllers/projects/google_cloud/deployments_controller.rb index fae8dbd59c7..92c99ad4271 100644 --- a/app/controllers/projects/google_cloud/deployments_controller.rb +++ b/app/controllers/projects/google_cloud/deployments_controller.rb @@ -22,7 +22,7 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base if enable_cloud_run_response[:status] == :error track_event(:error_enable_services) - flash[:error] = enable_cloud_run_response[:message] + flash[:alert] = enable_cloud_run_response[:message] redirect_to project_google_cloud_deployments_path(project) else params = { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } @@ -31,7 +31,7 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base if generate_pipeline_response[:status] == :error track_event(:error_generate_cloudrun_pipeline) - flash[:error] = 'Failed to generate pipeline' + flash[:alert] = 'Failed to generate pipeline' redirect_to project_google_cloud_deployments_path(project) else cloud_run_mr_params = cloud_run_mr_params(generate_pipeline_response[:branch_name]) diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 06c16297ce8..21227d62023 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -28,8 +28,7 @@ class Projects::IssuesController < Projects::ApplicationController SET_ISSUABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) && !index_html_request? } before_action :check_search_rate_limit!, if: ->(c) { - SET_ISSUABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) && !index_html_request? && - params[:search].present? && Feature.enabled?(:rate_limit_issuable_searches) + SET_ISSUABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) && !index_html_request? && params[:search].present? } # Allow write(create) issue @@ -47,6 +46,7 @@ class Projects::IssuesController < Projects::ApplicationController before_action do push_frontend_feature_flag(:preserve_unchanged_markdown, project) push_frontend_feature_flag(:content_editor_on_issues, project) + push_frontend_feature_flag(:service_desk_new_note_email_native_attachments, project) end before_action only: [:index, :show] do @@ -55,6 +55,7 @@ class Projects::IssuesController < Projects::ApplicationController before_action only: :index do push_frontend_feature_flag(:or_issuable_queries, project) + push_frontend_feature_flag(:frontend_caching, project&.group) end before_action only: :show do @@ -64,7 +65,7 @@ class Projects::IssuesController < Projects::ApplicationController 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&.group) - push_force_frontend_feature_flag(:work_items_create_from_markdown, project&.work_items_create_from_markdown_feature_flag_enabled?) + push_frontend_feature_flag(:incident_event_tags, project) end around_action :allow_gitaly_ref_name_caching, only: [:discussions] @@ -127,7 +128,7 @@ class Projects::IssuesController < Projects::ApplicationController discussion_to_resolve: params[:discussion_to_resolve], confidential: !!Gitlab::Utils.to_boolean(issue_params[:confidential]) ) - service = ::Issues::BuildService.new(project: project, current_user: current_user, params: build_params) + service = ::Issues::BuildService.new(container: project, current_user: current_user, params: build_params) @issue = @noteable = service.execute @@ -155,7 +156,7 @@ class Projects::IssuesController < Projects::ApplicationController ) spam_params = ::Spam::SpamParams.new_from_request(request: request) - service = ::Issues::CreateService.new(project: project, current_user: current_user, params: create_params, spam_params: spam_params) + service = ::Issues::CreateService.new(container: project, current_user: current_user, params: create_params, spam_params: spam_params) result = service.execute # Only irrecoverable errors such as unauthorized user won't contain an issue in the response @@ -190,7 +191,7 @@ class Projects::IssuesController < Projects::ApplicationController new_project = Project.find(params[:move_to_project_id]) return render_404 unless issue.can_move?(current_user, new_project) - @issue = ::Issues::MoveService.new(project: project, current_user: current_user).execute(issue, new_project) + @issue = ::Issues::MoveService.new(container: project, current_user: current_user).execute(issue, new_project) end respond_to do |format| @@ -204,7 +205,7 @@ class Projects::IssuesController < Projects::ApplicationController end def reorder - service = ::Issues::ReorderService.new(project: project, current_user: current_user, params: reorder_params) + service = ::Issues::ReorderService.new(container: project, current_user: current_user, params: reorder_params) if service.execute(issue) head :ok @@ -215,7 +216,7 @@ class Projects::IssuesController < Projects::ApplicationController def related_branches @related_branches = ::Issues::RelatedBranchesService - .new(project: project, current_user: current_user) + .new(container: project, current_user: current_user) .execute(issue) .map { |branch| branch.merge(link: branch_link(branch)) } @@ -370,7 +371,7 @@ class Projects::IssuesController < Projects::ApplicationController def update_service spam_params = ::Spam::SpamParams.new_from_request(request: request) - ::Issues::UpdateService.new(project: project, current_user: current_user, params: issue_params, spam_params: spam_params) + ::Issues::UpdateService.new(container: project, current_user: current_user, params: issue_params, spam_params: spam_params) end def finder_type diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index c6d442a6f27..3fea5c694f7 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -1,14 +1,15 @@ # frozen_string_literal: true class Projects::JobsController < Projects::ApplicationController + include Ci::AuthBuildTrace include SendFileUpload include ContinueParams include ProjectStatsRefreshConflictsGuard urgency :low, [:index, :show, :trace, :retry, :play, :cancel, :unschedule, :erase, :raw] - before_action :find_job_as_build, except: [:index, :play, :show] - before_action :find_job_as_processable, only: [:play, :show] + before_action :find_job_as_build, except: [:index, :play, :show, :retry] + before_action :find_job_as_processable, only: [:play, :show, :retry] before_action :authorize_read_build_trace!, only: [:trace, :raw] before_action :authorize_read_build! before_action :authorize_update_build!, @@ -76,7 +77,11 @@ class Projects::JobsController < Projects::ApplicationController response = Ci::RetryJobService.new(project, current_user).execute(@build) if response.success? - redirect_to build_path(response[:job]) + if @build.is_a?(::Ci::Build) + redirect_to build_path(response[:job]) + else + head :ok + end else respond_422 end diff --git a/app/controllers/projects/learn_gitlab_controller.rb b/app/controllers/projects/learn_gitlab_controller.rb deleted file mode 100644 index 6fe009c8a28..00000000000 --- a/app/controllers/projects/learn_gitlab_controller.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -class Projects::LearnGitlabController < Projects::ApplicationController - before_action :authenticate_user! - before_action :check_experiment_enabled? - before_action :enable_invite_for_help_continuous_onboarding_experiment - before_action :enable_video_tutorials_continuous_onboarding_experiment - - feature_category :users - urgency :low, [:index] - - def index - end - - private - - def check_experiment_enabled? - return access_denied! unless helpers.learn_gitlab_enabled?(project) - end - - def enable_invite_for_help_continuous_onboarding_experiment - return unless current_user.can?(:admin_group_member, project.namespace) - - experiment(:invite_for_help_continuous_onboarding, namespace: project.namespace) do |e| - e.candidate {} - end - end - - def enable_video_tutorials_continuous_onboarding_experiment - experiment(:video_tutorials_continuous_onboarding, namespace: project&.namespace).publish - end -end diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index cba0056ccd5..3b399e3294e 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -20,10 +20,6 @@ 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 @@ -97,7 +93,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap 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]) + .execute(include_routes: false, search: params[:search]).limit(20) render json: ProjectSerializer.new.represent(projects) end diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 1c546d70df9..6ca885cee4c 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -61,6 +61,8 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic options[:merge_ref_head_diff] ] + expires_in(1.day) if cache_with_max_age? + return unless stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs]) Gitlab::Metrics.measure(:diffs_unfold) do @@ -238,4 +240,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter .track_mr_diffs_single_file_action(merge_request: @merge_request, user: current_user) end + + def cache_with_max_age? + @merge_request.diffs_batch_cache_with_max_age? && + params[:ck].present? && + render_merge_ref_head_diff? + end end diff --git a/app/controllers/projects/merge_requests/drafts_controller.rb b/app/controllers/projects/merge_requests/drafts_controller.rb index 74bb3ad1a63..ca6ab83b877 100644 --- a/app/controllers/projects/merge_requests/drafts_controller.rb +++ b/app/controllers/projects/merge_requests/drafts_controller.rb @@ -49,24 +49,22 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli def publish result = DraftNotes::PublishService.new(merge_request, current_user).execute(draft_note(allow_nil: true)) - if Feature.enabled?(:mr_review_submit_comment, @project) - if create_note_params[:note] - ::Notes::CreateService.new(@project, current_user, create_note_params).execute + if create_note_params[:note] + ::Notes::CreateService.new(@project, current_user, create_note_params).execute - merge_request_activity_counter.track_submit_review_comment(user: current_user) - end + merge_request_activity_counter.track_submit_review_comment(user: current_user) + end - if Gitlab::Utils.to_boolean(approve_params[:approve]) - unless merge_request.approved_by?(current_user) - success = ::MergeRequests::ApprovalService.new(project: @project, current_user: current_user, params: approve_params).execute(merge_request) + if Gitlab::Utils.to_boolean(approve_params[:approve]) + unless merge_request.approved_by?(current_user) + success = ::MergeRequests::ApprovalService.new(project: @project, current_user: current_user, params: approve_params).execute(merge_request) - unless success - return render json: { message: _('An error occurred while approving, please try again.') }, status: :internal_server_error - end + unless success + return render json: { message: _('An error occurred while approving, please try again.') }, status: :internal_server_error end - - merge_request_activity_counter.track_submit_review_approve(user: current_user) end + + merge_request_activity_counter.track_submit_review_approve(user: current_user) end if result[:status] == :success @@ -145,7 +143,7 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli user_ids = notes.map(&:author_id) project.team.max_member_access_for_user_ids(user_ids) - notes.map(&method(:render_draft_note)) + notes.map { |note| render_draft_note(note) } end def render_draft_note(note) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index b0920b3fbdb..d92ef3de6d9 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -28,9 +28,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo :codequality_mr_diff_reports ] before_action :set_issuables_index, only: [:index] - before_action :check_search_rate_limit!, only: [:index], if: -> { - params[:search].present? && Feature.enabled?(:rate_limit_issuable_searches) - } + before_action :check_search_rate_limit!, only: [:index], if: -> { params[:search].present? } before_action :authenticate_user!, only: [:assign_related_issues] before_action :check_user_can_push_to_source_branch!, only: [:rebase] @@ -40,9 +38,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:refactor_security_extension, @project) push_frontend_feature_flag(:refactor_code_quality_inline_findings, project) push_frontend_feature_flag(:moved_mr_sidebar, project) - 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 @@ -282,11 +278,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo case result[:count] when 0 - flash[:error] = "Failed to assign you issues related to the merge request" - when 1 - flash[:notice] = "1 issue has been assigned to you" + flash[:alert] = _("Failed to assign you issues related to the merge request.") else - flash[:notice] = "#{result[:count]} issues have been assigned to you" + flash[:notice] = n_("An issue has been assigned to you.", "%d issues have been assigned to you.", result[:count]) end redirect_to(merge_request_path(@merge_request)) @@ -356,10 +350,20 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo private + # NOTE: Remove this disable with add_prepared_state_to_mr FF removal + # rubocop: disable Metrics/AbcSize def show_merge_request close_merge_request_if_no_source_project @merge_request.check_mergeability(async: true) + # NOTE: Remove the created_at check when removing the FF check + if ::Feature.enabled?(:add_prepared_state_to_mr, @merge_request.project) && + @merge_request.created_at < 5.minutes.ago && + !@merge_request.prepared? + + @merge_request.prepare + end + respond_to do |format| format.html do # use next to appease Rubocop @@ -401,6 +405,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo end end end + # rubocop: enable Metrics/AbcSize def render_html_page preload_assignees_for_render(@merge_request) @@ -419,6 +424,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @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) + @diffs_batch_cache_key = @merge_request.merge_head_diff&.id if merge_request.diffs_batch_cache_with_max_age? set_pipeline_variables @@ -576,6 +582,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo def endpoint_diff_batch_url(project, merge_request) per_page = current_user&.view_diffs_file_by_file ? '1' : '5' params = request.query_parameters.merge(view: 'inline', diff_head: true, w: show_whitespace, page: '0', per_page: per_page) + params[:ck] = merge_request.merge_head_diff&.id if merge_request.diffs_batch_cache_with_max_age? diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params) end diff --git a/app/controllers/projects/ml/experiments_controller.rb b/app/controllers/projects/ml/experiments_controller.rb index 1e1c4b1587c..00b965542f6 100644 --- a/app/controllers/projects/ml/experiments_controller.rb +++ b/app/controllers/projects/ml/experiments_controller.rb @@ -3,6 +3,8 @@ module Projects module Ml class ExperimentsController < ::Projects::ApplicationController + include Projects::Ml::ExperimentsHelper + before_action :check_feature_flag feature_category :mlops @@ -11,7 +13,12 @@ module Projects MAX_CANDIDATES_PER_PAGE = 30 def index - @experiments = ::Ml::Experiment.by_project_id(@project.id).page(params[:page]).per(MAX_EXPERIMENTS_PER_PAGE) + paginator = ::Ml::Experiment.by_project_id(@project.id) + .with_candidate_count + .keyset_paginate(cursor: params[:cursor], per_page: MAX_EXPERIMENTS_PER_PAGE) + + @experiments = paginator.records + @page_info = page_info(paginator) end def show @@ -19,26 +26,17 @@ module Projects return redirect_to project_ml_experiments_path(@project) unless @experiment.present? - page = params[:page].to_i - page = 1 if page == 0 - - @candidates = @experiment.candidates - .including_relationships - .page(page) - .per(MAX_CANDIDATES_PER_PAGE) - - return unless @candidates - - return redirect_to(url_for(page: @candidates.total_pages)) if @candidates.out_of_range? + find_params = params + .transform_keys(&:underscore) + .permit(:name, :order_by, :sort, :order_by_type) - @pagination = { - page: page, - is_last_page: @candidates.last_page?, - per_page: MAX_CANDIDATES_PER_PAGE, - total_items: @candidates.total_count - } + paginator = CandidateFinder + .new(@experiment, find_params) + .execute + .keyset_paginate(cursor: params[:cursor], per_page: MAX_CANDIDATES_PER_PAGE) - @candidates.each(&:artifact_lazy) + @candidates = paginator.records.each(&:artifact_lazy) + @page_info = page_info(paginator) end private diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index aa0838752e2..f3c63b1b97b 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -14,11 +14,7 @@ class Projects::NetworkController < Projects::ApplicationController urgency :low, [:show] def show - @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 + @url = project_network_path(@project, @ref, @options.merge(format: :json, ref_type: ref_type)) @ref_type = ref_type @commit_url = project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s") diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 9d3506d49b0..054e8c302c9 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -12,7 +12,8 @@ class Projects::NotesController < Projects::ApplicationController before_action :authorize_resolve_note!, only: [:resolve, :unresolve] feature_category :team_planning - urgency :low + urgency :medium, [:index] + urgency :low, [:create, :update, :destroy, :resolve, :unresolve, :toggle_award_emoji, :outdated_line_change] def delete_attachment note.remove_attachment! diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index 31030d958df..19d031bd59b 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -41,7 +41,9 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController end def update - if schedule.update(schedule_params) + response = Ci::PipelineSchedules::UpdateService.new(schedule, current_user, schedule_params).execute + + if response.success? redirect_to project_pipeline_schedules_path(@project) else render :edit @@ -63,7 +65,9 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController end def take_ownership - if schedule.update(owner: current_user) + response = Ci::PipelineSchedules::TakeOwnershipService.new(schedule, current_user).execute + + if response.success? redirect_to pipeline_schedules_path(@project) else redirect_to pipeline_schedules_path(@project), alert: _("Failed to change the owner") diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index db77127cb0a..10f58a9f479 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -5,7 +5,6 @@ class Projects::PipelinesController < Projects::ApplicationController include RedisTracking include ProductAnalyticsTracking include ProjectStatsRefreshConflictsGuard - include ZuoraCSP urgency :low, [ :index, :new, :builds, :show, :failures, :create, @@ -220,6 +219,8 @@ class Projects::PipelinesController < Projects::ApplicationController def config_variables respond_to do |format| format.json do + # Even if the parameter name is `sha`, it is actually a ref name. We always send `ref` to the endpoint. + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/389065 result = Ci::ListConfigVariablesService.new(@project, current_user).execute(params[:sha]) result.nil? ? head(:no_content) : render(json: result) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index cd9c6efb106..543ffa637e1 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -47,7 +47,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController end def membershipable_members - project.members + query_members_via_project_namespace_enabled? ? project.namespace_members : project.members end def plain_source_type @@ -65,6 +65,18 @@ class Projects::ProjectMembersController < Projects::ApplicationController def root_params_key :project_member end + + def members_and_requesters + query_members_via_project_namespace_enabled? ? project.namespace_members_and_requesters : super + end + + def requesters + query_members_via_project_namespace_enabled? ? project.namespace_requesters : super + end + + def query_members_via_project_namespace_enabled? + Feature.enabled?(:project_members_index_by_project_namespace, project) + end end Projects::ProjectMembersController.prepend_mod_with('Projects::ProjectMembersController') diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index 924de0ee7ea..895a9a00624 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -10,7 +10,7 @@ class Projects::RawController < Projects::ApplicationController prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:blob) } - before_action :set_ref_and_path + before_action :assign_ref_vars before_action :require_non_empty_project before_action :authorize_read_code! before_action :check_show_rate_limit!, only: [:show], unless: :external_storage_request? diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index 8ac6d872aae..4c2bd2a9d42 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -24,17 +24,9 @@ class Projects::RefsController < Projects::ApplicationController when "blob" project_blob_path(@project, @id) when "graph" - 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 + project_network_path(@project, @id, ref_type: ref_type) when "graphs" - if Feature.enabled?(:use_ref_type_parameter, @project) - project_graph_path(@project, @id, ref_type: ref_type) - else - project_graph_path(@project, @id) - end + project_graph_path(@project, @id, ref_type: ref_type) when "find_file" project_find_file_path(@project, @id) when "graphs_commits" @@ -42,11 +34,7 @@ class Projects::RefsController < Projects::ApplicationController when "badges" project_settings_ci_cd_path(@project, ref: @id) else - if Feature.enabled?(:use_ref_type_parameter, @project) - project_commits_path(@project, @id, ref_type: ref_type) - else - project_commits_path(@project, @id) - end + project_commits_path(@project, @id, ref_type: ref_type) end redirect_to new_path diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index da414d068a6..7c569df7267 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -9,6 +9,10 @@ class Projects::ReleasesController < Projects::ApplicationController before_action :authorize_create_release!, only: :new before_action :validate_suffix_path, :fetch_latest_tag, only: :latest_permalink + prepend_before_action(only: [:downloads]) do + authenticate_sessionless_user!(:download) + end + feature_category :release_orchestration urgency :low diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index 33ce37ef4fb..1cd4c5b6137 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -47,8 +47,13 @@ class Projects::RepositoriesController < Projects::ApplicationController end def set_cache_headers - expires_in cache_max_age(archive_metadata['CommitId']), public: Guest.can?(:download_code, project) - fresh_when(etag: archive_metadata['ArchivePath']) + commit_id = archive_metadata['CommitId'] + + expires_in(cache_max_age(commit_id), + public: Guest.can?(:download_code, project), must_revalidate: true, stale_if_error: 5.minutes, + stale_while_revalidate: 1.minute, 's-maxage': 1.minute) + + fresh_when(strong_etag: [commit_id, archive_metadata['ArchivePath']]) end def archive_not_modified? diff --git a/app/controllers/projects/service_ping_controller.rb b/app/controllers/projects/service_ping_controller.rb index cfc322b47e7..8c16b6b230e 100644 --- a/app/controllers/projects/service_ping_controller.rb +++ b/app/controllers/projects/service_ping_controller.rb @@ -5,24 +5,6 @@ class Projects::ServicePingController < Projects::ApplicationController feature_category :web_ide - def web_ide_clientside_preview - return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? - - Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_count - - head(:ok) - end - - def web_ide_clientside_preview_success - return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? - - Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_success_count - Gitlab::UsageDataCounters::EditorUniqueCounter.track_live_preview_edit_action(author: current_user, - project: project) - - head(:ok) - end - def web_ide_pipelines_count Gitlab::UsageDataCounters::WebIdeCounter.increment_pipelines_count diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index f8133c5836d..4ca665679c0 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -4,7 +4,6 @@ module Projects module Settings class CiCdController < Projects::ApplicationController include RunnerSetupScripts - include ZuoraCSP NUMBER_OF_RUNNERS_PER_PAGE = 20 @@ -13,6 +12,10 @@ module Projects before_action :check_builds_available! before_action :define_variables + before_action do + push_frontend_feature_flag(:ci_inbound_job_token_scope, @project) + end + helper_method :highlight_badge feature_category :continuous_integration diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 6d099aa8b3d..74d730db026 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -88,25 +88,20 @@ module Projects # rubocop: disable CodeReuse/ActiveRecord def define_protected_refs - @protected_branches = @project.protected_branches.order(:name).page(params[:page]) + @protected_branches = fetch_protected_branches(@project) @protected_tags = @project.protected_tags.order(:name).page(params[:page]) @protected_branch = @project.protected_branches.new @protected_tag = @project.protected_tags.new @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 + def fetch_protected_branches(project) + project.protected_branches.sorted_by_name.page(params[:page]) + end + def remote_mirror @remote_mirror = project.remote_mirrors.first_or_initialize end |