diff options
Diffstat (limited to 'app/controllers')
74 files changed, 549 insertions, 445 deletions
diff --git a/app/controllers/admin/cohorts_controller.rb b/app/controllers/admin/cohorts_controller.rb index d5cd9c55422..a26dc554506 100644 --- a/app/controllers/admin/cohorts_controller.rb +++ b/app/controllers/admin/cohorts_controller.rb @@ -5,7 +5,7 @@ class Admin::CohortsController < Admin::ApplicationController track_unique_visits :index, target_id: 'i_analytics_cohorts' - feature_category :instance_statistics + feature_category :devops_reports def index if Gitlab::CurrentSettings.usage_ping_enabled diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index 33a8cc4ae42..da89276f5eb 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -2,7 +2,6 @@ class Admin::DashboardController < Admin::ApplicationController include CountHelper - helper_method :show_license_breakdown? COUNTED_ITEMS = [Project, User, Group].freeze @@ -23,10 +22,6 @@ class Admin::DashboardController < Admin::ApplicationController def stats @users_statistics = UsersStatistics.latest end - - def show_license_breakdown? - false - end end Admin::DashboardController.prepend_if_ee('EE::Admin::DashboardController') diff --git a/app/controllers/admin/instance_review_controller.rb b/app/controllers/admin/instance_review_controller.rb index db304c82dd6..88ca2c88aab 100644 --- a/app/controllers/admin/instance_review_controller.rb +++ b/app/controllers/admin/instance_review_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true class Admin::InstanceReviewController < Admin::ApplicationController - feature_category :instance_statistics + feature_category :devops_reports def index redirect_to("#{::Gitlab::SubscriptionPortal::SUBSCRIPTIONS_URL}/instance_review?#{instance_review_params}") diff --git a/app/controllers/admin/instance_statistics_controller.rb b/app/controllers/admin/instance_statistics_controller.rb index 05a0a1ce314..30891fcfe7c 100644 --- a/app/controllers/admin/instance_statistics_controller.rb +++ b/app/controllers/admin/instance_statistics_controller.rb @@ -7,7 +7,7 @@ class Admin::InstanceStatisticsController < Admin::ApplicationController track_unique_visits :index, target_id: 'i_analytics_instance_statistics' - feature_category :instance_statistics + feature_category :devops_reports def index end diff --git a/app/controllers/admin/integrations_controller.rb b/app/controllers/admin/integrations_controller.rb index aab8705f5cb..4247446365c 100644 --- a/app/controllers/admin/integrations_controller.rb +++ b/app/controllers/admin/integrations_controller.rb @@ -4,6 +4,8 @@ class Admin::IntegrationsController < Admin::ApplicationController include IntegrationsActions include ServicesHelper + before_action :not_found, unless: -> { instance_level_integrations? } + feature_category :integrations private @@ -12,10 +14,6 @@ class Admin::IntegrationsController < Admin::ApplicationController Service.find_or_initialize_non_project_specific_integration(name, instance: true) end - def integrations_enabled? - instance_level_integrations? - end - def scoped_edit_integration_path(integration) edit_admin_application_settings_integration_path(integration) end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 2d0bb0bfebc..3fe972d1917 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -72,6 +72,16 @@ class Admin::UsersController < Admin::ApplicationController end end + def reject + result = Users::RejectService.new(current_user).execute(user) + + if result[:status] == :success + redirect_to admin_users_path, status: :found, notice: _("You've rejected %{user}" % { user: user.name }) + else + redirect_back_or_admin_user(alert: result[:message]) + end + end + def activate return redirect_back_or_admin_user(notice: _("Error occurred. A blocked user must be unblocked to be activated")) if user.blocked? diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c38c6abddc1..b78029a52cd 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -61,8 +61,7 @@ class ApplicationController < ActionController::Base :gitea_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, - :bitbucket_server_import_enabled?, - :google_code_import_enabled?, :fogbugz_import_enabled?, + :bitbucket_server_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled?, :manifest_import_enabled?, :phabricator_import_enabled? @@ -434,10 +433,6 @@ class ApplicationController < ActionController::Base Gitlab::Auth::OAuth::Provider.enabled?(:bitbucket) end - def google_code_import_enabled? - Gitlab::CurrentSettings.import_sources.include?('google_code') - end - def fogbugz_import_enabled? Gitlab::CurrentSettings.import_sources.include?('fogbugz') end diff --git a/app/controllers/boards/lists_controller.rb b/app/controllers/boards/lists_controller.rb index aecd287370f..19a4508c061 100644 --- a/app/controllers/boards/lists_controller.rb +++ b/app/controllers/boards/lists_controller.rb @@ -19,12 +19,12 @@ module Boards end def create - list = Boards::Lists::CreateService.new(board.resource_parent, current_user, create_list_params).execute(board) + response = Boards::Lists::CreateService.new(board.resource_parent, current_user, create_list_params).execute(board) - if list.valid? - render json: serialize_as_json(list) + if response.success? + render json: serialize_as_json(response.payload[:list]) else - render json: list.errors, status: :unprocessable_entity + render json: { errors: response.errors }, status: :unprocessable_entity end end diff --git a/app/controllers/concerns/dependency_proxy/auth.rb b/app/controllers/concerns/dependency_proxy/auth.rb new file mode 100644 index 00000000000..1276feedba6 --- /dev/null +++ b/app/controllers/concerns/dependency_proxy/auth.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module DependencyProxy + module Auth + extend ActiveSupport::Concern + + included do + # We disable `authenticate_user!` since the `DependencyProxy::Auth` performs auth using JWT token + skip_before_action :authenticate_user!, raise: false + prepend_before_action :authenticate_user_from_jwt_token! + end + + def authenticate_user_from_jwt_token! + return unless dependency_proxy_for_private_groups? + + authenticate_with_http_token do |token, _| + user = user_from_token(token) + sign_in(user) if user + end + + request_bearer_token! unless current_user + end + + private + + def dependency_proxy_for_private_groups? + Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) + end + + def request_bearer_token! + # unfortunately, we cannot use https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html#method-i-authentication_request + response.headers['WWW-Authenticate'] = ::DependencyProxy::Registry.authenticate_header + render plain: '', status: :unauthorized + end + + def user_from_token(token) + token_payload = DependencyProxy::AuthTokenService.decoded_token_payload(token) + User.find(token_payload['user_id']) + rescue JWT::DecodeError, JWT::ExpiredSignature, JWT::ImmatureSignature + nil + end + end +end diff --git a/app/controllers/concerns/dependency_proxy/group_access.rb b/app/controllers/concerns/dependency_proxy/group_access.rb new file mode 100644 index 00000000000..2a923d02752 --- /dev/null +++ b/app/controllers/concerns/dependency_proxy/group_access.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module DependencyProxy + module GroupAccess + extend ActiveSupport::Concern + + included do + before_action :verify_dependency_proxy_enabled! + before_action :authorize_read_dependency_proxy! + end + + private + + def verify_dependency_proxy_enabled! + render_404 unless group.dependency_proxy_feature_available? + end + + def authorize_read_dependency_proxy! + access_denied! unless can?(current_user, :read_dependency_proxy, group) + end + + def authorize_admin_dependency_proxy! + access_denied! unless can?(current_user, :admin_dependency_proxy, group) + end + end +end diff --git a/app/controllers/concerns/dependency_proxy_access.rb b/app/controllers/concerns/dependency_proxy_access.rb deleted file mode 100644 index 5036d0cfce4..00000000000 --- a/app/controllers/concerns/dependency_proxy_access.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -module DependencyProxyAccess - extend ActiveSupport::Concern - - included do - before_action :verify_dependency_proxy_enabled! - before_action :authorize_read_dependency_proxy! - end - - private - - def verify_dependency_proxy_enabled! - render_404 unless group.dependency_proxy_feature_available? - end - - def authorize_read_dependency_proxy! - access_denied! unless can?(current_user, :read_dependency_proxy, group) - end - - def authorize_admin_dependency_proxy! - access_denied! unless can?(current_user, :admin_dependency_proxy, group) - end -end diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb index 8e9b038437d..baebedb8e5d 100644 --- a/app/controllers/concerns/integrations_actions.rb +++ b/app/controllers/concerns/integrations_actions.rb @@ -6,7 +6,6 @@ module IntegrationsActions included do include ServiceParams - before_action :not_found, unless: :integrations_enabled? before_action :integration, only: [:edit, :update, :test] end @@ -43,12 +42,16 @@ module IntegrationsActions render json: {}, status: :ok end - private + def reset + integration.destroy! + + flash[:notice] = s_('Integrations|This integration, and inheriting projects were reset.') - def integrations_enabled? - false + render json: {}, status: :ok end + private + def integration # Using instance variable `@service` still required as it's used in ServiceParams. # Should be removed once that is refactored to use `@integration`. diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 0d7af57328a..3f5f3b6e9df 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -150,7 +150,7 @@ module IssuableCollections common_attributes + [:project, project: :namespace] when 'MergeRequest' common_attributes + [ - :target_project, :latest_merge_request_diff, :approvals, :approved_by_users, + :target_project, :latest_merge_request_diff, :approvals, :approved_by_users, :reviewers, source_project: :route, head_pipeline: :project, target_project: :namespace ] end diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb index a19c43a227a..c295290a123 100644 --- a/app/controllers/concerns/service_params.rb +++ b/app/controllers/concerns/service_params.rb @@ -23,6 +23,9 @@ module ServiceParams :comment_detail, :confidential_issues_events, :confluence_url, + :datadog_site, + :datadog_env, + :datadog_service, :default_irc_uri, :device, :disable_diffs, diff --git a/app/controllers/concerns/snippets_actions.rb b/app/controllers/concerns/snippets_actions.rb index 0153ede2821..c93e75b438b 100644 --- a/app/controllers/concerns/snippets_actions.rb +++ b/app/controllers/concerns/snippets_actions.rb @@ -9,11 +9,14 @@ module SnippetsActions include Gitlab::NoteableMetadata include Snippets::SendBlob include SnippetsSort + include RedisTracking included do skip_before_action :verify_authenticity_token, if: -> { action_name == 'show' && js_request? } + track_redis_hll_event :show, name: 'i_snippets_show', feature: :usage_data_i_snippets_show, feature_default_enabled: true + respond_to :html end diff --git a/app/controllers/concerns/sorting_preference.rb b/app/controllers/concerns/sorting_preference.rb index a51b68147d5..8d8845e2f41 100644 --- a/app/controllers/concerns/sorting_preference.rb +++ b/app/controllers/concerns/sorting_preference.rb @@ -4,8 +4,11 @@ module SortingPreference include SortingHelper include CookiesHelper - def set_sort_order - set_sort_order_from_user_preference || set_sort_order_from_cookie || params[:sort] || default_sort_order + def set_sort_order(field = sorting_field, default_order = default_sort_order) + set_sort_order_from_user_preference(field) || + set_sort_order_from_cookie(field) || + params[:sort] || + default_order end # Implement sorting_field method on controllers @@ -29,42 +32,42 @@ module SortingPreference private - def set_sort_order_from_user_preference + def set_sort_order_from_user_preference(field = sorting_field) return unless current_user - return unless sorting_field + return unless field user_preference = current_user.user_preference sort_param = params[:sort] - sort_param ||= user_preference[sorting_field] + sort_param ||= user_preference[field] return sort_param if Gitlab::Database.read_only? - if user_preference[sorting_field] != sort_param - user_preference.update(sorting_field => sort_param) + if user_preference[field] != sort_param + user_preference.update(field => sort_param) end sort_param end - def set_sort_order_from_cookie + def set_sort_order_from_cookie(field = sorting_field) return unless legacy_sort_cookie_name sort_param = params[:sort] if params[:sort].present? # fallback to legacy cookie value for backward compatibility sort_param ||= cookies[legacy_sort_cookie_name] - sort_param ||= cookies[remember_sorting_key] + sort_param ||= cookies[remember_sorting_key(field)] sort_value = update_cookie_value(sort_param) - set_secure_cookie(remember_sorting_key, sort_value) + set_secure_cookie(remember_sorting_key(field), sort_value) sort_value end # Convert sorting_field to legacy cookie name for backwards compatibility # :merge_requests_sort => 'mergerequest_sort' # :issues_sort => 'issue_sort' - def remember_sorting_key - @remember_sorting_key ||= sorting_field + def remember_sorting_key(field = sorting_field) + @remember_sorting_key ||= field .to_s .split('_')[0..-2] .map(&:singularize) diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb index 6abb2e16226..1ae90edd8f7 100644 --- a/app/controllers/concerns/wiki_actions.rb +++ b/app/controllers/concerns/wiki_actions.rb @@ -8,6 +8,8 @@ module WikiActions include RedisTracking extend ActiveSupport::Concern + RESCUE_GIT_TIMEOUTS_IN = %w[show edit history diff pages].freeze + included do before_action { respond_to :html } @@ -38,6 +40,12 @@ module WikiActions feature: :track_unique_wiki_page_views, feature_default_enabled: true helper_method :view_file_button, :diff_file_html_data + + rescue_from ::Gitlab::Git::CommandTimedOut do |exc| + raise exc unless RESCUE_GIT_TIMEOUTS_IN.include?(action_name) + + render 'shared/wikis/git_error' + end end def new @@ -46,11 +54,7 @@ module WikiActions # rubocop:disable Gitlab/ModuleWithInstanceVariables def pages - @wiki_pages = Kaminari.paginate_array( - wiki.list_pages(sort: params[:sort], direction: params[:direction]) - ).page(params[:page]) - - @wiki_entries = WikiDirectory.group_pages(@wiki_pages) + @wiki_entries = WikiDirectory.group_pages(wiki_pages) render 'shared/wikis/pages' end @@ -182,6 +186,10 @@ module WikiActions end # rubocop:enable Gitlab/ModuleWithInstanceVariables + def git_access + render 'shared/wikis/git_access' + end + private def container @@ -225,9 +233,19 @@ module WikiActions unless @sidebar_page # Fallback to default sidebar @sidebar_wiki_entries, @sidebar_limited = wiki.sidebar_entries end + rescue ::Gitlab::Git::CommandTimedOut => e + @sidebar_error = e end # rubocop:enable Gitlab/ModuleWithInstanceVariables + def wiki_pages + strong_memoize(:wiki_pages) do + Kaminari.paginate_array( + wiki.list_pages(sort: params[:sort], direction: params[:direction]) + ).page(params[:page]) + end + end + def wiki_params params.require(:wiki).permit(:title, :content, :format, :message, :last_commit_sha) end diff --git a/app/controllers/concerns/workhorse_import_export_upload.rb b/app/controllers/concerns/workhorse_authorization.rb index 3c52f4d7adf..a290ba256b6 100644 --- a/app/controllers/concerns/workhorse_import_export_upload.rb +++ b/app/controllers/concerns/workhorse_authorization.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module WorkhorseImportExportUpload +module WorkhorseAuthorization extend ActiveSupport::Concern include WorkhorseRequest @@ -12,10 +12,9 @@ module WorkhorseImportExportUpload def authorize set_workhorse_internal_api_content_type - authorized = ImportExportUploader.workhorse_authorize( + authorized = uploader_class.workhorse_authorize( has_length: false, - maximum_size: Gitlab::CurrentSettings.max_import_size.megabytes - ) + maximum_size: maximum_size.to_i) render json: authorized rescue SocketError @@ -27,7 +26,18 @@ module WorkhorseImportExportUpload def file_is_valid?(file) return false unless file.is_a?(::UploadedFile) + file_extension_whitelist.include?(File.extname(file.original_filename).downcase.delete('.')) + end + + def uploader_class + raise NotImplementedError + end + + def maximum_size + raise NotImplementedError + end + + def file_extension_whitelist ImportExportUploader::EXTENSION_WHITELIST - .include?(File.extname(file.original_filename).delete('.')) end end diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index f7a74f40e4b..aa3592ff209 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -108,7 +108,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController end def default_sort_order - sort_value_latest_activity + sort_value_name end def sorting_field diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index 7a485eebfe3..d210d0f66fd 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -94,7 +94,7 @@ class Explore::ProjectsController < Explore::ApplicationController end def default_sort_order - sort_value_latest_activity + sort_value_name end def sorting_field diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index b5deed70380..1852405e7cf 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -37,7 +37,11 @@ class GraphqlController < ApplicationController rescue_from StandardError do |exception| log_exception(exception) - render_error("Internal server error") + if Rails.env.test? || Rails.env.development? + render_error("Internal server error: #{exception.message}") + else + render_error("Internal server error") + end end rescue_from Gitlab::Graphql::Variables::Invalid do |exception| diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 9c2e361e92f..a504d2ce991 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -3,11 +3,14 @@ class Groups::ApplicationController < ApplicationController include RoutableActions include ControllerWithCrossProjectAccessCheck + include SortingHelper + include SortingPreference layout 'group' skip_before_action :authenticate_user! before_action :group + before_action :set_sorting requires_cross_project_access private @@ -57,6 +60,16 @@ class Groups::ApplicationController < ApplicationController url_for(safe_params) end + + def set_sorting + if has_project_list? + @group_projects_sort = set_sort_order(Project::SORTING_PREFERENCE_FIELD, sort_value_name) + end + end + + def has_project_list? + false + end end Groups::ApplicationController.prepend_if_ee('EE::Groups::ApplicationController') diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index c2d72610c66..093cdf258b2 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -8,7 +8,6 @@ class Groups::BoardsController < Groups::ApplicationController before_action :assign_endpoint_vars before_action do push_frontend_feature_flag(:graphql_board_lists, group, default_enabled: false) - push_frontend_feature_flag(:boards_with_swimlanes, group, default_enabled: true) end feature_category :boards diff --git a/app/controllers/groups/children_controller.rb b/app/controllers/groups/children_controller.rb index 718914dea35..10a6ad06ae5 100644 --- a/app/controllers/groups/children_controller.rb +++ b/app/controllers/groups/children_controller.rb @@ -2,12 +2,15 @@ module Groups class ChildrenController < Groups::ApplicationController + extend ::Gitlab::Utils::Override + before_action :group skip_cross_project_access_check :index feature_category :subgroups def index + params[:sort] ||= @group_projects_sort parent = if params[:parent_id].present? GroupFinder.new(current_user).execute(id: params[:parent_id]) else @@ -40,5 +43,12 @@ module Groups params: params.to_unsafe_h).execute @children = @children.page(params[:page]) end + + private + + override :has_project_list? + def has_project_list? + true + end end end diff --git a/app/controllers/groups/dependency_proxies_controller.rb b/app/controllers/groups/dependency_proxies_controller.rb index 367dbafdd59..b896b240daf 100644 --- a/app/controllers/groups/dependency_proxies_controller.rb +++ b/app/controllers/groups/dependency_proxies_controller.rb @@ -2,7 +2,7 @@ module Groups class DependencyProxiesController < Groups::ApplicationController - include DependencyProxyAccess + include DependencyProxy::GroupAccess before_action :authorize_admin_dependency_proxy!, only: :update before_action :dependency_proxy diff --git a/app/controllers/groups/dependency_proxy_auth_controller.rb b/app/controllers/groups/dependency_proxy_auth_controller.rb new file mode 100644 index 00000000000..e3e9bd88e24 --- /dev/null +++ b/app/controllers/groups/dependency_proxy_auth_controller.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class Groups::DependencyProxyAuthController < ApplicationController + include DependencyProxy::Auth + + feature_category :dependency_proxy + + def authenticate + render plain: '', status: :ok + end +end diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb index f46902ef90f..0f640397320 100644 --- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb +++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true class Groups::DependencyProxyForContainersController < Groups::ApplicationController - include DependencyProxyAccess + include DependencyProxy::Auth + include DependencyProxy::GroupAccess include SendFileUpload before_action :ensure_token_granted! @@ -9,13 +10,13 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro attr_reader :token - feature_category :package_registry + feature_category :dependency_proxy def manifest - result = DependencyProxy::PullManifestService.new(image, tag, token).execute + result = DependencyProxy::FindOrCreateManifestService.new(group, image, tag, token).execute if result[:status] == :success - render json: result[:manifest] + send_upload(result[:manifest].file) else render status: result[:http_status], json: result[:message] end diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 5df7ff0632a..d1b09e1b49e 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -14,6 +14,10 @@ class Groups::GroupMembersController < Groups::ApplicationController # Authorize before_action :authorize_admin_group_member!, except: admin_not_required_endpoints + before_action do + push_frontend_feature_flag(:group_members_filtered_search, @group, default_enabled: true) + end + skip_before_action :check_two_factor_requirement, only: :leave skip_cross_project_access_check :index, :create, :update, :destroy, :request_access, :approve_access_request, :leave, :resend_invite, diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 03d41f1dd6d..84dc570a1e9 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -5,9 +5,6 @@ class Groups::MilestonesController < Groups::ApplicationController before_action :milestone, only: [:edit, :show, :update, :issues, :merge_requests, :participants, :labels, :destroy] before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update, :destroy] - before_action do - push_frontend_feature_flag(:burnup_charts, @group, default_enabled: true) - end feature_category :issue_tracking diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb index a66372b3571..8903feaff04 100644 --- a/app/controllers/groups/settings/integrations_controller.rb +++ b/app/controllers/groups/settings/integrations_controller.rb @@ -25,10 +25,6 @@ module Groups Service.find_or_initialize_non_project_specific_integration(name, group_id: group.id) end - def integrations_enabled? - Feature.enabled?(:group_level_integrations, group, default_enabled: true) - end - def scoped_edit_integration_path(integration) edit_group_settings_integration_path(group, integration) end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 8d528e123e1..068815f7f07 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -69,7 +69,7 @@ class GroupsController < Groups::ApplicationController @group = Groups::CreateService.new(current_user, group_params).execute if @group.persisted? - track_experiment_event(:onboarding_issues, 'created_namespace') + successful_creation_hooks notice = if @group.chat_team.present? "Group '#{@group.name}' and its Mattermost team were successfully created." @@ -319,6 +319,10 @@ class GroupsController < Groups::ApplicationController private + def successful_creation_hooks + track_experiment_event(:onboarding_issues, 'created_namespace') + end + def groups if @group.supports_events? @group.self_and_descendants.public_or_visible_to_user(current_user) @@ -329,6 +333,11 @@ class GroupsController < Groups::ApplicationController def markdown_service_params params.merge(group: group) end + + override :has_project_list? + def has_project_list? + %w(details show index).include?(action_name) + end end GroupsController.prepend_if_ee('EE::GroupsController') diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb index 78f4a0cffca..4417cfe9098 100644 --- a/app/controllers/import/bulk_imports_controller.rb +++ b/app/controllers/import/bulk_imports_controller.rb @@ -20,8 +20,9 @@ class Import::BulkImportsController < ApplicationController format.json do render json: { importable_data: serialized_importable_data } end - - format.html + format.html do + @source_url = session[url_key] + end end end @@ -57,7 +58,7 @@ class Import::BulkImportsController < ApplicationController end def create_params - params.permit(:bulk_import, [*bulk_import_params]) + params.permit(bulk_import: bulk_import_params)[:bulk_import] end def bulk_import_params @@ -84,11 +85,9 @@ class Import::BulkImportsController < ApplicationController def verify_blocked_uri Gitlab::UrlBlocker.validate!( session[url_key], - **{ - allow_localhost: allow_local_requests?, - allow_local_network: allow_local_requests?, - schemes: %w(http https) - } + allow_localhost: allow_local_requests?, + allow_local_network: allow_local_requests?, + schemes: %w(http https) ) rescue Gitlab::UrlBlocker::BlockedUrlError => e clear_session_data @@ -129,7 +128,7 @@ class Import::BulkImportsController < ApplicationController def credentials { url: session[url_key], - access_token: [access_token_key] + access_token: session[access_token_key] } end end diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb index bcbf5938e11..17f937a3dfd 100644 --- a/app/controllers/import/fogbugz_controller.rb +++ b/app/controllers/import/fogbugz_controller.rb @@ -136,11 +136,9 @@ class Import::FogbugzController < Import::BaseController def verify_blocked_uri Gitlab::UrlBlocker.validate!( params[:uri], - **{ - allow_localhost: allow_local_requests?, - allow_local_network: allow_local_requests?, - schemes: %w(http https) - } + allow_localhost: allow_local_requests?, + allow_local_network: allow_local_requests?, + schemes: %w(http https) ) rescue Gitlab::UrlBlocker::BlockedUrlError => e redirect_to new_import_fogbugz_url, alert: _('Specified URL cannot be used: "%{reason}"') % { reason: e.message } diff --git a/app/controllers/import/gitea_controller.rb b/app/controllers/import/gitea_controller.rb index 4785a71b8a1..5a4eef352b8 100644 --- a/app/controllers/import/gitea_controller.rb +++ b/app/controllers/import/gitea_controller.rb @@ -72,11 +72,9 @@ class Import::GiteaController < Import::GithubController def verify_blocked_uri Gitlab::UrlBlocker.validate!( provider_url, - { - allow_localhost: allow_local_requests?, - allow_local_network: allow_local_requests?, - schemes: %w(http https) - } + allow_localhost: allow_local_requests?, + allow_local_network: allow_local_requests?, + schemes: %w(http https) ) rescue Gitlab::UrlBlocker::BlockedUrlError => e session[access_token_key] = nil diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb index 8ac93aeb9c0..beb3e92b5ea 100644 --- a/app/controllers/import/github_controller.rb +++ b/app/controllers/import/github_controller.rb @@ -17,6 +17,8 @@ class Import::GithubController < Import::BaseController rescue_from Octokit::TooManyRequests, with: :provider_rate_limit rescue_from Gitlab::GithubImport::RateLimitError, with: :rate_limit_threshold_exceeded + PAGE_LENGTH = 25 + def new if !ci_cd_only? && github_import_configured? && logged_in_with_provider? go_to_provider_for_permissions @@ -115,19 +117,16 @@ class Import::GithubController < Import::BaseController def client_repos @client_repos ||= if Feature.enabled?(:remove_legacy_github_client) - concatenated_repos + if sanitized_filter_param + client.search_repos_by_name(sanitized_filter_param, pagination_options)[:items] + else + client.octokit.repos(nil, pagination_options) + end else filtered(client.repos) end end - def concatenated_repos - return [] unless client.respond_to?(:each_page) - return client.each_page(:repos).flat_map(&:objects) unless sanitized_filter_param - - client.search_repos_by_name(sanitized_filter_param).flat_map(&:objects).flat_map(&:items) - end - def sanitized_filter_param super @@ -257,6 +256,13 @@ class Import::GithubController < Import::BaseController def rate_limit_threshold_exceeded head :too_many_requests end + + def pagination_options + { + page: [1, params[:page].to_i].max, + per_page: PAGE_LENGTH + } + end end Import::GithubController.prepend_if_ee('EE::Import::GithubController') diff --git a/app/controllers/import/gitlab_groups_controller.rb b/app/controllers/import/gitlab_groups_controller.rb index d8118477a80..f68b76a7b36 100644 --- a/app/controllers/import/gitlab_groups_controller.rb +++ b/app/controllers/import/gitlab_groups_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Import::GitlabGroupsController < ApplicationController - include WorkhorseImportExportUpload + include WorkhorseAuthorization before_action :ensure_group_import_enabled before_action :import_rate_limit, only: %i[create] @@ -64,4 +64,12 @@ class Import::GitlabGroupsController < ApplicationController redirect_to new_group_path end end + + def uploader_class + ImportExportUploader + end + + def maximum_size + Gitlab::CurrentSettings.max_import_size.megabytes + end end diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index 39d053347f0..0e6b0af6baf 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Import::GitlabProjectsController < Import::BaseController - include WorkhorseImportExportUpload + include WorkhorseAuthorization before_action :whitelist_query_limiting, only: [:create] before_action :verify_gitlab_project_import_enabled @@ -45,4 +45,12 @@ class Import::GitlabProjectsController < Import::BaseController def whitelist_query_limiting Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42437') end + + def uploader_class + ImportExportUploader + end + + def maximum_size + Gitlab::CurrentSettings.max_import_size.megabytes + end end diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb deleted file mode 100644 index 03bde0345e3..00000000000 --- a/app/controllers/import/google_code_controller.rb +++ /dev/null @@ -1,123 +0,0 @@ -# frozen_string_literal: true - -class Import::GoogleCodeController < Import::BaseController - before_action :verify_google_code_import_enabled - before_action :user_map, only: [:new_user_map, :create_user_map] - - def new - end - - def callback - dump_file = params[:dump_file] - - unless dump_file.respond_to?(:read) - return redirect_back_or_default(options: { alert: _("You need to upload a Google Takeout archive.") }) - end - - begin - dump = Gitlab::Json.parse(dump_file.read) - rescue - return redirect_back_or_default(options: { alert: _("The uploaded file is not a valid Google Takeout archive.") }) - end - - client = Gitlab::GoogleCodeImport::Client.new(dump) - unless client.valid? - return redirect_back_or_default(options: { alert: _("The uploaded file is not a valid Google Takeout archive.") }) - end - - session[:google_code_dump] = dump - - if params[:create_user_map] == "1" - redirect_to new_user_map_import_google_code_path - else - redirect_to status_import_google_code_path - end - end - - def new_user_map - end - - def create_user_map - user_map_json = params[:user_map] - user_map_json = "{}" if user_map_json.blank? - - begin - user_map = Gitlab::Json.parse(user_map_json) - rescue - flash.now[:alert] = _("The entered user map is not a valid JSON user map.") - - return render "new_user_map" - end - - unless user_map.is_a?(Hash) && user_map.all? { |k, v| k.is_a?(String) && v.is_a?(String) } - flash.now[:alert] = _("The entered user map is not a valid JSON user map.") - - return render "new_user_map" - end - - # This is the default, so let's not save it into the database. - user_map.reject! do |key, value| - value == Gitlab::GoogleCodeImport::Client.mask_email(key) - end - - session[:google_code_user_map] = user_map - - flash[:notice] = _("The user map has been saved. Continue by selecting the projects you want to import.") - - redirect_to status_import_google_code_path - end - - # rubocop: disable CodeReuse/ActiveRecord - def status - unless client.valid? - return redirect_to new_import_google_code_path - end - - @repos = client.repos - @incompatible_repos = client.incompatible_repos - - @already_added_projects = find_already_added_projects('google_code') - already_added_projects_names = @already_added_projects.pluck(:import_source) - - @repos.reject! { |repo| already_added_projects_names.include? repo.name } - end - # rubocop: enable CodeReuse/ActiveRecord - - def jobs - render json: find_jobs('google_code') - end - - def create - repo = client.repo(params[:repo_id]) - user_map = session[:google_code_user_map] - - project = Gitlab::GoogleCodeImport::ProjectCreator.new(repo, current_user.namespace, current_user, user_map).execute - - if project.persisted? - render json: ProjectSerializer.new.represent(project) - else - render json: { errors: project_save_error(project) }, status: :unprocessable_entity - end - end - - private - - def client - @client ||= Gitlab::GoogleCodeImport::Client.new(session[:google_code_dump]) - end - - def verify_google_code_import_enabled - render_404 unless google_code_import_enabled? - end - - def user_map - @user_map ||= begin - user_map = client.user_map - - stored_user_map = session[:google_code_user_map] - user_map.update(stored_user_map) if stored_user_map - - Hash[user_map.sort] - end - end -end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 26fc1c11f6d..ad92645c23e 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -20,7 +20,6 @@ class InvitesController < ApplicationController def accept if member.accept_invite!(current_user) - track_invitation_reminders_experiment('accepted') redirect_to invite_details[:path], notice: _("You have been granted %{member_human_access} access to %{title} %{name}.") % { member_human_access: member.human_access, title: invite_details[:title], name: invite_details[:name] } else @@ -107,17 +106,4 @@ class InvitesController < ApplicationController } end end - - def track_invitation_reminders_experiment(action) - return unless Gitlab::Experimentation.enabled?(:invitation_reminders) - - property = Gitlab::Experimentation.enabled_for_attribute?(:invitation_reminders, member.invite_email) ? 'experimental_group' : 'control_group' - - Gitlab::Tracking.event( - Gitlab::Experimentation.experiment(:invitation_reminders).tracking_category, - action, - property: property, - label: Digest::MD5.hexdigest(member.to_global_id.to_s) - ) - end end diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb index bf53c61601b..d1ba8a98c64 100644 --- a/app/controllers/jira_connect/app_descriptor_controller.rb +++ b/app/controllers/jira_connect/app_descriptor_controller.rb @@ -27,29 +27,9 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController authentication: { type: 'jwt' }, + modules: modules, scopes: %w(READ WRITE DELETE), apiVersion: 1, - modules: { - jiraDevelopmentTool: { - key: 'gitlab-development-tool', - application: { - value: 'GitLab' - }, - name: { - value: 'GitLab' - }, - url: 'https://gitlab.com', - logoUrl: view_context.image_url('gitlab_logo.png'), - capabilities: %w(branch commit pull_request) - }, - postInstallPage: { - key: 'gitlab-configuration', - name: { - value: 'GitLab Configuration' - }, - url: relative_to_base_path(jira_connect_subscriptions_path) - } - }, apiMigrations: { gdpr: true } @@ -58,6 +38,55 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController private + HOME_URL = 'https://gitlab.com' + DOC_URL = 'https://docs.gitlab.com/ee/user/project/integrations/jira.html#gitlab-jira-integration' + + def modules + modules = { + jiraDevelopmentTool: { + key: 'gitlab-development-tool', + application: { + value: 'GitLab' + }, + name: { + value: 'GitLab' + }, + url: HOME_URL, + logoUrl: logo_url, + capabilities: %w(branch commit pull_request) + }, + postInstallPage: { + key: 'gitlab-configuration', + name: { + value: 'GitLab Configuration' + }, + url: relative_to_base_path(jira_connect_subscriptions_path) + } + } + + modules.merge!(build_information_module) + + modules + end + + def logo_url + view_context.image_url('gitlab_logo.png') + end + + # See: https://developer.atlassian.com/cloud/jira/software/modules/build/ + def build_information_module + { + jiraBuildInfoProvider: { + homeUrl: HOME_URL, + logoUrl: logo_url, + documentationUrl: DOC_URL, + actions: {}, + name: { value: "GitLab CI" }, + key: "gitlab-ci" + } + } + end + def relative_to_base_path(full_path) full_path.sub(/^#{jira_connect_base_path}/, '') end diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index 5199bb25c8c..85ee2204324 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -11,7 +11,8 @@ class JwtController < ApplicationController feature_category :authentication_and_authorization SERVICES = { - Auth::ContainerRegistryAuthenticationService::AUDIENCE => Auth::ContainerRegistryAuthenticationService + ::Auth::ContainerRegistryAuthenticationService::AUDIENCE => ::Auth::ContainerRegistryAuthenticationService, + ::Auth::DependencyProxyAuthenticationService::AUDIENCE => ::Auth::DependencyProxyAuthenticationService }.freeze def auth diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb index 1e6340f285e..3a189c900ac 100644 --- a/app/controllers/profiles/keys_controller.rb +++ b/app/controllers/profiles/keys_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Profiles::KeysController < Profiles::ApplicationController - skip_before_action :authenticate_user!, only: [:get_keys] - feature_category :users def index @@ -35,25 +33,6 @@ class Profiles::KeysController < Profiles::ApplicationController end end - # Get all keys of a user(params[:username]) in a text format - # Helpful for sysadmins to put in respective servers - def get_keys - if params[:username].present? - begin - user = UserFinder.new(params[:username]).find_by_username - if user.present? - render plain: user.all_ssh_keys.join("\n") - else - render_404 - end - rescue => e - render html: e.message - end - else - render_404 - end - end - private def key_params diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb index 8ecf8fadefd..ebe867d915d 100644 --- a/app/controllers/projects/alert_management_controller.rb +++ b/app/controllers/projects/alert_management_controller.rb @@ -3,7 +3,7 @@ class Projects::AlertManagementController < Projects::ApplicationController before_action :authorize_read_alert_management_alert! - feature_category :alert_management + feature_category :incident_management def index end diff --git a/app/controllers/projects/alerting/notifications_controller.rb b/app/controllers/projects/alerting/notifications_controller.rb index a3f4d784f25..db5d91308db 100644 --- a/app/controllers/projects/alerting/notifications_controller.rb +++ b/app/controllers/projects/alerting/notifications_controller.rb @@ -10,7 +10,7 @@ module Projects prepend_before_action :repository, :project_without_auth - feature_category :alert_management + feature_category :incident_management def create token = extract_alert_manager_token(request) @@ -31,7 +31,7 @@ module Projects end def notify_service - notify_service_class.new(project, current_user, notification_payload) + notify_service_class.new(project, notification_payload) end def notify_service_class diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 02e941db636..8f16650a6f2 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -32,11 +32,6 @@ class Projects::BlobController < Projects::ApplicationController before_action :validate_diff_params, only: :diff before_action :set_last_commit_sha, only: [:edit, :update] - before_action only: :show do - push_frontend_feature_flag(:suggest_pipeline, default_enabled: true) - push_frontend_feature_flag(:gitlab_ci_yml_preview, @project, default_enabled: false) - end - track_redis_hll_event :create, :update, name: 'g_edit_by_sfe', feature: :track_editor_edit_actions, feature_default_enabled: true feature_category :source_code_management diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index fe4502a0e06..51c9bf3699a 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -8,7 +8,7 @@ class Projects::BoardsController < Projects::ApplicationController before_action :authorize_read_board!, only: [:index, :show] before_action :assign_endpoint_vars before_action do - push_frontend_feature_flag(:boards_with_swimlanes, project, default_enabled: true) + push_frontend_feature_flag(:add_issues_button) end feature_category :boards diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index cf1efda5d13..a753d5705aa 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -18,8 +18,8 @@ class Projects::BranchesController < Projects::ApplicationController def index respond_to do |format| format.html do - @sort = params[:sort].presence || sort_value_recently_updated @mode = params[:state].presence || 'overview' + @sort = sort_value_for_mode @overview_max_branches = 5 # Fetch branches for the specified mode @@ -42,10 +42,6 @@ class Projects::BranchesController < Projects::ApplicationController end end - def recent - @branches = @repository.recent_branches - end - def diverging_commit_counts respond_to do |format| format.json do @@ -129,6 +125,12 @@ class Projects::BranchesController < Projects::ApplicationController private + def sort_value_for_mode + return params[:sort] if params[:sort].present? + + 'stale' == @mode ? 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 @@ -173,19 +175,32 @@ class Projects::BranchesController < Projects::ApplicationController end def fetch_branches_by_mode - if @mode == 'overview' - # overview mode - @active_branches, @stale_branches = BranchesFinder.new(@repository, sort: sort_value_recently_updated).execute.partition(&:active?) - # Here we get one more branch to indicate if there are more data we're not showing - @active_branches = @active_branches.first(@overview_max_branches + 1) - @stale_branches = @stale_branches.first(@overview_max_branches + 1) - @branches = @active_branches + @stale_branches + return fetch_branches_for_overview if @mode == 'overview' + + # active/stale/all view mode + @branches = BranchesFinder.new(@repository, params.merge(sort: @sort)).execute + @branches = @branches.select { |b| b.state.to_s == @mode } if %w[active stale].include?(@mode) + @branches = Kaminari.paginate_array(@branches).page(params[:page]) + end + + def fetch_branches_for_overview + # Here we get one more branch to indicate if there are more data we're not showing + limit = @overview_max_branches + 1 + + if Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: true) + @active_branches = + BranchesFinder.new(@repository, { per_page: limit, sort: sort_value_recently_updated }) + .execute(gitaly_pagination: true).select(&:active?) + @stale_branches = + BranchesFinder.new(@repository, { per_page: limit, sort: sort_value_oldest_updated }) + .execute(gitaly_pagination: true).select(&:stale?) else - # active/stale/all view mode - @branches = BranchesFinder.new(@repository, params.merge(sort: @sort)).execute - @branches = @branches.select { |b| b.state.to_s == @mode } if %w[active stale].include?(@mode) - @branches = Kaminari.paginate_array(@branches).page(params[:page]) + @active_branches, @stale_branches = BranchesFinder.new(@repository, sort: sort_value_recently_updated).execute.partition(&:active?) + @active_branches = @active_branches.first(limit) + @stale_branches = @stale_branches.first(limit) end + + @branches = @active_branches + @stale_branches end def confidential_issue_project diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb index c2428270fa6..cc391868df0 100644 --- a/app/controllers/projects/ci/pipeline_editor_controller.rb +++ b/app/controllers/projects/ci/pipeline_editor_controller.rb @@ -2,6 +2,9 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController before_action :check_can_collaborate! + before_action do + push_frontend_feature_flag(:ci_config_visualization_tab, @project, default_enabled: false) + end feature_category :pipeline_authoring diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb index 1ddc9d567e0..ab1cf63c885 100644 --- a/app/controllers/projects/cycle_analytics_controller.rb +++ b/app/controllers/projects/cycle_analytics_controller.rb @@ -17,8 +17,6 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController def show @cycle_analytics = ::CycleAnalytics::ProjectLevel.new(@project, options: options(cycle_analytics_project_params)) - @cycle_analytics_no_data = @cycle_analytics.no_stats? - respond_to do |format| format.html do Gitlab::UsageDataCounters::CycleAnalyticsCounter.count(:views) diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb index 9142f769b28..da9dcd1c09c 100644 --- a/app/controllers/projects/feature_flags_controller.rb +++ b/app/controllers/projects/feature_flags_controller.rb @@ -14,7 +14,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController before_action do push_frontend_feature_flag(:feature_flag_permissions) - push_frontend_feature_flag(:feature_flags_new_version, project, default_enabled: true) push_frontend_feature_flag(:feature_flags_legacy_read_only, project, default_enabled: true) push_frontend_feature_flag(:feature_flags_legacy_read_only_override, project) end @@ -101,15 +100,7 @@ class Projects::FeatureFlagsController < Projects::ApplicationController protected def feature_flag - @feature_flag ||= @noteable = if new_version_feature_flags_enabled? - project.operations_feature_flags.find_by_iid!(params[:iid]) - else - project.operations_feature_flags.legacy_flag.find_by_iid!(params[:iid]) - end - end - - def new_version_feature_flags_enabled? - ::Feature.enabled?(:feature_flags_new_version, project, default_enabled: true) + @feature_flag ||= @noteable = project.operations_feature_flags.find_by_iid!(params[:iid]) end def ensure_legacy_flags_writable! diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 3a1b4f380a2..3a0e40f9745 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -44,14 +44,14 @@ class Projects::IssuesController < Projects::ApplicationController push_frontend_feature_flag(:vue_issuable_sidebar, project.group) push_frontend_feature_flag(:tribute_autocomplete, @project) push_frontend_feature_flag(:vue_issuables_list, project) - push_frontend_feature_flag(:vue_issue_header, @project, default_enabled: true) + push_frontend_feature_flag(:usage_data_design_action, project, default_enabled: true) end before_action only: :show do real_time_feature_flag = :real_time_issue_sidebar real_time_enabled = Gitlab::ActionCable::Config.in_app? || Feature.enabled?(real_time_feature_flag, @project) - push_to_gon_features(real_time_feature_flag, real_time_enabled) + push_to_gon_attributes(:features, real_time_feature_flag, real_time_enabled) record_experiment_user(:invite_members_version_a) record_experiment_user(:invite_members_version_b) @@ -59,6 +59,10 @@ class Projects::IssuesController < Projects::ApplicationController around_action :allow_gitaly_ref_name_caching, only: [:discussions] + before_action :run_null_hypothesis_experiment, + only: [:index, :new, :create], + if: -> { Feature.enabled?(:gitlab_experiments) } + respond_to :html alias_method :designs, :show @@ -74,6 +78,8 @@ class Projects::IssuesController < Projects::ApplicationController feature_category :service_desk, [:service_desk] feature_category :importers, [:import_csv, :export_csv] + attr_accessor :vulnerability_id + def index @issues = @issuables @@ -125,6 +131,8 @@ class Projects::IssuesController < Projects::ApplicationController service = ::Issues::CreateService.new(project, current_user, create_params) @issue = service.execute + create_vulnerability_issue_link(issue) + if service.discussions_to_resolve.count(&:resolved?) > 0 flash[:notice] = if service.discussion_to_resolve_id _("Resolved 1 discussion.") @@ -385,6 +393,17 @@ class Projects::IssuesController < Projects::ApplicationController def service_desk? action_name == 'service_desk' end + + def run_null_hypothesis_experiment + experiment(:null_hypothesis, project: project) do |e| + e.use { } # define the control + e.try { } # define the candidate + e.track(action_name) # track the action so we can build a funnel + end + end + + # Overridden in EE + def create_vulnerability_issue_link(issue); end end Projects::IssuesController.prepend_if_ee('EE::Projects::IssuesController') diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index 07e38c80291..900ebc61856 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -6,6 +6,7 @@ class Projects::JobsController < Projects::ApplicationController before_action :find_job_as_build, except: [:index, :play] before_action :find_job_as_processable, only: [:play] + before_action :authorize_read_build_trace!, only: [:trace, :raw] before_action :authorize_read_build! before_action :authorize_update_build!, except: [:index, :show, :status, :raw, :trace, :erase] @@ -14,8 +15,8 @@ class Projects::JobsController < Projects::ApplicationController before_action :verify_api_request!, only: :terminal_websocket_authorize before_action :authorize_create_proxy_build!, only: :proxy_websocket_authorize before_action :verify_proxy_request!, only: :proxy_websocket_authorize - before_action do - push_frontend_feature_flag(:ci_job_line_links, @project) + before_action only: :index do + frontend_experimentation_tracking_data(:jobs_empty_state, 'click_button') end layout 'project' @@ -157,6 +158,18 @@ class Projects::JobsController < Projects::ApplicationController private + def authorize_read_build_trace! + return if can?(current_user, :read_build_trace, @build) + + msg = _( + "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. " \ + "If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher." + ) + return access_denied!(msg) if @build.debug_mode? + + access_denied!(_('The current user is not authorized to access the job log.')) + end + def authorize_update_build! return access_denied! unless can?(current_user, :update_build, @build) end @@ -204,11 +217,7 @@ class Projects::JobsController < Projects::ApplicationController end def find_job_as_processable - if ::Gitlab::Ci::Features.manual_bridges_enabled?(project) - @build = project.processables.find(params[:id]) - else - find_job_as_build - end + @build = project.processables.find(params[:id]) end def build_path(build) diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index 3e077c1af37..7d3e7759081 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -11,6 +11,12 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap before_action :apply_diff_view_cookie!, only: [:diffs, :diff_for_path] before_action :build_merge_request, except: [:create] + before_action do + push_frontend_feature_flag(:merge_request_reviewers, @project, default_enabled: true) + push_frontend_feature_flag(:mr_collapsed_approval_rules, @project) + push_frontend_feature_flag(:reviewer_approval_rules, @project) + end + def new define_new_vars end diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 7fbeac12644..da19ddf6105 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -69,7 +69,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic } options = additional_attributes.merge( - diff_view: unified_diff_lines_view_type(@merge_request.project), + diff_view: "inline", merge_ref_head_diff: render_merge_ref_head_diff? ) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index f2b41294a85..382fbfaac25 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -21,13 +21,13 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo :exposed_artifacts, :coverage_reports, :terraform_reports, - :accessibility_reports + :accessibility_reports, + :codequality_reports ] 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: [:show] do - push_frontend_feature_flag(:suggest_pipeline, default_enabled: true) push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true) push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true) push_frontend_feature_flag(:multiline_comments, @project, default_enabled: true) @@ -36,13 +36,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true) push_frontend_feature_flag(:hide_jump_to_next_unresolved_in_threads, default_enabled: true) push_frontend_feature_flag(:merge_request_widget_graphql, @project) - push_frontend_feature_flag(:unified_diff_lines, @project, default_enabled: true) push_frontend_feature_flag(:unified_diff_components, @project) - push_frontend_feature_flag(:highlight_current_diff_row, @project) push_frontend_feature_flag(:default_merge_ref_for_diffs, @project) push_frontend_feature_flag(:core_security_mr_widget, @project, default_enabled: true) + push_frontend_feature_flag(:core_security_mr_widget_counts, @project) + push_frontend_feature_flag(:core_security_mr_widget_downloads, @project, default_enabled: true) push_frontend_feature_flag(:remove_resolve_note, @project, default_enabled: true) push_frontend_feature_flag(:test_failure_history, @project) + push_frontend_feature_flag(:diffs_gradual_load, @project, default_enabled: true) record_experiment_user(:invite_members_version_a) record_experiment_user(:invite_members_version_b) @@ -50,6 +51,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action do push_frontend_feature_flag(:vue_issuable_sidebar, @project.group) + push_frontend_feature_flag(:merge_request_reviewers, @project, default_enabled: true) + push_frontend_feature_flag(:mr_collapsed_approval_rules, @project) + push_frontend_feature_flag(:reviewer_approval_rules, @project) end around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions] @@ -98,9 +102,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @noteable = @merge_request @commits_count = @merge_request.commits_count + @merge_request.context_commits_count @issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar') - @current_user_data = UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestUserEntity).to_json + @current_user_data = UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestCurrentUserEntity).to_json @show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs - @file_by_file_default = Feature.enabled?(:view_diffs_file_by_file, default_enabled: true) && current_user&.view_diffs_file_by_file + @file_by_file_default = current_user&.view_diffs_file_by_file @coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports? @endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request) @@ -193,6 +197,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo end end + def codequality_reports + reports_response(@merge_request.compare_codequality_reports) + end + def terraform_reports reports_response(@merge_request.find_terraform_reports) end @@ -481,7 +489,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo def endpoint_metadata_url(project, merge_request) params = request.query_parameters - params[:view] = unified_diff_lines_view_type(project) + params[:view] = "inline" if Feature.enabled?(:default_merge_ref_for_diffs, project) params = params.merge(diff_head: true) diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 31189c888b7..dcd3c49441e 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -6,9 +6,6 @@ class Projects::MilestonesController < Projects::ApplicationController before_action :check_issuables_available! before_action :milestone, only: [:edit, :update, :destroy, :show, :issues, :merge_requests, :participants, :labels, :promote] - before_action do - push_frontend_feature_flag(:burnup_charts, @project, default_enabled: true) - end # Allow read any milestone before_action :authorize_read_milestone! diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index f71a92ee874..74513da8675 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -17,7 +17,8 @@ class Projects::PipelinesController < Projects::ApplicationController push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: true) push_frontend_feature_flag(:graphql_pipeline_header, project, type: :development, default_enabled: false) push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: false) - push_frontend_feature_flag(:new_pipeline_form_prefilled_vars, project, type: :development) + push_frontend_feature_flag(:graphql_pipeline_analytics, project, type: :development) + push_frontend_feature_flag(:new_pipeline_form_prefilled_vars, project, type: :development, default_enabled: true) end before_action :ensure_pipeline, only: [:show] @@ -39,7 +40,7 @@ class Projects::PipelinesController < Projects::ApplicationController .new(project, current_user, index_params) .execute .page(params[:page]) - .per(30) + .per(20) @pipelines_count = limited_pipelines_count(project) @@ -185,12 +186,15 @@ class Projects::PipelinesController < Projects::ApplicationController def charts @charts = {} + @counts = {} + + return if Feature.enabled?(:graphql_pipeline_analytics) + @charts[:week] = Gitlab::Ci::Charts::WeekChart.new(project) @charts[:month] = Gitlab::Ci::Charts::MonthChart.new(project) @charts[:year] = Gitlab::Ci::Charts::YearChart.new(project) @charts[:pipeline_times] = Gitlab::Ci::Charts::PipelineTime.new(project) - @counts = {} @counts[:total] = @project.all_pipelines.count(:all) @counts[:success] = @project.all_pipelines.success.count(:all) @counts[:failed] = @project.all_pipelines.failed.count(:all) @@ -214,7 +218,9 @@ class Projects::PipelinesController < Projects::ApplicationController def config_variables respond_to do |format| format.json do - render json: Ci::ListConfigVariablesService.new(@project, current_user).execute(params[:sha]) + result = Ci::ListConfigVariablesService.new(@project, current_user).execute(params[:sha]) + + result.nil? ? head(:no_content) : render(json: result) end end end diff --git a/app/controllers/projects/prometheus/alerts_controller.rb b/app/controllers/projects/prometheus/alerts_controller.rb index 2892542e63c..19c908026cf 100644 --- a/app/controllers/projects/prometheus/alerts_controller.rb +++ b/app/controllers/projects/prometheus/alerts_controller.rb @@ -16,7 +16,7 @@ module Projects before_action :authorize_read_prometheus_alerts!, except: [:notify] before_action :alert, only: [:update, :show, :destroy, :metrics_dashboard] - feature_category :alert_management + feature_category :incident_management def index render json: serialize_as_json(alerts) @@ -73,7 +73,7 @@ module Projects def notify_service Projects::Prometheus::Alerts::NotifyService - .new(project, current_user, params.permit!) + .new(project, params.permit!) end def create_service diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index d8ba7e4f235..8be7af3e2c5 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -10,29 +10,31 @@ class Projects::RawController < Projects::ApplicationController prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:blob) } + before_action :set_ref_and_path before_action :require_non_empty_project before_action :authorize_download_code! before_action :show_rate_limit, only: [:show], unless: :external_storage_request? - before_action :assign_ref_vars before_action :redirect_to_external_storage, only: :show, if: :static_objects_external_storage_enabled? feature_category :source_code_management def show - @blob = @repository.blob_at(@commit.id, @path) + @blob = @repository.blob_at(@ref, @path) send_blob(@repository, @blob, inline: (params[:inline] != 'false'), allow_caching: @project.public?) end private - def show_rate_limit + def set_ref_and_path # This bypasses assign_ref_vars to avoid a Gitaly FindCommit lookup. - # When rate limiting, we really don't care if a different commit is - # being requested. - _ref, path = extract_ref(get_id) + # We don't need to find the commit to either rate limit or send the + # blob. + @ref, @path = extract_ref(get_id) + end - if rate_limiter.throttled?(:show_raw_controller, scope: [@project, path], threshold: raw_blob_request_limit) + def show_rate_limit + if rate_limiter.throttled?(:show_raw_controller, scope: [@project, @path], threshold: raw_blob_request_limit) rate_limiter.log_request(request, :raw_blob_request_limit, current_user) render plain: _('You cannot access the raw file. Please wait a minute.'), status: :too_many_requests diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index 24fa0894a9c..b7a5a63e642 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -53,12 +53,23 @@ class Projects::RunnersController < Projects::ApplicationController def toggle_shared_runners if !project.shared_runners_enabled && project.group && project.group.shared_runners_setting == 'disabled_and_unoverridable' - return redirect_to project_runners_path(@project), alert: _("Cannot enable shared runners because parent group does not allow it") + + if Feature.enabled?(:vueify_shared_runners_toggle, @project) + render json: { error: _('Cannot enable shared runners because parent group does not allow it') }, status: :unauthorized + else + redirect_to project_runners_path(@project), alert: _('Cannot enable shared runners because parent group does not allow it') + end + + return end project.toggle!(:shared_runners_enabled) - redirect_to project_settings_ci_cd_path(@project, anchor: 'js-runners-settings') + if Feature.enabled?(:vueify_shared_runners_toggle, @project) + render json: {}, status: :ok + else + redirect_to project_settings_ci_cd_path(@project, anchor: 'js-runners-settings') + end end def toggle_group_runners diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index f76278a12a4..31533dfeea0 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -11,6 +11,7 @@ module Projects before_action :define_variables before_action do push_frontend_feature_flag(:ajax_new_deploy_token, @project) + push_frontend_feature_flag(:vueify_shared_runners_toggle, @project) end helper_method :highlight_badge diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index c9386a2edec..f8155b77e60 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -7,7 +7,6 @@ module Projects before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token] before_action do - push_frontend_feature_flag(:http_integrations_list, @project) push_frontend_feature_flag(:multiple_http_integrations_custom_mapping, @project) end diff --git a/app/controllers/projects/static_site_editor_controller.rb b/app/controllers/projects/static_site_editor_controller.rb index 5c3d9b60877..0d9a6f568a1 100644 --- a/app/controllers/projects/static_site_editor_controller.rb +++ b/app/controllers/projects/static_site_editor_controller.rb @@ -19,6 +19,10 @@ class Projects::StaticSiteEditorController < Projects::ApplicationController feature_category :static_site_editor + def index + render_404 + end + def show service_response = ::StaticSiteEditor::ConfigService.new( container: project, diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 8f794512486..d1486f765e4 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -6,7 +6,4 @@ class Projects::WikisController < Projects::ApplicationController alias_method :container, :project feature_category :wiki - - def git_access - end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index c03a820b384..3744517934a 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -19,9 +19,6 @@ class ProjectsController < Projects::ApplicationController before_action :redirect_git_extension, only: [:show] before_action :project, except: [:index, :new, :create, :resolve] before_action :repository, except: [:index, :new, :create, :resolve] - before_action :assign_ref_vars, if: -> { action_name == 'show' && repo_exists? } - before_action :tree, - if: -> { action_name == 'show' && repo_exists? && project_view_files? } before_action :project_export_enabled, only: [:export, :download_export, :remove_export, :generate_new_export] before_action :present_project, only: [:edit] before_action :authorize_download_code!, only: [:refs] @@ -34,15 +31,9 @@ class ProjectsController < Projects::ApplicationController # Project Export Rate Limit before_action :export_rate_limit, only: [:export, :download_export, :generate_new_export] - # Experiments - before_action only: [:new, :create] do - frontend_experimentation_tracking_data(:new_create_project_ui, 'click_tab') - push_frontend_experiment(:new_create_project_ui) - end - before_action only: [:edit] do - push_frontend_feature_flag(:service_desk_custom_address, @project) push_frontend_feature_flag(:approval_suggestions, @project, default_enabled: true) + push_frontend_feature_flag(:allow_editing_commit_messages, @project) end layout :determine_layout @@ -80,8 +71,6 @@ class ProjectsController < Projects::ApplicationController @project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute if @project.saved? - cookies[:issue_board_welcome_hidden] = { path: project_path(@project), value: nil, expires: Time.zone.at(0) } - redirect_to( project_path(@project, custom_import_params), notice: _("Project '%{project_name}' was successfully created.") % { project_name: @project.name } @@ -147,6 +136,8 @@ class ProjectsController < Projects::ApplicationController end def show + @id, @ref, @path = extract_ref_path + if @project.import_in_progress? redirect_to project_import_path(@project, custom_import_params) return @@ -334,7 +325,11 @@ class ProjectsController < Projects::ApplicationController if can?(current_user, :download_code, @project) return render 'projects/no_repo' unless @project.repository_exists? - render 'projects/empty' if @project.empty_repo? + if @project.empty_repo? + record_experiment_user(:invite_members_empty_project_version_a) + + render 'projects/empty' + end else if can?(current_user, :read_wiki, @project) @wiki = @project.wiki @@ -392,6 +387,8 @@ class ProjectsController < Projects::ApplicationController wiki_access_level pages_access_level metrics_dashboard_access_level + analytics_access_level + operations_access_level ] end @@ -435,6 +432,7 @@ class ProjectsController < Projects::ApplicationController project_setting_attributes: %i[ show_default_award_emojis squash_option + allow_editing_commit_messages ] ] + [project_feature_attributes: project_feature_attributes] end diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb index 5b3f78a92ad..4a6fef56ef5 100644 --- a/app/controllers/registrations/welcome_controller.rb +++ b/app/controllers/registrations/welcome_controller.rb @@ -45,7 +45,7 @@ module Registrations end def update_params - params.require(:user).permit(:role, :setup_for_company) + params.require(:user).permit(:role, :other_role, :setup_for_company) end def requires_confirmation?(user) diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 04cb9616cf6..e7872eeac27 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -6,8 +6,6 @@ class RegistrationsController < Devise::RegistrationsController include RecaptchaHelper include InvisibleCaptchaOnSignup - BLOCKED_PENDING_APPROVAL_STATE = 'blocked_pending_approval'.freeze - layout 'devise' prepend_before_action :check_captcha, only: :create @@ -167,12 +165,18 @@ class RegistrationsController < Devise::RegistrationsController end def set_user_state - return unless Gitlab::CurrentSettings.require_admin_approval_after_user_signup + return unless set_blocked_pending_approval? + + resource.state = User::BLOCKED_PENDING_APPROVAL_STATE + end - resource.state = BLOCKED_PENDING_APPROVAL_STATE + def set_blocked_pending_approval? + Gitlab::CurrentSettings.require_admin_approval_after_user_signup end def set_invite_params @invite_email = ActionController::Base.helpers.sanitize(params[:invite_email]) end end + +RegistrationsController.prepend_if_ee('EE::RegistrationsController') diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb index ec854bd0dde..a5b81054ee4 100644 --- a/app/controllers/repositories/git_http_client_controller.rb +++ b/app/controllers/repositories/git_http_client_controller.rb @@ -87,8 +87,12 @@ module Repositories @project end + def repository_path + @repository_path ||= params[:repository_path] + end + def parse_repo_path - @container, @project, @repo_type, @redirected_path = Gitlab::RepoPath.parse("#{params[:namespace_id]}/#{params[:repository_id]}") + @container, @project, @repo_type, @redirected_path = Gitlab::RepoPath.parse(repository_path) end def render_missing_personal_access_token diff --git a/app/controllers/repositories/git_http_controller.rb b/app/controllers/repositories/git_http_controller.rb index aa6609bef2a..3cf0a23b7f6 100644 --- a/app/controllers/repositories/git_http_controller.rb +++ b/app/controllers/repositories/git_http_controller.rb @@ -80,6 +80,8 @@ module Repositories return if Gitlab::Database.read_only? return unless repo_type.project? + OnboardingProgressService.new(project.namespace).execute(action: :git_read) + if Feature.enabled?(:project_statistics_sync, project, default_enabled: true) Projects::FetchStatisticsIncrementService.new(project).execute else @@ -90,7 +92,6 @@ module Repositories def access @access ||= access_klass.new(access_actor, container, 'http', authentication_abilities: authentication_abilities, - namespace_path: params[:namespace_id], repository_path: repository_path, redirected_path: redirected_path, auth_result_type: auth_result_type) @@ -113,10 +114,6 @@ module Repositories @access_klass ||= repo_type.access_checker_class end - def repository_path - @repository_path ||= params[:repository_id].sub(/\.git$/, '') - end - def log_user_activity Users::ActivityService.new(user).execute end diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb index 96185608c09..248323a0bb5 100644 --- a/app/controllers/repositories/lfs_api_controller.rb +++ b/app/controllers/repositories/lfs_api_controller.rb @@ -92,16 +92,26 @@ module Repositories { upload: { href: "#{project.http_url_to_repo}/gitlab-lfs/objects/#{object[:oid]}/#{object[:size]}", - header: { - Authorization: authorization_header, - # git-lfs v2.5.0 sets the Content-Type based on the uploaded file. This - # ensures that Workhorse can intercept the request. - 'Content-Type': LFS_TRANSFER_CONTENT_TYPE - }.compact + header: upload_headers } } end + def upload_headers + headers = { + Authorization: authorization_header, + # git-lfs v2.5.0 sets the Content-Type based on the uploaded file. This + # ensures that Workhorse can intercept the request. + 'Content-Type': LFS_TRANSFER_CONTENT_TYPE + } + + if Feature.enabled?(:lfs_chunked_encoding, project, default_enabled: true) + headers['Transfer-Encoding'] = 'chunked' + end + + headers + end + def lfs_check_batch_operation! if batch_operation_disallowed? render( diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index c92b3457640..196b1887ca7 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -3,16 +3,8 @@ class SearchController < ApplicationController include ControllerWithCrossProjectAccessCheck include SearchHelper - include RendersCommits include RedisTracking - SCOPE_PRELOAD_METHOD = { - projects: :with_web_entity_associations, - issues: :with_web_entity_associations, - merge_requests: :with_web_entity_associations, - epics: :with_web_entity_associations - }.freeze - track_redis_hll_event :show, name: 'i_search_total', feature: :search_track_unique_users, feature_default_enabled: true around_action :allow_gitaly_ref_name_caching @@ -41,14 +33,12 @@ class SearchController < ApplicationController @search_term = params[:search] @sort = params[:sort] || default_sort - @scope = search_service.scope - @show_snippets = search_service.show_snippets? - @search_results = search_service.search_results - @search_objects = search_service.search_objects(preload_method) - @search_highlight = search_service.search_highlight - - render_commits if @scope == 'commits' - eager_load_user_status if @scope == 'users' + @search_service = Gitlab::View::Presenter::Factory.new(search_service, current_user: current_user).fabricate! + @scope = @search_service.scope + @show_snippets = @search_service.show_snippets? + @search_results = @search_service.search_results + @search_objects = @search_service.search_objects + @search_highlight = @search_service.search_highlight increment_search_counters end @@ -79,10 +69,6 @@ class SearchController < ApplicationController private - def preload_method - SCOPE_PRELOAD_METHOD[@scope.to_sym] - end - # overridden in EE def default_sort 'created_desc' @@ -102,14 +88,6 @@ class SearchController < ApplicationController true end - def render_commits - @search_objects = prepare_commits_for_rendering(@search_objects) - end - - def eager_load_user_status - @search_objects = @search_objects.eager_load(:status) # rubocop:disable CodeReuse/ActiveRecord - end - def check_single_commit_result? return false if params[:force_search_results] return false unless @project.present? diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index 6692c285335..2c827292928 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -27,6 +27,10 @@ class UploadsController < ApplicationController feature_category :not_owned + def self.model_classes + MODEL_CLASSES + end + def uploader_class PersonalFileUploader end @@ -99,7 +103,7 @@ class UploadsController < ApplicationController end def upload_model_class - MODEL_CLASSES[params[:model]] || raise(UnknownUploadModelError) + self.class.model_classes[params[:model]] || raise(UnknownUploadModelError) end def upload_model_class_has_mounts? @@ -112,3 +116,5 @@ class UploadsController < ApplicationController upload_model_class.uploader_options.has_key?(upload_mount) end end + +UploadsController.prepend_if_ee('EE::UploadsController') diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 05573255066..46245286820 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -33,18 +33,36 @@ class UsersController < ApplicationController end format.json do + # In 13.8, this endpoint will be removed: + # https://gitlab.com/gitlab-org/gitlab/-/issues/289972 load_events pager_json("events/_events", @events.count, events: @events) end end end + # Get all keys of a user(params[:username]) in a text format + # Helpful for sysadmins to put in respective servers + def ssh_keys + render plain: user.all_ssh_keys.join("\n") + end + def activity respond_to do |format| format.html { render 'show' } + + format.json do + load_events + pager_json("events/_events", @events.count, events: @events) + end end end + # Get all gpg keys of a user(params[:username]) in a text format + def gpg_keys + render plain: user.gpg_keys.select(&:verified?).map(&:key).join("\n") + end + def groups load_groups diff --git a/app/controllers/whats_new_controller.rb b/app/controllers/whats_new_controller.rb index 384c984089a..cba86c65848 100644 --- a/app/controllers/whats_new_controller.rb +++ b/app/controllers/whats_new_controller.rb @@ -1,18 +1,19 @@ # frozen_string_literal: true class WhatsNewController < ApplicationController - include Gitlab::WhatsNew + include Gitlab::Utils::StrongMemoize skip_before_action :authenticate_user! - before_action :check_feature_flag, :check_valid_page_param, :set_pagination_headers + before_action :check_feature_flag + before_action :check_valid_page_param, :set_pagination_headers, unless: -> { has_version_param? } feature_category :navigation def index respond_to do |format| format.js do - render json: whats_new_release_items(page: current_page) + render json: highlight_items end end end @@ -27,18 +28,29 @@ class WhatsNewController < ApplicationController render_404 if current_page < 1 end - def set_pagination_headers - response.set_header('X-Next-Page', next_page) - end - def current_page params[:page]&.to_i || 1 end - def next_page - next_page = current_page + 1 - next_index = next_page - 1 + def highlights + strong_memoize(:highlights) do + if has_version_param? + ReleaseHighlight.for_version(version: params[:version]) + else + ReleaseHighlight.paginated(page: current_page) + end + end + end + + def highlight_items + highlights.map {|item| Gitlab::WhatsNew::ItemPresenter.present(item) } + end + + def set_pagination_headers + response.set_header('X-Next-Page', highlights.next_page) + end - next_page if whats_new_file_paths[next_index] + def has_version_param? + params[:version].present? end end |