diff options
Diffstat (limited to 'app/controllers')
70 files changed, 408 insertions, 226 deletions
diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb index 449aa90b0e6..ce7d64336c8 100644 --- a/app/controllers/admin/applications_controller.rb +++ b/app/controllers/admin/applications_controller.rb @@ -18,7 +18,10 @@ class Admin::ApplicationsController < Admin::ApplicationController end def new - @application = Doorkeeper::Application.new + # Default access tokens to expire. This preserves backward compatibility + # with existing applications. This will be removed in 15.0. + # Removal issue: https://gitlab.com/gitlab-org/gitlab/-/issues/340848 + @application = Doorkeeper::Application.new(expire_access_tokens: true) end def edit @@ -55,10 +58,13 @@ class Admin::ApplicationsController < Admin::ApplicationController @application = ApplicationsFinder.new(id: params[:id]).execute end - # Only allow a trusted parameter "white list" through. + def permitted_params + super << :trusted + end + def application_params - params - .require(:doorkeeper_application) - .permit(:name, :redirect_uri, :trusted, :scopes, :confidential) + super.tap do |params| + params[:owner] = nil + end end end diff --git a/app/controllers/admin/background_migrations_controller.rb b/app/controllers/admin/background_migrations_controller.rb index 65b47308e4c..e21e6fd2dcb 100644 --- a/app/controllers/admin/background_migrations_controller.rb +++ b/app/controllers/admin/background_migrations_controller.rb @@ -29,9 +29,16 @@ class Admin::BackgroundMigrationsController < Admin::ApplicationController redirect_back fallback_location: { action: 'index' } end + def retry + migration = batched_migration_class.find(params[:id]) + migration.retry_failed_jobs! if migration.failed? + + redirect_back fallback_location: { action: 'index' } + end + private def batched_migration_class - Gitlab::Database::BackgroundMigration::BatchedMigration + @batched_migration_class ||= Gitlab::Database::BackgroundMigration::BatchedMigration end end diff --git a/app/controllers/admin/runner_projects_controller.rb b/app/controllers/admin/runner_projects_controller.rb index 3b408de5f01..fdf681de9ef 100644 --- a/app/controllers/admin/runner_projects_controller.rb +++ b/app/controllers/admin/runner_projects_controller.rb @@ -9,7 +9,7 @@ class Admin::RunnerProjectsController < Admin::ApplicationController @runner = Ci::Runner.find(params[:runner_project][:runner_id]) if @runner.assign_to(@project, current_user) - redirect_to admin_runner_path(@runner) + redirect_to admin_runner_path(@runner), notice: s_('Runners|Runner assigned to project.') else redirect_to admin_runner_path(@runner), alert: 'Failed adding runner to project' end @@ -20,7 +20,7 @@ class Admin::RunnerProjectsController < Admin::ApplicationController runner = rp.runner rp.destroy - redirect_to admin_runner_path(runner), status: :found + redirect_to admin_runner_path(runner), status: :found, notice: s_('Runners|Runner unassigned from project.') end private diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 3801906635f..9c556d16913 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -307,7 +307,7 @@ class Admin::UsersController < Admin::ApplicationController end def user - @user ||= find_routable!(User, params[:id], request.path_info) + @user ||= find_routable!(User, params[:id], request.fullpath) end def build_canonical_path(user) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 34bad74a9fc..a83458f3260 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -42,6 +42,7 @@ class ApplicationController < ActionController::Base # Make sure the `auth_user` is memoized so it can be logged, we do this after # all other before filters that could have set the user. before_action :auth_user + before_action :limit_session_time, if: -> { !current_user } prepend_around_action :set_current_context @@ -51,7 +52,7 @@ class ApplicationController < ActionController::Base around_action :set_current_admin after_action :set_page_title_header, if: :json_request? - after_action :limit_session_time, if: -> { !current_user } + after_action :ensure_authenticated_session_time, if: -> { current_user } protect_from_forgery with: :exception, prepend: true @@ -62,7 +63,8 @@ class ApplicationController < ActionController::Base :bitbucket_import_enabled?, :bitbucket_import_configured?, :bitbucket_server_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled?, - :manifest_import_enabled?, :phabricator_import_enabled? + :manifest_import_enabled?, :phabricator_import_enabled?, + :masked_page_url # Adds `no-store` to the DEFAULT_CACHE_CONTROL, to prevent security # concerns due to caching private data. diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb index f0f074792ed..7dea6191fa4 100644 --- a/app/controllers/boards/issues_controller.rb +++ b/app/controllers/boards/issues_controller.rb @@ -27,9 +27,7 @@ module Boards list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params) issues = issues_from(list_service) - if Gitlab::Database.read_write? && !board.disabled_for?(current_user) - Issue.move_nulls_to_end(issues) - end + ::Boards::Issues::ListService.initialize_relative_positions(board, current_user, issues) render_issues(issues, list_service.metadata) end diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb index 10122b4c77b..62585ab95af 100644 --- a/app/controllers/concerns/integrations/params.rb +++ b/app/controllers/concerns/integrations/params.rb @@ -77,18 +77,15 @@ module Integrations :webhook ].freeze - # Parameters to ignore if no value is specified - FILTER_BLANK_PARAMS = [:password].freeze - def integration_params - dynamic_params = @integration.event_channel_names + @integration.event_names # rubocop:disable Gitlab/ModuleWithInstanceVariables + dynamic_params = integration.event_channel_names + integration.event_names allowed = allowed_integration_params + dynamic_params return_value = params.permit(:id, integration: allowed, service: allowed) return_value[:integration] ||= return_value.delete(:service) param_values = return_value[:integration] if param_values.is_a?(ActionController::Parameters) - FILTER_BLANK_PARAMS.each do |param| + integration.password_fields.each do |param| param_values.delete(param) if param_values[param].blank? end end diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index d2d2e656af8..4841225de08 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -13,8 +13,16 @@ module IssuableCollections private + def show_alert_if_search_is_disabled + return if current_user || params[:search].blank? || !html_request? || Feature.disabled?(:disable_anonymous_search, type: :ops) + + flash.now[:notice] = _('You must sign in to search for specific terms.') + end + # rubocop:disable Gitlab/ModuleWithInstanceVariables def set_issuables_index + show_alert_if_search_is_disabled + @issuables = issuables_collection unless pagination_disabled? diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb index ca2979a5a29..b68db0e3f9f 100644 --- a/app/controllers/concerns/issuable_collections_action.rb +++ b/app/controllers/concerns/issuable_collections_action.rb @@ -7,6 +7,8 @@ module IssuableCollectionsAction # rubocop:disable Gitlab/ModuleWithInstanceVariables def issues + show_alert_if_search_is_disabled + @issues = issuables_collection .non_archived .page(params[:page]) @@ -20,6 +22,8 @@ module IssuableCollectionsAction end def merge_requests + show_alert_if_search_is_disabled + @merge_requests = issuables_collection.page(params[:page]) @issuable_meta_data = Gitlab::IssuableMetadata.new(current_user, @merge_requests).data diff --git a/app/controllers/concerns/oauth_applications.rb b/app/controllers/concerns/oauth_applications.rb index d97e22df472..d2c746db12d 100644 --- a/app/controllers/concerns/oauth_applications.rb +++ b/app/controllers/concerns/oauth_applications.rb @@ -18,4 +18,14 @@ module OauthApplications def load_scopes @scopes ||= Doorkeeper.configuration.scopes end + + def permitted_params + %i{name redirect_uri scopes confidential expire_access_tokens} + end + + def application_params + params + .require(:doorkeeper_application) + .permit(*permitted_params) + end end diff --git a/app/controllers/concerns/project_unauthorized.rb b/app/controllers/concerns/project_unauthorized.rb index b58f6589f9b..563d6b6273b 100644 --- a/app/controllers/concerns/project_unauthorized.rb +++ b/app/controllers/concerns/project_unauthorized.rb @@ -3,7 +3,7 @@ module ProjectUnauthorized module ControllerActions def self.on_routable_not_found - lambda do |routable, path_info| + lambda do |routable, full_path| return unless routable.is_a?(Project) label = routable.external_authorization_classification_label diff --git a/app/controllers/concerns/renders_projects_list.rb b/app/controllers/concerns/renders_projects_list.rb index be45c676ad6..05bd9972ee7 100644 --- a/app/controllers/concerns/renders_projects_list.rb +++ b/app/controllers/concerns/renders_projects_list.rb @@ -4,9 +4,10 @@ module RendersProjectsList def prepare_projects_for_rendering(projects) preload_max_member_access_for_collection(Project, projects) - # Call the forks count method on every project, so the BatchLoader would load them all at + # Call the count methods on every project, so the BatchLoader would load them all at # once when the entities are rendered projects.each(&:forks_count) + projects.each(&:open_issues_count) projects end diff --git a/app/controllers/concerns/routable_actions.rb b/app/controllers/concerns/routable_actions.rb index 57108369c64..e34d6b09c24 100644 --- a/app/controllers/concerns/routable_actions.rb +++ b/app/controllers/concerns/routable_actions.rb @@ -3,13 +3,13 @@ module RoutableActions extend ActiveSupport::Concern - def find_routable!(routable_klass, routable_full_path, path_info, extra_authorization_proc: nil) + def find_routable!(routable_klass, routable_full_path, full_path, extra_authorization_proc: nil) routable = routable_klass.find_by_full_path(routable_full_path, follow_redirects: request.get?) if routable_authorized?(routable, extra_authorization_proc) ensure_canonical_path(routable, routable_full_path) routable else - perform_not_found_actions(routable, not_found_actions, path_info) + perform_not_found_actions(routable, not_found_actions, full_path) route_not_found unless performed? @@ -21,11 +21,11 @@ module RoutableActions [ProjectUnauthorized::ControllerActions.on_routable_not_found] end - def perform_not_found_actions(routable, actions, path_info) + def perform_not_found_actions(routable, actions, full_path) actions.each do |action| break if performed? - instance_exec(routable, path_info, &action) + instance_exec(routable, full_path, &action) end end diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb index 3c8a683439a..58e65ba20e2 100644 --- a/app/controllers/concerns/sessionless_authentication.rb +++ b/app/controllers/concerns/sessionless_authentication.rb @@ -8,7 +8,6 @@ module SessionlessAuthentication # This filter handles personal access tokens, atom requests with rss tokens, and static object tokens def authenticate_sessionless_user!(request_format) user = request_authenticator.find_sessionless_user(request_format) - sessionless_sign_in(user) if user end diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index d861ef646f8..74ad78ff4c1 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -36,7 +36,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def starred @projects = load_projects(params.merge(starred: true)) - .includes(:forked_from_project, :topics) + .includes(:forked_from_project, :topics, :topics_acts_as_taggable) @groups = [] diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index e0973b0f3b4..3dc6a16cbc1 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -26,6 +26,7 @@ class Explore::ProjectsController < Explore::ApplicationController feature_category :projects def index + show_alert_if_search_is_disabled @projects = load_projects respond_to do |format| @@ -120,6 +121,12 @@ class Explore::ProjectsController < Explore::ApplicationController end end end + + def show_alert_if_search_is_disabled + return if current_user || params[:name].blank? && params[:search].blank? || !html_request? || Feature.disabled?(:disable_anonymous_project_search, type: :ops) + + flash.now[:notice] = _('You must sign in to search for specific projects.') + end end Explore::ProjectsController.prepend_mod_with('Explore::ProjectsController') diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index aa0d49902c3..ab67a007bd9 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -16,7 +16,7 @@ class Groups::ApplicationController < ApplicationController private def group - @group ||= find_routable!(Group, params[:group_id] || params[:id], request.path_info) + @group ||= find_routable!(Group, params[:group_id] || params[:id], request.fullpath) end def group_projects diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index 96a3b38669d..60708c13b85 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -7,7 +7,6 @@ class Groups::BoardsController < Groups::ApplicationController before_action :assign_endpoint_vars before_action do - push_frontend_feature_flag(:graphql_board_lists, group, default_enabled: :yaml) push_frontend_feature_flag(:issue_boards_filtered_search, group, default_enabled: :yaml) push_frontend_feature_flag(:board_multi_select, group, default_enabled: :yaml) push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml) diff --git a/app/controllers/groups/clusters/integrations_controller.rb b/app/controllers/groups/clusters/integrations_controller.rb index 61b308f7d1b..4ab8c021ee2 100644 --- a/app/controllers/groups/clusters/integrations_controller.rb +++ b/app/controllers/groups/clusters/integrations_controller.rb @@ -13,6 +13,6 @@ class Groups::Clusters::IntegrationsController < Clusters::IntegrationsControlle end def group - @group ||= find_routable!(Group, params[:group_id] || params[:id], request.path_info) + @group ||= find_routable!(Group, params[:group_id] || params[:id], request.fullpath) end end diff --git a/app/controllers/groups/clusters_controller.rb b/app/controllers/groups/clusters_controller.rb index 6f3eecf8296..666a96d6fc0 100644 --- a/app/controllers/groups/clusters_controller.rb +++ b/app/controllers/groups/clusters_controller.rb @@ -15,7 +15,7 @@ class Groups::ClustersController < Clusters::ClustersController end def group - @group ||= find_routable!(Group, params[:group_id] || params[:id], request.path_info) + @group ||= find_routable!(Group, params[:group_id] || params[:id], request.fullpath) end def metrics_dashboard_params diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb index dbbfdd76fe8..f37c08da22a 100644 --- a/app/controllers/groups/runners_controller.rb +++ b/app/controllers/groups/runners_controller.rb @@ -10,6 +10,8 @@ class Groups::RunnersController < Groups::ApplicationController feature_category :runner def index + 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 @@ -59,7 +61,7 @@ class Groups::RunnersController < Groups::ApplicationController private def runner - @runner ||= Ci::RunnersFinder.new(current_user: current_user, group: @group, params: {}).execute + @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }).execute .except(:limit, :offset) .find(params[:id]) end diff --git a/app/controllers/groups/settings/applications_controller.rb b/app/controllers/groups/settings/applications_controller.rb index cefb5425867..f05a96d7810 100644 --- a/app/controllers/groups/settings/applications_controller.rb +++ b/app/controllers/groups/settings/applications_controller.rb @@ -54,8 +54,10 @@ module Groups # https://gitlab.com/gitlab-org/gitlab/-/issues/324187 @applications = @group.oauth_applications.limit(100) - # Don't overwrite a value possibly set by `create` - @application ||= Doorkeeper::Application.new + # Default access tokens to expire. This preserves backward compatibility + # with existing applications. This will be removed in 15.0. + # Removal issue: https://gitlab.com/gitlab-org/gitlab/-/issues/340848 + @application ||= Doorkeeper::Application.new(expire_access_tokens: true) end def set_application @@ -63,12 +65,9 @@ module Groups end def application_params - params - .require(:doorkeeper_application) - .permit(:name, :redirect_uri, :scopes, :confidential) - .tap do |params| - params[:owner] = @group - end + super.tap do |params| + params[:owner] = @group + end end end end diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index 0f40c9bfd2c..a290ef9b5e7 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -17,7 +17,7 @@ module Groups NUMBER_OF_RUNNERS_PER_PAGE = 4 def show - runners_finder = Ci::RunnersFinder.new(current_user: current_user, group: @group, params: params) + runners_finder = Ci::RunnersFinder.new(current_user: current_user, params: params.merge({ group: @group })) # We need all runners for count @all_group_runners = runners_finder.execute.except(:limit, :offset) @group_runners = runners_finder.execute.page(params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 2796760fbe1..a419171039e 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -33,6 +33,7 @@ class GroupsController < Groups::ApplicationController before_action do push_frontend_feature_flag(:vue_issuables_list, @group) + push_frontend_feature_flag(:vue_issues_list, @group, default_enabled: :yaml) push_frontend_feature_flag(:iteration_cadences, @group, default_enabled: :yaml) end @@ -64,6 +65,7 @@ class GroupsController < Groups::ApplicationController def new @group = Group.new(params.permit(:parent_id)) + @group.build_namespace_settings end def create @@ -269,7 +271,9 @@ class GroupsController < Groups::ApplicationController :default_branch_name, :allow_mfa_for_subgroups, :resource_access_token_creation_allowed, - :prevent_sharing_groups_outside_hierarchy + :prevent_sharing_groups_outside_hierarchy, + :setup_for_company, + :jobs_to_be_done ] end @@ -342,7 +346,15 @@ class GroupsController < Groups::ApplicationController render action: 'new' end - def successful_creation_hooks; end + def successful_creation_hooks + update_user_role_and_setup_for_company + end + + def update_user_role_and_setup_for_company + user_params = params.fetch(:user, {}).permit(:role) + user_params[:setup_for_company] = @group.setup_for_company if !@group.setup_for_company.nil? && current_user.setup_for_company.nil? + Users::UpdateService.new(current_user, user_params.merge(user: current_user)).execute if user_params.present? + end def groups if @group.supports_events? diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 57bd39bbe06..d32755dbd94 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -62,14 +62,10 @@ class Import::BitbucketController < Import::BaseController protected - # rubocop: disable CodeReuse/ActiveRecord override :importable_repos def importable_repos - already_added_projects_names = already_added_projects.map(&:import_source) - - bitbucket_repos.reject { |repo| already_added_projects_names.include?(repo.full_name) || !repo.valid? } + bitbucket_repos.filter { |repo| repo.valid? } end - # rubocop: enable CodeReuse/ActiveRecord override :incompatible_repos def incompatible_repos diff --git a/app/controllers/import/bitbucket_server_controller.rb b/app/controllers/import/bitbucket_server_controller.rb index 1846b1e0cec..31e9694ca1d 100644 --- a/app/controllers/import/bitbucket_server_controller.rb +++ b/app/controllers/import/bitbucket_server_controller.rb @@ -62,16 +62,10 @@ class Import::BitbucketServerController < Import::BaseController protected - # rubocop: disable CodeReuse/ActiveRecord override :importable_repos def importable_repos - # Use the import URL to filter beyond what BaseService#find_already_added_projects - already_added_projects = filter_added_projects('bitbucket_server', bitbucket_repos.map(&:browse_url)) - already_added_projects_names = already_added_projects.map(&:import_source) - - bitbucket_repos.reject { |repo| already_added_projects_names.include?(repo.browse_url) || !repo.valid? } + bitbucket_repos.filter { |repo| repo.valid? } end - # rubocop: enable CodeReuse/ActiveRecord override :incompatible_repos def incompatible_repos @@ -90,12 +84,6 @@ class Import::BitbucketServerController < Import::BaseController private - # rubocop: disable CodeReuse/ActiveRecord - def filter_added_projects(import_type, import_sources) - current_user.created_projects.where(import_type: import_type, import_source: import_sources).with_import_state - end - # rubocop: enable CodeReuse/ActiveRecord - def client @client ||= BitbucketServer::Client.new(credentials) end diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb index e99b8cfa0c7..da936215ad4 100644 --- a/app/controllers/import/bulk_imports_controller.rb +++ b/app/controllers/import/bulk_imports_controller.rb @@ -112,7 +112,7 @@ class Import::BulkImportsController < ApplicationController end def ensure_group_import_enabled - render_404 unless Feature.enabled?(:bulk_import) + render_404 unless Feature.enabled?(:bulk_import, default_enabled: :yaml) end def access_token_key diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb index 9f91f3a1e1c..377292d47d8 100644 --- a/app/controllers/import/fogbugz_controller.rb +++ b/app/controllers/import/fogbugz_controller.rb @@ -74,16 +74,10 @@ class Import::FogbugzController < Import::BaseController protected - # rubocop: disable CodeReuse/ActiveRecord override :importable_repos def importable_repos - repos = client.repos - - already_added_projects_names = already_added_projects.map(&:import_source) - - repos.reject { |repo| already_added_projects_names.include? repo.name } + client.repos end - # rubocop: enable CodeReuse/ActiveRecord override :incompatible_repos def incompatible_repos diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb index 22bcd14d664..d7aebd25432 100644 --- a/app/controllers/import/github_controller.rb +++ b/app/controllers/import/github_controller.rb @@ -64,9 +64,7 @@ class Import::GithubController < Import::BaseController # rubocop: disable CodeReuse/ActiveRecord override :importable_repos def importable_repos - already_added_projects_names = already_added_projects.pluck(:import_source) - - client_repos.reject { |repo| already_added_projects_names.include?(repo.full_name) } + client_repos.to_a end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb index cc68eb02741..662b02010ba 100644 --- a/app/controllers/import/gitlab_controller.rb +++ b/app/controllers/import/gitlab_controller.rb @@ -39,16 +39,10 @@ class Import::GitlabController < Import::BaseController protected - # rubocop: disable CodeReuse/ActiveRecord override :importable_repos def importable_repos - repos = client.projects(starting_page: 1, page_limit: MAX_PROJECT_PAGES, per_page: PER_PAGE_PROJECTS) - - already_added_projects_names = already_added_projects.map(&:import_source) - - repos.reject { |repo| already_added_projects_names.include? repo["path_with_namespace"] } + client.projects(starting_page: 1, page_limit: MAX_PROJECT_PAGES, per_page: PER_PAGE_PROJECTS) end - # rubocop: enable CodeReuse/ActiveRecord override :incompatible_repos def incompatible_repos diff --git a/app/controllers/import/manifest_controller.rb b/app/controllers/import/manifest_controller.rb index 8497e15c07c..956d0c9a2ae 100644 --- a/app/controllers/import/manifest_controller.rb +++ b/app/controllers/import/manifest_controller.rb @@ -41,7 +41,7 @@ class Import::ManifestController < Import::BaseController end def create - repository = repositories.find do |project| + repository = importable_repos.find do |project| project[:id] == params[:repo_id].to_i end @@ -56,14 +56,10 @@ class Import::ManifestController < Import::BaseController protected - # rubocop: disable CodeReuse/ActiveRecord override :importable_repos def importable_repos - already_added_projects_names = already_added_projects.pluck(:import_url) - - repositories.reject { |repo| already_added_projects_names.include?(repo[:url]) } + @importable_repos ||= manifest_import_metadata.repositories end - # rubocop: enable CodeReuse/ActiveRecord override :incompatible_repos def incompatible_repos @@ -88,7 +84,7 @@ class Import::ManifestController < Import::BaseController private def ensure_import_vars - unless group && repositories.present? + unless group && importable_repos.present? redirect_to(new_import_manifest_path) end end @@ -103,10 +99,6 @@ class Import::ManifestController < Import::BaseController @manifest_import_status ||= Gitlab::ManifestImport::Metadata.new(current_user, fallback: session) end - def repositories - @repositories ||= manifest_import_metadata.repositories - end - def find_jobs find_already_added_projects.to_json(only: [:id], methods: [:import_status]) end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 7f5750d2011..4242f918ea0 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -77,7 +77,12 @@ class InvitesController < ApplicationController def track_invite_join_click return unless member && initial_invite_email? - experiment(:invite_email_preview_text, actor: member).track(:join_clicked) if params[:experiment_name] == 'invite_email_preview_text' + if params[:experiment_name] == 'invite_email_preview_text' + experiment(:invite_email_preview_text, actor: member).track(:join_clicked) + elsif params[:experiment_name] == 'invite_email_from' + experiment(:invite_email_from, actor: member).track(:join_clicked) + end + Gitlab::Tracking.event(self.class.name, 'join_clicked', label: 'invite_email', property: member.id.to_s) end diff --git a/app/controllers/jira_connect/installations_controller.rb b/app/controllers/jira_connect/installations_controller.rb new file mode 100644 index 00000000000..401bc4f9c87 --- /dev/null +++ b/app/controllers/jira_connect/installations_controller.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class JiraConnect::InstallationsController < JiraConnect::ApplicationController + def index + render json: installation_json(current_jira_installation) + end + + def update + if current_jira_installation.update(installation_params) + render json: installation_json(current_jira_installation) + else + render( + json: { errors: current_jira_installation.errors }, + status: :unprocessable_entity + ) + end + end + + private + + def installation_json(installation) + { + gitlab_com: installation.instance_url.blank?, + instance_url: installation.instance_url + } + end + + def installation_params + params.require(:installation).permit(:instance_url) + end +end diff --git a/app/controllers/members/mailgun/permanent_failures_controller.rb b/app/controllers/members/mailgun/permanent_failures_controller.rb new file mode 100644 index 00000000000..685faa34694 --- /dev/null +++ b/app/controllers/members/mailgun/permanent_failures_controller.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +module Members + module Mailgun + class PermanentFailuresController < ApplicationController + respond_to :json + + skip_before_action :authenticate_user! + skip_before_action :verify_authenticity_token + + before_action :ensure_feature_enabled! + before_action :authenticate_signature! + before_action :validate_invite_email! + + feature_category :authentication_and_authorization + + def create + webhook_processor.execute + + head :ok + end + + private + + def ensure_feature_enabled! + render_406 unless Gitlab::CurrentSettings.mailgun_events_enabled? + end + + def authenticate_signature! + access_denied! unless valid_signature? + end + + def valid_signature? + return false if Gitlab::CurrentSettings.mailgun_signing_key.blank? + + # per this guide: https://documentation.mailgun.com/en/latest/user_manual.html#webhooks + digest = OpenSSL::Digest.new('SHA256') + data = [params.dig(:signature, :timestamp), params.dig(:signature, :token)].join + + hmac_digest = OpenSSL::HMAC.hexdigest(digest, Gitlab::CurrentSettings.mailgun_signing_key, data) + + ActiveSupport::SecurityUtils.secure_compare(params.dig(:signature, :signature), hmac_digest) + end + + def validate_invite_email! + # permanent_failures webhook does not provide a way to filter failures, so we'll get them all on this endpoint + # and we only care about our invite_emails + render_406 unless payload[:tags]&.include?(::Members::Mailgun::INVITE_EMAIL_TAG) + end + + def webhook_processor + ::Members::Mailgun::ProcessWebhookService.new(payload) + end + + def payload + @payload ||= params.permit!['event-data'] + end + + def render_406 + # failure to stop retries per https://documentation.mailgun.com/en/latest/user_manual.html#webhooks + head :not_acceptable + end + end + end +end diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index 8158db282fb..81f188256ba 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -25,7 +25,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController end def create - @application = Applications::CreateService.new(current_user, create_application_params).execute(request) + @application = Applications::CreateService.new(current_user, application_params).execute(request) if @application.persisted? flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) @@ -51,8 +51,10 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController @authorized_anonymous_tokens = @authorized_tokens.reject(&:application) @authorized_apps = @authorized_tokens.map(&:application).uniq.reject(&:nil?) - # Don't overwrite a value possibly set by `create` - @application ||= Doorkeeper::Application.new + # Default access tokens to expire. This preserves backward compatibility + # with existing applications. This will be removed in 15.0. + # Removal issue: https://gitlab.com/gitlab-org/gitlab/-/issues/340848 + @application ||= Doorkeeper::Application.new(expire_access_tokens: true) end # Override Doorkeeper to scope to the current user @@ -64,8 +66,8 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController render "errors/not_found", layout: "errors", status: :not_found end - def create_application_params - application_params.tap do |params| + def application_params + super.tap do |params| params[:owner] = current_user end end diff --git a/app/controllers/profiles/groups_controller.rb b/app/controllers/profiles/groups_controller.rb index 2571e92e071..5962b10c44b 100644 --- a/app/controllers/profiles/groups_controller.rb +++ b/app/controllers/profiles/groups_controller.rb @@ -6,7 +6,7 @@ class Profiles::GroupsController < Profiles::ApplicationController feature_category :users def update - group = find_routable!(Group, params[:id], request.path_info) + group = find_routable!(Group, params[:id], request.fullpath) notification_setting = current_user.notification_settings_for(group) if notification_setting.update(update_params) diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb index effd3514c1b..5eb46421583 100644 --- a/app/controllers/profiles/two_factor_auths_controller.rb +++ b/app/controllers/profiles/two_factor_auths_controller.rb @@ -2,6 +2,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController skip_before_action :check_two_factor_requirement + before_action :ensure_verified_primary_email, only: [:show, :create] before_action do push_frontend_feature_flag(:webauthn) end @@ -57,7 +58,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController @codes = user.generate_otp_backup_codes! end - helpers.dismiss_account_recovery_regular_check + helpers.dismiss_two_factor_auth_recovery_settings_check render 'create' else @@ -108,7 +109,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController Users::UpdateService.new(current_user, user: current_user).execute! do |user| @codes = user.generate_otp_backup_codes! - helpers.dismiss_account_recovery_regular_check + helpers.dismiss_two_factor_auth_recovery_settings_check end end @@ -218,4 +219,12 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController s_(%{The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}.}) .html_safe % { group_links: group_links.html_safe, leave_group_links: leave_group_links.html_safe } end + + def ensure_verified_primary_email + return unless Feature.enabled?(:ensure_verified_primary_email_for_2fa, default_enabled: :yaml) + + unless current_user.two_factor_enabled? || current_user.primary_email_verified? + redirect_to profile_emails_path, notice: s_('You need to verify your primary email first before enabling Two-Factor Authentication.') + end + end end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 6cc602fec88..29ae268ef67 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -103,8 +103,8 @@ class ProfilesController < Profiles::ApplicationController @username_param ||= user_params.require(:username) end - def user_params - @user_params ||= params.require(:user).permit( + def user_params_attributes + [ :avatar, :bio, :email, @@ -130,6 +130,12 @@ class ProfilesController < Profiles::ApplicationController :pronouns, :pronunciation, status: [:emoji, :message, :availability] - ) + ] + end + + def user_params + @user_params ||= params.require(:user).permit(user_params_attributes) end end + +ProfilesController.prepend_mod diff --git a/app/controllers/projects/analytics/cycle_analytics/summary_controller.rb b/app/controllers/projects/analytics/cycle_analytics/summary_controller.rb index c51a5ac7b88..bf8742bf6e8 100644 --- a/app/controllers/projects/analytics/cycle_analytics/summary_controller.rb +++ b/app/controllers/projects/analytics/cycle_analytics/summary_controller.rb @@ -20,7 +20,7 @@ class Projects::Analytics::CycleAnalytics::SummaryController < Projects::Applica end def allowed_params - params.permit(:created_after, :created_before) + request_params.to_data_collector_params end end diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index cf2ecb0673e..7a03e7b84b7 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -26,7 +26,7 @@ class Projects::ApplicationController < ApplicationController path = File.join(params[:namespace_id], params[:project_id] || params[:id]) auth_proc = ->(project) { !project.pending_delete? } - @project = find_routable!(Project, path, request.path_info, extra_authorization_proc: auth_proc) + @project = find_routable!(Project, path, request.fullpath, extra_authorization_proc: auth_proc) end def build_canonical_path(project) diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 035b76abfd6..316582f3994 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -8,7 +8,6 @@ class Projects::BoardsController < Projects::ApplicationController before_action :assign_endpoint_vars before_action do push_frontend_feature_flag(:swimlanes_buffered_rendering, project, default_enabled: :yaml) - push_frontend_feature_flag(:graphql_board_lists, project, default_enabled: :yaml) push_frontend_feature_flag(:issue_boards_filtered_search, project, default_enabled: :yaml) push_frontend_feature_flag(:board_multi_select, project, default_enabled: :yaml) push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml) diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb index ed1d5ca9594..550877548e1 100644 --- a/app/controllers/projects/ci/pipeline_editor_controller.rb +++ b/app/controllers/projects/ci/pipeline_editor_controller.rb @@ -4,7 +4,6 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController before_action :check_can_collaborate! before_action do push_frontend_feature_flag(:pipeline_editor_empty_state_action, @project, default_enabled: :yaml) - push_frontend_feature_flag(:pipeline_editor_branch_switcher, @project, default_enabled: :yaml) push_frontend_feature_flag(:pipeline_editor_drawer, @project, default_enabled: :yaml) push_frontend_feature_flag(:schema_linting, @project, default_enabled: :yaml) end diff --git a/app/controllers/projects/clusters/integrations_controller.rb b/app/controllers/projects/clusters/integrations_controller.rb index eed6c1dccc4..77314d19469 100644 --- a/app/controllers/projects/clusters/integrations_controller.rb +++ b/app/controllers/projects/clusters/integrations_controller.rb @@ -10,6 +10,6 @@ class Projects::Clusters::IntegrationsController < ::Clusters::IntegrationsContr end def project - @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), request.path_info) + @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), request.fullpath) end end diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb index 0aef497d28d..8f45fa1cb9f 100644 --- a/app/controllers/projects/clusters_controller.rb +++ b/app/controllers/projects/clusters_controller.rb @@ -17,7 +17,7 @@ class Projects::ClustersController < Clusters::ClustersController end def project - @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), request.path_info) + @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), request.fullpath) end def repository diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index cac0aa9d513..23dabd885c8 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -213,8 +213,14 @@ class Projects::EnvironmentsController < Projects::ApplicationController end end + def allowed_environment_attributes + attributes = [:external_url] + attributes << :name if action_name == "create" + attributes + end + def environment_params - params.require(:environment).permit(:name, :external_url) + params.require(:environment).permit(allowed_environment_attributes) end def environment diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb index b99c233411a..7c0da8f8a24 100644 --- a/app/controllers/projects/feature_flags_controller.rb +++ b/app/controllers/projects/feature_flags_controller.rb @@ -10,9 +10,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController before_action :feature_flag, only: [:edit, :update, :destroy] - before_action :ensure_flag_writable!, only: [:update] - before_action :exclude_legacy_flags_check, only: [:edit] - feature_category :feature_flags def index @@ -98,18 +95,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController @feature_flag ||= @noteable = project.operations_feature_flags.find_by_iid!(params[:iid]) end - def ensure_flag_writable! - if feature_flag.legacy_flag? - render_error_json(['Legacy feature flags are read-only']) - end - end - - def exclude_legacy_flags_check - if feature_flag.legacy_flag? - not_found - end - end - def create_params params.require(:operations_feature_flag) .permit(:name, :description, :active, :version, diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index bdfaaf2b143..f885ff9b45b 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -42,9 +42,8 @@ class Projects::IssuesController < Projects::ApplicationController before_action do push_frontend_feature_flag(:tribute_autocomplete, @project) push_frontend_feature_flag(:vue_issuables_list, project) - push_frontend_feature_flag(:usage_data_design_action, project, default_enabled: true) push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml) - push_frontend_feature_flag(:vue_issues_list, project) + push_frontend_feature_flag(:vue_issues_list, project&.group, default_enabled: :yaml) push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml) end @@ -118,7 +117,11 @@ class Projects::IssuesController < Projects::ApplicationController @issue = @noteable = service.execute @merge_request_to_resolve_discussions_of = service.merge_request_to_resolve_discussions_of - @discussion_to_resolve = service.discussions_to_resolve.first if params[:discussion_to_resolve] + + if params[:discussion_to_resolve] + Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_resolve_thread_in_issue_action(user: current_user) + @discussion_to_resolve = service.discussions_to_resolve.first + end respond_with(@issue) end @@ -228,7 +231,7 @@ class Projects::IssuesController < Projects::ApplicationController IssuableExportCsvWorker.perform_async(:issue, current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker index_path = project_issues_path(project) - message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email } + message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email_or_default } redirect_to(index_path, notice: message) end diff --git a/app/controllers/projects/learn_gitlab_controller.rb b/app/controllers/projects/learn_gitlab_controller.rb index 162ba9bd5cb..91a43c5f03f 100644 --- a/app/controllers/projects/learn_gitlab_controller.rb +++ b/app/controllers/projects/learn_gitlab_controller.rb @@ -7,13 +7,11 @@ class Projects::LearnGitlabController < Projects::ApplicationController feature_category :users def index - push_frontend_experiment(:learn_gitlab_a, subject: current_user) - push_frontend_experiment(:learn_gitlab_b, subject: current_user) end private def check_experiment_enabled? - return access_denied! unless helpers.learn_gitlab_experiment_enabled?(project) + return access_denied! unless helpers.learn_gitlab_enabled?(project) end end diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 8ccc658dfe7..1188aec24a8 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -42,7 +42,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic allow_tree_conflicts: display_merge_conflicts_in_diff? } - if diff_options_hash[:paths].blank? && Feature.enabled?(:diffs_batch_render_cached, project, default_enabled: :yaml) + if diff_options_hash[:paths].blank? # NOTE: Any variables that would affect the resulting json needs to be added to the cache_context to avoid stale cache issues. cache_context = [ current_user&.cache_key, diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 8b3f2df69df..cb68aaf4583 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -13,6 +13,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo include DiffHelper include Gitlab::Cache::Helpers + prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv] before_action :apply_diff_view_cookie!, only: [:show] before_action :disable_query_limiting, only: [:assign_related_issues, :update] @@ -34,12 +35,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo 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(:local_file_reviews, default_enabled: :yaml) push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml) push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml) push_frontend_feature_flag(:usage_data_i_testing_summary_widget_total, @project, default_enabled: :yaml) push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml) push_frontend_feature_flag(:diffs_virtual_scrolling, project, default_enabled: :yaml) + push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml) # Usage data feature flags push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml) @@ -85,6 +86,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo respond_to do |format| format.html + format.atom { render layout: 'xml.atom' } format.json do render json: { html: view_to_html_string("projects/merge_requests/_merge_requests") @@ -124,13 +126,17 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo set_pipeline_variables + ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336891') do + @number_of_pipelines = @pipelines.size + end + render end format.json do Gitlab::PollingInterval.set_header(response, interval: 10_000) - if params[:serializer] == 'sidebar_extras' && Feature.enabled?(:merge_request_show_render_cached, @project, default_enabled: :yaml) + if params[:serializer] == 'sidebar_extras' cache_context = [ params[:serializer], current_user&.cache_key, @@ -173,7 +179,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo # or from cache if already merged @commits = set_commits_for_rendering( - @merge_request.recent_commits.with_latest_pipeline(@merge_request.source_branch).with_markdown_cache, + @merge_request.recent_commits(load_from_gitaly: true).with_latest_pipeline(@merge_request.source_branch).with_markdown_cache, commits_count: @merge_request.commits_count ) @@ -372,7 +378,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo IssuableExportCsvWorker.perform_async(:merge_request, current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker index_path = project_merge_requests_path(project) - message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email } + message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email_or_default } redirect_to(index_path, notice: message) end diff --git a/app/controllers/projects/packages/packages_controller.rb b/app/controllers/projects/packages/packages_controller.rb index 15dc11f5df8..5de71466c10 100644 --- a/app/controllers/projects/packages/packages_controller.rb +++ b/app/controllers/projects/packages/packages_controller.rb @@ -9,8 +9,6 @@ module Projects def show @package = project.packages.find(params[:id]) - @package_files = @package.package_files.recent - @maven_metadatum = @package.maven_metadatum end end end diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index 006cb8a2201..4af7508b935 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -10,10 +10,6 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController before_action :authorize_update_pipeline_schedule!, except: [:index, :new, :create, :play] before_action :authorize_admin_pipeline_schedule!, only: [:destroy] - before_action do - push_frontend_feature_flag(:ci_daily_limit_for_pipeline_schedules, @project, default_enabled: :yaml) - end - feature_category :continuous_integration # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index a411264b350..a2312484a9b 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -14,10 +14,6 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action :ensure_pipeline, only: [:show, :downloadable_artifacts] - before_action do - push_frontend_feature_flag(:pipeline_source_filter, project, type: :development, default_enabled: :yaml) - end - # Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596 before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? } @@ -195,7 +191,8 @@ class Projects::PipelinesController < Projects::ApplicationController def config_variables respond_to do |format| format.json do - result = Ci::ListConfigVariablesService.new(@project, current_user).execute(params[:sha]) + project = @project.uses_external_project_ci_config? ? @project.ci_config_external_project : @project + result = Ci::ListConfigVariablesService.new(project, current_user).execute(params[:sha]) result.nil? ? head(:no_content) : render(json: result) end @@ -297,7 +294,7 @@ class Projects::PipelinesController < Projects::ApplicationController end def index_params - params.permit(:scope, :username, :ref, :status) + params.permit(:scope, :username, :ref, :status, :source) end def enable_code_quality_walkthrough_experiment diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb index 5da81045e02..39db7618db0 100644 --- a/app/controllers/projects/runner_projects_controller.rb +++ b/app/controllers/projects/runner_projects_controller.rb @@ -15,7 +15,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController path = project_runners_path(project) if @runner.assign_to(project, current_user) - redirect_to path + redirect_to path, notice: s_('Runners|Runner assigned to project.') else assign_to_messages = @runner.errors.messages[:assign_to] alert = assign_to_messages&.join(',') || 'Failed adding runner to project' @@ -28,6 +28,6 @@ class Projects::RunnerProjectsController < Projects::ApplicationController runner_project = project.runner_projects.find(params[:id]) runner_project.destroy - redirect_to project_runners_path(project), status: :found + redirect_to project_runners_path(project), status: :found, notice: s_('Runners|Runner unassigned from project.') end end diff --git a/app/controllers/projects/service_desk_controller.rb b/app/controllers/projects/service_desk_controller.rb index f7c0a54fb9e..1fb07c3a903 100644 --- a/app/controllers/projects/service_desk_controller.rb +++ b/app/controllers/projects/service_desk_controller.rb @@ -24,24 +24,31 @@ class Projects::ServiceDeskController < Projects::ApplicationController private def setting_params - params.permit(:issue_template_key, :outgoing_name, :project_key) + params.permit(*allowed_update_attributes) + end + + def allowed_update_attributes + %i(issue_template_key outgoing_name project_key) + end + + def service_desk_attributes + service_desk_settings = project.service_desk_setting + + { + service_desk_address: project.service_desk_address, + service_desk_enabled: project.service_desk_enabled, + issue_template_key: service_desk_settings&.issue_template_key, + template_file_missing: service_desk_settings&.issue_template_missing?, + outgoing_name: service_desk_settings&.outgoing_name, + project_key: service_desk_settings&.project_key + } end def json_response respond_to do |format| - service_desk_settings = project.service_desk_setting - - service_desk_attributes = - { - service_desk_address: project.service_desk_address, - service_desk_enabled: project.service_desk_enabled, - issue_template_key: service_desk_settings&.issue_template_key, - template_file_missing: service_desk_settings&.issue_template_missing?, - outgoing_name: service_desk_settings&.outgoing_name, - project_key: service_desk_settings&.project_key - } - format.json { render json: service_desk_attributes } end end end + +Projects::ServiceDeskController.prepend_mod diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 0dcaab7160b..c42d382c4bb 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -26,15 +26,15 @@ class Projects::ServicesController < Projects::ApplicationController attributes = integration_params[:integration] if use_inherited_settings?(attributes) - @integration.inherit_from_id = default_integration.id + integration.inherit_from_id = default_integration.id - if saved = @integration.save(context: :manual_change) - BulkUpdateIntegrationService.new(default_integration, [@integration]).execute + if saved = integration.save(context: :manual_change) + BulkUpdateIntegrationService.new(default_integration, [integration]).execute end else attributes[:inherit_from_id] = nil - @integration.attributes = attributes - saved = @integration.save(context: :manual_change) + integration.attributes = attributes + saved = integration.save(context: :manual_change) end respond_to do |format| @@ -65,15 +65,15 @@ class Projects::ServicesController < Projects::ApplicationController private def redirect_path - safe_redirect_path(params[:redirect_to]).presence || edit_project_service_path(@project, @integration) + safe_redirect_path(params[:redirect_to]).presence || edit_project_service_path(project, integration) end def service_test_response - unless @integration.update(integration_params[:integration]) - return { error: true, message: _('Validations failed.'), service_response: @integration.errors.full_messages.join(','), test_failed: false } + unless integration.update(integration_params[:integration]) + return { error: true, message: _('Validations failed.'), service_response: integration.errors.full_messages.join(','), test_failed: false } end - result = ::Integrations::Test::ProjectService.new(@integration, current_user, params[:event]).execute + result = ::Integrations::Test::ProjectService.new(integration, current_user, params[:event]).execute unless result[:success] return { error: true, message: s_('Integrations|Connection failed. Please check your settings.'), service_response: result[:message].to_s, test_failed: true } @@ -93,7 +93,7 @@ class Projects::ServicesController < Projects::ApplicationController end def integration - @integration ||= @project.find_or_initialize_integration(params[:id]) + @integration ||= project.find_or_initialize_integration(params[:id]) end alias_method :service, :integration diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index e32815b6239..56e201c592f 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -136,6 +136,7 @@ module Projects error_tracking_setting_attributes: [ :enabled, + :integrated, :api_host, :token, project: [:slug, :name, :organization_slug, :organization_name] diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 475c9de2503..6fd4c632dd3 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -15,6 +15,10 @@ class Projects::TreeController < Projects::ApplicationController before_action :authorize_download_code! before_action :authorize_edit_tree!, only: [:create_dir] + before_action do + push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml) + end + feature_category :source_code_management def show diff --git a/app/controllers/projects/usage_quotas_controller.rb b/app/controllers/projects/usage_quotas_controller.rb new file mode 100644 index 00000000000..179c7fc8db1 --- /dev/null +++ b/app/controllers/projects/usage_quotas_controller.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class Projects::UsageQuotasController < Projects::ApplicationController + before_action :authorize_admin_project! + before_action :verify_usage_quotas_enabled! + + layout "project_settings" + + feature_category :utilization + + def index + @storage_app_data = { + project_path: @project.full_path, + usage_quotas_help_page_path: help_page_path('user/usage_quotas'), + build_artifacts_help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'when-job-artifacts-are-deleted'), + packages_help_page_path: help_page_path('user/packages/package_registry/index.md', anchor: 'delete-a-package'), + repository_help_page_path: help_page_path('user/project/repository/reducing_the_repo_size_using_git'), + snippets_help_page_path: help_page_path('user/snippets', anchor: 'reduce-snippets-repository-size'), + 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 d1486f765e4..9ee8847004e 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -5,5 +5,9 @@ class Projects::WikisController < Projects::ApplicationController alias_method :container, :project + before_action do + push_frontend_feature_flag(:content_editor_block_tables, @project, default_enabled: :yaml) + end + feature_category :wiki end diff --git a/app/controllers/projects/work_items_controller.rb b/app/controllers/projects/work_items_controller.rb new file mode 100644 index 00000000000..1bd2762f277 --- /dev/null +++ b/app/controllers/projects/work_items_controller.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class Projects::WorkItemsController < Projects::ApplicationController + before_action do + push_frontend_feature_flag(:work_items, project, default_enabled: :yaml) + end + + feature_category :not_owned + + def index + render_404 unless Feature.enabled?(:work_items, project, default_enabled: :yaml) + end +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index bdb645e1934..d7c1d87ae4b 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -34,6 +34,7 @@ class ProjectsController < Projects::ApplicationController before_action do push_frontend_feature_flag(:refactor_blob_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) end layout :determine_layout diff --git a/app/controllers/registrations/experience_levels_controller.rb b/app/controllers/registrations/experience_levels_controller.rb deleted file mode 100644 index 3c94bce126c..00000000000 --- a/app/controllers/registrations/experience_levels_controller.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -module Registrations - class ExperienceLevelsController < ApplicationController - layout 'minimal' - - before_action :ensure_namespace_path_param - - feature_category :onboarding - - def update - current_user.experience_level = params[:experience_level] - - if current_user.save - hide_advanced_issues - - if learn_gitlab.available? - redirect_to namespace_project_board_path(params[:namespace_path], learn_gitlab.project, learn_gitlab.board) - else - redirect_to group_path(params[:namespace_path]) - end - else - render :show - end - end - - private - - def ensure_namespace_path_param - redirect_to root_path unless params[:namespace_path].present? - end - - def hide_advanced_issues - return unless current_user.user_preference.novice? - return unless learn_gitlab.available? - - Boards::UpdateService.new(learn_gitlab.project, current_user, label_ids: [learn_gitlab.label.id]).execute(learn_gitlab.board) - end - - def learn_gitlab - @learn_gitlab ||= LearnGitlab::Project.new(current_user) - end - end -end diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb index ced21b8f291..416bbf43464 100644 --- a/app/controllers/registrations/welcome_controller.rb +++ b/app/controllers/registrations/welcome_controller.rb @@ -16,7 +16,7 @@ module Registrations result = ::Users::SignupService.new(current_user, update_params).execute if result[:status] == :success - return redirect_to new_users_sign_up_group_path(trial_params) if show_signup_onboarding? + return redirect_to experiment(:combined_registration, user: current_user).redirect_path(trial_params) if show_signup_onboarding? members = current_user.members diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index cc985e84542..fe800de5dd8 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -21,9 +21,10 @@ class RegistrationsController < Devise::RegistrationsController def create set_user_state - accept_pending_invitations super do |new_user| + accept_pending_invitations if new_user.persisted? + persist_accepted_terms_if_required(new_user) set_role_required(new_user) @@ -146,8 +147,12 @@ class RegistrationsController < Devise::RegistrationsController resource.persisted? && resource.blocked_pending_approval? end + def sign_up_params_attributes + [:username, :email, :name, :first_name, :last_name, :password] + end + def sign_up_params - params.require(:user).permit(:username, :email, :name, :first_name, :last_name, :password) + params.require(:user).permit(sign_up_params_attributes) end def resource_name @@ -201,6 +206,7 @@ class RegistrationsController < Devise::RegistrationsController experiment_name = session.delete(:invite_email_experiment_name) experiment(:invite_email_preview_text, actor: member).track(:accepted) if experiment_name == 'invite_email_preview_text' + experiment(:invite_email_from, actor: member).track(:accepted) if experiment_name == 'invite_email_from' Gitlab::Tracking.event(self.class.name, 'accepted', label: 'invite_email', property: member.id.to_s) end diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index dbddb35d358..5f1b3750e41 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -11,7 +11,7 @@ class SearchController < ApplicationController around_action :allow_gitaly_ref_name_caching - before_action :block_anonymous_global_searches, except: :opensearch + before_action :block_anonymous_global_searches, :check_scope_global_search_enabled, except: :opensearch skip_before_action :authenticate_user! requires_cross_project_access if: -> do search_term_present = params[:search].present? || params[:term].present? @@ -156,6 +156,29 @@ class SearchController < ApplicationController redirect_to new_user_session_path, alert: _('You must be logged in to search across all of GitLab') end + def check_scope_global_search_enabled + return if params[:project_id].present? || params[:group_id].present? + + search_allowed = case params[:scope] + when 'blobs' + Feature.enabled?(:global_search_code_tab, current_user, type: :ops, default_enabled: true) + when 'commits' + Feature.enabled?(:global_search_commits_tab, current_user, type: :ops, default_enabled: true) + when 'issues' + Feature.enabled?(:global_search_issues_tab, current_user, type: :ops, default_enabled: true) + when 'merge_requests' + Feature.enabled?(:global_search_merge_requests_tab, current_user, type: :ops, default_enabled: true) + when 'wiki_blobs' + Feature.enabled?(:global_search_wiki_tab, current_user, type: :ops, default_enabled: true) + else + true + end + + return if search_allowed + + redirect_to search_path, alert: _('Global Search is disabled for this scope') + end + def render_timeout(exception) raise exception unless action_name.to_sym.in?(RESCUE_FROM_TIMEOUT_ACTIONS) diff --git a/app/controllers/user_callouts_controller.rb b/app/controllers/user_callouts_controller.rb index df3e2425e9f..f52a09adf5a 100644 --- a/app/controllers/user_callouts_controller.rb +++ b/app/controllers/user_callouts_controller.rb @@ -4,10 +4,6 @@ class UserCalloutsController < ApplicationController feature_category :navigation def create - callout = Users::DismissUserCalloutService.new( - container: nil, current_user: current_user, params: { feature_name: feature_name } - ).execute - if callout.persisted? respond_to do |format| format.json { head :ok } @@ -21,6 +17,12 @@ class UserCalloutsController < ApplicationController private + def callout + Users::DismissUserCalloutService.new( + container: nil, current_user: current_user, params: { feature_name: feature_name } + ).execute + end + def feature_name params.require(:feature_name) end diff --git a/app/controllers/users/group_callouts_controller.rb b/app/controllers/users/group_callouts_controller.rb new file mode 100644 index 00000000000..cc27452e6a3 --- /dev/null +++ b/app/controllers/users/group_callouts_controller.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Users + class GroupCalloutsController < UserCalloutsController + private + + def callout + Users::DismissGroupCalloutService.new( + container: nil, current_user: current_user, params: callout_params + ).execute + end + + def callout_params + params.permit(:group_id).merge(feature_name: feature_name) + end + end +end diff --git a/app/controllers/users/terms_controller.rb b/app/controllers/users/terms_controller.rb index be670658048..7fbf0faa68b 100644 --- a/app/controllers/users/terms_controller.rb +++ b/app/controllers/users/terms_controller.rb @@ -77,3 +77,5 @@ module Users end end end + +Users::TermsController.prepend_mod diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 30ccceec1af..26f56307862 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -167,7 +167,7 @@ class UsersController < ApplicationController private def user - @user ||= find_routable!(User, params[:username], request.path_info) + @user ||= find_routable!(User, params[:username], request.fullpath) end def personal_projects |