From 311b0269b4eb9839fa63f80c8d7a58f32b8138a0 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 18 Nov 2021 13:16:36 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-5-stable-ee --- .../admin/application_settings_controller.rb | 4 +- app/controllers/admin/applications_controller.rb | 3 + app/controllers/admin/hook_logs_controller.rb | 3 +- app/controllers/admin/hooks_controller.rb | 5 +- app/controllers/admin/integrations_controller.rb | 2 +- app/controllers/admin/labels_controller.rb | 2 +- app/controllers/admin/runners_controller.rb | 10 ++- app/controllers/application_controller.rb | 3 +- app/controllers/autocomplete_controller.rb | 2 +- app/controllers/boards/issues_controller.rb | 2 +- app/controllers/boards/lists_controller.rb | 2 +- app/controllers/concerns/gitlab_recaptcha.rb | 22 ++++++ app/controllers/concerns/group_tree.rb | 8 +- app/controllers/concerns/hooks_execution.rb | 47 ------------ app/controllers/concerns/integrations/actions.rb | 73 ++++++++++++++++++ .../concerns/integrations/hooks_execution.rb | 47 ++++++++++++ app/controllers/concerns/integrations/params.rb | 4 +- app/controllers/concerns/integrations_actions.rb | 71 ----------------- app/controllers/concerns/issuable_actions.rb | 35 ++++++++- app/controllers/concerns/oauth_applications.rb | 10 +++ app/controllers/concerns/one_trust_csp.rb | 2 +- .../concerns/workhorse_authorization.rb | 6 +- app/controllers/confirmations_controller.rb | 10 +++ app/controllers/dashboard/labels_controller.rb | 2 +- app/controllers/dashboard/milestones_controller.rb | 2 +- app/controllers/dashboard/todos_controller.rb | 2 +- app/controllers/dashboard_controller.rb | 2 +- app/controllers/explore/projects_controller.rb | 22 ++++++ app/controllers/graphql_controller.rb | 1 - .../groups/autocomplete_sources_controller.rb | 2 +- app/controllers/groups/boards_controller.rb | 6 +- app/controllers/groups/crm_controller.rb | 30 ++++++++ .../dependency_proxy_for_containers_controller.rb | 88 +++++++++++++++++----- .../groups/email_campaigns_controller.rb | 7 +- app/controllers/groups/labels_controller.rb | 2 +- app/controllers/groups/milestones_controller.rb | 2 +- app/controllers/groups/packages_controller.rb | 4 - .../groups/settings/applications_controller.rb | 3 + .../groups/settings/integrations_controller.rb | 2 +- app/controllers/groups_controller.rb | 10 ++- app/controllers/help_controller.rb | 2 + app/controllers/import/bitbucket_controller.rb | 4 +- app/controllers/invites_controller.rb | 2 +- .../jira_connect/app_descriptor_controller.rb | 2 +- .../jira_connect/application_controller.rb | 4 - app/controllers/jira_connect/events_controller.rb | 7 +- .../jira_connect/subscriptions_controller.rb | 4 +- app/controllers/jwks_controller.rb | 10 ++- app/controllers/oauth/applications_controller.rb | 6 ++ app/controllers/passwords_controller.rb | 10 +++ .../profiles/two_factor_auths_controller.rb | 4 +- app/controllers/profiles_controller.rb | 2 +- .../projects/alert_management_controller.rb | 4 - .../projects/alerting/notifications_controller.rb | 6 +- .../projects/autocomplete_sources_controller.rb | 2 +- app/controllers/projects/badges_controller.rb | 3 +- app/controllers/projects/blame_controller.rb | 1 + app/controllers/projects/blob_controller.rb | 1 + app/controllers/projects/boards_controller.rb | 6 +- app/controllers/projects/branches_controller.rb | 4 +- .../projects/ci/pipeline_editor_controller.rb | 9 ++- .../projects/cluster_agents_controller.rb | 6 ++ app/controllers/projects/commit_controller.rb | 1 + app/controllers/projects/commits_controller.rb | 7 +- app/controllers/projects/compare_controller.rb | 1 + .../projects/cycle_analytics_controller.rb | 12 +++ app/controllers/projects/discussions_controller.rb | 2 +- .../projects/environments_controller.rb | 4 +- app/controllers/projects/find_file_controller.rb | 1 + app/controllers/projects/forks_controller.rb | 1 + .../projects/google_cloud_controller.rb | 26 ++++++- app/controllers/projects/graphs_controller.rb | 5 +- app/controllers/projects/hook_logs_controller.rb | 3 +- app/controllers/projects/hooks_controller.rb | 5 +- app/controllers/projects/issue_links_controller.rb | 2 +- app/controllers/projects/issues_controller.rb | 7 +- app/controllers/projects/jobs_controller.rb | 8 +- app/controllers/projects/labels_controller.rb | 2 +- .../projects/merge_requests_controller.rb | 6 +- .../projects/metrics_dashboard_controller.rb | 1 - app/controllers/projects/milestones_controller.rb | 2 +- app/controllers/projects/network_controller.rb | 1 + app/controllers/projects/notes_controller.rb | 10 ++- .../projects/packages/packages_controller.rb | 4 - .../projects/prometheus/alerts_controller.rb | 6 +- app/controllers/projects/refs_controller.rb | 1 + .../projects/releases/evidences_controller.rb | 1 - app/controllers/projects/releases_controller.rb | 3 - app/controllers/projects/services_controller.rb | 1 + .../projects/settings/ci_cd_controller.rb | 3 +- .../projects/settings/repository_controller.rb | 1 + app/controllers/projects/tags_controller.rb | 26 ++++--- app/controllers/projects/templates_controller.rb | 1 + app/controllers/projects/todos_controller.rb | 2 +- app/controllers/projects/tree_controller.rb | 3 +- .../projects/usage_quotas_controller.rb | 7 -- app/controllers/projects/wikis_controller.rb | 6 +- app/controllers/projects_controller.rb | 16 ++-- .../registrations/welcome_controller.rb | 17 ++++- app/controllers/repositories/lfs_api_controller.rb | 1 + .../repositories/lfs_storage_controller.rb | 2 + app/controllers/search_controller.rb | 3 +- 102 files changed, 580 insertions(+), 290 deletions(-) create mode 100644 app/controllers/concerns/gitlab_recaptcha.rb delete mode 100644 app/controllers/concerns/hooks_execution.rb create mode 100644 app/controllers/concerns/integrations/actions.rb create mode 100644 app/controllers/concerns/integrations/hooks_execution.rb delete mode 100644 app/controllers/concerns/integrations_actions.rb create mode 100644 app/controllers/groups/crm_controller.rb (limited to 'app/controllers') diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 8039fac02ec..8644d95b96c 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -98,7 +98,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController # Specs are in spec/requests/self_monitoring_project_spec.rb def create_self_monitoring_project - job_id = SelfMonitoringProjectCreateWorker.perform_async # rubocop:disable CodeReuse/Worker + job_id = SelfMonitoringProjectCreateWorker.with_status.perform_async # rubocop:disable CodeReuse/Worker render status: :accepted, json: { job_id: job_id, @@ -137,7 +137,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController # Specs are in spec/requests/self_monitoring_project_spec.rb def delete_self_monitoring_project - job_id = SelfMonitoringProjectDeleteWorker.perform_async # rubocop:disable CodeReuse/Worker + job_id = SelfMonitoringProjectDeleteWorker.with_status.perform_async # rubocop:disable CodeReuse/Worker render status: :accepted, json: { job_id: job_id, diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb index ce7d64336c8..83413afb6b7 100644 --- a/app/controllers/admin/applications_controller.rb +++ b/app/controllers/admin/applications_controller.rb @@ -15,6 +15,7 @@ class Admin::ApplicationsController < Admin::ApplicationController end def show + @created = get_created_session end def new @@ -33,6 +34,8 @@ class Admin::ApplicationsController < Admin::ApplicationController if @application.persisted? flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) + set_created_session + redirect_to admin_application_url(@application) else render :new diff --git a/app/controllers/admin/hook_logs_controller.rb b/app/controllers/admin/hook_logs_controller.rb index 444ad17f86d..aa13673095d 100644 --- a/app/controllers/admin/hook_logs_controller.rb +++ b/app/controllers/admin/hook_logs_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Admin::HookLogsController < Admin::ApplicationController - include HooksExecution + include ::Integrations::HooksExecution before_action :hook, only: [:show, :retry] before_action :hook_log, only: [:show, :retry] @@ -9,6 +9,7 @@ class Admin::HookLogsController < Admin::ApplicationController respond_to :html feature_category :integrations + urgency :low, [:retry] def show end diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb index ca24f671b9d..6f5475a4a78 100644 --- a/app/controllers/admin/hooks_controller.rb +++ b/app/controllers/admin/hooks_controller.rb @@ -1,14 +1,15 @@ # frozen_string_literal: true class Admin::HooksController < Admin::ApplicationController - include HooksExecution + include ::Integrations::HooksExecution before_action :hook_logs, only: :edit feature_category :integrations + urgency :low, [:test] def index - @hooks = SystemHook.all + @hooks = SystemHook.all.load @hook = SystemHook.new end diff --git a/app/controllers/admin/integrations_controller.rb b/app/controllers/admin/integrations_controller.rb index a3eb24b9b6f..ad0ee0b2cef 100644 --- a/app/controllers/admin/integrations_controller.rb +++ b/app/controllers/admin/integrations_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Admin::IntegrationsController < Admin::ApplicationController - include IntegrationsActions + include ::Integrations::Actions before_action :not_found, unless: -> { instance_level_integrations? } diff --git a/app/controllers/admin/labels_controller.rb b/app/controllers/admin/labels_controller.rb index 6cc11b40de0..822b7a93c9c 100644 --- a/app/controllers/admin/labels_controller.rb +++ b/app/controllers/admin/labels_controller.rb @@ -3,7 +3,7 @@ class Admin::LabelsController < Admin::ApplicationController before_action :set_label, only: [:show, :edit, :update, :destroy] - feature_category :issue_tracking + feature_category :team_planning def index @labels = Label.templates.page(params[:page]) diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb index 8c74352a179..9312651b8bf 100644 --- a/app/controllers/admin/runners_controller.rb +++ b/app/controllers/admin/runners_controller.rb @@ -8,7 +8,6 @@ class Admin::RunnersController < Admin::ApplicationController feature_category :runner def index - @active_runners_count = Ci::Runner.online.count end def show @@ -86,9 +85,12 @@ class Admin::RunnersController < Admin::ApplicationController Project.all end - @projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any? - @projects = @projects.inc_routes - @projects = @projects.page(params[:page]).per(30).without_count + ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659') do + @projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any? + @projects = @projects.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659') + @projects = @projects.inc_routes + @projects = @projects.page(params[:page]).per(30).without_count + end end # rubocop: enable CodeReuse/ActiveRecord end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b22167a3952..3af1afab06e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -163,7 +163,8 @@ class ApplicationController < ActionController::Base payload[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id payload[:metadata] = @current_context - + payload[:request_urgency] = urgency&.name + payload[:target_duration_s] = urgency&.duration logged_user = auth_user if logged_user.present? payload[:user_id] = logged_user.try(:id) diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index 1c07245da08..5cb5690d72d 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -5,7 +5,7 @@ class AutocompleteController < ApplicationController feature_category :users, [:users, :user] feature_category :projects, [:projects] - feature_category :issue_tracking, [:award_emojis] + feature_category :team_planning, [:award_emojis] feature_category :code_review, [:merge_request_target_branches] feature_category :continuous_delivery, [:deploy_keys_with_owners] diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb index 7dea6191fa4..e7ae941886d 100644 --- a/app/controllers/boards/issues_controller.rb +++ b/app/controllers/boards/issues_controller.rb @@ -21,7 +21,7 @@ module Boards before_action :validate_id_list, only: [:bulk_move] before_action :can_move_issues?, only: [:bulk_move] - feature_category :boards + feature_category :team_planning def index list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params) diff --git a/app/controllers/boards/lists_controller.rb b/app/controllers/boards/lists_controller.rb index 8ab8337a3ad..696b251301f 100644 --- a/app/controllers/boards/lists_controller.rb +++ b/app/controllers/boards/lists_controller.rb @@ -8,7 +8,7 @@ module Boards before_action :authorize_read_list, only: [:index] skip_before_action :authenticate_user!, only: [:index] - feature_category :boards + feature_category :team_planning def index lists = Boards::Lists::ListService.new(board.resource_parent, current_user).execute(board) diff --git a/app/controllers/concerns/gitlab_recaptcha.rb b/app/controllers/concerns/gitlab_recaptcha.rb new file mode 100644 index 00000000000..15e856463ea --- /dev/null +++ b/app/controllers/concerns/gitlab_recaptcha.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module GitlabRecaptcha + extend ActiveSupport::Concern + include Recaptcha::Verify + include RecaptchaHelper + + def load_recaptcha + recaptcha_enabled? && Gitlab::Recaptcha.load_configurations! + end + + def check_recaptcha + return unless load_recaptcha + return if verify_recaptcha + + flash[:alert] = _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.') + flash.delete :recaptcha_error + + self.resource = resource_class.new + render action: 'new' + end +end diff --git a/app/controllers/concerns/group_tree.rb b/app/controllers/concerns/group_tree.rb index 35c1f358a77..e02a766d2b9 100644 --- a/app/controllers/concerns/group_tree.rb +++ b/app/controllers/concerns/group_tree.rb @@ -38,13 +38,7 @@ module GroupTree # # Pagination needs to be applied before loading the ancestors to # make sure ancestors are not cut off by pagination. - filtered_groups_relation = Group.where(id: filtered_groups.select(:id)) - - if Feature.enabled?(:linear_group_tree_ancestor_scopes, current_user, default_enabled: :yaml) - filtered_groups_relation.self_and_ancestors - else - Gitlab::ObjectHierarchy.new(filtered_groups_relation).base_and_ancestors - end + Group.where(id: filtered_groups.select(:id)).self_and_ancestors end # rubocop: enable CodeReuse/ActiveRecord end diff --git a/app/controllers/concerns/hooks_execution.rb b/app/controllers/concerns/hooks_execution.rb deleted file mode 100644 index 87d215f50e7..00000000000 --- a/app/controllers/concerns/hooks_execution.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -module HooksExecution - extend ActiveSupport::Concern - - private - - def destroy_hook(hook) - result = WebHooks::DestroyService.new(current_user).execute(hook) - - if result[:status] == :success - flash[:notice] = - if result[:async] - _("%{hook_type} was scheduled for deletion") % { hook_type: hook.model_name.human } - else - _("%{hook_type} was deleted") % { hook_type: hook.model_name.human } - end - else - flash[:alert] = result[:message] - end - end - - def set_hook_execution_notice(result) - http_status = result[:http_status] - message = result[:message] - - if http_status && http_status >= 200 && http_status < 400 - flash[:notice] = "Hook executed successfully: HTTP #{http_status}" - elsif http_status - flash[:alert] = "Hook executed successfully but returned HTTP #{http_status} #{message}" - else - flash[:alert] = "Hook execution failed: #{message}" - end - end - - def create_rate_limit(key, scope) - if rate_limiter.throttled?(key, scope: [scope, current_user]) - rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user) - - render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests - end - end - - def rate_limiter - ::Gitlab::ApplicationRateLimiter - end -end diff --git a/app/controllers/concerns/integrations/actions.rb b/app/controllers/concerns/integrations/actions.rb new file mode 100644 index 00000000000..6490742c0f8 --- /dev/null +++ b/app/controllers/concerns/integrations/actions.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +module Integrations::Actions + extend ActiveSupport::Concern + + included do + include Integrations::Params + include IntegrationsHelper + + before_action :integration, only: [:edit, :update, :overrides, :test] + + urgency :low, [:test] + end + + def edit + render 'shared/integrations/edit' + end + + def update + saved = integration.update(integration_params[:integration]) + + respond_to do |format| + format.html do + if saved + PropagateIntegrationWorker.perform_async(integration.id) + redirect_to scoped_edit_integration_path(integration), notice: success_message + else + render 'shared/integrations/edit' + end + end + + format.json do + status = saved ? :ok : :unprocessable_entity + + render json: serialize_as_json, status: status + end + end + end + + def test + render json: {}, status: :ok + end + + def reset + integration.destroy! + + flash[:notice] = s_('Integrations|This integration, and inheriting projects were reset.') + + render json: {}, status: :ok + end + + private + + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def integration + @integration ||= find_or_initialize_non_project_specific_integration(params[:id]) + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + + def success_message + if integration.active? + s_('Integrations|%{integration} settings saved and active.') % { integration: integration.title } + else + s_('Integrations|%{integration} settings saved, but not active.') % { integration: integration.title } + end + end + + def serialize_as_json + integration + .as_json(only: integration.json_fields) + .merge(errors: integration.errors.as_json) + end +end diff --git a/app/controllers/concerns/integrations/hooks_execution.rb b/app/controllers/concerns/integrations/hooks_execution.rb new file mode 100644 index 00000000000..af039057a9c --- /dev/null +++ b/app/controllers/concerns/integrations/hooks_execution.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module Integrations::HooksExecution + extend ActiveSupport::Concern + + private + + def destroy_hook(hook) + result = WebHooks::DestroyService.new(current_user).execute(hook) + + if result[:status] == :success + flash[:notice] = + if result[:async] + _("%{hook_type} was scheduled for deletion") % { hook_type: hook.model_name.human } + else + _("%{hook_type} was deleted") % { hook_type: hook.model_name.human } + end + else + flash[:alert] = result[:message] + end + end + + def set_hook_execution_notice(result) + http_status = result[:http_status] + message = result[:message] + + if http_status && http_status >= 200 && http_status < 400 + flash[:notice] = "Hook executed successfully: HTTP #{http_status}" + elsif http_status + flash[:alert] = "Hook executed successfully but returned HTTP #{http_status} #{message}" + else + flash[:alert] = "Hook execution failed: #{message}" + end + end + + def create_rate_limit(key, scope) + if rate_limiter.throttled?(key, scope: [scope, current_user]) + rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user) + + render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests + end + end + + def rate_limiter + ::Gitlab::ApplicationRateLimiter + end +end diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb index 62585ab95af..201fb1dc83f 100644 --- a/app/controllers/concerns/integrations/params.rb +++ b/app/controllers/concerns/integrations/params.rb @@ -9,6 +9,7 @@ module Integrations :add_pusher, :alert_events, :api_key, + :api_token, :api_url, :bamboo_url, :branches_to_be_notified, @@ -74,7 +75,8 @@ module Integrations :url, :user_key, :username, - :webhook + :webhook, + :zentao_product_xid ].freeze def integration_params diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb deleted file mode 100644 index dd066cc1b02..00000000000 --- a/app/controllers/concerns/integrations_actions.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -module IntegrationsActions - extend ActiveSupport::Concern - - included do - include Integrations::Params - include IntegrationsHelper - - before_action :integration, only: [:edit, :update, :overrides, :test] - end - - def edit - render 'shared/integrations/edit' - end - - def update - saved = integration.update(integration_params[:integration]) - - respond_to do |format| - format.html do - if saved - PropagateIntegrationWorker.perform_async(integration.id) - redirect_to scoped_edit_integration_path(integration), notice: success_message - else - render 'shared/integrations/edit' - end - end - - format.json do - status = saved ? :ok : :unprocessable_entity - - render json: serialize_as_json, status: status - end - end - end - - def test - render json: {}, status: :ok - end - - def reset - integration.destroy! - - flash[:notice] = s_('Integrations|This integration, and inheriting projects were reset.') - - render json: {}, status: :ok - end - - private - - # rubocop:disable Gitlab/ModuleWithInstanceVariables - def integration - @integration ||= find_or_initialize_non_project_specific_integration(params[:id]) - end - # rubocop:enable Gitlab/ModuleWithInstanceVariables - - def success_message - if integration.active? - s_('Integrations|%{integration} settings saved and active.') % { integration: integration.title } - else - s_('Integrations|%{integration} settings saved, but not active.') % { integration: integration.title } - end - end - - def serialize_as_json - integration - .as_json(only: integration.json_fields) - .merge(errors: integration.errors.as_json) - end -end diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index e1e662a1968..2d7fbb78209 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -149,8 +149,20 @@ module IssuableActions .includes(:noteable) .fresh + if paginated_discussions + paginated_discussions_by_type = paginated_discussions.records.group_by(&:table_name) + + notes = if paginated_discussions_by_type['notes'].present? + notes.with_discussion_ids(paginated_discussions_by_type['notes'].map(&:discussion_id)) + else + notes.none + end + + response.headers['X-Next-Page-Cursor'] = paginated_discussions.cursor_for_next_page if paginated_discussions.has_next_page? + end + if notes_filter != UserPreference::NOTES_FILTERS[:only_comments] - notes = ResourceEvents::MergeIntoNotesService.new(issuable, current_user).execute(notes) + notes = ResourceEvents::MergeIntoNotesService.new(issuable, current_user, paginated_notes: paginated_discussions_by_type).execute(notes) end notes = prepare_notes_for_rendering(notes) @@ -159,9 +171,9 @@ module IssuableActions discussions = Discussion.build_collection(notes, issuable) if issuable.is_a?(MergeRequest) - cache_context = [current_user&.cache_key, project.team.human_max_access(current_user&.id)].join(':') - - render_cached(discussions, with: discussion_serializer, cache_context: -> (_) { cache_context }, context: self) + render_cached(discussions, with: discussion_serializer, cache_context: -> (_) { discussion_cache_context }, context: self) + elsif issuable.is_a?(Issue) + render json: discussion_serializer.represent(discussions, context: self) if stale?(etag: [discussion_cache_context, discussions]) else render json: discussion_serializer.represent(discussions, context: self) end @@ -170,6 +182,17 @@ module IssuableActions private + def paginated_discussions + return if params[:per_page].blank? + return unless issuable.instance_of?(Issue) && Feature.enabled?(:paginated_issue_discussions, project, default_enabled: :yaml) + + strong_memoize(:paginated_discussions) do + issuable + .discussion_root_note_ids(notes_filter: notes_filter) + .keyset_paginate(cursor: params[:cursor], per_page: params[:per_page].to_i) + end + end + def notes_filter strong_memoize(:notes_filter) do notes_filter_param = params[:notes_filter]&.to_i @@ -197,6 +220,10 @@ module IssuableActions current_user&.user_preference&.previous_changes&.any? end + def discussion_cache_context + [current_user&.cache_key, project.team.human_max_access(current_user&.id)].join(':') + end + def discussion_serializer DiscussionSerializer.new(project: project, noteable: issuable, current_user: current_user, note_entity: ProjectNoteEntity) end diff --git a/app/controllers/concerns/oauth_applications.rb b/app/controllers/concerns/oauth_applications.rb index d2c746db12d..794307ebb0c 100644 --- a/app/controllers/concerns/oauth_applications.rb +++ b/app/controllers/concerns/oauth_applications.rb @@ -3,6 +3,8 @@ module OauthApplications extend ActiveSupport::Concern + CREATED_SESSION_KEY = :oauth_applications_created + included do before_action :prepare_scopes, only: [:create, :update] end @@ -15,6 +17,14 @@ module OauthApplications end end + def set_created_session + session[CREATED_SESSION_KEY] = true + end + + def get_created_session + session.delete(CREATED_SESSION_KEY) || false + end + def load_scopes @scopes ||= Doorkeeper.configuration.scopes end diff --git a/app/controllers/concerns/one_trust_csp.rb b/app/controllers/concerns/one_trust_csp.rb index 4e98ec586ca..fbd44f52590 100644 --- a/app/controllers/concerns/one_trust_csp.rb +++ b/app/controllers/concerns/one_trust_csp.rb @@ -5,7 +5,7 @@ module OneTrustCSP included do content_security_policy do |policy| - next if policy.directives.blank? + next unless helpers.one_trust_enabled? || policy.directives.present? default_script_src = policy.directives['script-src'] || policy.directives['default-src'] script_src_values = Array.wrap(default_script_src) | ["'unsafe-eval'", 'https://cdn.cookielaw.org https://*.onetrust.com'] diff --git a/app/controllers/concerns/workhorse_authorization.rb b/app/controllers/concerns/workhorse_authorization.rb index a290ba256b6..f9b85944307 100644 --- a/app/controllers/concerns/workhorse_authorization.rb +++ b/app/controllers/concerns/workhorse_authorization.rb @@ -26,7 +26,7 @@ module WorkhorseAuthorization def file_is_valid?(file) return false unless file.is_a?(::UploadedFile) - file_extension_whitelist.include?(File.extname(file.original_filename).downcase.delete('.')) + file_extension_allowlist.include?(File.extname(file.original_filename).downcase.delete('.')) end def uploader_class @@ -37,7 +37,7 @@ module WorkhorseAuthorization raise NotImplementedError end - def file_extension_whitelist - ImportExportUploader::EXTENSION_WHITELIST + def file_extension_allowlist + ImportExportUploader::EXTENSION_ALLOWLIST end end diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 0b833e149a4..6725e19df25 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -2,6 +2,10 @@ class ConfirmationsController < Devise::ConfirmationsController include AcceptsPendingInvitations + include GitlabRecaptcha + + prepend_before_action :check_recaptcha, only: :create + before_action :load_recaptcha, only: :new feature_category :users @@ -31,6 +35,12 @@ class ConfirmationsController < Devise::ConfirmationsController end end + def check_recaptcha + return unless resource_params[:email].present? + + super + end + def after_sign_in(resource) after_sign_in_path_for(resource) end diff --git a/app/controllers/dashboard/labels_controller.rb b/app/controllers/dashboard/labels_controller.rb index b661efa12c0..d2f31258ecd 100644 --- a/app/controllers/dashboard/labels_controller.rb +++ b/app/controllers/dashboard/labels_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Dashboard::LabelsController < Dashboard::ApplicationController - feature_category :issue_tracking + feature_category :team_planning def index respond_to do |format| diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb index 1369e82a69b..34d9739d91c 100644 --- a/app/controllers/dashboard/milestones_controller.rb +++ b/app/controllers/dashboard/milestones_controller.rb @@ -4,7 +4,7 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController before_action :projects before_action :groups, only: :index - feature_category :issue_tracking + feature_category :team_planning def index respond_to do |format| diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 21bbb4d0c98..2c5e6817427 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -8,7 +8,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController before_action :authorize_read_group!, only: :index before_action :find_todos, only: [:index, :destroy_all] - feature_category :issue_tracking + feature_category :team_planning def index @sort = params[:sort] diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 227dd0591d4..8d7686a95fb 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -15,7 +15,7 @@ class DashboardController < Dashboard::ApplicationController respond_to :html feature_category :users, [:activity] - feature_category :issue_tracking, [:issues, :issues_calendar] + feature_category :team_planning, [:issues, :issues_calendar] feature_category :code_review, [:merge_requests] def activity diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index 3dc6a16cbc1..14dd2ae5691 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -68,6 +68,20 @@ class Explore::ProjectsController < Explore::ApplicationController end # rubocop: enable CodeReuse/ActiveRecord + def topics + load_project_counts + load_topics + end + + def topic + load_topic + + return render_404 unless @topic + + params[:topic] = @topic.name + @projects = load_projects + end + private def load_project_counts @@ -86,6 +100,14 @@ class Explore::ProjectsController < Explore::ApplicationController prepare_projects_for_rendering(projects) end + def load_topics + @topics = Projects::TopicsFinder.new(params: params.permit(:search)).execute.page(params[:page]).without_count + end + + def load_topic + @topic = Projects::Topic.find_by_name(params[:topic_name]) + end + # rubocop: disable CodeReuse/ActiveRecord def preload_associations(projects) projects.includes(:route, :creator, :group, :project_feature, :topics, namespace: [:route, :owner]) diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 0722a712b5c..fde0f133e53 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -188,6 +188,5 @@ class GraphqlController < ApplicationController def logs RequestStore.store[:graphql_logs].to_a - .map { |log| log.except(:duration_s, :query_string) } end end diff --git a/app/controllers/groups/autocomplete_sources_controller.rb b/app/controllers/groups/autocomplete_sources_controller.rb index 5270a718952..82f8854bd2b 100644 --- a/app/controllers/groups/autocomplete_sources_controller.rb +++ b/app/controllers/groups/autocomplete_sources_controller.rb @@ -2,7 +2,7 @@ class Groups::AutocompleteSourcesController < Groups::ApplicationController feature_category :subgroups, [:members] - feature_category :issue_tracking, [:issues, :labels, :milestones, :commands] + feature_category :team_planning, [:issues, :labels, :milestones, :commands] feature_category :code_review, [:merge_requests] def members diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index e8e6a7e5c1a..3152c4d733f 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -12,9 +12,13 @@ class Groups::BoardsController < Groups::ApplicationController push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml) push_frontend_feature_flag(:iteration_cadences, group, default_enabled: :yaml) push_frontend_feature_flag(:labels_widget, group, default_enabled: :yaml) + experiment(:prominent_create_board_btn, subject: current_user) do |e| + e.use { } + e.try { } + end.run end - feature_category :boards + feature_category :team_planning private diff --git a/app/controllers/groups/crm_controller.rb b/app/controllers/groups/crm_controller.rb new file mode 100644 index 00000000000..40661b09be6 --- /dev/null +++ b/app/controllers/groups/crm_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Groups::CrmController < Groups::ApplicationController + feature_category :team_planning + + before_action :authorize_read_crm_contact!, only: [:contacts] + before_action :authorize_read_crm_organization!, only: [:organizations] + + def contacts + respond_to do |format| + format.html + end + end + + def organizations + respond_to do |format| + format.html + end + end + + private + + def authorize_read_crm_contact! + render_404 unless can?(current_user, :read_crm_contact, group) + end + + def authorize_read_crm_organization! + render_404 unless can?(current_user, :read_crm_organization, group) + end +end diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb index e19b8ae35f8..fc930ffebbd 100644 --- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb +++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb @@ -11,8 +11,8 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy before_action :ensure_token_granted!, only: [:blob, :manifest] before_action :ensure_feature_enabled! - before_action :verify_workhorse_api!, only: [:authorize_upload_blob, :upload_blob] - skip_before_action :verify_authenticity_token, only: [:authorize_upload_blob, :upload_blob] + before_action :verify_workhorse_api!, only: [:authorize_upload_blob, :upload_blob, :authorize_upload_manifest, :upload_manifest] + skip_before_action :verify_authenticity_token, only: [:authorize_upload_blob, :upload_blob, :authorize_upload_manifest, :upload_manifest] attr_reader :token @@ -22,20 +22,11 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy result = DependencyProxy::FindOrCreateManifestService.new(group, image, tag, token).execute if result[:status] == :success - response.headers['Docker-Content-Digest'] = result[:manifest].digest - response.headers['Content-Length'] = result[:manifest].size - response.headers['Docker-Distribution-Api-Version'] = DependencyProxy::DISTRIBUTION_API_VERSION - response.headers['Etag'] = "\"#{result[:manifest].digest}\"" - content_type = result[:manifest].content_type - - event_name = tracking_event_name(object_type: :manifest, from_cache: result[:from_cache]) - track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user) - send_upload( - result[:manifest].file, - proxy: true, - redirect_params: { query: { 'response-content-type' => content_type } }, - send_params: { type: content_type } - ) + if result[:manifest] + send_manifest(result[:manifest], from_cache: result[:from_cache]) + else + send_dependency(manifest_header, DependencyProxy::Registry.manifest_url(image, tag), manifest_file_name) + end else render status: result[:http_status], json: result[:message] end @@ -59,7 +50,7 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy def authorize_upload_blob set_workhorse_internal_api_content_type - render json: DependencyProxy::FileUploader.workhorse_authorize(has_length: false) + render json: DependencyProxy::FileUploader.workhorse_authorize(has_length: false, maximum_size: DependencyProxy::Blob::MAX_FILE_SIZE) end def upload_blob @@ -75,6 +66,37 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy head :ok end + def authorize_upload_manifest + set_workhorse_internal_api_content_type + + render json: DependencyProxy::FileUploader.workhorse_authorize(has_length: false, maximum_size: DependencyProxy::Manifest::MAX_FILE_SIZE) + end + + def upload_manifest + attrs = { + file_name: manifest_file_name, + content_type: request.headers[Gitlab::Workhorse::SEND_DEPENDENCY_CONTENT_TYPE_HEADER], + digest: request.headers[DependencyProxy::Manifest::DIGEST_HEADER], + file: params[:file], + size: params[:file].size + } + + manifest = @group.dependency_proxy_manifests + .active + .find_by_file_name(manifest_file_name) + + if manifest + manifest.update!(attrs) + else + @group.dependency_proxy_manifests.create!(attrs) + end + + event_name = tracking_event_name(object_type: :manifest, from_cache: false) + track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user) + + head :ok + end + private def blob_via_workhorse @@ -86,14 +108,36 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy send_upload(blob.file) else - send_dependency(token, DependencyProxy::Registry.blob_url(image, params[:sha]), blob_file_name) + send_dependency(token_header, DependencyProxy::Registry.blob_url(image, params[:sha]), blob_file_name) end end + def send_manifest(manifest, from_cache:) + response.headers[DependencyProxy::Manifest::DIGEST_HEADER] = manifest.digest + response.headers['Content-Length'] = manifest.size + response.headers['Docker-Distribution-Api-Version'] = DependencyProxy::DISTRIBUTION_API_VERSION + response.headers['Etag'] = "\"#{manifest.digest}\"" + content_type = manifest.content_type + + event_name = tracking_event_name(object_type: :manifest, from_cache: from_cache) + track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user) + + send_upload( + manifest.file, + proxy: true, + redirect_params: { query: { 'response-content-type' => content_type } }, + send_params: { type: content_type } + ) + end + def blob_file_name @blob_file_name ||= params[:sha].sub('sha256:', '') + '.gz' end + def manifest_file_name + @manifest_file_name ||= "#{image}:#{tag}.json" + end + def group strong_memoize(:group) do Group.find_by_full_path(params[:group_id], follow_redirects: true) @@ -137,4 +181,12 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy render status: result[:http_status], json: result[:message] end end + + def token_header + { Authorization: ["Bearer #{token}"] } + end + + def manifest_header + token_header.merge(Accept: ::ContainerRegistry::Client::ACCEPTED_TYPES) + end end diff --git a/app/controllers/groups/email_campaigns_controller.rb b/app/controllers/groups/email_campaigns_controller.rb index 70c8a23d918..520ad768939 100644 --- a/app/controllers/groups/email_campaigns_controller.rb +++ b/app/controllers/groups/email_campaigns_controller.rb @@ -40,7 +40,7 @@ class Groups::EmailCampaignsController < Groups::ApplicationController project_pipelines_url(group.projects.first) when :trial, :trial_short 'https://about.gitlab.com/free-trial/' - when :team, :team_short + when :team, :team_short, :invite_team group_group_members_url(group) when :admin_verify project_settings_ci_cd_path(group.projects.first, ci_runner_templates: true, anchor: 'js-runners-settings') @@ -59,6 +59,11 @@ class Groups::EmailCampaignsController < Groups::ApplicationController @track = params[:track]&.to_sym @series = params[:series]&.to_i + # There is only one email that will be sent for invite team track so series + # should only have the value 0. Return early if track is invite team and + # condition for series value is met + return if @track == Namespaces::InviteTeamEmailService::TRACK && @series == 0 + track_valid = @track.in?(Namespaces::InProductMarketingEmailsService::TRACKS.keys) return render_404 unless track_valid diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb index 86dde454cbc..7bcc8182bd6 100644 --- a/app/controllers/groups/labels_controller.rb +++ b/app/controllers/groups/labels_controller.rb @@ -9,7 +9,7 @@ class Groups::LabelsController < Groups::ApplicationController respond_to :html - feature_category :issue_tracking + feature_category :team_planning def index respond_to do |format| diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 63eff750d1b..75877cdef9c 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -6,7 +6,7 @@ class Groups::MilestonesController < Groups::ApplicationController before_action :milestone, only: [:edit, :show, :update, :issues, :merge_requests, :participants, :labels, :destroy] before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update, :destroy] - feature_category :issue_tracking + feature_category :team_planning def index respond_to do |format| diff --git a/app/controllers/groups/packages_controller.rb b/app/controllers/groups/packages_controller.rb index d02a8262948..47f1816cc4c 100644 --- a/app/controllers/groups/packages_controller.rb +++ b/app/controllers/groups/packages_controller.rb @@ -6,10 +6,6 @@ module Groups feature_category :package_registry - before_action do - push_frontend_feature_flag(:package_list_apollo, default_enabled: :yaml) - end - private def verify_packages_enabled! diff --git a/app/controllers/groups/settings/applications_controller.rb b/app/controllers/groups/settings/applications_controller.rb index f05a96d7810..6388277e4dc 100644 --- a/app/controllers/groups/settings/applications_controller.rb +++ b/app/controllers/groups/settings/applications_controller.rb @@ -16,6 +16,7 @@ module Groups end def show + @created = get_created_session end def edit @@ -27,6 +28,8 @@ module Groups if @application.persisted? flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) + set_created_session + redirect_to group_settings_application_url(@group, @application) else set_index_vars diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb index a7a1de03224..0a63c3d304b 100644 --- a/app/controllers/groups/settings/integrations_controller.rb +++ b/app/controllers/groups/settings/integrations_controller.rb @@ -3,7 +3,7 @@ module Groups module Settings class IntegrationsController < Groups::ApplicationController - include IntegrationsActions + include ::Integrations::Actions before_action :authorize_admin_group! diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index a419171039e..6ae711a6e14 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -54,7 +54,7 @@ class GroupsController < Groups::ApplicationController :destroy, :details, :transfer, :activity ] - feature_category :issue_tracking, [:issues, :issues_calendar, :preview_markdown] + feature_category :team_planning, [:issues, :issues_calendar, :preview_markdown] feature_category :code_review, [:merge_requests, :unfoldered_environment_names] feature_category :projects, [:projects] feature_category :importers, [:export, :download_export] @@ -92,6 +92,7 @@ class GroupsController < Groups::ApplicationController if @group.import_state&.in_progress? redirect_to group_import_path(@group) else + publish_invite_members_for_task_experiment render_show_html end end @@ -379,6 +380,13 @@ class GroupsController < Groups::ApplicationController def captcha_required? captcha_enabled? && !params[:parent_id] end + + def publish_invite_members_for_task_experiment + return unless params[:open_modal] == 'invite_members_for_task' + return unless current_user&.can?(:admin_group_member, @group) + + experiment(:invite_members_for_task, namespace: @group).publish_to_client + end end GroupsController.prepend_mod_with('GroupsController') diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 0ad7478584f..e0020c22145 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -122,3 +122,5 @@ class HelpController < ApplicationController end end end + +::HelpController.prepend_mod diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index d32755dbd94..cfd86429df0 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -116,7 +116,9 @@ class Import::BitbucketController < Import::BaseController redirect_to oauth_client.auth_code.authorize_url(redirect_uri: users_import_bitbucket_callback_url) end - def bitbucket_unauthorized + def bitbucket_unauthorized(exception) + log_exception(exception) + go_to_bitbucket_for_permissions end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 4242f918ea0..d4b1306cc5e 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -52,7 +52,7 @@ class InvitesController < ApplicationController end def current_user_matches_invite? - current_user.verified_emails.include?(@member.invite_email) + current_user.verified_email?(@member.invite_email) end def member? diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb index e96242c7052..16bd73f5ab6 100644 --- a/app/controllers/jira_connect/app_descriptor_controller.rb +++ b/app/controllers/jira_connect/app_descriptor_controller.rb @@ -32,7 +32,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController apiVersion: 1, apiMigrations: { 'context-qsh': true, - 'signed-install': signed_install_active?, + 'signed-install': true, gdpr: true } } diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb index ecb23c326fe..352e78d6255 100644 --- a/app/controllers/jira_connect/application_controller.rb +++ b/app/controllers/jira_connect/application_controller.rb @@ -74,8 +74,4 @@ class JiraConnect::ApplicationController < ApplicationController params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last end end - - def signed_install_active? - Feature.enabled?(:jira_connect_asymmetric_jwt) - end end diff --git a/app/controllers/jira_connect/events_controller.rb b/app/controllers/jira_connect/events_controller.rb index 76ac15f7631..1ea0a92662b 100644 --- a/app/controllers/jira_connect/events_controller.rb +++ b/app/controllers/jira_connect/events_controller.rb @@ -4,14 +4,9 @@ class JiraConnect::EventsController < JiraConnect::ApplicationController # See https://developer.atlassian.com/cloud/jira/software/app-descriptor/#lifecycle skip_before_action :verify_atlassian_jwt! - before_action :verify_asymmetric_atlassian_jwt!, if: :signed_install_active? - - before_action :verify_atlassian_jwt!, only: :uninstalled, unless: :signed_install_active? - before_action :verify_qsh_claim!, only: :uninstalled, unless: :signed_install_active? + before_action :verify_asymmetric_atlassian_jwt! def installed - return head :ok if !signed_install_active? && atlassian_jwt_valid? - return head :ok if current_jira_installation installation = JiraConnectInstallation.new(event_params) diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb index 903ad395e44..fcd95c7942c 100644 --- a/app/controllers/jira_connect/subscriptions_controller.rb +++ b/app/controllers/jira_connect/subscriptions_controller.rb @@ -7,8 +7,8 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController 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 https://unpkg.com/jquery@3.3.1/) - style_src_values = Array.wrap(p.directives['style-src']) | %w('self' 'unsafe-inline' https://unpkg.com/@atlaskit/) + 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 p.frame_ancestors :self, 'https://*.atlassian.net' diff --git a/app/controllers/jwks_controller.rb b/app/controllers/jwks_controller.rb index e7b839f5590..3b0e6ca2eb1 100644 --- a/app/controllers/jwks_controller.rb +++ b/app/controllers/jwks_controller.rb @@ -1,13 +1,17 @@ # frozen_string_literal: true -class JwksController < ActionController::Base # rubocop:disable Rails/ApplicationController +class JwksController < Doorkeeper::OpenidConnect::DiscoveryController def index - render json: { keys: keys } + render json: { keys: payload } + end + + def keys + index end private - def keys + def payload [ # We keep openid_connect_signing_key so that we can seamlessly # replace it with ci_jwt_signing_key and remove it on the next release. diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index 81f188256ba..81084ffe38b 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -24,12 +24,18 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController set_index_vars end + def show + @created = get_created_session + end + def create @application = Applications::CreateService.new(current_user, application_params).execute(request) if @application.persisted? flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) + set_created_session + redirect_to oauth_application_url(@application) else set_index_vars diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index c764f2d0459..ead5d7c9026 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -1,8 +1,12 @@ # frozen_string_literal: true class PasswordsController < Devise::PasswordsController + include GitlabRecaptcha + skip_before_action :require_no_authentication, only: [:edit, :update] + prepend_before_action :check_recaptcha, only: :create + before_action :load_recaptcha, only: :new before_action :resource_from_email, only: [:create] before_action :check_password_authentication_available, only: [:create] before_action :throttle_reset, only: [:create] @@ -59,6 +63,12 @@ class PasswordsController < Devise::PasswordsController alert: _("Password authentication is unavailable.") end + def check_recaptcha + return unless resource_params[:email].present? + + super + end + def throttle_reset return unless resource && resource.recently_sent_password_reset? diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb index e0b5d6be155..e607346b40e 100644 --- a/app/controllers/profiles/two_factor_auths_controller.rb +++ b/app/controllers/profiles/two_factor_auths_controller.rb @@ -66,7 +66,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController render 'create' else - @error = _('Invalid pin code') + @error = { message: _('Invalid pin code.') } @qr_code = build_qr_code if Feature.enabled?(:webauthn) @@ -147,7 +147,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController end def current_password_required? - !current_user.password_automatically_set? + !current_user.password_automatically_set? && current_user.allow_password_authentication_for_web? end def build_qr_code diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 69257081cc9..6330a6aa107 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -63,7 +63,7 @@ class ProfilesController < Profiles::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def audit_log - @events = AuditEvent.where(entity_type: "User", entity_id: current_user.id) + @events = AuthenticationEvent.where(user: current_user) .order("created_at DESC") .page(params[:page]) diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb index 34f9f361e43..ebe867d915d 100644 --- a/app/controllers/projects/alert_management_controller.rb +++ b/app/controllers/projects/alert_management_controller.rb @@ -3,10 +3,6 @@ class Projects::AlertManagementController < Projects::ApplicationController before_action :authorize_read_alert_management_alert! - before_action(only: [:index]) do - push_frontend_feature_flag(:managed_alerts_deprecation, @project, default_enabled: :yaml) - end - feature_category :incident_management def index diff --git a/app/controllers/projects/alerting/notifications_controller.rb b/app/controllers/projects/alerting/notifications_controller.rb index 95b403faf55..ae8498ce65f 100644 --- a/app/controllers/projects/alerting/notifications_controller.rb +++ b/app/controllers/projects/alerting/notifications_controller.rb @@ -18,7 +18,11 @@ module Projects token = extract_alert_manager_token(request) result = notify_service.execute(token, integration) - head result.http_status + if result.success? + render json: AlertManagement::AlertSerializer.new.represent(result.payload[:alerts]), code: result.http_status + else + head result.http_status + end end private diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb index 7c419cac1cc..0d5f64c739c 100644 --- a/app/controllers/projects/autocomplete_sources_controller.rb +++ b/app/controllers/projects/autocomplete_sources_controller.rb @@ -3,7 +3,7 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController before_action :authorize_read_milestone!, only: :milestones - feature_category :issue_tracking, [:issues, :labels, :milestones, :commands] + feature_category :team_planning, [:issues, :labels, :milestones, :commands] feature_category :code_review, [:merge_requests] feature_category :users, [:members] feature_category :snippets, [:snippets] diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb index 0cd59c136e5..8023e51b552 100644 --- a/app/controllers/projects/badges_controller.rb +++ b/app/controllers/projects/badges_controller.rb @@ -6,7 +6,8 @@ class Projects::BadgesController < Projects::ApplicationController before_action :no_cache_headers, only: [:pipeline, :coverage] before_action :authorize_read_build!, only: [:pipeline, :coverage] - feature_category :continuous_integration + feature_category :continuous_integration, [:index, :pipeline] + feature_category :code_testing, [:coverage] def pipeline pipeline_status = Gitlab::Ci::Badge::Pipeline::Status diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb index 1df7b9ed165..0f87690bba5 100644 --- a/app/controllers/projects/blame_controller.rb +++ b/app/controllers/projects/blame_controller.rb @@ -10,6 +10,7 @@ class Projects::BlameController < Projects::ApplicationController before_action :authorize_download_code! feature_category :source_code_management + urgency :low, [:show] def show @blob = @repository.blob_at(@commit.id, @path) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 17fd28ee06a..cd50c8cf5b1 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -40,6 +40,7 @@ class Projects::BlobController < Projects::ApplicationController track_redis_hll_event :create, :update, name: 'g_edit_by_sfe' feature_category :source_code_management + urgency :low, [:create, :show, :edit, :update, :diff] before_action do push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml) diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 834e4baa7dd..7354c2c71ac 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -12,9 +12,13 @@ class Projects::BoardsController < Projects::ApplicationController push_frontend_feature_flag(:board_multi_select, project, default_enabled: :yaml) push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml) push_frontend_feature_flag(:labels_widget, project, default_enabled: :yaml) + experiment(:prominent_create_board_btn, subject: current_user) do |e| + e.use { } + e.try { } + end.run end - feature_category :boards + feature_category :team_planning private diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index b75effc52d1..63ac5f97420 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -14,6 +14,7 @@ class Projects::BranchesController < Projects::ApplicationController before_action :limit_diverging_commit_counts!, only: [:diverging_commit_counts] feature_category :source_code_management + urgency :low, [:index, :diverging_commit_counts, :create, :destroy] def index respond_to do |format| @@ -105,8 +106,7 @@ class Projects::BranchesController < Projects::ApplicationController # rubocop: enable CodeReuse/ActiveRecord def destroy - @branch_name = Addressable::URI.unescape(params[:id]) - result = ::Branches::DeleteService.new(project, current_user).execute(@branch_name) + result = ::Branches::DeleteService.new(project, current_user).execute(params[:id]) respond_to do |format| format.html do diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb index 22cd247644d..600516f95a2 100644 --- a/app/controllers/projects/ci/pipeline_editor_controller.rb +++ b/app/controllers/projects/ci/pipeline_editor_controller.rb @@ -2,8 +2,8 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController before_action :check_can_collaborate! + before_action :setup_walkthrough_experiment, only: :show before_action do - push_frontend_feature_flag(:pipeline_editor_mini_graph, @project, default_enabled: :yaml) push_frontend_feature_flag(:schema_linting, @project, default_enabled: :yaml) end @@ -17,4 +17,11 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController def check_can_collaborate! render_404 unless can_collaborate_with_project?(@project) end + + def setup_walkthrough_experiment + experiment(:pipeline_editor_walkthrough, namespace: @project.namespace, sticky_to: current_user) do |e| + e.candidate {} + e.record! + end + end end diff --git a/app/controllers/projects/cluster_agents_controller.rb b/app/controllers/projects/cluster_agents_controller.rb index e7fbe93131d..404d3907128 100644 --- a/app/controllers/projects/cluster_agents_controller.rb +++ b/app/controllers/projects/cluster_agents_controller.rb @@ -3,6 +3,10 @@ class Projects::ClusterAgentsController < Projects::ApplicationController before_action :authorize_can_read_cluster_agent! + before_action do + push_frontend_feature_flag(:cluster_vulnerabilities, project, default_enabled: :yaml) + end + feature_category :kubernetes_management def show @@ -17,3 +21,5 @@ class Projects::ClusterAgentsController < Projects::ApplicationController access_denied! end end + +Projects::ClusterAgentsController.prepend_mod_with('Projects::ClusterAgentsController') diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 6748be06ded..62935e133c5 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -24,6 +24,7 @@ class Projects::CommitController < Projects::ApplicationController COMMIT_DIFFS_PER_PAGE = 20 feature_category :source_code_management + urgency :low, [:pipelines, :merge_requests, :show] def show apply_diff_view_cookie! diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 9ca917841e9..1ca35903703 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -6,6 +6,8 @@ class Projects::CommitsController < Projects::ApplicationController include ExtractsPath include RendersCommits + COMMITS_DEFAULT_LIMIT = 40 + prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } around_action :allow_gitaly_ref_name_caching before_action :require_non_empty_project @@ -15,6 +17,7 @@ class Projects::CommitsController < Projects::ApplicationController before_action :set_commits, except: :commits_root feature_category :source_code_management + urgency :low, [:signatures, :show] def commits_root redirect_to project_commits_path(@project, @project.default_branch) @@ -63,7 +66,9 @@ class Projects::CommitsController < Projects::ApplicationController def set_commits render_404 unless @path.empty? || request.format == :atom || @repository.blob_at(@commit.id, @path) || @repository.tree(@commit.id, @path).entries.present? - @limit = (params[:limit] || 40).to_i + + limit = params[:limit].to_i + @limit = limit > 0 ? limit : COMMITS_DEFAULT_LIMIT # limit can only ever be a positive number @offset = (params[:offset] || 0).to_i search = params[:search] author = params[:author] diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 99f62c18593..07f7c1cf7de 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -21,6 +21,7 @@ class Projects::CompareController < Projects::ApplicationController before_action :validate_refs! feature_category :source_code_management + urgency :low, [:show, :create, :signatures] # Diffs may be pretty chunky, the less is better in this endpoint. # Pagination design guides: https://design.gitlab.com/components/pagination/#behavior diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb index db5ba51ee01..dc6a9a73d9e 100644 --- a/app/controllers/projects/cycle_analytics_controller.rb +++ b/app/controllers/projects/cycle_analytics_controller.rb @@ -6,8 +6,10 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController include CycleAnalyticsParams include GracefulTimeoutHandling include RedisTracking + extend ::Gitlab::Utils::Override before_action :authorize_read_cycle_analytics! + before_action :load_value_stream, only: :show track_redis_hll_event :show, name: 'p_analytics_valuestream' @@ -19,6 +21,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController def show @cycle_analytics = Analytics::CycleAnalytics::ProjectLevel.new(project: @project, options: options(cycle_analytics_project_params)) + @request_params ||= ::Gitlab::Analytics::CycleAnalytics::RequestParams.new(all_cycle_analytics_params) respond_to do |format| format.html do @@ -34,6 +37,15 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController private + override :all_cycle_analytics_params + def all_cycle_analytics_params + super.merge({ project: @project, value_stream: @value_stream }) + end + + def load_value_stream + @value_stream = Analytics::CycleAnalytics::ProjectValueStream.build_default_value_stream(@project) + end + def cycle_analytics_json { summary: @cycle_analytics.summary, diff --git a/app/controllers/projects/discussions_controller.rb b/app/controllers/projects/discussions_controller.rb index 708b7a6c7ba..9f7d47b95f3 100644 --- a/app/controllers/projects/discussions_controller.rb +++ b/app/controllers/projects/discussions_controller.rb @@ -9,7 +9,7 @@ class Projects::DiscussionsController < Projects::ApplicationController before_action :discussion, only: [:resolve, :unresolve] before_action :authorize_resolve_discussion!, only: [:resolve, :unresolve] - feature_category :issue_tracking + feature_category :team_planning def resolve Discussions::ResolveService.new(project, current_user, one_or_more_discussions: discussion).execute diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 23dabd885c8..84ebdcd9364 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -70,11 +70,9 @@ class Projects::EnvironmentsController < Projects::ApplicationController end # rubocop: enable CodeReuse/ActiveRecord - # rubocop: disable CodeReuse/ActiveRecord def show - @deployments = environment.deployments.order(id: :desc).page(params[:page]) + @deployments = environment.deployments.ordered.page(params[:page]) end - # rubocop: enable CodeReuse/ActiveRecord def new @environment = project.environments.new diff --git a/app/controllers/projects/find_file_controller.rb b/app/controllers/projects/find_file_controller.rb index 89e72d98a33..c6bc115e737 100644 --- a/app/controllers/projects/find_file_controller.rb +++ b/app/controllers/projects/find_file_controller.rb @@ -11,6 +11,7 @@ class Projects::FindFileController < Projects::ApplicationController before_action :authorize_download_code! feature_category :source_code_management + urgency :low, [:show, :list] def show return render_404 unless @repository.commit(@ref) diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 7135c0d959e..5154f145b46 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -15,6 +15,7 @@ class Projects::ForksController < Projects::ApplicationController before_action :authorize_fork_namespace!, only: [:create] feature_category :source_code_management + urgency :low, [:index] before_action do push_frontend_feature_flag(:fork_project_form, @project, default_enabled: :yaml) diff --git a/app/controllers/projects/google_cloud_controller.rb b/app/controllers/projects/google_cloud_controller.rb index d185457aeb3..7257ed1ef6f 100644 --- a/app/controllers/projects/google_cloud_controller.rb +++ b/app/controllers/projects/google_cloud_controller.rb @@ -1,16 +1,34 @@ # frozen_string_literal: true class Projects::GoogleCloudController < Projects::ApplicationController - before_action :authorize_can_manage_google_cloud_deployments! + feature_category :google_cloud - feature_category :release_orchestration + before_action :admin_project_google_cloud? + before_action :google_oauth2_enabled? + before_action :feature_flag_enabled? def index + @js_data = { + serviceAccounts: GoogleCloud::ServiceAccountsService.new(project).find_for_project, + createServiceAccountUrl: '#mocked-url-create-service', + emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg') + }.to_json end private - def authorize_can_manage_google_cloud_deployments! - access_denied! unless can?(current_user, :manage_project_google_cloud, project) + def admin_project_google_cloud? + access_denied! unless can?(current_user, :admin_project_google_cloud, project) + end + + def google_oauth2_enabled? + config = Gitlab::Auth::OAuth::Provider.config_for('google_oauth2') + if config.app_id.blank? || config.app_secret.blank? + access_denied! 'This GitLab instance not configured for Google Oauth2.' + end + end + + def feature_flag_enabled? + access_denied! unless Feature.enabled?(:incubation_5mp_google_cloud) end end diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index 7a7961c28bb..d3a05736a47 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -11,7 +11,10 @@ class Projects::GraphsController < Projects::ApplicationController track_redis_hll_event :charts, name: 'p_analytics_repo' - feature_category :source_code_management + feature_category :source_code_management, [:show, :commits, :languages, :charts] + urgency :low, [:show] + + feature_category :continuous_integration, [:ci] def show respond_to do |format| diff --git a/app/controllers/projects/hook_logs_controller.rb b/app/controllers/projects/hook_logs_controller.rb index 99ebe3335c0..0ca3d71f728 100644 --- a/app/controllers/projects/hook_logs_controller.rb +++ b/app/controllers/projects/hook_logs_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Projects::HookLogsController < Projects::ApplicationController - include HooksExecution + include ::Integrations::HooksExecution before_action :authorize_admin_project! @@ -13,6 +13,7 @@ class Projects::HookLogsController < Projects::ApplicationController layout 'project_settings' feature_category :integrations + urgency :low, [:retry] def show end diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index b87bfc58f8b..c79e5a8cc85 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Projects::HooksController < Projects::ApplicationController - include HooksExecution + include ::Integrations::HooksExecution # Authorize before_action :authorize_admin_project! @@ -13,9 +13,10 @@ class Projects::HooksController < Projects::ApplicationController layout "project_settings" feature_category :integrations + urgency :low, [:test] def index - @hooks = @project.hooks + @hooks = @project.hooks.load @hook = ProjectHook.new end diff --git a/app/controllers/projects/issue_links_controller.rb b/app/controllers/projects/issue_links_controller.rb index 35f3e00fae7..e8c3110574f 100644 --- a/app/controllers/projects/issue_links_controller.rb +++ b/app/controllers/projects/issue_links_controller.rb @@ -7,7 +7,7 @@ module Projects before_action :authorize_admin_issue_link!, only: [:create, :destroy] before_action :authorize_issue_link_association!, only: :destroy - feature_category :issue_tracking + feature_category :team_planning private diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index fd508d5f127..853e9c7ccdd 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -48,12 +48,11 @@ class Projects::IssuesController < Projects::ApplicationController end before_action only: :show do - real_time_enabled = Gitlab::ActionCable::Config.in_app? || Feature.enabled?(:real_time_issue_sidebar, @project) - - push_to_gon_attributes(:features, :real_time_issue_sidebar, real_time_enabled) + push_frontend_feature_flag(:real_time_issue_sidebar, @project, default_enabled: :yaml) push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml) push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml) push_frontend_feature_flag(:labels_widget, @project, default_enabled: :yaml) + push_frontend_feature_flag(:paginated_issue_discussions, @project, default_enabled: :yaml) experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance| experiment_instance.exclude! unless helpers.can_admin_project_member?(@project) @@ -71,7 +70,7 @@ class Projects::IssuesController < Projects::ApplicationController alias_method :designs, :show - feature_category :issue_tracking, [ + feature_category :team_planning, [ :index, :calendar, :show, :new, :create, :edit, :update, :destroy, :move, :reorder, :designs, :toggle_subscription, :discussions, :bulk_update, :realtime_changes, diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index 994be5c2b5c..81b8da9cba3 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -133,9 +133,9 @@ class Projects::JobsController < Projects::ApplicationController end def raw - if trace_artifact_file + if @build.trace.archived_trace_exist? workhorse_set_content_type! - send_upload(trace_artifact_file, + send_upload(@build.job_artifacts_trace.file, send_params: raw_send_params, redirect_params: raw_redirect_params) else @@ -219,10 +219,6 @@ class Projects::JobsController < Projects::ApplicationController params.permit(job_variables_attributes: %i[key secret_value]) end - def trace_artifact_file - @trace_artifact_file ||= @build.job_artifacts_trace&.file - end - def find_job_as_build @build = project.builds.find(params[:id]) end diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 6bf3885fb7a..814081194d6 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -14,7 +14,7 @@ class Projects::LabelsController < Projects::ApplicationController respond_to :js, :html - feature_category :issue_tracking + feature_category :team_planning def index respond_to do |format| diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 46df514abcb..6c5a8aa0610 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -41,6 +41,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:diffs_virtual_scrolling, project, default_enabled: :yaml) push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml) push_frontend_feature_flag(:mr_changes_fluid_layout, project, default_enabled: :yaml) + push_frontend_feature_flag(:mr_attention_requests, project, default_enabled: :yaml) + push_frontend_feature_flag(:labels_widget, project, default_enabled: :yaml) # Usage data feature flags push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml) @@ -140,8 +142,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo cache_context = [ params[:serializer], current_user&.cache_key, - @merge_request.assignees.map(&:cache_key), - @merge_request.reviewers.map(&:cache_key) + @merge_request.merge_request_assignees.map(&:cache_key), + @merge_request.merge_request_reviewers.map(&:cache_key) ] render_cached(@merge_request, diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb index 89c99a5fd5a..3f10749602e 100644 --- a/app/controllers/projects/metrics_dashboard_controller.rb +++ b/app/controllers/projects/metrics_dashboard_controller.rb @@ -12,7 +12,6 @@ module Projects before_action do push_frontend_feature_flag(:prometheus_computed_alerts) push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate) - push_frontend_feature_flag(:managed_alerts_deprecation, @project, default_enabled: :yaml) end feature_category :metrics diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 630e7ccd43f..5dc9718d7a4 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -18,7 +18,7 @@ class Projects::MilestonesController < Projects::ApplicationController respond_to :html - feature_category :issue_tracking + feature_category :team_planning def index @sort = params[:sort] || 'due_date_asc' diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index f3a7bc7913e..84ac9fb01fd 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -11,6 +11,7 @@ class Projects::NetworkController < Projects::ApplicationController before_action :assign_commit feature_category :source_code_management + urgency :low, [:show] def show @url = project_network_path(@project, @ref, @options.merge(format: :json)) diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index e7e6aed8ec8..e8057308386 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -11,7 +11,7 @@ class Projects::NotesController < Projects::ApplicationController before_action :authorize_create_note!, only: [:create] before_action :authorize_resolve_note!, only: [:resolve, :unresolve] - feature_category :issue_tracking + feature_category :team_planning def delete_attachment note.remove_attachment! @@ -55,6 +55,14 @@ class Projects::NotesController < Projects::ApplicationController end end + def outdated_line_change + diff_lines = Rails.cache.fetch(['note', note.id, 'oudated_line_change'], expires_in: 7.days) do + ::MergeRequests::OutdatedDiscussionDiffLinesService.new(project: @project, note: note).execute.to_json + end + + render json: diff_lines + end + private def render_json_with_notes_serializer diff --git a/app/controllers/projects/packages/packages_controller.rb b/app/controllers/projects/packages/packages_controller.rb index dd7c2ad3cbd..5de71466c10 100644 --- a/app/controllers/projects/packages/packages_controller.rb +++ b/app/controllers/projects/packages/packages_controller.rb @@ -7,10 +7,6 @@ module Projects feature_category :package_registry - before_action do - push_frontend_feature_flag(:package_list_apollo, default_enabled: :yaml) - end - def show @package = project.packages.find(params[:id]) end diff --git a/app/controllers/projects/prometheus/alerts_controller.rb b/app/controllers/projects/prometheus/alerts_controller.rb index 19c908026cf..312919831d4 100644 --- a/app/controllers/projects/prometheus/alerts_controller.rb +++ b/app/controllers/projects/prometheus/alerts_controller.rb @@ -30,7 +30,11 @@ module Projects token = extract_alert_manager_token(request) result = notify_service.execute(token) - head result.http_status + if result.success? + render json: AlertManagement::AlertSerializer.new.represent(result.payload[:alerts]), code: result.http_status + else + head result.http_status + end end def create diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index 4d23c853334..73eb6bb2bf2 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -12,6 +12,7 @@ class Projects::RefsController < Projects::ApplicationController before_action :authorize_download_code! feature_category :source_code_management + urgency :low, [:switch, :logs_tree] def switch respond_to do |format| diff --git a/app/controllers/projects/releases/evidences_controller.rb b/app/controllers/projects/releases/evidences_controller.rb index 1e2dbf8047c..41e2ce81eb8 100644 --- a/app/controllers/projects/releases/evidences_controller.rb +++ b/app/controllers/projects/releases/evidences_controller.rb @@ -20,7 +20,6 @@ module Projects private def authorize_read_release_evidence! - access_denied! unless Feature.enabled?(:release_evidence, project, default_enabled: true) access_denied! unless can?(current_user, :read_release_evidence, evidence) end diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index be2abc5cddf..7fba6cc5bf4 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -5,9 +5,6 @@ class Projects::ReleasesController < Projects::ApplicationController before_action :require_non_empty_project, except: [:index] before_action :release, only: %i[edit show update downloads] before_action :authorize_read_release! - # We have to check `download_code` permission because detail URL path - # contains git-tag name. - before_action :authorize_download_code!, except: [:index] before_action :authorize_update_release!, only: %i[edit update] before_action :authorize_create_release!, only: :new before_action only: :index do diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index c42d382c4bb..9464826701d 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -18,6 +18,7 @@ class Projects::ServicesController < Projects::ApplicationController layout "project_settings" feature_category :integrations + urgency :low, [:test] def edit end diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 3033dac8246..4fe37352995 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -104,8 +104,7 @@ module Projects CreatePipelineWorker.perform_async(project.id, current_user.id, project.default_branch, :web, ignore_skip_ci: true, save_on_errors: false) # rubocop:enable CodeReuse/Worker - pipelines_link_start = ''.html_safe % { url: project_pipelines_path(@project) } - flash[:toast] = _("A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details") % { pipelines_link_start: pipelines_link_start, pipelines_link_end: "".html_safe } + flash[:toast] = _("A new Auto DevOps pipeline has been created, go to the Pipelines page for details") end def define_variables diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 728231dbdbd..cc419bab687 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -12,6 +12,7 @@ module Projects feature_category :source_code_management, [:show, :cleanup] feature_category :continuous_delivery, [:create_deploy_token] + urgency :low, [:show] def show render_show diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 02d36c3353d..de0faaca9c0 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -10,23 +10,29 @@ class Projects::TagsController < Projects::ApplicationController before_action :authorize_download_code! before_action :authorize_admin_tag!, only: [:new, :create, :destroy] - feature_category :source_code_management, [:index, :show, :new, :destroy] - feature_category :release_evidence, [:create] + feature_category :source_code_management + urgency :low, [:new, :show, :index] # rubocop: disable CodeReuse/ActiveRecord def index - params[:sort] = params[:sort].presence || sort_value_recently_updated + begin + params[:sort] = params[:sort].presence || sort_value_recently_updated - @sort = params[:sort] + @sort = params[:sort] - @tags, @tags_loading_error = TagsFinder.new(@repository, params).execute + @tags = TagsFinder.new(@repository, params).execute - @tags = Kaminari.paginate_array(@tags).page(params[:page]) - tag_names = @tags.map(&:name) - @tags_pipelines = @project.ci_pipelines.latest_successful_for_refs(tag_names) + @tags = Kaminari.paginate_array(@tags).page(params[:page]) + tag_names = @tags.map(&:name) + @tags_pipelines = @project.ci_pipelines.latest_successful_for_refs(tag_names) - @releases = project.releases.where(tag: tag_names) - @tag_pipeline_statuses = Ci::CommitStatusesFinder.new(@project, @repository, current_user, @tags).execute + @releases = project.releases.where(tag: tag_names) + @tag_pipeline_statuses = Ci::CommitStatusesFinder.new(@project, @repository, current_user, @tags).execute + + rescue Gitlab::Git::CommandError => e + @tags = [] + @tags_loading_error = e + end respond_to do |format| status = @tags_loading_error ? :service_unavailable : :ok diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb index 4bad6dc1b3d..6d06b05c1e9 100644 --- a/app/controllers/projects/templates_controller.rb +++ b/app/controllers/projects/templates_controller.rb @@ -6,6 +6,7 @@ class Projects::TemplatesController < Projects::ApplicationController before_action :get_template_class feature_category :source_code_management + urgency :low, [:names] def index templates = @template_type.template_subsets(project) diff --git a/app/controllers/projects/todos_controller.rb b/app/controllers/projects/todos_controller.rb index 6ba89ab34f8..dafdeb4c9ef 100644 --- a/app/controllers/projects/todos_controller.rb +++ b/app/controllers/projects/todos_controller.rb @@ -6,7 +6,7 @@ class Projects::TodosController < Projects::ApplicationController before_action :authenticate_user!, only: [:create] - feature_category :issue_tracking + feature_category :team_planning private diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index a76d45411dd..f8f2c1f0836 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -17,11 +17,12 @@ class Projects::TreeController < Projects::ApplicationController before_action do push_frontend_feature_flag(:lazy_load_commits, @project, default_enabled: :yaml) - push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml) push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml) + push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml) end feature_category :source_code_management + urgency :low, [:show] def show return render_404 unless @commit diff --git a/app/controllers/projects/usage_quotas_controller.rb b/app/controllers/projects/usage_quotas_controller.rb index 103e1cc596a..b319e427eaa 100644 --- a/app/controllers/projects/usage_quotas_controller.rb +++ b/app/controllers/projects/usage_quotas_controller.rb @@ -2,7 +2,6 @@ class Projects::UsageQuotasController < Projects::ApplicationController before_action :authorize_admin_project! - before_action :verify_usage_quotas_enabled! layout "project_settings" @@ -20,10 +19,4 @@ class Projects::UsageQuotasController < Projects::ApplicationController wiki_help_page_path: help_page_path('administration/wikis/index.md', anchor: 'reduce-wiki-repository-size') } end - - private - - def verify_usage_quotas_enabled! - render_404 unless Feature.enabled?(:project_storage_ui, project&.group, default_enabled: :yaml) - end end diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 9ee8847004e..02dfaf4c193 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -3,11 +3,9 @@ class Projects::WikisController < Projects::ApplicationController include WikiActions - alias_method :container, :project + urgency :low - before_action do - push_frontend_feature_flag(:content_editor_block_tables, @project, default_enabled: :yaml) - end + alias_method :container, :project feature_category :wiki end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 0760f97d7c1..5b17b75a963 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -37,7 +37,6 @@ class ProjectsController < Projects::ApplicationController push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml) push_frontend_feature_flag(:refactor_text_viewer, @project, default_enabled: :yaml) push_frontend_feature_flag(:increase_page_size_exponentially, @project, default_enabled: :yaml) - push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml) push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml) end @@ -49,9 +48,10 @@ class ProjectsController < Projects::ApplicationController ] feature_category :source_code_management, [:remove_fork, :housekeeping, :refs] - feature_category :issue_tracking, [:preview_markdown, :new_issuable_address] + feature_category :team_planning, [:preview_markdown, :new_issuable_address] feature_category :importers, [:export, :remove_export, :generate_new_export, :download_export] feature_category :code_review, [:unfoldered_environment_names] + urgency :low, [:refs] def index redirect_to(current_user ? root_path : explore_root_path) @@ -293,7 +293,11 @@ class ProjectsController < Projects::ApplicationController end if find_tags && @repository.tag_count.nonzero? - tags, _ = TagsFinder.new(@repository, params).execute + tags = begin + TagsFinder.new(@repository, params).execute + rescue Gitlab::Git::CommandError + [] + end options['Tags'] = tags.take(100).map(&:name) end @@ -336,11 +340,6 @@ class ProjectsController < Projects::ApplicationController if can?(current_user, :download_code, @project) return render 'projects/no_repo' unless @project.repository_exists? - if @project.can_current_user_push_to_default_branch? - property = @project.empty_repo? ? 'empty' : 'nonempty' - experiment(:empty_repo_upload, project: @project).track(:view_project_show, property: property) - end - render 'projects/empty' if @project.empty_repo? else if can?(current_user, :read_wiki, @project) @@ -452,6 +451,7 @@ class ProjectsController < Projects::ApplicationController :suggestion_commit_message, :packages_enabled, :service_desk_enabled, + :merge_commit_template, project_setting_attributes: project_setting_attributes ] + [project_feature_attributes: project_feature_attributes] end diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb index 416bbf43464..39d3125a4a3 100644 --- a/app/controllers/registrations/welcome_controller.rb +++ b/app/controllers/registrations/welcome_controller.rb @@ -16,7 +16,9 @@ module Registrations result = ::Users::SignupService.new(current_user, update_params).execute if result[:status] == :success - return redirect_to experiment(:combined_registration, user: current_user).redirect_path(trial_params) if show_signup_onboarding? + 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? members = current_user.members @@ -64,12 +66,23 @@ module Registrations members.last.source.activity_path end + # overridden in EE def show_signup_onboarding? false end + def show_tasks_to_be_done? + return unless experiment(:invite_members_for_task).enabled? + + MemberTask.for_members(current_user.members).exists? + end + + # overridden in EE def trial_params - nil + end + + # overridden in EE + def update_success_path end end end diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb index a7719516cb6..30cafb6747e 100644 --- a/app/controllers/repositories/lfs_api_controller.rb +++ b/app/controllers/repositories/lfs_api_controller.rb @@ -13,6 +13,7 @@ module Repositories # added here as a part of the refactor, will be removed # https://gitlab.com/gitlab-org/gitlab/-/issues/328692 delegate :deploy_token, :user, to: :authentication_result, allow_nil: true + urgency :medium, [:batch] def batch unless objects.present? diff --git a/app/controllers/repositories/lfs_storage_controller.rb b/app/controllers/repositories/lfs_storage_controller.rb index 6ec63a0f939..252b604dcb0 100644 --- a/app/controllers/repositories/lfs_storage_controller.rb +++ b/app/controllers/repositories/lfs_storage_controller.rb @@ -11,6 +11,8 @@ module Repositories # added here as a part of the refactor, will be removed # https://gitlab.com/gitlab-org/gitlab/-/issues/328692 delegate :deploy_token, :user, to: :authentication_result, allow_nil: true + urgency :medium, [:download, :upload_authorize] + urgency :low, [:upload_finalize] def download lfs_object = LfsObject.find_by_oid(oid) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 0a18559fc81..0e285dae089 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -46,6 +46,7 @@ class SearchController < ApplicationController @search_results = @search_service.search_results @search_objects = @search_service.search_objects @search_highlight = @search_service.search_highlight + @aggregations = @search_service.search_aggregations increment_search_counters end @@ -151,7 +152,7 @@ class SearchController < ApplicationController def block_anonymous_global_searches return if params[:project_id].present? || params[:group_id].present? return if current_user - return unless ::Feature.enabled?(:block_anonymous_global_searches) + return unless ::Feature.enabled?(:block_anonymous_global_searches, type: :ops) store_location_for(:user, request.fullpath) -- cgit v1.2.3