diff options
60 files changed, 475 insertions, 173 deletions
diff --git a/.rubocop_todo/layout/line_continuation_spacing.yml b/.rubocop_todo/layout/line_continuation_spacing.yml index 248922d7397..64b8bd91872 100644 --- a/.rubocop_todo/layout/line_continuation_spacing.yml +++ b/.rubocop_todo/layout/line_continuation_spacing.yml @@ -110,7 +110,6 @@ Layout/LineContinuationSpacing: - 'ee/spec/services/phone_verification/telesign_client/send_verification_code_service_spec.rb' - 'ee/spec/services/phone_verification/users/send_verification_code_service_spec.rb' - 'ee/spec/services/security/security_orchestration_policies/ci_configuration_service_spec.rb' - - 'ee/spec/services/security/security_orchestration_policies/legacy_ci_configuration_service_spec.rb' - 'ee/spec/views/compliance_management/compliance_framework/_project_settings.html.haml_spec.rb' - 'ee/spec/workers/ee/issuable_export_csv_worker_spec.rb' - 'lib/api/dependency_proxy.rb' diff --git a/app/assets/javascripts/analytics/shared/utils.js b/app/assets/javascripts/analytics/shared/utils.js index 71b719d1ed2..aafbf642766 100644 --- a/app/assets/javascripts/analytics/shared/utils.js +++ b/app/assets/javascripts/analytics/shared/utils.js @@ -1,5 +1,4 @@ import { flatten } from 'lodash'; -import { hideFlash } from '~/flash'; import dateFormat from '~/lib/dateformat'; import { slugify } from '~/lib/utils/text_utility'; import { urlQueryToFilter } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils'; @@ -74,10 +73,8 @@ export const getDataZoomOption = ({ }; export const removeFlash = (type = 'alert') => { - const flashEl = document.querySelector(`.flash-${type}`); - if (flashEl) { - hideFlash(flashEl); - } + // flash-warning don't have dismiss button. + document.querySelector(`.flash-${type} .js-close`)?.click(); }; /** diff --git a/app/assets/javascripts/service_ping_consent.js b/app/assets/javascripts/service_ping_consent.js index f2c3f28cefa..654263ba27b 100644 --- a/app/assets/javascripts/service_ping_consent.js +++ b/app/assets/javascripts/service_ping_consent.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import { createAlert, hideFlash } from './flash'; +import { createAlert } from './flash'; import axios from './lib/utils/axios_utils'; import { parseBoolean } from './lib/utils/common_utils'; import { __ } from './locale'; @@ -18,7 +18,7 @@ export default () => { }; const hideConsentMessage = () => - hideFlash(document.querySelector('.service-ping-consent-message')); + document.querySelector('.service-ping-consent-message .js-close')?.click(); axios .put(url, data) diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue index eb93f42e2f3..3226cd45077 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue @@ -139,9 +139,11 @@ export default { this.fetchingApprovals = false; }) .catch(() => - createAlert({ - message: FETCH_ERROR, - }), + this.alerts.push( + createAlert({ + message: FETCH_ERROR, + }), + ), ); }, methods: { @@ -154,9 +156,11 @@ export default { this.updateApproval( () => this.service.approveMergeRequest(), () => - createAlert({ - message: APPROVE_ERROR, - }), + this.alerts.push( + createAlert({ + message: APPROVE_ERROR, + }), + ), ); }, approveWithAuth(data) { @@ -167,9 +171,11 @@ export default { this.hasApprovalAuthError = true; return; } - createAlert({ - message: APPROVE_ERROR, - }); + this.alerts.push( + createAlert({ + message: APPROVE_ERROR, + }), + ); }, ); }, @@ -177,9 +183,11 @@ export default { this.updateApproval( () => this.service.unapproveMergeRequest(), () => - createAlert({ - message: UNAPPROVE_ERROR, - }), + this.alerts.push( + createAlert({ + message: UNAPPROVE_ERROR, + }), + ), ); }, updateApproval(serviceFn, errFn) { diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js b/app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js index 943011949fd..7d0871f696b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js +++ b/app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js @@ -1,14 +1,15 @@ -import { hideFlash } from '~/flash'; - export default { + data() { + return { + alerts: [], + }; + }, methods: { clearError() { this.$emit('clearError'); this.hasApprovalAuthError = false; - const flashEl = document.querySelector('.flash-alert'); - if (flashEl) { - hideFlash(flashEl); - } + this.alerts.forEach((alert) => alert.dismiss()); + this.alerts = []; }, refreshApprovals() { return this.service.fetchApprovals().then((data) => { diff --git a/app/controllers/admin/application_settings/appearances_controller.rb b/app/controllers/admin/application_settings/appearances_controller.rb index 3cb31ff756f..7950c207f69 100644 --- a/app/controllers/admin/application_settings/appearances_controller.rb +++ b/app/controllers/admin/application_settings/appearances_controller.rb @@ -68,8 +68,10 @@ class Admin::ApplicationSettings::AppearancesController < Admin::ApplicationCont def allowed_appearance_params %i[ title - pwa_short_name description + pwa_name + pwa_short_name + pwa_description logo logo_cache header_logo diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb index 96fe0c9331d..b8d414b9d73 100644 --- a/app/controllers/admin/runners_controller.rb +++ b/app/controllers/admin/runners_controller.rb @@ -29,28 +29,6 @@ class Admin::RunnersController < Admin::ApplicationController end end - def destroy - Ci::Runners::UnregisterRunnerService.new(@runner, current_user).execute - - redirect_to admin_runners_path, status: :found - end - - def resume - if Ci::Runners::UpdateRunnerService.new(@runner).execute(active: true).success? - redirect_to admin_runners_path, notice: _('Runner was successfully updated.') - else - redirect_to admin_runners_path, alert: _('Runner was not updated.') - end - end - - def pause - if Ci::Runners::UpdateRunnerService.new(@runner).execute(active: false).success? - redirect_to admin_runners_path, notice: _('Runner was successfully updated.') - else - redirect_to admin_runners_path, alert: _('Runner was not updated.') - end - end - def tag_list tags = Autocomplete::ActsAsTaggableOn::TagsFinder.new(params: params).execute diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb index 18b055b3f05..859bb0adb4e 100644 --- a/app/controllers/groups/runners_controller.rb +++ b/app/controllers/groups/runners_controller.rb @@ -9,8 +9,6 @@ class Groups::RunnersController < Groups::ApplicationController urgency :low 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) @group_runner_registration_token = @group.runners_token if can?(current_user, :register_group_runners, group) Gitlab::Tracking.event(self.class.name, 'index', user: current_user, namespace: @group) diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb index e9705c45116..f4eea3abd32 100644 --- a/app/controllers/import/bulk_imports_controller.rb +++ b/app/controllers/import/bulk_imports_controller.rb @@ -53,6 +53,7 @@ class Import::BulkImportsController < ApplicationController end def create + return render json: { success: false }, status: :too_many_requests if throttled_request? return render json: { success: false }, status: :unprocessable_entity unless valid_create_params? responses = create_params.map do |entry| @@ -204,4 +205,8 @@ class Import::BulkImportsController < ApplicationController def current_user_bulk_imports current_user.bulk_imports.gitlab end + + def throttled_request? + ::Gitlab::ApplicationRateLimiter.throttled_request?(request, current_user, :bulk_import, scope: current_user) + end end diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb index ab743e27603..70f3b8dbb74 100644 --- a/app/helpers/appearances_helper.rb +++ b/app/helpers/appearances_helper.rb @@ -4,14 +4,26 @@ module AppearancesHelper include MarkupHelper include Gitlab::Utils::StrongMemoize - def appearance_short_name - Appearance.current&.pwa_short_name.presence || _('GitLab') - end - def brand_title current_appearance&.title.presence || default_brand_title end + def appearance_pwa_name + current_appearance&.pwa_name.presence || _('GitLab') + end + + def appearance_pwa_short_name + current_appearance&.pwa_short_name.presence || _('GitLab') + end + + def appearance_pwa_description + current_appearance&.pwa_description.presence || + _("The complete DevOps platform. " \ + "One application with endless possibilities. " \ + "Organizations rely on GitLab’s source code management, " \ + "CI/CD, security, and more to deliver software rapidly.") + end + def default_brand_title # This resides in a separate method so that EE can easily redefine it. _('GitLab Community Edition') diff --git a/app/models/appearance.rb b/app/models/appearance.rb index 3a5e06e9a1c..34cc8d1a64d 100644 --- a/app/models/appearance.rb +++ b/app/models/appearance.rb @@ -6,8 +6,10 @@ class Appearance < ApplicationRecord include WithUploads attribute :title, default: '' - attribute :pwa_short_name, default: '' attribute :description, default: '' + attribute :pwa_name, default: '' + attribute :pwa_short_name, default: '' + attribute :pwa_description, default: '' attribute :new_project_guidelines, default: '' attribute :profile_image_guidelines, default: '' attribute :header_message, default: '' @@ -22,6 +24,18 @@ class Appearance < ApplicationRecord cache_markdown_field :header_message, pipeline: :broadcast_message cache_markdown_field :footer_message, pipeline: :broadcast_message + validates :pwa_name, + length: { maximum: 255, message: N_("is too long (maximum is %{count} characters)") }, + allow_blank: true + + validates :pwa_short_name, + length: { maximum: 255, message: N_("is too long (maximum is %{count} characters)") }, + allow_blank: true + + validates :pwa_description, + length: { maximum: 2048, message: N_("is too long (maximum is %{count} characters)") }, + allow_blank: true + validates :logo, file_size: { maximum: 1.megabyte } validates :pwa_icon, file_size: { maximum: 1.megabyte } validates :header_logo, file_size: { maximum: 1.megabyte } diff --git a/app/views/groups/runners/index.html.haml b/app/views/groups/runners/index.html.haml index 9ea83397348..819e77a8698 100644 --- a/app/views/groups/runners/index.html.haml +++ b/app/views/groups/runners/index.html.haml @@ -1,3 +1,3 @@ - page_title s_('Runners|Runners') -#js-group-runners{ data: group_runners_data_attributes(@group).merge({ group_runners_limited_count: @group_runners_limited_count, registration_token: @group_runner_registration_token }) } +#js-group-runners{ data: group_runners_data_attributes(@group).merge({registration_token: @group_runner_registration_token }) } diff --git a/app/views/pwa/manifest.json.erb b/app/views/pwa/manifest.json.erb index 9abb759389d..501660bba57 100644 --- a/app/views/pwa/manifest.json.erb +++ b/app/views/pwa/manifest.json.erb @@ -1,7 +1,7 @@ { - "name": "<%= Appearance.current&.title.presence || _('GitLab') %>", - "short_name": "<%= appearance_short_name %>", - "description": "<%= Appearance.current&.description.presence || _("The complete DevOps platform. One application with endless possibilities. Organizations rely on GitLab’s source code management, CI/CD, security, and more to deliver software rapidly.") %>", + "name": "<%= appearance_pwa_name %>", + "short_name": "<%= appearance_pwa_short_name %>", + "description": "<%= appearance_pwa_description %>", "start_url": "<%= explore_projects_path %>", "scope": "<%= root_path %>", "display": "browser", diff --git a/db/migrate/20221228072549_add_pwa_attributes_to_appearances.rb b/db/migrate/20221228072549_add_pwa_attributes_to_appearances.rb new file mode 100644 index 00000000000..4c800d3305c --- /dev/null +++ b/db/migrate/20221228072549_add_pwa_attributes_to_appearances.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddPwaAttributesToAppearances < Gitlab::Database::Migration[2.1] + # rubocop:disable Migration/AddLimitToTextColumns + def up + add_column :appearances, :pwa_name, :text + add_column :appearances, :pwa_description, :text + end + # rubocop:enable Migration/AddLimitToTextColumns + + def down + remove_column :appearances, :pwa_name + remove_column :appearances, :pwa_description + end +end diff --git a/db/migrate/20221228073206_add_text_limit_to_pwa_attributes.rb b/db/migrate/20221228073206_add_text_limit_to_pwa_attributes.rb new file mode 100644 index 00000000000..0f3bf66dfa8 --- /dev/null +++ b/db/migrate/20221228073206_add_text_limit_to_pwa_attributes.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddTextLimitToPwaAttributes < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + def up + add_text_limit :appearances, :pwa_name, 255 + add_text_limit :appearances, :pwa_description, 2048 + end + + def down + remove_text_limit :appearances, :pwa_name + remove_text_limit :appearances, :pwa_description + end +end diff --git a/db/migrate/20230109095622_rename_web_hook_calls_to_web_hook_calls_high.rb b/db/migrate/20230109095622_rename_web_hook_calls_to_web_hook_calls_high.rb new file mode 100644 index 00000000000..d3a461b3abb --- /dev/null +++ b/db/migrate/20230109095622_rename_web_hook_calls_to_web_hook_calls_high.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class RenameWebHookCallsToWebHookCallsHigh < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + def up + rename_column_concurrently :plan_limits, :web_hook_calls, :web_hook_calls_high + end + + def down + undo_rename_column_concurrently :plan_limits, :web_hook_calls, :web_hook_calls_high + end +end diff --git a/db/post_migrate/20230109100044_cleanup_web_hook_calls_column_rename.rb b/db/post_migrate/20230109100044_cleanup_web_hook_calls_column_rename.rb new file mode 100644 index 00000000000..28769b20e5a --- /dev/null +++ b/db/post_migrate/20230109100044_cleanup_web_hook_calls_column_rename.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class CleanupWebHookCallsColumnRename < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + def up + cleanup_concurrent_column_rename :plan_limits, :web_hook_calls, :web_hook_calls_high + end + + def down + undo_cleanup_concurrent_column_rename :plan_limits, :web_hook_calls, :web_hook_calls_high + end +end diff --git a/db/post_migrate/20230112144946_add_tmp_index_to_ci_build_need.rb b/db/post_migrate/20230112144946_add_tmp_index_to_ci_build_need.rb new file mode 100644 index 00000000000..d1e0ae6665f --- /dev/null +++ b/db/post_migrate/20230112144946_add_tmp_index_to_ci_build_need.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class AddTmpIndexToCiBuildNeed < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + INDEX_NAME = :tmp_index_ci_build_needs_on_partition_id_and_id + TABLE_NAME = :ci_build_needs + + def up + return unless Gitlab.com? + + prepare_async_index(TABLE_NAME, [:partition_id, :id], where: 'partition_id = 101', name: INDEX_NAME) + end + + def down + return unless Gitlab.com? + + unprepare_async_index_by_name(TABLE_NAME, INDEX_NAME) + end +end diff --git a/db/post_migrate/20230112145326_add_tmp_index_to_ci_pipeline_variable.rb b/db/post_migrate/20230112145326_add_tmp_index_to_ci_pipeline_variable.rb new file mode 100644 index 00000000000..920b70765cc --- /dev/null +++ b/db/post_migrate/20230112145326_add_tmp_index_to_ci_pipeline_variable.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class AddTmpIndexToCiPipelineVariable < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + INDEX_NAME = :tmp_index_ci_pipeline_variables_on_partition_id_and_id + TABLE_NAME = :ci_pipeline_variables + + def up + return unless Gitlab.com? + + prepare_async_index(TABLE_NAME, [:partition_id, :id], where: 'partition_id = 101', name: INDEX_NAME) + end + + def down + return unless Gitlab.com? + + unprepare_async_index_by_name(TABLE_NAME, INDEX_NAME) + end +end diff --git a/db/post_migrate/20230117092947_add_tmp_index_to_ci_build_report_results.rb b/db/post_migrate/20230117092947_add_tmp_index_to_ci_build_report_results.rb new file mode 100644 index 00000000000..a116562e9ec --- /dev/null +++ b/db/post_migrate/20230117092947_add_tmp_index_to_ci_build_report_results.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class AddTmpIndexToCiBuildReportResults < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + INDEX_NAME = :tmp_index_ci_build_report_results_on_partition_id_and_id + TABLE_NAME = :ci_build_report_results + + def up + return unless Gitlab.com? + + prepare_async_index(TABLE_NAME, [:partition_id, :id], where: 'partition_id = 101', name: INDEX_NAME) + end + + def down + return unless Gitlab.com? + + unprepare_async_index_by_name(TABLE_NAME, INDEX_NAME) + end +end diff --git a/db/post_migrate/20230117093222_add_tmp_index_to_ci_builds_on_partition_id.rb b/db/post_migrate/20230117093222_add_tmp_index_to_ci_builds_on_partition_id.rb new file mode 100644 index 00000000000..3a40e636ef9 --- /dev/null +++ b/db/post_migrate/20230117093222_add_tmp_index_to_ci_builds_on_partition_id.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class AddTmpIndexToCiBuildsOnPartitionId < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + INDEX_NAME = :tmp_index_ci_builds_on_partition_id_and_id + + def up + return unless Gitlab.com? + + prepare_async_index :ci_builds, [:partition_id, :id], name: INDEX_NAME, where: 'partition_id = 101' + end + + def down + return unless Gitlab.com? + + unprepare_async_index :ci_builds, [:partition_id, :id], name: INDEX_NAME, where: 'partition_id = 101' + end +end diff --git a/db/post_migrate/20230117093736_add_tmp_index_to_ci_pipelines_on_partition_id.rb b/db/post_migrate/20230117093736_add_tmp_index_to_ci_pipelines_on_partition_id.rb new file mode 100644 index 00000000000..a8e5da592af --- /dev/null +++ b/db/post_migrate/20230117093736_add_tmp_index_to_ci_pipelines_on_partition_id.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class AddTmpIndexToCiPipelinesOnPartitionId < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + INDEX_NAME = :tmp_index_ci_pipelines_on_partition_id_and_id + + def up + return unless Gitlab.com? + + prepare_async_index :ci_pipelines, [:partition_id, :id], name: INDEX_NAME, where: 'partition_id = 101' + end + + def down + return unless Gitlab.com? + + unprepare_async_index :ci_pipelines, [:partition_id, :id], name: INDEX_NAME, where: 'partition_id = 101' + end +end diff --git a/db/post_migrate/20230117093924_add_tmp_index_to_ci_stages_on_partition_id.rb b/db/post_migrate/20230117093924_add_tmp_index_to_ci_stages_on_partition_id.rb new file mode 100644 index 00000000000..33273ee2ba4 --- /dev/null +++ b/db/post_migrate/20230117093924_add_tmp_index_to_ci_stages_on_partition_id.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class AddTmpIndexToCiStagesOnPartitionId < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + INDEX_NAME = :tmp_index_ci_stages_on_partition_id_and_id + + def up + return unless Gitlab.com? + + prepare_async_index :ci_stages, [:partition_id, :id], name: INDEX_NAME, where: 'partition_id = 101' + end + + def down + return unless Gitlab.com? + + unprepare_async_index :ci_stages, [:partition_id, :id], name: INDEX_NAME, where: 'partition_id = 101' + end +end diff --git a/db/schema_migrations/20221228072549 b/db/schema_migrations/20221228072549 new file mode 100644 index 00000000000..e0079614de0 --- /dev/null +++ b/db/schema_migrations/20221228072549 @@ -0,0 +1 @@ +2935444c762f3fdc8bd04055fc6048be4b637d2136e71a84479135e44c50856b
\ No newline at end of file diff --git a/db/schema_migrations/20221228073206 b/db/schema_migrations/20221228073206 new file mode 100644 index 00000000000..cbd5116deea --- /dev/null +++ b/db/schema_migrations/20221228073206 @@ -0,0 +1 @@ +0105a4d40b8ecb6e4c1bc543001f223bf9bbb25c03288dd394859d4926bb4801
\ No newline at end of file diff --git a/db/schema_migrations/20230109095622 b/db/schema_migrations/20230109095622 new file mode 100644 index 00000000000..1a0f0c80918 --- /dev/null +++ b/db/schema_migrations/20230109095622 @@ -0,0 +1 @@ +a567168b41dc56069e485ef303aeb69b967e685d463ed44d99f54dc96cdf9bbd
\ No newline at end of file diff --git a/db/schema_migrations/20230109100044 b/db/schema_migrations/20230109100044 new file mode 100644 index 00000000000..6e72af38f8f --- /dev/null +++ b/db/schema_migrations/20230109100044 @@ -0,0 +1 @@ +052c36d0911e104f8bc42f3229170c234f3c61555f53712adbfee6ab385233b3
\ No newline at end of file diff --git a/db/schema_migrations/20230112144946 b/db/schema_migrations/20230112144946 new file mode 100644 index 00000000000..e9e307791f5 --- /dev/null +++ b/db/schema_migrations/20230112144946 @@ -0,0 +1 @@ +a2cb76b2138b3edc014c01c4b130fcd58bf81a10c68c897376f5bf8d69d5a660
\ No newline at end of file diff --git a/db/schema_migrations/20230112145326 b/db/schema_migrations/20230112145326 new file mode 100644 index 00000000000..1878bebba66 --- /dev/null +++ b/db/schema_migrations/20230112145326 @@ -0,0 +1 @@ +97a52b54895ff5f5ea3c2dac6148c8d8110081bffe9064c50547b776ec56e78a
\ No newline at end of file diff --git a/db/schema_migrations/20230117092947 b/db/schema_migrations/20230117092947 new file mode 100644 index 00000000000..4eeca7e3526 --- /dev/null +++ b/db/schema_migrations/20230117092947 @@ -0,0 +1 @@ +775eb98fc81524f667cfab4dfdcee9bd668143c7286011dd1f0d40f87fc06ab0
\ No newline at end of file diff --git a/db/schema_migrations/20230117093222 b/db/schema_migrations/20230117093222 new file mode 100644 index 00000000000..5b539456dd1 --- /dev/null +++ b/db/schema_migrations/20230117093222 @@ -0,0 +1 @@ +4d38db045a0d505ea8f62327de8cc58fc0896e7c194cf71ca28ba08113757696
\ No newline at end of file diff --git a/db/schema_migrations/20230117093736 b/db/schema_migrations/20230117093736 new file mode 100644 index 00000000000..7d61bf2ba5c --- /dev/null +++ b/db/schema_migrations/20230117093736 @@ -0,0 +1 @@ +28b959fe3c79a9d24e24d296112ee7ada71b9932e608cbf5fa2d01cac3db0247
\ No newline at end of file diff --git a/db/schema_migrations/20230117093924 b/db/schema_migrations/20230117093924 new file mode 100644 index 00000000000..0fc56af4b10 --- /dev/null +++ b/db/schema_migrations/20230117093924 @@ -0,0 +1 @@ +0a34ab643f8ac5fdd0dd604f53244fe07a88ebf992fed7863bf38300817c9acb
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 701022fe113..1fb41bf1245 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -11065,8 +11065,12 @@ CREATE TABLE appearances ( profile_image_guidelines_html text, pwa_short_name text, pwa_icon text, + pwa_name text, + pwa_description text, CONSTRAINT appearances_profile_image_guidelines CHECK ((char_length(profile_image_guidelines) <= 4096)), + CONSTRAINT check_13b2165eca CHECK ((char_length(pwa_name) <= 255)), CONSTRAINT check_5c3fd63577 CHECK ((char_length(pwa_short_name) <= 255)), + CONSTRAINT check_5e0e6f24ed CHECK ((char_length(pwa_description) <= 2048)), CONSTRAINT check_5e5b7ac344 CHECK ((char_length(pwa_icon) <= 1024)) ); @@ -19565,7 +19569,6 @@ CREATE TABLE plan_limits ( helm_max_file_size bigint DEFAULT 5242880 NOT NULL, ci_registered_group_runners integer DEFAULT 1000 NOT NULL, ci_registered_project_runners integer DEFAULT 1000 NOT NULL, - web_hook_calls integer DEFAULT 0 NOT NULL, ci_daily_pipeline_schedule_triggers integer DEFAULT 0 NOT NULL, ci_max_artifact_size_running_container_scanning integer DEFAULT 0 NOT NULL, ci_max_artifact_size_cluster_image_scanning integer DEFAULT 0 NOT NULL, @@ -19589,7 +19592,9 @@ CREATE TABLE plan_limits ( pipeline_hierarchy_size integer DEFAULT 1000 NOT NULL, enforcement_limit integer DEFAULT 0 NOT NULL, notification_limit integer DEFAULT 0 NOT NULL, - dashboard_limit_enabled_at timestamp with time zone + dashboard_limit_enabled_at timestamp with time zone, + web_hook_calls_high integer DEFAULT 0, + CONSTRAINT check_0fa68f370e CHECK ((web_hook_calls_high IS NOT NULL)) ); CREATE SEQUENCE plan_limits_id_seq diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md index 20b395c77b1..c5063f61293 100644 --- a/doc/administration/instance_limits.md +++ b/doc/administration/instance_limits.md @@ -147,7 +147,7 @@ To set this limit for a self-managed installation, run the following in the # If limits don't exist for the default plan, you can create one with: # Plan.default.create_limits! -Plan.default.actual_limits.update!(web_hook_calls: 10) +Plan.default.actual_limits.update!(web_hook_calls_high: 10) ``` Set the limit to `0` to disable it. diff --git a/doc/api/appearance.md b/doc/api/appearance.md index eb88ec5e1b3..94fb092c739 100644 --- a/doc/api/appearance.md +++ b/doc/api/appearance.md @@ -29,8 +29,10 @@ Example response: ```json { "title": "GitLab Test Instance", - "pwa_short_name": "GitLab", "description": "gitlab-test.example.com", + "pwa_name": "GitLab PWA", + "pwa_short_name": "GitLab", + "pwa_description": "GitLab as PWA", "pwa_icon": "/uploads/-/system/appearance/pwa_icon/1/pwa_logo.png", "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", @@ -56,8 +58,10 @@ PUT /application/appearance | Attribute | Type | Required | Description | | --------------------------------- | ------- | -------- | ----------- | | `title` | string | no | Instance title on the sign in / sign up page -| `pwa_short_name` | string | no | Optional, short name for Progressive Web App | `description` | string | no | Markdown text shown on the sign in / sign up page +| `pwa_name` | string | no | Full name of the Progressive Web App. Used for the attribute `name` in `manifest.json`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375708) in GitLab 15.8. +| `pwa_short_name` | string | no | Short name for Progressive Web App. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375708) in GitLab 15.8. +| `pwa_description` | string | no | An explanation of what the Progressive Web App does. Used for the attribute `description` in `manifest.json`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375708) in GitLab 15.8. | `pwa_icon` | mixed | no | Icon used for Progressive Web App. See [Change logo](#change-logo). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375708) in GitLab 15.8. | `logo` | mixed | no | Instance image used on the sign in / sign up page. See [Change logo](#change-logo) | `header_logo` | mixed | no | Instance image used for the main navigation bar @@ -79,8 +83,10 @@ Example response: ```json { "title": "GitLab Test Instance", - "pwa_short_name": "GitLab", "description": "gitlab-test.example.com", + "pwa_name": "GitLab PWA", + "pwa_short_name": "GitLab", + "pwa_description": "GitLab as PWA", "pwa_icon": "/uploads/-/system/appearance/pwa_icon/1/pwa_logo.png", "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", diff --git a/doc/update/background_migrations.md b/doc/update/background_migrations.md index c5ffefdd77f..38ea82667ca 100644 --- a/doc/update/background_migrations.md +++ b/doc/update/background_migrations.md @@ -78,7 +78,7 @@ sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::Database::Ba > - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/329511) in GitLab 13.12. > - Enabled on GitLab.com. > - Recommended for production use. -> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-batched-background-migrations). +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-background-migrations). There can be [risks when disabling released features](../administration/feature_flags.md#risks-when-disabling-released-features). Refer to this feature's version history for more details. @@ -203,17 +203,21 @@ Feature.disable(:optimize_batched_migrations) ## Troubleshooting -### Enable or disable batched background migrations +### Enable or disable background migrations -In extremely limited circumstances, a GitLab administrator can disable the -`execute_batched_migrations_on_schedule` [feature flag](../administration/feature_flags.md). -This flag is enabled by default, and should be disabled only as a last resort +In extremely limited circumstances, a GitLab administrator can disable either or +both of these [feature flags](../administration/feature_flags.md): + +- `execute_background_migrations` +- `execute_batched_migrations_on_schedule` + +These flags are enabled by default. Disable them only as a last resort to limit database operations in special circumstances, like database host maintenance. WARNING: -Do not disable this flag unless you fully understand the ramifications. If you disable -the `execute_batched_migrations_on_schedule` feature flag, GitLab upgrades may fail -and data loss may occur. +Do not disable either of these flags unless you fully understand the ramifications. If you disable +the `execute_background_migrations` or `execute_batched_migrations_on_schedule` feature flag, +GitLab upgrades might fail and data loss might occur. ### Database migrations failing because of batched background migration not finished diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md index 7c44b49b78c..e7ff10820c3 100644 --- a/doc/user/application_security/security_dashboard/index.md +++ b/doc/user/application_security/security_dashboard/index.md @@ -21,12 +21,18 @@ To use the Security Dashboards, you must: ## When Security Dashboards are updated -The Security Dashboards show results of the most recent security scan on the +The Security Dashboards show results of scans from the most recent completed pipeline on the [default branch](../../project/repository/branches/default.md). -Security scans run only when the default branch updates, so -information on the Security Dashboard might not reflect newly-discovered vulnerabilities. +Dashboards are updated with the result of completed pipelines run on the default branch; they do not include vulnerabilities discovered in pipelines from other un-merged branches. -To run a daily security scan, +If you use manual jobs, for example gate deployments, in the default branch's pipeline, +the results of any scans are only updated when the job has been successfully run. +If manual jobs are skipped regularly, you should to define the job as optional, +using the [`allow_failure`](../../../ci/jobs/job_control.md#types-of-manual-jobs) attribute. + +To ensure regular security scans (even on infrequently developed projects), +you should use [scan execution policies](../../../user/application_security/policies/scan-execution-policies.md). +Alternatively, you can [configure a scheduled pipeline](../../../ci/pipelines/schedules.md). ## Reduce false negatives in dependency scans diff --git a/doc/user/packages/terraform_module_registry/index.md b/doc/user/packages/terraform_module_registry/index.md index d107d6f7444..b098a1b2d7a 100644 --- a/doc/user/packages/terraform_module_registry/index.md +++ b/doc/user/packages/terraform_module_registry/index.md @@ -37,8 +37,8 @@ PUT /projects/:id/packages/terraform/modules/:module-name/:module-system/:module | Attribute | Type | Required | Description | | -------------------| --------------- | ---------| -------------------------------------------------------------------------------------------------------------------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](../../../api/rest/index.md#namespaced-path-encoding). | -| `module-name` | string | yes | The package name. **Supported syntax**: One to 64 ASCII characters, including lowercase letters (a-z), digits (0-9), and hyphens (`-`). -| `module-system` | string | yes | The package system. **Supported syntax**: One to 64 ASCII characters, including lowercase letters (a-z), digits (0-9), and hyphens (`-`). More information can be found in the [Terraform Module Registry Protocol documentation](https://www.terraform.io/internals/module-registry-protocol). +| `module-name` | string | yes | The package name. **Supported syntax**: One to 64 ASCII characters, including lowercase letters (a-z) and digits (0-9). The package name can't exceed 64 characters. +| `module-system` | string | yes | The package system. **Supported syntax**: One to 64 ASCII characters, including lowercase letters (a-z) and digits (0-9). The package system can't exceed 64 characters. More information can be found in the [Terraform Module Registry Protocol documentation](https://www.terraform.io/internals/module-registry-protocol). | `module-version` | string | yes | The package version. It must be valid according to the [Semantic Versioning Specification](https://semver.org/). Provide the file content in the request body. diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 21651fd645c..6fcc696285d 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -243,7 +243,7 @@ like in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87727/diffs?diff_i FLAG: On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `moved_mr_sidebar`. -On GitLab.com, this feature is not available. +On GitLab.com, this feature is enabled in the following projects: `gitlab-org/gitlab`, `gitlab-com/www-gitlab-com`, and `gitlab-org/customers-gitlab-com`. When this feature flag is enabled, you can find the following actions in **Merge request actions** (**{ellipsis_v}**) on the top right: diff --git a/lib/api/appearance.rb b/lib/api/appearance.rb index 99278bdf8b0..2023c43b463 100644 --- a/lib/api/appearance.rb +++ b/lib/api/appearance.rb @@ -26,8 +26,10 @@ module API end params do optional :title, type: String, desc: 'Instance title on the sign in / sign up page' - optional :pwa_short_name, type: String, desc: 'Optional, short name for Progressive Web App' optional :description, type: String, desc: 'Markdown text shown on the sign in / sign up page' + optional :pwa_name, type: String, desc: 'Name of the Progressive Web App' + optional :pwa_short_name, type: String, desc: 'Optional, short name for Progressive Web App' + optional :pwa_description, type: String, desc: 'An explanation of what the Progressive Web App does' # TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960 optional :logo, type: File, desc: 'Instance image used on the sign in / sign up page' # rubocop:disable Scalability/FileUploads optional :pwa_icon, type: File, desc: 'Icon used for Progressive Web App' # rubocop:disable Scalability/FileUploads diff --git a/lib/api/bulk_imports.rb b/lib/api/bulk_imports.rb index 6c07b15329e..e3dc9ea52cb 100644 --- a/lib/api/bulk_imports.rb +++ b/lib/api/bulk_imports.rb @@ -91,6 +91,8 @@ module API end end post do + check_rate_limit!(:bulk_import, scope: current_user) + params[:entities].each do |entity| if entity[:destination_name] entity[:destination_slug] ||= entity[:destination_name] diff --git a/lib/api/entities/appearance.rb b/lib/api/entities/appearance.rb index cabdf68c23a..2825c84e01d 100644 --- a/lib/api/entities/appearance.rb +++ b/lib/api/entities/appearance.rb @@ -4,8 +4,10 @@ module API module Entities class Appearance < Grape::Entity expose :title - expose :pwa_short_name expose :description + expose :pwa_name + expose :pwa_short_name + expose :pwa_description expose :logo do |appearance, options| appearance.logo.url diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb index a788586ebec..2b4a6c12314 100644 --- a/lib/gitlab/application_rate_limiter.rb +++ b/lib/gitlab/application_rate_limiter.rb @@ -31,7 +31,7 @@ module Gitlab group_import: { threshold: -> { application_settings.group_import_limit }, interval: 1.minute }, group_testing_hook: { threshold: 5, interval: 1.minute }, profile_add_new_email: { threshold: 5, interval: 1.minute }, - web_hook_calls: { interval: 1.minute }, + web_hook_calls_high: { interval: 1.minute }, web_hook_calls_mid: { interval: 1.minute }, web_hook_calls_low: { interval: 1.minute }, users_get_by_id: { threshold: -> { application_settings.users_get_by_id_limit }, interval: 10.minutes }, @@ -55,7 +55,8 @@ module Gitlab phone_verification_verify_code: { threshold: 10, interval: 10.minutes }, namespace_exists: { threshold: 20, interval: 1.minute }, fetch_google_ip_list: { threshold: 10, interval: 1.minute }, - jobs_index: { threshold: 600, interval: 1.minute } + jobs_index: { threshold: 600, interval: 1.minute }, + bulk_import: { threshold: 6, interval: 1.minute } }.freeze end diff --git a/lib/gitlab/web_hooks/rate_limiter.rb b/lib/gitlab/web_hooks/rate_limiter.rb index 73d59f6f786..5efe1573c09 100644 --- a/lib/gitlab/web_hooks/rate_limiter.rb +++ b/lib/gitlab/web_hooks/rate_limiter.rb @@ -5,7 +5,7 @@ module Gitlab class RateLimiter include Gitlab::Utils::StrongMemoize - LIMIT_NAME = :web_hook_calls + LIMIT_NAME = :web_hook_calls_high NO_LIMIT = 0 # SystemHooks (instance admin hooks) and ServiceHooks (integration hooks) # are not rate-limited. diff --git a/package.json b/package.json index 82e1ba64eae..d0964afcc31 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "codesandbox-api": "0.0.23", "compression-webpack-plugin": "^5.0.2", "copy-webpack-plugin": "^6.4.1", - "core-js": "^3.27.1", + "core-js": "^3.27.2", "cron-validator": "^1.1.1", "cronstrue": "^1.122.0", "cropper": "^2.3.0", diff --git a/spec/controllers/admin/application_settings/appearances_controller_spec.rb b/spec/controllers/admin/application_settings/appearances_controller_spec.rb index 78dce4558c3..f21c93e85d2 100644 --- a/spec/controllers/admin/application_settings/appearances_controller_spec.rb +++ b/spec/controllers/admin/application_settings/appearances_controller_spec.rb @@ -11,8 +11,10 @@ RSpec.describe Admin::ApplicationSettings::AppearancesController do let(:create_params) do { title: 'Foo', - pwa_short_name: 'F', description: 'Bar', + pwa_name: 'GitLab PWA', + pwa_short_name: 'F', + pwa_description: 'This is GitLab as PWA', header_message: header_message, footer_message: footer_message } @@ -26,6 +28,11 @@ RSpec.describe Admin::ApplicationSettings::AppearancesController do post :create, params: { appearance: create_params } expect(Appearance.current).to have_attributes( + title: 'Foo', + description: 'Bar', + pwa_name: 'GitLab PWA', + pwa_short_name: 'F', + pwa_description: 'This is GitLab as PWA', header_message: header_message, footer_message: footer_message, email_header_and_footer_enabled: false, @@ -41,6 +48,11 @@ RSpec.describe Admin::ApplicationSettings::AppearancesController do post :create, params: { appearance: create_params } expect(Appearance.current).to have_attributes( + title: 'Foo', + description: 'Bar', + pwa_name: 'GitLab PWA', + pwa_short_name: 'F', + pwa_description: 'This is GitLab as PWA', header_message: header_message, footer_message: footer_message, email_header_and_footer_enabled: true diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb index 6d58abb9d4d..9350742433a 100644 --- a/spec/controllers/admin/runners_controller_spec.rb +++ b/spec/controllers/admin/runners_controller_spec.rb @@ -105,49 +105,6 @@ RSpec.describe Admin::RunnersController, feature_category: :runner_fleet do end end - describe '#destroy' do - it 'destroys the runner' do - expect_next_instance_of(Ci::Runners::UnregisterRunnerService, runner, user) do |service| - expect(service).to receive(:execute).once.and_call_original - end - - delete :destroy, params: { id: runner.id } - - expect(response).to have_gitlab_http_status(:found) - expect(Ci::Runner.find_by(id: runner.id)).to be_nil - end - end - - describe '#resume' do - it 'marks the runner as active and ticks the queue' do - runner.update!(active: false) - - expect do - post :resume, params: { id: runner.id } - end.to change { runner.ensure_runner_queue_value } - - runner.reload - - expect(response).to have_gitlab_http_status(:found) - expect(runner.active).to eq(true) - end - end - - describe '#pause' do - it 'marks the runner as inactive and ticks the queue' do - runner.update!(active: true) - - expect do - post :pause, params: { id: runner.id } - end.to change { runner.ensure_runner_queue_value } - - runner.reload - - expect(response).to have_gitlab_http_status(:found) - expect(runner.active).to eq(false) - end - end - describe 'GET #runner_setup_scripts' do it 'renders the setup scripts' do get :runner_setup_scripts, params: { os: 'linux', arch: 'amd64' } diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb index 93c1571bb6c..1a60f7d824e 100644 --- a/spec/controllers/groups/runners_controller_spec.rb +++ b/spec/controllers/groups/runners_controller_spec.rb @@ -30,7 +30,6 @@ RSpec.describe Groups::RunnersController, feature_category: :runner_fleet do expect(response).to have_gitlab_http_status(:ok) expect(response).to render_template(:index) - expect(assigns(:group_runners_limited_count)).to be(2) end it 'tracks the event' do diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb index a0d5b576e74..a3992ae850e 100644 --- a/spec/controllers/import/bulk_imports_controller_spec.rb +++ b/spec/controllers/import/bulk_imports_controller_spec.rb @@ -9,14 +9,12 @@ RSpec.describe Import::BulkImportsController, feature_category: :importers do stub_application_setting(bulk_import_enabled: true) sign_in(user) + + allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(false) end context 'when user is signed in' do context 'when bulk_import feature flag is enabled' do - before do - stub_feature_flags(bulk_import: true) - end - describe 'POST configure' do before do allow_next_instance_of(BulkImports::Clients::HTTP) do |instance| @@ -400,6 +398,18 @@ RSpec.describe Import::BulkImportsController, feature_category: :importers do expect(response).to have_gitlab_http_status(:unprocessable_entity) end end + + context 'when request exceeds rate limits' do + it 'prevents user from starting a new migration' do + allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(true) + + post :create, params: { bulk_import: {} } + + request + + expect(response).to have_gitlab_http_status(:too_many_requests) + end + end end end diff --git a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js index 1f3b6dce620..3d212ee03af 100644 --- a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js @@ -13,7 +13,12 @@ import { } from '~/vue_merge_request_widget/components/approvals/messages'; import eventHub from '~/vue_merge_request_widget/event_hub'; -jest.mock('~/flash'); +const mockAlertDismiss = jest.fn(); +jest.mock('~/flash', () => ({ + createAlert: jest.fn().mockImplementation(() => ({ + dismiss: mockAlertDismiss, + })), +})); const RULE_NAME = 'first_rule'; const TEST_HELP_PATH = 'help/path'; @@ -267,9 +272,16 @@ describe('MRWidget approvals', () => { return nextTick(); }); - it('flashes error message', () => { + it('shows an alert with error message', () => { expect(createAlert).toHaveBeenCalledWith({ message: APPROVE_ERROR }); }); + + it('clears the previous alert', () => { + expect(mockAlertDismiss).toHaveBeenCalledTimes(0); + + findAction().vm.$emit('click'); + expect(mockAlertDismiss).toHaveBeenCalledTimes(1); + }); }); }); }); diff --git a/spec/helpers/appearances_helper_spec.rb b/spec/helpers/appearances_helper_spec.rb index 8673353996e..3c698fb2d41 100644 --- a/spec/helpers/appearances_helper_spec.rb +++ b/spec/helpers/appearances_helper_spec.rb @@ -10,17 +10,45 @@ RSpec.describe AppearancesHelper do allow(helper).to receive(:current_user).and_return(user) end - describe '#appearance_short_name' do + describe '#appearance_pwa_name' do it 'returns the default value' do create(:appearance) - expect(helper.appearance_short_name).to match('GitLab') + expect(helper.appearance_pwa_name).to match('GitLab') + end + + it 'returns the customized value' do + create(:appearance, pwa_name: 'GitLab as PWA') + + expect(helper.appearance_pwa_name).to match('GitLab as PWA') + end + end + + describe '#appearance_pwa_short_name' do + it 'returns the default value' do + create(:appearance) + + expect(helper.appearance_pwa_short_name).to match('GitLab') end it 'returns the customized value' do create(:appearance, pwa_short_name: 'Short') - expect(helper.appearance_short_name).to match('Short') + expect(helper.appearance_pwa_short_name).to match('Short') + end + end + + describe '#appearance_pwa_description' do + it 'returns the default value' do + create(:appearance) + + expect(helper.appearance_pwa_description).to include('The complete DevOps platform.') + end + + it 'returns the customized value' do + create(:appearance, pwa_description: 'This is a description') + + expect(helper.appearance_pwa_description).to match('This is a description') end end diff --git a/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb b/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb index b25ce4ea9da..42151c494f1 100644 --- a/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb +++ b/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb @@ -32,7 +32,7 @@ RSpec.describe Gitlab::WebHooks::RateLimiter, :clean_gitlab_redis_rate_limiting context 'when there is a plan limit' do before_all do - create(:plan_limits, plan: plan, web_hook_calls: limit) + create(:plan_limits, plan: plan, web_hook_calls_high: limit) end where(:hook, :limitless_hook_type) do @@ -65,7 +65,7 @@ RSpec.describe Gitlab::WebHooks::RateLimiter, :clean_gitlab_redis_rate_limiting describe 'rate limit scope' do it 'rate limits all hooks from the same namespace', :freeze_time do - create(:plan_limits, plan: plan, web_hook_calls: limit) + create(:plan_limits, plan: plan, web_hook_calls_high: limit) project_hook_in_different_namespace = create(:project_hook) project_hook_in_same_namespace = create(:project_hook, project: create(:project, namespace: project_hook.project.namespace) @@ -92,7 +92,7 @@ RSpec.describe Gitlab::WebHooks::RateLimiter, :clean_gitlab_redis_rate_limiting context 'when there is a plan limit' do before_all do - create(:plan_limits, plan: plan, web_hook_calls: limit) + create(:plan_limits, plan: plan, web_hook_calls_high: limit) end context 'when hook is not rate-limited' do diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb index 54dc280d7ac..0a1de1d5dc4 100644 --- a/spec/models/appearance_spec.rb +++ b/spec/models/appearance_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' RSpec.describe Appearance do + using RSpec::Parameterized::TableSyntax subject { build(:appearance) } it { include(CacheableAttributes) } @@ -14,8 +15,10 @@ RSpec.describe Appearance do subject(:appearance) { described_class.new } it { expect(appearance.title).to eq('') } - it { expect(appearance.pwa_short_name).to eq('') } it { expect(appearance.description).to eq('') } + it { expect(appearance.pwa_name).to eq('') } + it { expect(appearance.pwa_short_name).to eq('') } + it { expect(appearance.pwa_description).to eq('') } it { expect(appearance.new_project_guidelines).to eq('') } it { expect(appearance.profile_image_guidelines).to eq('') } it { expect(appearance.header_message).to eq('') } @@ -96,6 +99,41 @@ RSpec.describe Appearance do it { is_expected.not_to allow_value('000').for(:message_font_color) } end + shared_examples 'validation allows' do + it { is_expected.to allow_value(value).for(attribute) } + end + + shared_examples 'validation permits with message' do + it { is_expected.not_to allow_value(value).for(attribute).with_message(message) } + end + + context 'valid pwa attributes' do + where(:attribute, :value) do + :pwa_name | nil + :pwa_name | "G" * 255 + :pwa_short_name | nil + :pwa_short_name | "S" * 255 + :pwa_description | nil + :pwa_description | "T" * 2048 + end + + with_them do + it_behaves_like 'validation allows' + end + end + + context 'invalid pwa attributes' do + where(:attribute, :value, :message) do + :pwa_name | "G" * 256 | 'is too long (maximum is 255 characters)' + :pwa_short_name | "S" * 256 | 'is too long (maximum is 255 characters)' + :pwa_description | "T" * 2049 | 'is too long (maximum is 2048 characters)' + end + + with_them do + it_behaves_like 'validation permits with message' + end + end + describe 'email_header_and_footer_enabled' do context 'default email_header_and_footer_enabled flag value' do it 'returns email_header_and_footer_enabled as true' do diff --git a/spec/models/plan_limits_spec.rb b/spec/models/plan_limits_spec.rb index 3705cab7ef5..093c78198d1 100644 --- a/spec/models/plan_limits_spec.rb +++ b/spec/models/plan_limits_spec.rb @@ -213,7 +213,7 @@ RSpec.describe PlanLimits do ci_active_jobs storage_size_limit daily_invites - web_hook_calls + web_hook_calls_high web_hook_calls_mid web_hook_calls_low ci_daily_pipeline_schedule_triggers diff --git a/spec/requests/api/appearance_spec.rb b/spec/requests/api/appearance_spec.rb index 5aba7e096a7..1b54fcc94f4 100644 --- a/spec/requests/api/appearance_spec.rb +++ b/spec/requests/api/appearance_spec.rb @@ -34,7 +34,9 @@ RSpec.describe API::Appearance, 'Appearance', feature_category: :navigation do expect(json_response['new_project_guidelines']).to eq('') expect(json_response['profile_image_guidelines']).to eq('') expect(json_response['title']).to eq('') + expect(json_response['pwa_name']).to eq('') expect(json_response['pwa_short_name']).to eq('') + expect(json_response['pwa_description']).to eq('') end end end @@ -53,8 +55,10 @@ RSpec.describe API::Appearance, 'Appearance', feature_category: :navigation do it "allows updating the settings" do put api("/application/appearance", admin), params: { title: "GitLab Test Instance", - pwa_short_name: "GitLab PWA", description: "gitlab-test.example.com", + pwa_name: "GitLab PWA Test", + pwa_short_name: "GitLab PWA", + pwa_description: "This is GitLab as PWA", new_project_guidelines: "Please read the FAQs for help.", profile_image_guidelines: "Custom profile image guidelines" } @@ -74,7 +78,9 @@ RSpec.describe API::Appearance, 'Appearance', feature_category: :navigation do expect(json_response['new_project_guidelines']).to eq('Please read the FAQs for help.') expect(json_response['profile_image_guidelines']).to eq('Custom profile image guidelines') expect(json_response['title']).to eq('GitLab Test Instance') + expect(json_response['pwa_name']).to eq('GitLab PWA Test') expect(json_response['pwa_short_name']).to eq('GitLab PWA') + expect(json_response['pwa_description']).to eq('This is GitLab as PWA') end end diff --git a/spec/requests/api/bulk_imports_spec.rb b/spec/requests/api/bulk_imports_spec.rb index 4fb4fbe6d5c..23dfe865ba3 100644 --- a/spec/requests/api/bulk_imports_spec.rb +++ b/spec/requests/api/bulk_imports_spec.rb @@ -13,6 +13,8 @@ RSpec.describe API::BulkImports, feature_category: :importers do before do stub_application_setting(bulk_import_enabled: true) + + allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(false) end shared_examples 'disabled feature' do @@ -73,6 +75,24 @@ RSpec.describe API::BulkImports, feature_category: :importers do end describe 'POST /bulk_imports' do + let(:request) { post api('/bulk_imports', user), params: params } + let(:destination_param) { { destination_slug: 'destination_slug' } } + let(:params) do + { + configuration: { + url: 'http://gitlab.example', + access_token: 'access_token' + }, + entities: [ + { + source_type: 'group_entity', + source_full_path: 'full_path', + destination_namespace: 'destination_namespace' + }.merge(destination_param) + ] + } + end + before do allow_next_instance_of(BulkImports::Clients::HTTP) do |instance| allow(instance) @@ -86,23 +106,6 @@ RSpec.describe API::BulkImports, feature_category: :importers do end shared_examples 'starting a new migration' do - let(:request) { post api('/bulk_imports', user), params: params } - let(:params) do - { - configuration: { - url: 'http://gitlab.example', - access_token: 'access_token' - }, - entities: [ - { - source_type: 'group_entity', - source_full_path: 'full_path', - destination_namespace: 'destination_namespace' - }.merge(destination_param) - ] - } - end - it 'starts a new migration' do request @@ -278,6 +281,17 @@ RSpec.describe API::BulkImports, feature_category: :importers do end include_examples 'disabled feature' + + context 'when request exceeds rate limits' do + it 'prevents user from starting a new migration' do + allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(true) + + request + + expect(response).to have_gitlab_http_status(:too_many_requests) + expect(json_response['message']['error']).to eq('This endpoint has been requested too many times. Try again later.') + end + end end describe 'GET /bulk_imports/entities' do diff --git a/spec/requests/pwa_controller_spec.rb b/spec/requests/pwa_controller_spec.rb index a80d083c11f..393f8803375 100644 --- a/spec/requests/pwa_controller_spec.rb +++ b/spec/requests/pwa_controller_spec.rb @@ -7,14 +7,15 @@ RSpec.describe PwaController, feature_category: :navigation do it 'responds with json' do get manifest_path(format: :json) - expect(response.body).to include('The complete DevOps platform.') + expect(Gitlab::Json.parse(response.body)).to include({ 'name' => 'GitLab' }) expect(Gitlab::Json.parse(response.body)).to include({ 'short_name' => 'GitLab' }) + expect(response.body).to include('The complete DevOps platform.') expect(response).to have_gitlab_http_status(:success) end context 'with customized appearance' do let_it_be(:appearance) do - create(:appearance, title: 'Long name', pwa_short_name: 'Short name', description: 'This is a test') + create(:appearance, pwa_name: 'PWA name', pwa_short_name: 'Short name', pwa_description: 'This is a test') end it 'uses custom values', :aggregate_failures do @@ -22,7 +23,7 @@ RSpec.describe PwaController, feature_category: :navigation do expect(Gitlab::Json.parse(response.body)).to include({ 'description' => 'This is a test', - 'name' => 'Long name', + 'name' => 'PWA name', 'short_name' => 'Short name' }) expect(response).to have_gitlab_http_status(:success) diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb index 4b925a058e7..a756e75214b 100644 --- a/spec/services/web_hook_service_spec.rb +++ b/spec/services/web_hook_service_spec.rb @@ -606,7 +606,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state def expect_to_rate_limit(hook, threshold:, throttled: false) expect(Gitlab::ApplicationRateLimiter).to receive(:throttled?) - .with(:web_hook_calls, scope: [hook.parent.root_namespace], threshold: threshold) + .with(:web_hook_calls_high, scope: [hook.parent.root_namespace], threshold: threshold) .and_return(throttled) end @@ -621,7 +621,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state context 'when rate limiting is configured' do let_it_be(:threshold) { 3 } - let_it_be(:plan_limits) { create(:plan_limits, :default_plan, web_hook_calls: threshold) } + let_it_be(:plan_limits) { create(:plan_limits, :default_plan, web_hook_calls_high: threshold) } it 'queues a worker and tracks the call' do expect_to_rate_limit(project_hook, threshold: threshold) diff --git a/yarn.lock b/yarn.lock index 1859dc16ee1..a9728ad7cb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3999,10 +3999,10 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== -core-js@^3.27.1, core-js@^3.6.5: - version "3.27.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.27.1.tgz#23cc909b315a6bb4e418bf40a52758af2103ba46" - integrity sha512-GutwJLBChfGCpwwhbYoqfv03LAfmiz7e7D/BNxzeMxwQf10GRSzqiOjx7AmtEk+heiD/JWmBuyBPgFtx0Sg1ww== +core-js@^3.27.2, core-js@^3.6.5: + version "3.27.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.27.2.tgz#85b35453a424abdcacb97474797815f4d62ebbf7" + integrity sha512-9ashVQskuh5AZEZ1JdQWp1GqSoC1e1G87MzRqg2gIfVAQ7Qn9K+uFj8EcniUFA4P2NLZfV+TOlX1SzoKfo+s7w== core-util-is@~1.0.0: version "1.0.3" |