diff options
Diffstat (limited to 'app/controllers')
65 files changed, 432 insertions, 126 deletions
diff --git a/app/controllers/abuse_reports_controller.rb b/app/controllers/abuse_reports_controller.rb index 9d1c68eea89..206a5b11e4b 100644 --- a/app/controllers/abuse_reports_controller.rb +++ b/app/controllers/abuse_reports_controller.rb @@ -20,8 +20,10 @@ class AbuseReportsController < ApplicationController message = _("Thank you for your report. A GitLab administrator will look into it shortly.") redirect_to root_path, notice: message - else + elsif report_params[:user_id].present? render :new + else + redirect_to root_path, alert: _("Cannot create the abuse report. The reported user was invalid. Please try again or contact support.") end end diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 8644d95b96c..1d0930ba73c 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -27,7 +27,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController feature_category :source_code_management, [:repository, :clear_repository_check_states] feature_category :continuous_integration, [:ci_cd, :reset_registration_token] - feature_category :service_ping, [:usage_data] + feature_category :service_ping, [:usage_data, :service_usage_data] feature_category :integrations, [:integrations] feature_category :pages, [:lets_encrypt_terms_of_service] @@ -52,6 +52,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController @integrations = Integration.find_or_initialize_all_non_project_specific(Integration.for_instance).sort_by(&:title) end + def service_usage_data + end + def update perform_update end @@ -59,11 +62,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController def usage_data respond_to do |format| format.html do - usage_data_json = Gitlab::Json.pretty_generate(Gitlab::UsageData.data) + usage_data_json = Gitlab::Json.pretty_generate(Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values, cached: true)) render html: Gitlab::Highlight.highlight('payload.json', usage_data_json, language: 'json') end - format.json { render json: Gitlab::UsageData.to_json } + format.json { render json: Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values, cached: true).to_json } end end diff --git a/app/controllers/admin/instance_review_controller.rb b/app/controllers/admin/instance_review_controller.rb index 5567ffbdc84..1ce6e66c6de 100644 --- a/app/controllers/admin/instance_review_controller.rb +++ b/app/controllers/admin/instance_review_controller.rb @@ -16,7 +16,7 @@ class Admin::InstanceReviewController < Admin::ApplicationController } if Gitlab::CurrentSettings.usage_ping_enabled? - data = ::Gitlab::UsageData.data + data = Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values, cached: true) counts = data[:counts] result[:instance_review].merge!( diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb index 16657612050..f7f78ab3229 100644 --- a/app/controllers/admin/runners_controller.rb +++ b/app/controllers/admin/runners_controller.rb @@ -34,7 +34,7 @@ class Admin::RunnersController < Admin::ApplicationController end def destroy - @runner.destroy + Ci::UnregisterRunnerService.new(@runner).execute redirect_to admin_runners_path, status: :found end @@ -85,7 +85,11 @@ class Admin::RunnersController < Admin::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def assign_builds_and_projects - @builds = runner.builds.order('id DESC').preload_project_and_pipeline_project.first(30) + @builds = runner + .builds + .order_id_desc + .preload_project_and_pipeline_project.first(30) + @projects = if params[:search].present? ::Project.search(params[:search]) @@ -93,12 +97,10 @@ class Admin::RunnersController < Admin::ApplicationController Project.all end - ::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 + runner_projects_ids = runner.runner_projects.pluck(:project_id) + @projects = @projects.where.not(id: runner_projects_ids) if runner_projects_ids.any? + @projects = @projects.inc_routes + @projects = @projects.page(params[:page]).per(30).without_count end # rubocop: enable CodeReuse/ActiveRecord end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index b40e2affcee..c1fa104ffda 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -16,7 +16,7 @@ class Admin::UsersController < Admin::ApplicationController return redirect_to admin_cohorts_path if params[:tab] == 'cohorts' @users = User.filter_items(params[:filter]).order_name_asc - @users = @users.search_with_secondary_emails(params[:search_query]) if params[:search_query].present? + @users = @users.search(params[:search_query], with_private_emails: true) if params[:search_query].present? @users = users_with_included_associations(@users) @users = @users.sort_by_attribute(@sort = params[:sort]) @users = @users.page(params[:page]) @@ -370,7 +370,7 @@ class Admin::UsersController < Admin::ApplicationController end def check_ban_user_feature_flag - access_denied! unless Feature.enabled?(:ban_user_feature_flag) + access_denied! unless Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml) end def log_impersonation_event diff --git a/app/controllers/clusters/base_controller.rb b/app/controllers/clusters/base_controller.rb index b1ffdf00b87..f88d381b3bf 100644 --- a/app/controllers/clusters/base_controller.rb +++ b/app/controllers/clusters/base_controller.rb @@ -4,7 +4,7 @@ class Clusters::BaseController < ApplicationController include RoutableActions skip_before_action :authenticate_user! - before_action :authorize_read_cluster! + before_action :authorize_admin_cluster!, except: [:show, :index, :new, :authorize_aws_role, :update] helper_method :clusterable @@ -18,11 +18,11 @@ class Clusters::BaseController < ApplicationController end def authorize_update_cluster! - access_denied! unless can?(current_user, :update_cluster, cluster) + access_denied! unless can?(current_user, :update_cluster, clusterable) end def authorize_admin_cluster! - access_denied! unless can?(current_user, :admin_cluster, cluster) + access_denied! unless can?(current_user, :admin_cluster, clusterable) end def authorize_read_cluster! diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index 15a261f572a..c12ceca9c3b 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -10,9 +10,9 @@ class Clusters::ClustersController < Clusters::BaseController before_action :validate_gcp_token, only: [:new] before_action :gcp_cluster, only: [:new] before_action :user_cluster, only: [:new] + before_action :authorize_read_cluster!, only: [:show, :index] before_action :authorize_create_cluster!, only: [:new, :authorize_aws_role] before_action :authorize_update_cluster!, only: [:update] - before_action :authorize_admin_cluster!, only: [:destroy, :clear_cache] before_action :update_applications_status, only: [:cluster_status] helper_method :token_in_session diff --git a/app/controllers/concerns/bizible_csp.rb b/app/controllers/concerns/bizible_csp.rb new file mode 100644 index 00000000000..521f3127759 --- /dev/null +++ b/app/controllers/concerns/bizible_csp.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module BizibleCSP + extend ActiveSupport::Concern + + included do + content_security_policy do |policy| + next unless helpers.bizible_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.bizible.com/scripts/bizible.js'] + policy.script_src(*script_src_values) + end + end +end diff --git a/app/controllers/concerns/integrations/actions.rb b/app/controllers/concerns/integrations/actions.rb index f6e98c25b72..1f788860c8f 100644 --- a/app/controllers/concerns/integrations/actions.rb +++ b/app/controllers/concerns/integrations/actions.rb @@ -8,9 +8,6 @@ module Integrations::Actions include IntegrationsHelper before_action :integration, only: [:edit, :update, :overrides, :test] - before_action do - push_frontend_feature_flag(:vue_integration_form, current_user, default_enabled: :yaml) - end urgency :low, [:test] end diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb index 945540d1f8c..80acb369cb2 100644 --- a/app/controllers/concerns/integrations/params.rb +++ b/app/controllers/concerns/integrations/params.rb @@ -30,6 +30,7 @@ module Integrations :datadog_site, :datadog_env, :datadog_service, + :datadog_tags, :default_irc_uri, :device, :disable_diffs, diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index bac9732018c..eae087bca4d 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -17,7 +17,10 @@ module IssuableActions def show respond_to do |format| format.html do - @show_crm_contacts = issuable.is_a?(Issue) && can?(current_user, :read_crm_contact, issuable.project.group) # rubocop:disable Gitlab/ModuleWithInstanceVariables + @show_crm_contacts = issuable.is_a?(Issue) && # rubocop:disable Gitlab/ModuleWithInstanceVariables + can?(current_user, :read_crm_contact, issuable.project.group) && + CustomerRelations::Contact.exists_for_group?(issuable.project.group) + @issuable_sidebar = serializer.represent(issuable, serializer: 'sidebar') # rubocop:disable Gitlab/ModuleWithInstanceVariables render 'show' end diff --git a/app/controllers/concerns/multiple_boards_actions.rb b/app/controllers/concerns/multiple_boards_actions.rb index 85bb73463db..685c93fc2a2 100644 --- a/app/controllers/concerns/multiple_boards_actions.rb +++ b/app/controllers/concerns/multiple_boards_actions.rb @@ -14,7 +14,7 @@ module MultipleBoardsActions end def recent - recent_visits = ::Boards::VisitsFinder.new(parent, current_user).latest(4) + recent_visits = ::Boards::VisitsFinder.new(parent, current_user).latest(Board::RECENT_BOARDS_SIZE) recent_boards = recent_visits.map(&:board) render json: serialize_as_json(recent_boards) diff --git a/app/controllers/concerns/planning_hierarchy.rb b/app/controllers/concerns/planning_hierarchy.rb new file mode 100644 index 00000000000..5df838bc183 --- /dev/null +++ b/app/controllers/concerns/planning_hierarchy.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module PlanningHierarchy + extend ActiveSupport::Concern + + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def planning_hierarchy + return access_denied! unless can?(current_user, :read_planning_hierarchy, @project) + + render 'shared/planning_hierarchy' + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables +end + +PlanningHierarchy.prepend_mod_with('PlanningHierarchy') diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb index f489de42864..e1bfe92f61b 100644 --- a/app/controllers/concerns/uploads_actions.rb +++ b/app/controllers/concerns/uploads_actions.rb @@ -142,6 +142,14 @@ module UploadsActions uploader && uploader.exists? && uploader.embeddable? end + def bypass_auth_checks_on_uploads? + if ::Feature.enabled?(:enforce_auth_checks_on_uploads, default_enabled: :yaml) + false + else + action_name == 'show' && embeddable? + end + end + def find_model nil end diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index d861ef646f8..0074bcac360 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -35,7 +35,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def starred - @projects = load_projects(params.merge(starred: true)) + @projects = load_projects(params.merge(starred: true, not_aimed_for_deletion: true)) .includes(:forked_from_project, :topics) @groups = [] @@ -54,7 +54,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController private def projects - @projects ||= load_projects(params.merge(non_public: true)) + @projects ||= load_projects(params.merge(non_public: true, not_aimed_for_deletion: true)) end def render_projects @@ -65,8 +65,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController end def load_projects(finder_params) - @total_user_projects_count = ProjectsFinder.new(params: { non_public: true, without_deleted: true }, current_user: current_user).execute - @total_starred_projects_count = ProjectsFinder.new(params: { starred: true, without_deleted: true }, current_user: current_user).execute + @total_user_projects_count = ProjectsFinder.new(params: { non_public: true, without_deleted: true, not_aimed_for_deletion: true }, current_user: current_user).execute + @total_starred_projects_count = ProjectsFinder.new(params: { starred: true, without_deleted: true, not_aimed_for_deletion: true }, current_user: current_user).execute finder_params[:use_cte] = true if use_cte_for_finder? finder_params[:without_deleted] = true diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 2ecd17db487..f94da77609f 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -20,6 +20,10 @@ class DashboardController < Dashboard::ApplicationController urgency :low, [:merge_requests] + before_action only: [:merge_requests] do + push_frontend_feature_flag(:mr_attention_requests, default_enabled: :yaml) + end + def activity respond_to do |format| format.html diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index 14dd2ae5691..f8a6d9f808e 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -92,7 +92,12 @@ class Explore::ProjectsController < Explore::ApplicationController def load_projects load_project_counts - projects = ProjectsFinder.new(current_user: current_user, params: params.merge(minimum_search_length: MIN_SEARCH_LENGTH)).execute + finder_params = { + minimum_search_length: MIN_SEARCH_LENGTH, + not_aimed_for_deletion: true + } + + projects = ProjectsFinder.new(current_user: current_user, params: params.merge(finder_params)).execute projects = preload_associations(projects) projects = projects.page(params[:page]).without_count diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 689ca32f6d9..ef229a2abec 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -31,6 +31,7 @@ class GraphqlController < ApplicationController before_action :authorize_access_api! before_action :set_user_last_activity before_action :track_vs_code_usage + before_action :track_jetbrains_usage before_action :disable_query_limiting before_action :limit_query_size @@ -137,6 +138,11 @@ class GraphqlController < ApplicationController .track_api_request_when_trackable(user_agent: request.user_agent, user: current_user) end + def track_jetbrains_usage + Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter + .track_api_request_when_trackable(user_agent: request.user_agent, user: current_user) + end + def execute_multiplex GitlabSchema.multiplex(multiplex_queries, context: context) end diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index 6de77450a46..6fac6fcf426 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -11,8 +11,8 @@ class Groups::BoardsController < Groups::ApplicationController push_frontend_feature_flag(:board_multi_select, group, default_enabled: :yaml) push_frontend_feature_flag(:iteration_cadences, group, default_enabled: :yaml) experiment(:prominent_create_board_btn, subject: current_user) do |e| - e.use { } - e.try { } + e.control { } + e.candidate { } end.run end diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb index 00839583ecc..8513979c53b 100644 --- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb +++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb @@ -120,7 +120,7 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy end def manifest_file_name - @manifest_file_name ||= "#{image}:#{tag}.json" + @manifest_file_name ||= Gitlab::Utils.check_path_traversal!("#{image}:#{tag}.json") end def group diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb index f602d02a165..b194aeff80d 100644 --- a/app/controllers/groups/runners_controller.rb +++ b/app/controllers/groups/runners_controller.rb @@ -9,10 +9,8 @@ class Groups::RunnersController < Groups::ApplicationController feature_category :runner def index - ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433') do - finder = Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }) - @group_runners_limited_count = finder.execute.except(:limit, :offset).page.total_count_with_limit(:all, limit: 1000) - end + finder = Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }) + @group_runners_limited_count = finder.execute.except(:limit, :offset).page.total_count_with_limit(:all, limit: 1000) end def runner_list_group_view_vue_ui_enabled @@ -37,7 +35,7 @@ class Groups::RunnersController < Groups::ApplicationController if @runner.belongs_to_more_than_one_project? redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), status: :found, alert: _('Runner was not deleted because it is assigned to multiple projects.') else - @runner.destroy + Ci::UnregisterRunnerService.new(@runner).execute redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), status: :found end @@ -62,11 +60,9 @@ class Groups::RunnersController < Groups::ApplicationController private def runner - ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433') do - @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }).execute - .except(:limit, :offset) - .find(params[:id]) - end + @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }).execute + .except(:limit, :offset) + .find(params[:id]) end def runner_params diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index e125385f841..a290ef9b5e7 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -23,11 +23,6 @@ module Groups @group_runners = runners_finder.execute.page(params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE) @sort = runners_finder.sort_key - - # Allow sql generated by the two relations above, @all_group_runners and @group_runners - ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433') do - render - end end def update diff --git a/app/controllers/groups/uploads_controller.rb b/app/controllers/groups/uploads_controller.rb index 49249f87d31..387f7be56cd 100644 --- a/app/controllers/groups/uploads_controller.rb +++ b/app/controllers/groups/uploads_controller.rb @@ -4,7 +4,7 @@ class Groups::UploadsController < Groups::ApplicationController include UploadsActions include WorkhorseRequest - skip_before_action :group, if: -> { action_name == 'show' && embeddable? } + skip_before_action :group, if: -> { bypass_auth_checks_on_uploads? } before_action :authorize_upload_file!, only: [:create, :authorize] before_action :verify_workhorse_api!, only: [:authorize] diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 4acbb0482f3..12af76efe0d 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -38,6 +38,8 @@ class GroupsController < Groups::ApplicationController before_action :check_export_rate_limit!, only: [:export, :download_export] + before_action :track_experiment_event, only: [:new] + helper_method :captcha_required? skip_cross_project_access_check :index, :new, :create, :edit, :update, @@ -207,6 +209,20 @@ class GroupsController < Groups::ApplicationController end end + def issues + return super if !html_request? || Feature.disabled?(:vue_issues_list, group, default_enabled: :yaml) + + @has_issues = IssuesFinder.new(current_user, group_id: group.id).execute + .non_archived + .exists? + + @has_projects = group_projects.exists? + + respond_to do |format| + format.html + end + end + protected def render_show_html @@ -378,6 +394,12 @@ class GroupsController < Groups::ApplicationController def captcha_required? captcha_enabled? && !params[:parent_id] end + + def track_experiment_event + return if params[:parent_id] + + experiment(:require_verification_for_namespace_creation, user: current_user).track(:start_create_group) + end end GroupsController.prepend_mod_with('GroupsController') diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index 8de270e9d25..9b8c480e529 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -38,7 +38,7 @@ class Import::GitlabProjectsController < Import::BaseController def project_params params.permit( - :path, :namespace_id, :file + :name, :path, :namespace_id, :file ) end diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb index d3dea2ce159..a0c307a0a03 100644 --- a/app/controllers/metrics_controller.rb +++ b/app/controllers/metrics_controller.rb @@ -7,7 +7,6 @@ class MetricsController < ActionController::Base def index response = if Gitlab::Metrics.prometheus_metrics_enabled? - Gitlab::Metrics::RailsSlis.initialize_request_slis_if_needed! metrics_service.metrics_text else help_page = help_page_url('administration/monitoring/prometheus/gitlab_metrics', diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb index ddf70c1892a..d1c409d071e 100644 --- a/app/controllers/oauth/authorizations_controller.rb +++ b/app/controllers/oauth/authorizations_controller.rb @@ -3,6 +3,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController include Gitlab::Experimentation::ControllerConcern include InitializesCurrentUserMode + include Gitlab::Utils::StrongMemoize before_action :verify_confirmed_email!, :verify_confidential_application! @@ -27,6 +28,56 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController private + def pre_auth_params + # Cannot be achieved with a before_action hook, due to the execution order. + downgrade_scopes! if action_name == 'new' + + super + end + + # limit scopes when signing in with GitLab + def downgrade_scopes! + return unless Feature.enabled?(:omniauth_login_minimal_scopes, current_user, + default_enabled: :yaml) + + auth_type = params.delete('gl_auth_type') + return unless auth_type == 'login' + + ensure_read_user_scope! + + params['scope'] = Gitlab::Auth::READ_USER_SCOPE.to_s if application_has_read_user_scope? + end + + # Configure the application to support read_user scope, if it already + # supports scopes with greater levels of privileges. + def ensure_read_user_scope! + return if application_has_read_user_scope? + return unless application_has_api_scope? + + add_read_user_scope! + end + + def add_read_user_scope! + return unless doorkeeper_application + + scopes = doorkeeper_application.scopes + scopes.add(Gitlab::Auth::READ_USER_SCOPE) + doorkeeper_application.scopes = scopes + doorkeeper_application.save! + end + + def doorkeeper_application + strong_memoize(:doorkeeper_application) { ::Doorkeeper::OAuth::Client.find(params['client_id'])&.application } + end + + def application_has_read_user_scope? + doorkeeper_application&.includes_scope?(Gitlab::Auth::READ_USER_SCOPE) + end + + def application_has_api_scope? + doorkeeper_application&.includes_scope?(*::Gitlab::Auth::API_SCOPES) + end + # Confidential apps require the client_secret to be sent with the request. # Doorkeeper allows implicit grant flow requests (response_type=token) to # work without client_secret regardless of the confidential setting. diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb index cf432cfb429..f678e19d05d 100644 --- a/app/controllers/projects/autocomplete_sources_controller.rb +++ b/app/controllers/projects/autocomplete_sources_controller.rb @@ -2,8 +2,9 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController before_action :authorize_read_milestone!, only: :milestones + before_action :authorize_read_crm_contact!, only: :contacts - feature_category :team_planning, [:issues, :labels, :milestones, :commands] + feature_category :team_planning, [:issues, :labels, :milestones, :commands, :contacts] feature_category :code_review, [:merge_requests] feature_category :users, [:members] feature_category :snippets, [:snippets] @@ -38,6 +39,10 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController render json: autocomplete_service.snippets end + def contacts + render json: autocomplete_service.contacts + end + private def autocomplete_service @@ -49,6 +54,10 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController .new(project, current_user) .execute(params[:type], params[:type_id]) end + + def authorize_read_crm_contact! + render_404 unless can?(current_user, :read_crm_contact, project.root_ancestor) + end end Projects::AutocompleteSourcesController.prepend_mod_with('Projects::AutocompleteSourcesController') diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb index 8023e51b552..42bd87e1c01 100644 --- a/app/controllers/projects/badges_controller.rb +++ b/app/controllers/projects/badges_controller.rb @@ -8,6 +8,7 @@ class Projects::BadgesController < Projects::ApplicationController feature_category :continuous_integration, [:index, :pipeline] feature_category :code_testing, [:coverage] + feature_category :release_orchestration, [:release] def pipeline pipeline_status = Gitlab::Ci::Badge::Pipeline::Status @@ -34,6 +35,17 @@ class Projects::BadgesController < Projects::ApplicationController render_badge coverage_report end + def release + latest_release = Gitlab::Ci::Badge::Release::LatestRelease + .new(project, current_user, opts: { + key_text: params[:key_text], + key_width: params[:key_width], + order_by: params[:order_by] + }) + + render_badge latest_release + end + private def badge_layout diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index adaa47b48cb..0170cff6160 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -11,8 +11,8 @@ 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) experiment(:prominent_create_board_btn, subject: current_user) do |e| - e.use { } - e.try { } + e.control { } + e.candidate { } end.run end diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 63ac5f97420..dad73c37fea 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -131,11 +131,28 @@ class Projects::BranchesController < Projects::ApplicationController private def sort_value_for_mode - return params[:sort] if params[:sort].present? + custom_sort || default_sort + end + + def custom_sort + sort = params[:sort].presence + + unless sort.in?(supported_sort_options) + flash.now[:alert] = _("Unsupported sort value.") + sort = nil + end + sort + end + + def default_sort 'stale' == @mode ? sort_value_oldest_updated : sort_value_recently_updated end + def supported_sort_options + [nil, sort_value_name, sort_value_oldest_updated, sort_value_recently_updated] + end + # It can be expensive to calculate the diverging counts for each # branch. Normally the frontend should be specifying a set of branch # names, but prior to diff --git a/app/controllers/projects/cluster_agents_controller.rb b/app/controllers/projects/cluster_agents_controller.rb index 404d3907128..84bb01ee266 100644 --- a/app/controllers/projects/cluster_agents_controller.rb +++ b/app/controllers/projects/cluster_agents_controller.rb @@ -16,7 +16,7 @@ class Projects::ClusterAgentsController < Projects::ApplicationController private def authorize_can_read_cluster_agent! - return if can?(current_user, :admin_cluster, project) + return if can?(current_user, :read_cluster, project) access_denied! end diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb index 8f45fa1cb9f..440375bf3c9 100644 --- a/app/controllers/projects/clusters_controller.rb +++ b/app/controllers/projects/clusters_controller.rb @@ -6,6 +6,7 @@ class Projects::ClustersController < Clusters::ClustersController before_action do push_frontend_feature_flag(:prometheus_computed_alerts) + push_frontend_feature_flag(:show_gitlab_agent_feedback, type: :ops, default_enabled: :yaml) end layout 'project' diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 62935e133c5..0ce0b8b8895 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -92,6 +92,8 @@ class Projects::CommitController < Projects::ApplicationController end def branches + return git_not_found! unless commit + # branch_names_contains/tag_names_contains can take a long time when there are thousands of # branches/tags - each `git branch --contains xxx` request can consume a cpu core. # so only do the query when there are a manageable number of branches/tags diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 1ca35903703..82a13b60b13 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -67,11 +67,11 @@ 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].to_i + limit = permitted_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] + @offset = (permitted_params[:offset] || 0).to_i + search = permitted_params[:search] + author = permitted_params[:author] @commits = if search.present? @@ -87,4 +87,8 @@ class Projects::CommitsController < Projects::ApplicationController @commits = @commits.with_latest_pipeline(@ref) @commits = set_commits_for_rendering(@commits) end + + def permitted_params + params.permit(:limit, :offset, :search, :author) + end end diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 07f7c1cf7de..243cc7a346c 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -28,6 +28,7 @@ class Projects::CompareController < Projects::ApplicationController COMMIT_DIFFS_PER_PAGE = 20 def index + compare_params end def show @@ -44,9 +45,9 @@ class Projects::CompareController < Projects::ApplicationController def create from_to_vars = { - from: params[:from].presence, - to: params[:to].presence, - from_project_id: params[:from_project_id].presence + from: compare_params[:from].presence, + to: compare_params[:to].presence, + from_project_id: compare_params[:from_project_id].presence } if from_to_vars[:from].blank? || from_to_vars[:to].blank? @@ -87,10 +88,10 @@ class Projects::CompareController < Projects::ApplicationController # target == start_ref == from def target_project strong_memoize(:target_project) do - next source_project unless params.key?(:from_project_id) - next source_project if params[:from_project_id].to_i == source_project.id + next source_project unless compare_params.key?(:from_project_id) + next source_project if compare_params[:from_project_id].to_i == source_project.id - target_project = target_projects(source_project).find_by_id(params[:from_project_id]) + target_project = target_projects(source_project).find_by_id(compare_params[:from_project_id]) # Just ignore the field if it points at a non-existent or hidden project next source_project unless target_project && can?(current_user, :download_code, target_project) @@ -111,13 +112,13 @@ class Projects::CompareController < Projects::ApplicationController end def start_ref - @start_ref ||= Addressable::URI.unescape(params[:from]) + @start_ref ||= Addressable::URI.unescape(compare_params[:from]) end def head_ref return @ref if defined?(@ref) - @ref = @head_ref = Addressable::URI.unescape(params[:to]) + @ref = @head_ref = Addressable::URI.unescape(compare_params[:to]) end def define_commits @@ -146,4 +147,8 @@ class Projects::CompareController < Projects::ApplicationController .find_by(source_project: source_project, source_branch: head_ref, target_branch: start_ref) end # rubocop: enable CodeReuse/ActiveRecord + + def compare_params + @compare_params ||= params.permit(:from, :to, :from_project_id) + end end diff --git a/app/controllers/projects/design_management/designs_controller.rb b/app/controllers/projects/design_management/designs_controller.rb index 550d8578396..2aa48249c0e 100644 --- a/app/controllers/projects/design_management/designs_controller.rb +++ b/app/controllers/projects/design_management/designs_controller.rb @@ -4,6 +4,7 @@ class Projects::DesignManagement::DesignsController < Projects::ApplicationContr before_action :authorize_read_design! feature_category :design_management + urgency :low private diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index ba83f8dad35..475c41eec9c 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -22,14 +22,14 @@ class Projects::ForksController < Projects::ApplicationController end def index - @sort = params[:sort] + @sort = forks_params[:sort] @total_forks_count = project.forks.size @public_forks_count = project.forks.public_only.size @private_forks_count = @total_forks_count - project.forks.public_and_internal_only.size @internal_forks_count = @total_forks_count - @public_forks_count - @private_forks_count - @forks = load_forks.page(params[:page]) + @forks = load_forks.page(forks_params[:page]) prepare_projects_for_rendering(@forks) @@ -98,7 +98,7 @@ class Projects::ForksController < Projects::ApplicationController def load_forks forks = ForkProjectsFinder.new( project, - params: params.merge(search: params[:filter_projects]), + params: forks_params.merge(search: forks_params[:filter_projects]), current_user: current_user ).execute @@ -117,6 +117,10 @@ class Projects::ForksController < Projects::ApplicationController end end + def forks_params + params.permit(:filter_projects, :sort, :page) + end + def fork_params params.permit(:path, :name, :description, :visibility).tap do |param| param[:namespace] = fork_namespace diff --git a/app/controllers/projects/google_cloud/deployments_controller.rb b/app/controllers/projects/google_cloud/deployments_controller.rb index 4e7fd73e378..1941eb8a5f9 100644 --- a/app/controllers/projects/google_cloud/deployments_controller.rb +++ b/app/controllers/projects/google_cloud/deployments_controller.rb @@ -4,10 +4,63 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base before_action :validate_gcp_token! def cloud_run - render json: "Placeholder" + params = { token_in_session: token_in_session } + enable_cloud_run_response = GoogleCloud::EnableCloudRunService + .new(project, current_user, params).execute + + if enable_cloud_run_response[:status] == :error + flash[:error] = enable_cloud_run_response[:message] + redirect_to project_google_cloud_index_path(project) + else + params = { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } + generate_pipeline_response = GoogleCloud::GeneratePipelineService + .new(project, current_user, params).execute + + if generate_pipeline_response[:status] == :error + flash[:error] = 'Failed to generate pipeline' + redirect_to project_google_cloud_index_path(project) + else + cloud_run_mr_params = cloud_run_mr_params(generate_pipeline_response[:branch_name]) + redirect_to project_new_merge_request_path(project, merge_request: cloud_run_mr_params) + end + end + rescue Google::Apis::ClientError => error + handle_gcp_error(error, project) end def cloud_storage render json: "Placeholder" end + + private + + def cloud_run_mr_params(branch_name) + { + title: cloud_run_mr_title, + description: cloud_run_mr_description(branch_name), + source_project_id: project.id, + target_project_id: project.id, + source_branch: branch_name, + target_branch: project.default_branch + } + end + + def cloud_run_mr_title + 'Enable deployments to Cloud Run' + end + + def cloud_run_mr_description(branch_name) + <<-TEXT +This merge request includes a Cloud Run deployment job in the pipeline definition (.gitlab-ci.yml). + +The `deploy-to-cloud-run` job: +* Requires the following environment variables + * `GCP_PROJECT_ID` + * `GCP_SERVICE_ACCOUNT_KEY` +* Job definition can be found at: https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library + +This pipeline definition has been committed to the branch `#{branch_name}`. +You may modify the pipeline definition further or accept the changes as-is if suitable. + TEXT + end end diff --git a/app/controllers/projects/google_cloud_controller.rb b/app/controllers/projects/google_cloud_controller.rb index 1fa8ae60376..206a8c7e391 100644 --- a/app/controllers/projects/google_cloud_controller.rb +++ b/app/controllers/projects/google_cloud_controller.rb @@ -6,6 +6,8 @@ class Projects::GoogleCloudController < Projects::GoogleCloud::BaseController screen: 'home', serviceAccounts: GoogleCloud::ServiceAccountsService.new(project).find_for_project, createServiceAccountUrl: project_google_cloud_service_accounts_path(project), + enableCloudRunUrl: project_google_cloud_deployments_cloud_run_path(project), + enableCloudStorageUrl: project_google_cloud_deployments_cloud_storage_path(project), emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg') }.to_json end diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index 27893fe510d..6bc81381d92 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -28,7 +28,7 @@ class Projects::GroupLinksController < Projects::ApplicationController if group_link.expires? render json: { - expires_in: helpers.distance_of_time_in_words_to_now(group_link.expires_at), + expires_in: helpers.time_ago_with_tooltip(group_link.expires_at), expires_soon: group_link.expires_soon? } else diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 785fbdaa611..1b98810b09b 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -10,7 +10,7 @@ class Projects::IssuesController < Projects::ApplicationController include RecordUserLastActivity ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze - SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze + SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[calendar service_desk].freeze prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) } @@ -42,18 +42,20 @@ class Projects::IssuesController < Projects::ApplicationController if: -> { Feature.disabled?('rate_limited_service_issues_create', project, default_enabled: :yaml) } before_action do - push_frontend_feature_flag(:tribute_autocomplete, @project) push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml) push_frontend_feature_flag(:vue_issues_list, project&.group, default_enabled: :yaml) push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml) + push_frontend_feature_flag(:contacts_autocomplete, project&.group, default_enabled: :yaml) + push_frontend_feature_flag(:markdown_continue_lists, project, default_enabled: :yaml) end before_action only: :show do - push_frontend_feature_flag(:real_time_issue_sidebar, @project, default_enabled: :yaml) + push_frontend_feature_flag(:real_time_issue_sidebar, project, default_enabled: :yaml) push_frontend_feature_flag(:confidential_notes, project&.group, default_enabled: :yaml) - push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml) - push_frontend_feature_flag(:paginated_issue_discussions, @project, default_enabled: :yaml) - push_frontend_feature_flag(:fix_comment_scroll, @project, default_enabled: :yaml) + push_frontend_feature_flag(:issue_assignees_widget, project, default_enabled: :yaml) + push_frontend_feature_flag(:paginated_issue_discussions, project, default_enabled: :yaml) + push_frontend_feature_flag(:fix_comment_scroll, project, default_enabled: :yaml) + push_frontend_feature_flag(:work_items, project, default_enabled: :yaml) end around_action :allow_gitaly_ref_name_caching, only: [:discussions] @@ -71,11 +73,14 @@ class Projects::IssuesController < Projects::ApplicationController ] feature_category :service_desk, [:service_desk] + urgency :low, [:service_desk] feature_category :importers, [:import_csv, :export_csv] attr_accessor :vulnerability_id def index + set_issuables_index if !html_request? || Feature.disabled?(:vue_issues_list, project&.group, default_enabled: :yaml) + @issues = @issuables respond_to do |format| @@ -317,7 +322,7 @@ class Projects::IssuesController < Projects::ApplicationController end def reorder_params - params.permit(:move_before_id, :move_after_id, :group_full_path) + params.permit(:move_before_id, :move_after_id) end def store_uri diff --git a/app/controllers/projects/merge_requests/drafts_controller.rb b/app/controllers/projects/merge_requests/drafts_controller.rb index 645720a0889..686d2c1dc1f 100644 --- a/app/controllers/projects/merge_requests/drafts_controller.rb +++ b/app/controllers/projects/merge_requests/drafts_controller.rb @@ -92,7 +92,8 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli :commit_id, :note, :position, - :resolve_discussion + :resolve_discussion, + :line_code ).tap do |h| # Old FE version will still be sending `draft_note[commit_id]` as 'undefined'. # That can result to having a note linked to a commit with 'undefined' ID diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index f936aeb0084..6445f920db5 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -30,24 +30,31 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action :set_issuables_index, only: [:index] before_action :authenticate_user!, only: [:assign_related_issues] before_action :check_user_can_push_to_source_branch!, only: [:rebase] + before_action only: [:index, :show] do + push_frontend_feature_flag(:mr_attention_requests, project, default_enabled: :yaml) + end + before_action only: [:show] do push_frontend_feature_flag(:file_identifier_hash) - push_frontend_feature_flag(:merge_request_widget_graphql, @project, default_enabled: :yaml) - push_frontend_feature_flag(:default_merge_ref_for_diffs, @project, default_enabled: :yaml) - push_frontend_feature_flag(:core_security_mr_widget_counts, @project) - push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml) - push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml) + push_frontend_feature_flag(:merge_request_widget_graphql, project, default_enabled: :yaml) + push_frontend_feature_flag(:default_merge_ref_for_diffs, project, default_enabled: :yaml) + push_frontend_feature_flag(:core_security_mr_widget_counts, project) + push_frontend_feature_flag(:paginated_notes, project, default_enabled: :yaml) + push_frontend_feature_flag(:confidential_notes, project, default_enabled: :yaml) push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml) - 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(:refactor_mr_widgets_extensions, @project, default_enabled: :yaml) - push_frontend_feature_flag(:rebase_without_ci_ui, @project, default_enabled: :yaml) + push_frontend_feature_flag(:refactor_mr_widgets_extensions, project, default_enabled: :yaml) + push_frontend_feature_flag(:rebase_without_ci_ui, project, default_enabled: :yaml) + push_frontend_feature_flag(:rearrange_pipelines_table, project, default_enabled: :yaml) + push_frontend_feature_flag(:markdown_continue_lists, project, default_enabled: :yaml) # Usage data feature flags - push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml) + push_frontend_feature_flag(:users_expanding_widgets_usage_data, project, default_enabled: :yaml) push_frontend_feature_flag(:diff_settings_usage_data, default_enabled: :yaml) - push_frontend_feature_flag(:diff_searching_usage_data, @project, default_enabled: :yaml) + push_frontend_feature_flag(:usage_data_diff_searches, project, default_enabled: :yaml) + end + + before_action do + push_frontend_feature_flag(:permit_all_shared_groups_for_approval, @project, default_enabled: :yaml) end around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions] @@ -100,10 +107,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo # rubocop:disable Metrics/AbcSize def show close_merge_request_if_no_source_project - - if Feature.disabled?(:check_mergeability_async_in_widget, @project, default_enabled: :yaml) - @merge_request.check_mergeability(async: true) - end + @merge_request.check_mergeability(async: true) respond_to do |format| format.html do @@ -504,6 +508,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo .can_push_to_branch?(@merge_request.source_branch) access_denied! unless access_check + + access_denied! unless merge_request.permits_force_push? end def merge_access_check diff --git a/app/controllers/projects/packages/infrastructure_registry_controller.rb b/app/controllers/projects/packages/infrastructure_registry_controller.rb index c02a0a56e03..2fe353b7acb 100644 --- a/app/controllers/projects/packages/infrastructure_registry_controller.rb +++ b/app/controllers/projects/packages/infrastructure_registry_controller.rb @@ -9,11 +9,7 @@ module Projects def show @package = project.packages.find(params[:id]) - @package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml) - @package.installable_package_files.recent - else - @package.package_files.recent - end + @package_files = @package.installable_package_files.recent end end end diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 71dc67bb6dc..7f680bbf121 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -13,6 +13,9 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_create_pipeline!, only: [:new, :create, :config_variables] before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action :ensure_pipeline, only: [:show, :downloadable_artifacts] + before_action do + push_frontend_feature_flag(:rearrange_pipelines_table, project, default_enabled: :yaml) + end before_action do push_frontend_feature_flag(:jobs_tab_vue, @project, default_enabled: :yaml) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index e8074f7d793..dc0614c6bdd 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -13,8 +13,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController def index @sort = params[:sort].presence || sort_value_name - @skip_groups = @project.invited_group_ids - @skip_groups += @project.group.self_and_ancestors_ids if @project.group + @skip_groups = @project.related_group_ids @group_links = @project.project_group_links @group_links = @group_links.search(params[:search_groups]) if params[:search_groups].present? diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index 73eb6bb2bf2..b070f9419fc 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -18,7 +18,7 @@ class Projects::RefsController < Projects::ApplicationController respond_to do |format| format.html do new_path = - case params[:destination] + case permitted_params[:destination] when "tree" project_tree_path(@project, @id) when "blob" @@ -45,7 +45,7 @@ class Projects::RefsController < Projects::ApplicationController def logs_tree tree_summary = ::Gitlab::TreeSummary.new( @commit, @project, current_user, - path: @path, offset: params[:offset], limit: 25) + path: @path, offset: permitted_params[:offset], limit: 25) respond_to do |format| format.html { render_404 } @@ -62,6 +62,10 @@ class Projects::RefsController < Projects::ApplicationController private def validate_ref_id - return not_found! if params[:id].present? && params[:id] !~ Gitlab::PathRegex.git_reference_regex + return not_found if permitted_params[:id].present? && permitted_params[:id] !~ Gitlab::PathRegex.git_reference_regex + end + + def permitted_params + params.permit(:id, :offset, :destination) end end diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index 77826a2f789..9fc75fff807 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -23,7 +23,7 @@ class Projects::RepositoriesController < Projects::ApplicationController feature_category :source_code_management def create - @project.create_repository + @project.create_repository unless @project.repository_exists? redirect_to project_path(@project) end diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index 62a9f8a4625..192a29730d9 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -23,7 +23,7 @@ class Projects::RunnersController < Projects::ApplicationController def destroy if @runner.only_for?(project) - @runner.destroy + Ci::UnregisterRunnerService.new(@runner).execute end redirect_to project_runners_path(@project), status: :found diff --git a/app/controllers/projects/security/configuration_controller.rb b/app/controllers/projects/security/configuration_controller.rb index 14f765814e6..7b799cc0aa6 100644 --- a/app/controllers/projects/security/configuration_controller.rb +++ b/app/controllers/projects/security/configuration_controller.rb @@ -10,6 +10,8 @@ module Projects def show render_403 unless can?(current_user, :read_security_configuration, project) + @configuration ||= configuration_presenter + respond_to do |format| format.html format.json do diff --git a/app/controllers/projects/service_desk_controller.rb b/app/controllers/projects/service_desk_controller.rb index 1fb07c3a903..aa0e70121df 100644 --- a/app/controllers/projects/service_desk_controller.rb +++ b/app/controllers/projects/service_desk_controller.rb @@ -4,6 +4,7 @@ class Projects::ServiceDeskController < Projects::ApplicationController before_action :authorize_admin_project! feature_category :service_desk + urgency :low def show json_response diff --git a/app/controllers/projects/service_ping_controller.rb b/app/controllers/projects/service_ping_controller.rb index 00530c09be8..368da8d1ef2 100644 --- a/app/controllers/projects/service_ping_controller.rb +++ b/app/controllers/projects/service_ping_controller.rb @@ -13,6 +13,14 @@ class Projects::ServicePingController < Projects::ApplicationController head(200) end + def web_ide_clientside_preview_success + return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? + + Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_success_count + + head(200) + end + def web_ide_pipelines_count Gitlab::UsageDataCounters::WebIdeCounter.increment_pipelines_count diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 9896f75c099..1321111faaf 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -12,9 +12,6 @@ class Projects::ServicesController < Projects::ApplicationController before_action :web_hook_logs, only: [:edit, :update] before_action :set_deprecation_notice_for_prometheus_integration, only: [:edit, :update] before_action :redirect_deprecated_prometheus_integration, only: [:update] - before_action do - push_frontend_feature_flag(:vue_integration_form, current_user, default_enabled: :yaml) - end respond_to :html diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index c71134e0547..dd2fb57f7ac 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -160,6 +160,8 @@ module Projects @badges.map! do |badge| badge.new(@project, @ref).metadata end + + @badges.append(Gitlab::Ci::Badge::Release::LatestRelease.new(@project, current_user).metadata) end def define_auto_devops_variables diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index d750bd201e2..a28c08e87cb 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -25,7 +25,7 @@ module Projects if result[:status] == :success flash[:notice] = _('Repository cleanup has started. You will receive an email once the cleanup operation is complete.') else - flash[:alert] = status.fetch(:message, _('Failed to upload object map file')) + flash[:alert] = result.fetch(:message, _('Failed to upload object map file')) end redirect_to project_settings_repository_path(project) diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index de0faaca9c0..6472d3c3454 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -16,13 +16,16 @@ class Projects::TagsController < Projects::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def index begin - params[:sort] = params[:sort].presence || sort_value_recently_updated + tags_params = params + .permit(:search, :sort, :per_page, :page_token, :page) + .with_defaults(sort: sort_value_recently_updated) - @sort = params[:sort] + @sort = tags_params[:sort] + @search = tags_params[:search] - @tags = TagsFinder.new(@repository, params).execute + @tags = TagsFinder.new(@repository, tags_params).execute - @tags = Kaminari.paginate_array(@tags).page(params[:page]) + @tags = Kaminari.paginate_array(@tags).page(tags_params[:page]) tag_names = @tags.map(&:name) @tags_pipelines = @project.ci_pipelines.latest_successful_for_refs(tag_names) @@ -31,6 +34,7 @@ class Projects::TagsController < Projects::ApplicationController rescue Gitlab::Git::CommandError => e @tags = [] + @releases = [] @tags_loading_error = e end diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb index c15768e7bbb..ed5bd73d6d1 100644 --- a/app/controllers/projects/uploads_controller.rb +++ b/app/controllers/projects/uploads_controller.rb @@ -6,7 +6,7 @@ class Projects::UploadsController < Projects::ApplicationController # These will kick you out if you don't have access. skip_before_action :project, :repository, - if: -> { action_name == 'show' && embeddable? } + if: -> { bypass_auth_checks_on_uploads? } before_action :authorize_upload_file!, only: [:create, :authorize] before_action :verify_workhorse_api!, only: [:authorize] diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 64abcd7cc33..519d9cd0d52 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -10,6 +10,7 @@ class ProjectsController < Projects::ApplicationController include ImportUrlParams include FiltersEvents include SourcegraphDecorator + include PlanningHierarchy prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } @@ -41,6 +42,7 @@ class ProjectsController < Projects::ApplicationController push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml) push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks) push_frontend_feature_flag(:consolidated_edit_button, @project, default_enabled: :yaml) + push_frontend_feature_flag(:work_items, @project, default_enabled: :yaml) end layout :determine_layout @@ -54,6 +56,7 @@ class ProjectsController < Projects::ApplicationController 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] + feature_category :portfolio_management, [:planning_hierarchy] urgency :low, [:refs] urgency :high, [:unfoldered_environment_names] @@ -283,7 +286,7 @@ class ProjectsController < Projects::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def refs - find_refs = params['find'] + find_refs = refs_params['find'] find_branches = true find_tags = true @@ -298,13 +301,13 @@ class ProjectsController < Projects::ApplicationController options = {} if find_branches - branches = BranchesFinder.new(@repository, params).execute.take(100).map(&:name) + branches = BranchesFinder.new(@repository, refs_params).execute.take(100).map(&:name) options['Branches'] = branches end if find_tags && @repository.tag_count.nonzero? tags = begin - TagsFinder.new(@repository, params).execute + TagsFinder.new(@repository, refs_params).execute rescue Gitlab::Git::CommandError [] end @@ -313,7 +316,7 @@ class ProjectsController < Projects::ApplicationController end # If reference is commit id - we should add it to branch/tag selectbox - ref = Addressable::URI.unescape(params[:ref]) + ref = Addressable::URI.unescape(refs_params[:ref]) if find_commits && ref && options.flatten(2).exclude?(ref) && ref =~ /\A[0-9a-zA-Z]{6,52}\z/ options['Commits'] = [ref] end @@ -342,6 +345,14 @@ class ProjectsController < Projects::ApplicationController private + def refs_params + if Feature.enabled?(:strong_parameters_for_project_controller, @project, default_enabled: :yaml) + params.permit(:search, :sort, :ref, find: []) + else + params + end + end + # Render project landing depending of which features are available # So if page is not available in the list it renders the next page # @@ -461,8 +472,8 @@ class ProjectsController < Projects::ApplicationController :suggestion_commit_message, :packages_enabled, :service_desk_enabled, - :merge_commit_template, - :squash_commit_template, + :merge_commit_template_or_default, + :squash_commit_template_or_default, project_setting_attributes: project_setting_attributes ] + [project_feature_attributes: project_feature_attributes] end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index c1765d367d1..057c451ace2 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -6,6 +6,7 @@ class RegistrationsController < Devise::RegistrationsController include RecaptchaHelper include InvisibleCaptchaOnSignup include OneTrustCSP + include BizibleCSP layout 'devise' @@ -35,6 +36,7 @@ class RegistrationsController < Devise::RegistrationsController persist_accepted_terms_if_required(new_user) set_role_required(new_user) + track_experiment_event(new_user) if pending_approval? NotificationService.new.new_instance_access_request(new_user) @@ -223,6 +225,14 @@ class RegistrationsController < Devise::RegistrationsController def context_user current_user end + + def track_experiment_event(new_user) + # Track signed up event to relate it with click "Sign up" button events from + # the experimental logged out header with marketing links. This allows us to + # have a funnel of visitors clicking on the header and those visitors + # signing up and becoming users + experiment(:logged_out_marketing_header, actor: new_user).track(:signed_up) if new_user.persisted? + end end RegistrationsController.prepend_mod_with('RegistrationsController') diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb index c002c9b83f9..24520a187e3 100644 --- a/app/controllers/repositories/git_http_client_controller.rb +++ b/app/controllers/repositories/git_http_client_controller.rb @@ -17,6 +17,9 @@ module Repositories prepend_before_action :authenticate_user, :parse_repo_path + skip_around_action :sessionless_bypass_admin_mode! + around_action :bypass_admin_mode!, if: :authenticated_user + feature_category :source_code_management def authenticated_user @@ -136,6 +139,12 @@ module Repositories container && Guest.can?(repo_type.guest_read_ability, container) end + + def bypass_admin_mode!(&block) + return yield unless Gitlab::CurrentSettings.admin_mode + + Gitlab::Auth::CurrentUserMode.bypass_session!(authenticated_user.id, &block) + end end end diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb index 2b0aa67326e..7deda473b9d 100644 --- a/app/controllers/repositories/lfs_api_controller.rb +++ b/app/controllers/repositories/lfs_api_controller.rb @@ -155,7 +155,6 @@ module Repositories end def should_auto_link? - return false unless Feature.enabled?(:lfs_auto_link_fork_source, project, default_enabled: :yaml) return false unless project.forked? # Sanity check in case for some reason the user doesn't have access to the parent diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index d58ed252a36..e38eeaed367 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -144,6 +144,7 @@ class SearchController < ApplicationController payload[:metadata]['meta.search.filters.state'] = params[:state] payload[:metadata]['meta.search.force_search_results'] = params[:force_search_results] payload[:metadata]['meta.search.project_ids'] = params[:project_ids] + payload[:metadata]['meta.search.search_level'] = params[:search_level] if search_service.abuse_detected? payload[:metadata]['abuse.confidence'] = Gitlab::Abuse.confidence(:certain) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 7e8e3ea8789..e907e291eeb 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -10,6 +10,7 @@ class SessionsController < Devise::SessionsController include KnownSignIn include Gitlab::Utils::StrongMemoize include OneTrustCSP + include BizibleCSP skip_before_action :check_two_factor_requirement, only: [:destroy] skip_before_action :check_password_expiration, only: [:destroy] diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 8710eebf210..f6cef7e133c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -148,7 +148,11 @@ class UsersController < ApplicationController end def exists - render json: { exists: !!Namespace.find_by_path_or_name(params[:username]) } + if Gitlab::CurrentSettings.signup_enabled? || current_user + render json: { exists: !!Namespace.find_by_path_or_name(params[:username]) } + else + render json: { error: _('You must be authenticated to access this path.') }, status: :unauthorized + end end def follow @@ -182,7 +186,7 @@ class UsersController < ApplicationController end def starred_projects - StarredProjectsFinder.new(user, current_user: current_user).execute + StarredProjectsFinder.new(user, params: finder_params, current_user: current_user).execute end def contributions_calendar @@ -248,6 +252,15 @@ class UsersController < ApplicationController end end end + + def finder_params + { + # don't display projects pending deletion + without_deleted: true, + # don't display projects marked for deletion + not_aimed_for_deletion: true + } + end end UsersController.prepend_mod_with('UsersController') |