diff options
55 files changed, 628 insertions, 178 deletions
@@ -10,7 +10,7 @@ gem 'responders', '~> 3.0' gem 'sprockets', '~> 3.7.0' # Default values for AR models -gem 'default_value_for', '~> 3.3.0' +gem 'default_value_for', '~> 3.4.0' # Supported DBs gem 'pg', '~> 1.1' @@ -374,7 +374,7 @@ group :development, :test do gem 'scss_lint', '~> 0.59.0', require: false gem 'haml_lint', '~> 0.36.0', require: false - gem 'bundler-audit', '~> 0.6.1', require: false + gem 'bundler-audit', '~> 0.7.0.1', require: false gem 'benchmark-ips', '~> 2.3.0', require: false diff --git a/Gemfile.lock b/Gemfile.lock index ac97a5d1433..59eb3421266 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -150,9 +150,9 @@ GEM bullet (6.1.0) activesupport (>= 3.0.0) uniform_notifier (~> 1.11) - bundler-audit (0.6.1) + bundler-audit (0.7.0.1) bundler (>= 1.2.0, < 3) - thor (~> 0.18) + thor (>= 0.18, < 2) byebug (11.1.3) capybara (3.34.0) addressable @@ -227,8 +227,8 @@ GEM html-pipeline declarative (0.0.20) declarative-option (0.1.0) - default_value_for (3.3.0) - activerecord (>= 3.2.0, < 6.1) + default_value_for (3.4.0) + activerecord (>= 3.2.0, < 7.0) deprecation_toolkit (1.5.1) activesupport (>= 4.2) derailed_benchmarks (1.8.1) @@ -1177,7 +1177,7 @@ GEM daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0, >= 1.0.4) rack (>= 1, < 3) - thor (0.20.3) + thor (1.1.0) thread_safe (0.3.6) thrift (0.13.0) tilt (2.0.10) @@ -1306,7 +1306,7 @@ DEPENDENCIES brakeman (~> 4.2) browser (~> 4.2) bullet (~> 6.1.0) - bundler-audit (~> 0.6.1) + bundler-audit (~> 0.7.0.1) capybara (~> 3.34.0) capybara-screenshot (~> 1.0.22) carrierwave (~> 1.3) @@ -1320,7 +1320,7 @@ DEPENDENCIES danger (~> 8.0.6) database_cleaner (~> 1.7.0) deckar01-task_list (= 2.3.1) - default_value_for (~> 3.3.0) + default_value_for (~> 3.4.0) deprecation_toolkit (~> 1.5.1) derailed_benchmarks device_detector diff --git a/app/graphql/mutations/alert_management/http_integration/create.rb b/app/graphql/mutations/alert_management/http_integration/create.rb index ff165d7f302..e1531148a76 100644 --- a/app/graphql/mutations/alert_management/http_integration/create.rb +++ b/app/graphql/mutations/alert_management/http_integration/create.rb @@ -21,27 +21,20 @@ module Mutations description: 'Whether the integration is receiving alerts.' def resolve(args) - @project = authorized_find!(full_path: args[:project_path]) + project = authorized_find!(full_path: args[:project_path]) response ::AlertManagement::HttpIntegrations::CreateService.new( project, current_user, - http_integration_params(args) + http_integration_params(project, args) ).execute end private - attr_reader :project - def find_object(full_path:) resolve_project(full_path: full_path) end - - # overriden in EE - def http_integration_params(args) - args.slice(:name, :active) - end end end end diff --git a/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb index 147df982bec..e33b7bb399a 100644 --- a/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb +++ b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb @@ -23,7 +23,14 @@ module Mutations errors: result.errors } end + + # overriden in EE + def http_integration_params(_project, args) + args.slice(:name, :active) + end end end end end + +Mutations::AlertManagement::HttpIntegration::HttpIntegrationBase.prepend_if_ee('::EE::Mutations::AlertManagement::HttpIntegration::HttpIntegrationBase') diff --git a/app/graphql/mutations/alert_management/http_integration/update.rb b/app/graphql/mutations/alert_management/http_integration/update.rb index 431fccaa5e5..b1e4ce841ee 100644 --- a/app/graphql/mutations/alert_management/http_integration/update.rb +++ b/app/graphql/mutations/alert_management/http_integration/update.rb @@ -24,10 +24,12 @@ module Mutations response ::AlertManagement::HttpIntegrations::UpdateService.new( integration, current_user, - args.slice(:name, :active) + http_integration_params(integration.project, args) ).execute end end end end end + +Mutations::AlertManagement::HttpIntegration::Update.prepend_if_ee('::EE::Mutations::AlertManagement::HttpIntegration::Update') diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb index 76f31dc97cb..0f2c7ba2630 100644 --- a/app/helpers/groups/group_members_helper.rb +++ b/app/helpers/groups/group_members_helper.rb @@ -14,7 +14,7 @@ module Groups::GroupMembersHelper end def group_group_links_data_json(group_links) - GroupGroupLinkSerializer.new.represent(group_links, { current_user: current_user }).to_json + GroupLink::GroupGroupLinkSerializer.new.represent(group_links, { current_user: current_user }).to_json end def members_data_json(group, members) diff --git a/app/helpers/projects/project_members_helper.rb b/app/helpers/projects/project_members_helper.rb index 168526d2abb..7c6989c0830 100644 --- a/app/helpers/projects/project_members_helper.rb +++ b/app/helpers/projects/project_members_helper.rb @@ -26,4 +26,30 @@ module Projects::ProjectMembersHelper project.group.has_owner?(current_user) end + + def project_group_links_data_json(group_links) + GroupLink::ProjectGroupLinkSerializer.new.represent(group_links, { current_user: current_user }).to_json + end + + def project_members_data_json(project, members) + MemberSerializer.new.represent(members, { current_user: current_user, group: project.group }).to_json + end + + def project_members_list_data_attributes(project, members) + { + members: project_members_data_json(project, members), + member_path: project_project_member_path(project, ':id'), + source_id: project.id, + can_manage_members: can_manage_project_members?(project) + } + end + + def project_group_links_list_data_attributes(project, group_links) + { + members: project_group_links_data_json(group_links), + member_path: project_group_link_path(project, ':id'), + source_id: project.id, + can_manage_members: can_manage_project_members?(project) + } + end end diff --git a/app/serializers/group_group_link_entity.rb b/app/serializers/group_group_link_entity.rb deleted file mode 100644 index 1e736214f54..00000000000 --- a/app/serializers/group_group_link_entity.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -class GroupGroupLinkEntity < Grape::Entity - include RequestAwareEntity - - expose :id - expose :created_at - expose :expires_at do |group_link| - group_link.expires_at&.to_time - end - - expose :can_update do |group_link| - can_manage?(group_link) - end - - expose :can_remove do |group_link| - can_manage?(group_link) - end - - expose :access_level do - expose :human_access, as: :string_value - expose :group_access, as: :integer_value - end - - expose :valid_roles do |group_link| - group_link.class.access_options - end - - expose :shared_with_group do - expose :avatar_url do |group_link| - group_link.shared_with_group.avatar_url(only_path: false) - end - - expose :web_url do |group_link| - group_link.shared_with_group.web_url - end - - expose :shared_with_group, merge: true, using: GroupBasicEntity - end - - private - - def current_user - options[:current_user] - end - - def can_manage?(group_link) - can?(current_user, :admin_group_member, group_link.shared_group) - end -end diff --git a/app/serializers/group_group_link_serializer.rb b/app/serializers/group_group_link_serializer.rb deleted file mode 100644 index 6ae8daf9207..00000000000 --- a/app/serializers/group_group_link_serializer.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -class GroupGroupLinkSerializer < BaseSerializer - entity GroupGroupLinkEntity -end diff --git a/app/serializers/group_link/group_group_link_entity.rb b/app/serializers/group_link/group_group_link_entity.rb new file mode 100644 index 00000000000..cedc8bd8582 --- /dev/null +++ b/app/serializers/group_link/group_group_link_entity.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module GroupLink + class GroupGroupLinkEntity < GroupLink::GroupLinkEntity + include RequestAwareEntity + + expose :can_update do |group_link| + can_manage?(group_link) + end + + expose :can_remove do |group_link| + can_manage?(group_link) + end + + private + + def current_user + options[:current_user] + end + + def can_manage?(group_link) + can?(current_user, :admin_group_member, group_link.shared_group) + end + end +end diff --git a/app/serializers/group_link/group_group_link_serializer.rb b/app/serializers/group_link/group_group_link_serializer.rb new file mode 100644 index 00000000000..1e3f861f09a --- /dev/null +++ b/app/serializers/group_link/group_group_link_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module GroupLink + class GroupGroupLinkSerializer < BaseSerializer + entity GroupLink::GroupGroupLinkEntity + end +end diff --git a/app/serializers/group_link/group_link_entity.rb b/app/serializers/group_link/group_link_entity.rb new file mode 100644 index 00000000000..12349320b6f --- /dev/null +++ b/app/serializers/group_link/group_link_entity.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module GroupLink + class GroupLinkEntity < Grape::Entity + include RequestAwareEntity + + expose :id + expose :created_at + expose :expires_at do |group_link| + group_link.expires_at&.to_time + end + + expose :access_level do + expose :human_access, as: :string_value + expose :group_access, as: :integer_value + end + + expose :valid_roles do |group_link| + group_link.class.access_options + end + + expose :shared_with_group do + expose :avatar_url do |group_link| + group_link.shared_with_group.avatar_url(only_path: false, size: Member::AVATAR_SIZE) + end + + expose :web_url do |group_link| + group_link.shared_with_group.web_url + end + + expose :shared_with_group, merge: true, using: GroupBasicEntity + end + end +end diff --git a/app/serializers/group_link/project_group_link_entity.rb b/app/serializers/group_link/project_group_link_entity.rb new file mode 100644 index 00000000000..2ff275fff01 --- /dev/null +++ b/app/serializers/group_link/project_group_link_entity.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module GroupLink + class ProjectGroupLinkEntity < GroupLink::GroupLinkEntity + include RequestAwareEntity + include Projects::ProjectMembersHelper + + expose :can_update do |group_link| + can_manage_project_members?(group_link.project) + end + + expose :can_remove do |group_link| + can_manage_project_members?(group_link.project) + end + + private + + def current_user + options[:current_user] + end + end +end diff --git a/app/serializers/group_link/project_group_link_serializer.rb b/app/serializers/group_link/project_group_link_serializer.rb new file mode 100644 index 00000000000..b2559e61e31 --- /dev/null +++ b/app/serializers/group_link/project_group_link_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module GroupLink + class ProjectGroupLinkSerializer < BaseSerializer + entity GroupLink::ProjectGroupLinkEntity + end +end diff --git a/app/services/alert_management/http_integrations/update_service.rb b/app/services/alert_management/http_integrations/update_service.rb index 220c4e759f0..af079f670b8 100644 --- a/app/services/alert_management/http_integrations/update_service.rb +++ b/app/services/alert_management/http_integrations/update_service.rb @@ -9,7 +9,7 @@ module AlertManagement def initialize(integration, current_user, params) @integration = integration @current_user = current_user - @params = params + @params = params.with_indifferent_access end def execute @@ -17,7 +17,7 @@ module AlertManagement params[:token] = nil if params.delete(:regenerate_token) - if integration.update(params) + if integration.update(permitted_params) success else error(integration.errors.full_messages.to_sentence) @@ -32,6 +32,15 @@ module AlertManagement current_user&.can?(:admin_operations, integration) end + def permitted_params + params.slice(*permitted_params_keys) + end + + # overriden in EE + def permitted_params_keys + %i[name active token] + end + def error(message) ServiceResponse.error(message: message) end @@ -46,3 +55,5 @@ module AlertManagement end end end + +::AlertManagement::HttpIntegrations::UpdateService.prepend_if_ee('::EE::AlertManagement::HttpIntegrations::UpdateService') diff --git a/changelogs/unreleased/fj-create-group-repository-storage-move-table.yml b/changelogs/unreleased/fj-create-group-repository-storage-move-table.yml new file mode 100644 index 00000000000..bd0b61cf944 --- /dev/null +++ b/changelogs/unreleased/fj-create-group-repository-storage-move-table.yml @@ -0,0 +1,5 @@ +--- +title: Create Groups::RepositoryStorageMove table +merge_request: 51803 +author: +type: added diff --git a/changelogs/unreleased/id-update-bundler-audit.yml b/changelogs/unreleased/id-update-bundler-audit.yml new file mode 100644 index 00000000000..99cca4f2319 --- /dev/null +++ b/changelogs/unreleased/id-update-bundler-audit.yml @@ -0,0 +1,5 @@ +--- +title: Update bundler-audit gem to 0.7.0.1 +merge_request: 52269 +author: +type: other diff --git a/changelogs/unreleased/id-update-default-value-for.yml b/changelogs/unreleased/id-update-default-value-for.yml new file mode 100644 index 00000000000..e696aef5ab6 --- /dev/null +++ b/changelogs/unreleased/id-update-default-value-for.yml @@ -0,0 +1,5 @@ +--- +title: Update default_value_for gem to 3.4.0 +merge_request: 52271 +author: +type: other diff --git a/changelogs/unreleased/mc-backstage-cleanup-artifact-expiry-migration-problem.yml b/changelogs/unreleased/mc-backstage-cleanup-artifact-expiry-migration-problem.yml new file mode 100644 index 00000000000..bbe9a5bebfe --- /dev/null +++ b/changelogs/unreleased/mc-backstage-cleanup-artifact-expiry-migration-problem.yml @@ -0,0 +1,5 @@ +--- +title: Cancel artifact expiry backfill background jobs. +merge_request: 51821 +author: +type: fixed diff --git a/changelogs/unreleased/remove-owner-data-from-group-webhooks.yml b/changelogs/unreleased/remove-owner-data-from-group-webhooks.yml new file mode 100644 index 00000000000..0b1114ab974 --- /dev/null +++ b/changelogs/unreleased/remove-owner-data-from-group-webhooks.yml @@ -0,0 +1,5 @@ +--- +title: Remove group owner data from webhooks +merge_request: 52071 +author: +type: changed diff --git a/config/routes/project.rb b/config/routes/project.rb index 2e61bc8175e..c74d0c19d35 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -132,7 +132,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do end end - resources :project_members, except: [:show, :new, :edit], constraints: { id: %r{[a-zA-Z./0-9_\-#%+]+} }, concerns: :access_requestable do + resources :project_members, except: [:show, :new, :edit], constraints: { id: %r{[a-zA-Z./0-9_\-#%+:]+} }, concerns: :access_requestable do collection do delete :leave @@ -219,7 +219,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do resources :starrers, only: [:index] resources :forks, only: [:index, :new, :create] - resources :group_links, only: [:create, :update, :destroy], constraints: { id: /\d+/ } + resources :group_links, only: [:create, :update, :destroy], constraints: { id: /\d+|:id/ } resource :import, only: [:new, :create, :show] resource :avatar, only: [:show, :destroy] diff --git a/db/migrate/20210115090452_create_group_repository_storage_move.rb b/db/migrate/20210115090452_create_group_repository_storage_move.rb new file mode 100644 index 00000000000..bd168dce5ac --- /dev/null +++ b/db/migrate/20210115090452_create_group_repository_storage_move.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +class CreateGroupRepositoryStorageMove < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + unless table_exists?(:group_repository_storage_moves) + with_lock_retries do + create_table :group_repository_storage_moves do |t| + t.timestamps_with_timezone + t.references :group, references: :namespace, column: :group_id, index: true, null: false + t.integer :state, limit: 2, default: 1, null: false + t.text :source_storage_name, null: false + t.text :destination_storage_name, null: false + + t.foreign_key :namespaces, column: :group_id, on_delete: :cascade + end + end + end + + add_text_limit(:group_repository_storage_moves, :source_storage_name, 255, constraint_name: 'group_repository_storage_moves_source_storage_name') + add_text_limit(:group_repository_storage_moves, :destination_storage_name, 255, constraint_name: 'group_repository_storage_moves_destination_storage_name') + end + + def down + with_lock_retries do + drop_table :group_repository_storage_moves + end + end +end diff --git a/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb b/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb index f11c0bbe33a..1ffe9abbc58 100644 --- a/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb +++ b/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb @@ -24,12 +24,18 @@ class ScheduleBackfillingArtifactExpiryMigration < ActiveRecord::Migration[6.0] # Needs to be removed in a later migration add_concurrent_index(:ci_job_artifacts, %i(id created_at), where: INDEX_CONDITION, name: INDEX_NAME) - queue_background_migration_jobs_by_range_at_intervals( - JobArtifact.without_expiry_date.before_switch, - ::Gitlab::BackgroundMigration::BackfillArtifactExpiryDate, - 2.minutes, - batch_size: 200_000 - ) + # queue_background_migration_jobs_by_range_at_intervals( + # JobArtifact.without_expiry_date.before_switch, + # ::Gitlab::BackgroundMigration::BackfillArtifactExpiryDate, + # 2.minutes, + # batch_size: 200_000 + # ) + # The scheduling code was using the full class symbol + # (`::Gitlab::BackgroundMigration::BackfillArtifactExpiryDate`) instead of a + # string with the class name (`BackfillArtifactExpiryDate`) by mistake, + # which resulted in an error. It is commented out so it's a no-op to prevent + # errors and will be reintroduced with + # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51822. end def down diff --git a/db/post_migrate/20210115215854_cancel_artifact_expiry_backfill.rb b/db/post_migrate/20210115215854_cancel_artifact_expiry_backfill.rb new file mode 100644 index 00000000000..8a03a90a1c5 --- /dev/null +++ b/db/post_migrate/20210115215854_cancel_artifact_expiry_backfill.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class CancelArtifactExpiryBackfill < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + MIGRATION = 'BackfillArtifactExpiryDate' + + disable_ddl_transaction! + + def up + Gitlab::BackgroundMigration.steal(MIGRATION) do |job| + job.delete + + false + end + end + + def down + # no-op + end +end diff --git a/db/schema_migrations/20210115090452 b/db/schema_migrations/20210115090452 new file mode 100644 index 00000000000..92c5574e71f --- /dev/null +++ b/db/schema_migrations/20210115090452 @@ -0,0 +1 @@ +5415850ae27c507fd8b1df20951e25b42352f4f9ec8e1402019533170edabdb8
\ No newline at end of file diff --git a/db/schema_migrations/20210115215854 b/db/schema_migrations/20210115215854 new file mode 100644 index 00000000000..c27de41ad0a --- /dev/null +++ b/db/schema_migrations/20210115215854 @@ -0,0 +1 @@ +cb846ce5f6270cfdc543c3d4ad3e861b2a92445b952ee8f0a02f4171b9792411
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index ddbd329d9f2..2939895ec07 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -13044,6 +13044,27 @@ CREATE TABLE group_merge_request_approval_settings ( allow_author_approval boolean DEFAULT false NOT NULL ); +CREATE TABLE group_repository_storage_moves ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + group_id bigint NOT NULL, + state smallint DEFAULT 1 NOT NULL, + source_storage_name text NOT NULL, + destination_storage_name text NOT NULL, + CONSTRAINT group_repository_storage_moves_destination_storage_name CHECK ((char_length(destination_storage_name) <= 255)), + CONSTRAINT group_repository_storage_moves_source_storage_name CHECK ((char_length(source_storage_name) <= 255)) +); + +CREATE SEQUENCE group_repository_storage_moves_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE group_repository_storage_moves_id_seq OWNED BY group_repository_storage_moves.id; + CREATE TABLE group_wiki_repositories ( shard_id bigint NOT NULL, group_id bigint NOT NULL, @@ -18733,6 +18754,8 @@ ALTER TABLE ONLY group_group_links ALTER COLUMN id SET DEFAULT nextval('group_gr ALTER TABLE ONLY group_import_states ALTER COLUMN group_id SET DEFAULT nextval('group_import_states_group_id_seq'::regclass); +ALTER TABLE ONLY group_repository_storage_moves ALTER COLUMN id SET DEFAULT nextval('group_repository_storage_moves_id_seq'::regclass); + ALTER TABLE ONLY historical_data ALTER COLUMN id SET DEFAULT nextval('historical_data_id_seq'::regclass); ALTER TABLE ONLY identities ALTER COLUMN id SET DEFAULT nextval('identities_id_seq'::regclass); @@ -19969,6 +19992,9 @@ ALTER TABLE ONLY group_import_states ALTER TABLE ONLY group_merge_request_approval_settings ADD CONSTRAINT group_merge_request_approval_settings_pkey PRIMARY KEY (group_id); +ALTER TABLE ONLY group_repository_storage_moves + ADD CONSTRAINT group_repository_storage_moves_pkey PRIMARY KEY (id); + ALTER TABLE ONLY group_wiki_repositories ADD CONSTRAINT group_wiki_repositories_pkey PRIMARY KEY (group_id); @@ -21950,6 +21976,8 @@ CREATE INDEX index_group_import_states_on_group_id ON group_import_states USING CREATE INDEX index_group_import_states_on_user_id ON group_import_states USING btree (user_id) WHERE (user_id IS NOT NULL); +CREATE INDEX index_group_repository_storage_moves_on_group_id ON group_repository_storage_moves USING btree (group_id); + CREATE UNIQUE INDEX index_group_stages_on_group_id_group_value_stream_id_and_name ON analytics_cycle_analytics_group_stages USING btree (group_id, group_value_stream_id, name); CREATE UNIQUE INDEX index_group_wiki_repositories_on_disk_path ON group_wiki_repositories USING btree (disk_path); @@ -25260,6 +25288,9 @@ ALTER TABLE ONLY packages_pypi_metadata ALTER TABLE ONLY packages_dependency_links ADD CONSTRAINT fk_rails_96ef1c00d3 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE; +ALTER TABLE ONLY group_repository_storage_moves + ADD CONSTRAINT fk_rails_982bb5daf1 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE; + ALTER TABLE ONLY resource_label_events ADD CONSTRAINT fk_rails_9851a00031 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE; diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md index 0d8eba555ab..41e9dbe677c 100644 --- a/doc/administration/geo/replication/version_specific_updates.md +++ b/doc/administration/geo/replication/version_specific_updates.md @@ -11,6 +11,14 @@ Check this document if it includes instructions for the version you are updating These steps go together with the [general steps](updating_the_geo_nodes.md#general-update-steps) for updating Geo nodes. +## Updating to GitLab 13.8 + +We've detected an issue with the `FetchRemove` call that is used by Geo secondaries. This causes performance issues as we execute reference transaction hooks for each updated reference. Please hold off upgrading until this is in [the 13.8.1 patch release.](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3002). More details are available [in this issue](https://gitlab.com/gitlab-org/git/-/issues/79). + +## Updating to GitLab 13.7 + +We've detected an issue with the `FetchRemove` call that is used by Geo secondaries. This causes performance issues as we execute reference transaction hooks for each updated reference. Please hold off upgrading until this is in [the 13.7.5 patch release.](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3002). More details are available [in this issue](https://gitlab.com/gitlab-org/git/-/issues/79). + ## Updating to GitLab 13.5 In GitLab 13.5, there is a [regression that prevents viewing a list of container repositories and registries](https://gitlab.com/gitlab-org/gitlab/-/issues/285475) on Geo secondaries. This issue is fixed in GitLab 13.6.1 and later. diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql index 5bd712a9caa..c0bf434bf98 100644 --- a/doc/api/graphql/reference/gitlab_schema.graphql +++ b/doc/api/graphql/reference/gitlab_schema.graphql @@ -11622,6 +11622,16 @@ input HttpIntegrationUpdateInput { The name of the integration. """ name: String + + """ + The custom mapping of GitLab alert attributes to fields from the payload_example. + """ + payloadAttributeMappings: [AlertManagementPayloadAlertFieldInput!] + + """ + The example of an alert payload. + """ + payloadExample: JsonString } """ diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json index eb1792dc4b8..156befc5109 100644 --- a/doc/api/graphql/reference/gitlab_schema.json +++ b/doc/api/graphql/reference/gitlab_schema.json @@ -31575,6 +31575,34 @@ "defaultValue": null }, { + "name": "payloadExample", + "description": "The example of an alert payload.", + "type": { + "kind": "SCALAR", + "name": "JsonString", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "payloadAttributeMappings", + "description": "The custom mapping of GitLab alert attributes to fields from the payload_example.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AlertManagementPayloadAlertFieldInput", + "ofType": null + } + } + }, + "defaultValue": null + }, + { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", "type": { diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md index 7e4d274f21b..196d88bc530 100644 --- a/doc/system_hooks/system_hooks.md +++ b/doc/system_hooks/system_hooks.md @@ -300,15 +300,11 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`. "updated_at": "2012-07-21T07:38:22Z", "event_name": "group_create", "name": "StoreCloud", - "owner_email": null, - "owner_name": null, "path": "storecloud", "group_id": 78 } ``` -`owner_name` and `owner_email` are always `null`. Please see <https://gitlab.com/gitlab-org/gitlab/-/issues/20011>. - **Group removed:** ```json @@ -317,15 +313,11 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`. "updated_at": "2012-07-21T07:38:22Z", "event_name": "group_destroy", "name": "StoreCloud", - "owner_email": null, - "owner_name": null, "path": "storecloud", "group_id": 78 } ``` -`owner_name` and `owner_email` are always `null`. Please see [issue #20011](https://gitlab.com/gitlab-org/gitlab/-/issues/20011). - **Group renamed:** ```json @@ -337,15 +329,11 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`. "path": "better-name", "full_path": "parent-group/better-name", "group_id": 64, - "owner_name": null, - "owner_email": null, "old_path": "old-name", "old_full_path": "parent-group/old-name" } ``` -`owner_name` and `owner_email` are always `null`. Please see <https://gitlab.com/gitlab-org/gitlab/-/issues/20011>. - **New Group Member:** ```json diff --git a/lib/api/debian_group_packages.rb b/lib/api/debian_group_packages.rb index e3cacc4132f..2235e0858ac 100644 --- a/lib/api/debian_group_packages.rb +++ b/lib/api/debian_group_packages.rb @@ -13,7 +13,7 @@ module API authorize_read_package!(user_group) end - namespace ':id/-/packages/debian' do + namespace ':id/packages/debian' do include DebianPackageEndpoints end end diff --git a/lib/api/debian_package_endpoints.rb b/lib/api/debian_package_endpoints.rb index 9aff34933f7..507c9a5c3eb 100644 --- a/lib/api/debian_package_endpoints.rb +++ b/lib/api/debian_package_endpoints.rb @@ -51,7 +51,7 @@ module API end namespace 'dists/*distribution', requirements: DISTRIBUTION_REQUIREMENTS do - # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/Release.gpg + # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release.gpg desc 'The Release file signature' do detail 'This feature was introduced in GitLab 13.5' end @@ -61,7 +61,7 @@ module API not_found! end - # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/Release + # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release desc 'The unsigned Release file' do detail 'This feature was introduced in GitLab 13.5' end @@ -72,7 +72,7 @@ module API 'TODO Release' end - # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/InRelease + # GET {projects|groups}/:id/packages/debian/dists/*distribution/InRelease desc 'The signed Release file' do detail 'This feature was introduced in GitLab 13.5' end @@ -88,7 +88,7 @@ module API end namespace ':component/binary-:architecture', requirements: COMPONENT_ARCHITECTURE_REQUIREMENTS do - # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages + # GET {projects|groups}/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages desc 'The binary files index' do detail 'This feature was introduced in GitLab 13.5' end @@ -108,7 +108,7 @@ module API end namespace 'pool/:component/:letter/:source_package', requirements: COMPONENT_LETTER_SOURCE_PACKAGE_REQUIREMENTS do - # GET {projects|groups}/:id/-/packages/debian/pool/:component/:letter/:source_package/:file_name + # GET {projects|groups}/:id/packages/debian/pool/:component/:letter/:source_package/:file_name params do requires :file_name, type: String, desc: 'The Debian File Name' end diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb index f8129c18dff..8ae0d2ba28b 100644 --- a/lib/api/debian_project_packages.rb +++ b/lib/api/debian_project_packages.rb @@ -13,17 +13,17 @@ module API authorize_read_package! end - namespace ':id/-/packages/debian' do + namespace ':id/packages/debian' do include DebianPackageEndpoints params do requires :file_name, type: String, desc: 'The file name' end - namespace 'incoming/:file_name', requirements: FILE_NAME_REQUIREMENTS do + namespace ':file_name', requirements: FILE_NAME_REQUIREMENTS do content_type :json, Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE - # PUT {projects|groups}/:id/-/packages/debian/incoming/:file_name + # PUT {projects|groups}/:id/packages/debian/:file_name params do requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' end @@ -42,7 +42,7 @@ module API forbidden! end - # PUT {projects|groups}/:id/-/packages/debian/incoming/:file_name/authorize + # PUT {projects|groups}/:id/packages/debian/:file_name/authorize route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth put 'authorize' do authorize_workhorse!( diff --git a/lib/gitlab/hook_data/group_builder.rb b/lib/gitlab/hook_data/group_builder.rb index 25c34a4c4a7..5f76144eb83 100644 --- a/lib/gitlab/hook_data/group_builder.rb +++ b/lib/gitlab/hook_data/group_builder.rb @@ -14,8 +14,6 @@ module Gitlab # :path=>"group1", # :full_path=>"group1", # :group_id=>1, - # :owner_name=>nil, - # :owner_email=>nil, # :old_path=>"old-path", # :old_full_path=>"old-path" # } @@ -32,15 +30,11 @@ module Gitlab private def group_data - owner = group.owner - { name: group.name, path: group.path, full_path: group.full_path, - group_id: group.id, - owner_name: owner.try(:name), - owner_email: owner.try(:email) + group_id: group.id } end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 48e9d55d3ca..87184ea37aa 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -7989,6 +7989,9 @@ msgstr "" msgid "Copy value" msgstr "" +msgid "CorpusManagement|Fuzz testing corpus management" +msgstr "" + msgid "Could not add admins as members" msgstr "" diff --git a/spec/fixtures/api/schemas/group_group_links.json b/spec/fixtures/api/schemas/group_group_links.json deleted file mode 100644 index f8b4e7f035b..00000000000 --- a/spec/fixtures/api/schemas/group_group_links.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "type": "array", - "items": { - "$ref": "entities/group_group_link.json" - } -} diff --git a/spec/fixtures/api/schemas/group_link/group_group_link.json b/spec/fixtures/api/schemas/group_link/group_group_link.json new file mode 100644 index 00000000000..bfca5c885e3 --- /dev/null +++ b/spec/fixtures/api/schemas/group_link/group_group_link.json @@ -0,0 +1,16 @@ +{ + "type": "object", + "allOf": [ + { "$ref": "group_link.json" }, + { + "required": [ + "can_update", + "can_remove" + ], + "properties": { + "can_update": { "type": "boolean" }, + "can_remove": { "type": "boolean" } + } + } + ] +} diff --git a/spec/fixtures/api/schemas/group_link/group_group_links.json b/spec/fixtures/api/schemas/group_link/group_group_links.json new file mode 100644 index 00000000000..2c0bf20f524 --- /dev/null +++ b/spec/fixtures/api/schemas/group_link/group_group_links.json @@ -0,0 +1,6 @@ +{ + "type": "array", + "items": { + "$ref": "group_group_link.json" + } +} diff --git a/spec/fixtures/api/schemas/entities/group_group_link.json b/spec/fixtures/api/schemas/group_link/group_link.json index bf94bbb3ce4..300790728a8 100644 --- a/spec/fixtures/api/schemas/entities/group_group_link.json +++ b/spec/fixtures/api/schemas/group_link/group_link.json @@ -4,8 +4,6 @@ "id", "created_at", "expires_at", - "can_update", - "can_remove", "access_level", "valid_roles" ], @@ -13,15 +11,14 @@ "id": { "type": "integer" }, "created_at": { "type": "date-time" }, "expires_at": { "type": ["date-time", "null"] }, - "can_update": { "type": "boolean" }, - "can_remove": { "type": "boolean" }, "access_level": { "type": "object", "required": ["integer_value", "string_value"], "properties": { "integer_value": { "type": "integer" }, "string_value": { "type": "string" } - } + }, + "additionalProperties": false }, "valid_roles": { "type": "object" }, "shared_with_group": { @@ -34,7 +31,8 @@ "full_path": { "type": "string" }, "avatar_url": { "type": ["string", "null"] }, "web_url": { "type": "string" } - } + }, + "additionalProperties": false } } } diff --git a/spec/fixtures/api/schemas/group_link/project_group_link.json b/spec/fixtures/api/schemas/group_link/project_group_link.json new file mode 100644 index 00000000000..bfca5c885e3 --- /dev/null +++ b/spec/fixtures/api/schemas/group_link/project_group_link.json @@ -0,0 +1,16 @@ +{ + "type": "object", + "allOf": [ + { "$ref": "group_link.json" }, + { + "required": [ + "can_update", + "can_remove" + ], + "properties": { + "can_update": { "type": "boolean" }, + "can_remove": { "type": "boolean" } + } + } + ] +} diff --git a/spec/fixtures/api/schemas/group_link/project_group_links.json b/spec/fixtures/api/schemas/group_link/project_group_links.json new file mode 100644 index 00000000000..fc024d67f36 --- /dev/null +++ b/spec/fixtures/api/schemas/group_link/project_group_links.json @@ -0,0 +1,6 @@ +{ + "type": "array", + "items": { + "$ref": "project_group_link.json" + } +} diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb index e83585e5efb..99efc7963e6 100644 --- a/spec/helpers/groups/group_members_helper_spec.rb +++ b/spec/helpers/groups/group_members_helper_spec.rb @@ -29,7 +29,7 @@ RSpec.describe Groups::GroupMembersHelper do it 'matches json schema' do json = helper.group_group_links_data_json(shared_group.shared_with_group_links) - expect(json).to match_schema('group_group_links') + expect(json).to match_schema('group_link/group_group_links') end end diff --git a/spec/helpers/projects/project_members_helper_spec.rb b/spec/helpers/projects/project_members_helper_spec.rb index cc290367e34..5e0b4df7f7f 100644 --- a/spec/helpers/projects/project_members_helper_spec.rb +++ b/spec/helpers/projects/project_members_helper_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Projects::ProjectMembersHelper do + include MembersPresentation + let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } @@ -142,4 +144,58 @@ RSpec.describe Projects::ProjectMembersHelper do it { is_expected.to be(false) } end end + + describe 'project members' do + let_it_be(:project_members) { create_list(:project_member, 1, project: project) } + + describe '#project_members_data_json' do + it 'matches json schema' do + expect(helper.project_members_data_json(project, present_members(project_members))).to match_schema('members') + end + end + + describe '#project_members_list_data_attributes' do + let(:allow_admin_project) { true } + + before do + allow(helper).to receive(:project_project_member_path).with(project, ':id').and_return('/foo-bar/-/project_members/:id') + end + + it 'returns expected hash' do + expect(helper.project_members_list_data_attributes(project, present_members(project_members))).to include({ + members: helper.project_members_data_json(project, present_members(project_members)), + member_path: '/foo-bar/-/project_members/:id', + source_id: project.id, + can_manage_members: true + }) + end + end + end + + describe 'project group links' do + let_it_be(:project_group_links) { create_list(:project_group_link, 1, project: project) } + let(:allow_admin_project) { true } + + describe '#project_group_links_data_json' do + it 'matches json schema' do + expect(helper.project_group_links_data_json(project_group_links)).to match_schema('group_link/project_group_links') + end + end + + describe '#project_group_links_list_data_attributes' do + before do + allow(helper).to receive(:project_group_link_path).with(project, ':id').and_return('/foo-bar/-/group_links/:id') + allow(helper).to receive(:can?).with(current_user, :admin_project_member, project).and_return(true) + end + + it 'returns expected hash' do + expect(helper.project_group_links_list_data_attributes(project, project_group_links)).to include({ + members: helper.project_group_links_data_json(project_group_links), + member_path: '/foo-bar/-/group_links/:id', + source_id: project.id, + can_manage_members: true + }) + end + end + end end diff --git a/spec/lib/gitlab/hook_data/group_builder_spec.rb b/spec/lib/gitlab/hook_data/group_builder_spec.rb index d95669d502f..d7347ff99d4 100644 --- a/spec/lib/gitlab/hook_data/group_builder_spec.rb +++ b/spec/lib/gitlab/hook_data/group_builder_spec.rb @@ -10,8 +10,7 @@ RSpec.describe Gitlab::HookData::GroupBuilder do let(:event_name) { data[:event_name] } let(:attributes) do [ - :event_name, :created_at, :updated_at, :name, :path, :full_path, :group_id, - :owner_name, :owner_email + :event_name, :created_at, :updated_at, :name, :path, :full_path, :group_id ] end @@ -24,8 +23,6 @@ RSpec.describe Gitlab::HookData::GroupBuilder do expect(data[:path]).to eq(group.path) expect(data[:full_path]).to eq(group.full_path) expect(data[:group_id]).to eq(group.id) - expect(data[:owner_name]).to eq(nil) - expect(data[:owner_email]).to eq(nil) expect(data[:created_at]).to eq(group.created_at.xmlschema) expect(data[:updated_at]).to eq(group.updated_at.xmlschema) end diff --git a/spec/requests/api/debian_group_packages_spec.rb b/spec/requests/api/debian_group_packages_spec.rb index 8a05d20fb33..9d63d675a02 100644 --- a/spec/requests/api/debian_group_packages_spec.rb +++ b/spec/requests/api/debian_group_packages_spec.rb @@ -6,32 +6,32 @@ RSpec.describe API::DebianGroupPackages do include WorkhorseHelpers include_context 'Debian repository shared context', :group do - describe 'GET groups/:id/-/packages/debian/dists/*distribution/Release.gpg' do - let(:url) { "/groups/#{group.id}/-/packages/debian/dists/#{distribution}/Release.gpg" } + describe 'GET groups/:id/packages/debian/dists/*distribution/Release.gpg' do + let(:url) { "/groups/#{group.id}/packages/debian/dists/#{distribution}/Release.gpg" } it_behaves_like 'Debian group repository GET endpoint', :not_found, nil end - describe 'GET groups/:id/-/packages/debian/dists/*distribution/Release' do - let(:url) { "/groups/#{group.id}/-/packages/debian/dists/#{distribution}/Release" } + describe 'GET groups/:id/packages/debian/dists/*distribution/Release' do + let(:url) { "/groups/#{group.id}/packages/debian/dists/#{distribution}/Release" } it_behaves_like 'Debian group repository GET endpoint', :success, 'TODO Release' end - describe 'GET groups/:id/-/packages/debian/dists/*distribution/InRelease' do - let(:url) { "/groups/#{group.id}/-/packages/debian/dists/#{distribution}/InRelease" } + describe 'GET groups/:id/packages/debian/dists/*distribution/InRelease' do + let(:url) { "/groups/#{group.id}/packages/debian/dists/#{distribution}/InRelease" } it_behaves_like 'Debian group repository GET endpoint', :not_found, nil end - describe 'GET groups/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do - let(:url) { "/groups/#{group.id}/-/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" } + describe 'GET groups/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do + let(:url) { "/groups/#{group.id}/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" } it_behaves_like 'Debian group repository GET endpoint', :success, 'TODO Packages' end - describe 'GET groups/:id/-/packages/debian/pool/:component/:letter/:source_package/:file_name' do - let(:url) { "/groups/#{group.id}/-/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" } + describe 'GET groups/:id/packages/debian/pool/:component/:letter/:source_package/:file_name' do + let(:url) { "/groups/#{group.id}/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" } it_behaves_like 'Debian group repository GET endpoint', :success, 'TODO File' end diff --git a/spec/requests/api/debian_project_packages_spec.rb b/spec/requests/api/debian_project_packages_spec.rb index 663b69b1b76..4941f2a77f4 100644 --- a/spec/requests/api/debian_project_packages_spec.rb +++ b/spec/requests/api/debian_project_packages_spec.rb @@ -6,46 +6,46 @@ RSpec.describe API::DebianProjectPackages do include WorkhorseHelpers include_context 'Debian repository shared context', :project do - describe 'GET projects/:id/-/packages/debian/dists/*distribution/Release.gpg' do - let(:url) { "/projects/#{project.id}/-/packages/debian/dists/#{distribution}/Release.gpg" } + describe 'GET projects/:id/packages/debian/dists/*distribution/Release.gpg' do + let(:url) { "/projects/#{project.id}/packages/debian/dists/#{distribution}/Release.gpg" } it_behaves_like 'Debian project repository GET endpoint', :not_found, nil end - describe 'GET projects/:id/-/packages/debian/dists/*distribution/Release' do - let(:url) { "/projects/#{project.id}/-/packages/debian/dists/#{distribution}/Release" } + describe 'GET projects/:id/packages/debian/dists/*distribution/Release' do + let(:url) { "/projects/#{project.id}/packages/debian/dists/#{distribution}/Release" } it_behaves_like 'Debian project repository GET endpoint', :success, 'TODO Release' end - describe 'GET projects/:id/-/packages/debian/dists/*distribution/InRelease' do - let(:url) { "/projects/#{project.id}/-/packages/debian/dists/#{distribution}/InRelease" } + describe 'GET projects/:id/packages/debian/dists/*distribution/InRelease' do + let(:url) { "/projects/#{project.id}/packages/debian/dists/#{distribution}/InRelease" } it_behaves_like 'Debian project repository GET endpoint', :not_found, nil end - describe 'GET projects/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do - let(:url) { "/projects/#{project.id}/-/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" } + describe 'GET projects/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do + let(:url) { "/projects/#{project.id}/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" } it_behaves_like 'Debian project repository GET endpoint', :success, 'TODO Packages' end - describe 'GET projects/:id/-/packages/debian/pool/:component/:letter/:source_package/:file_name' do - let(:url) { "/projects/#{project.id}/-/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" } + describe 'GET projects/:id/packages/debian/pool/:component/:letter/:source_package/:file_name' do + let(:url) { "/projects/#{project.id}/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" } it_behaves_like 'Debian project repository GET endpoint', :success, 'TODO File' end - describe 'PUT projects/:id/-/packages/debian/incoming/:file_name' do + describe 'PUT projects/:id/packages/debian/:file_name' do let(:method) { :put } - let(:url) { "/projects/#{project.id}/-/packages/debian/incoming/#{file_name}" } + let(:url) { "/projects/#{project.id}/packages/debian/#{file_name}" } it_behaves_like 'Debian project repository PUT endpoint', :created, nil end - describe 'PUT projects/:id/-/packages/debian/incoming/:file_name/authorize' do + describe 'PUT projects/:id/packages/debian/:file_name/authorize' do let(:method) { :put } - let(:url) { "/projects/#{project.id}/-/packages/debian/incoming/#{file_name}/authorize" } + let(:url) { "/projects/#{project.id}/packages/debian/#{file_name}/authorize" } it_behaves_like 'Debian project repository PUT endpoint', :created, nil, is_authorize: true end diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb index bf7eb3d980c..18cbb7d8b00 100644 --- a/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Updating an existing HTTP Integration' do include GraphqlHelpers - let_it_be(:user) { create(:user) } + let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } let_it_be(:integration) { create(:alert_management_http_integration, project: project) } @@ -32,18 +32,8 @@ RSpec.describe 'Updating an existing HTTP Integration' do let(:mutation_response) { graphql_mutation_response(:http_integration_update) } before do - project.add_maintainer(user) + project.add_maintainer(current_user) end - it 'updates the integration' do - post_graphql_mutation(mutation, current_user: user) - - integration_response = mutation_response['integration'] - - expect(response).to have_gitlab_http_status(:success) - expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s) - expect(integration_response['name']).to eq('Modified Name') - expect(integration_response['active']).to be_falsey - expect(integration_response['url']).to include('modified-name') - end + it_behaves_like 'updating an existing HTTP integration' end diff --git a/spec/serializers/group_group_link_entity_spec.rb b/spec/serializers/group_link/group_group_link_entity_spec.rb index 9affe4af381..15bcbbcb1d6 100644 --- a/spec/serializers/group_group_link_entity_spec.rb +++ b/spec/serializers/group_link/group_group_link_entity_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GroupGroupLinkEntity do +RSpec.describe GroupLink::GroupGroupLinkEntity do include_context 'group_group_link' let_it_be(:current_user) { create(:user) } @@ -13,15 +13,15 @@ RSpec.describe GroupGroupLinkEntity do end it 'matches json schema' do - expect(entity.to_json).to match_schema('entities/group_group_link') + expect(entity.to_json).to match_schema('group_link/group_group_link') end - context 'a user with :admin_group_member permissions' do + context 'when current user has `:admin_group_member` permissions' do before do allow(entity).to receive(:can?).with(current_user, :admin_group_member, shared_group).and_return(true) end - it 'sets `can_update` and `can_remove` to `true`' do + it 'exposes `can_update` and `can_remove` as `true`' do json = entity.as_json expect(json[:can_update]).to be true diff --git a/spec/serializers/group_group_link_serializer_spec.rb b/spec/serializers/group_link/group_group_link_serializer_spec.rb index 0d977ea0a9a..a4ca32dae7b 100644 --- a/spec/serializers/group_group_link_serializer_spec.rb +++ b/spec/serializers/group_link/group_group_link_serializer_spec.rb @@ -2,12 +2,12 @@ require 'spec_helper' -RSpec.describe GroupGroupLinkSerializer do +RSpec.describe GroupLink::GroupGroupLinkSerializer do include_context 'group_group_link' subject(:json) { described_class.new.represent(shared_group.shared_with_group_links).to_json } it 'matches json schema' do - expect(json).to match_schema('group_group_links') + expect(json).to match_schema('group_link/group_group_links') end end diff --git a/spec/serializers/group_link/group_link_entity_spec.rb b/spec/serializers/group_link/group_link_entity_spec.rb new file mode 100644 index 00000000000..941445feaa2 --- /dev/null +++ b/spec/serializers/group_link/group_link_entity_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GroupLink::GroupLinkEntity do + include_context 'group_group_link' + + let(:entity) { described_class.new(group_group_link) } + let(:entity_hash) { entity.as_json } + + it 'matches json schema' do + expect(entity.to_json).to match_schema('group_link/group_link') + end + + it 'correctly exposes `valid_roles`' do + expect(entity_hash[:valid_roles]).to include(Gitlab::Access.options_with_owner) + end + + it 'correctly exposes `shared_with_group.avatar_url`' do + avatar_url = 'https://gitlab.com/uploads/-/system/group/avatar/24/foobar.png?width=40' + allow(shared_with_group).to receive(:avatar_url).with(only_path: false, size: Member::AVATAR_SIZE).and_return(avatar_url) + + expect(entity_hash[:shared_with_group][:avatar_url]).to match(avatar_url) + end +end diff --git a/spec/serializers/group_link/project_group_link_entity_spec.rb b/spec/serializers/group_link/project_group_link_entity_spec.rb new file mode 100644 index 00000000000..0bb3d06933b --- /dev/null +++ b/spec/serializers/group_link/project_group_link_entity_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GroupLink::ProjectGroupLinkEntity do + let_it_be(:current_user) { create(:user) } + let_it_be(:project_group_link) { create(:project_group_link) } + let(:entity) { described_class.new(project_group_link) } + + before do + allow(entity).to receive(:current_user).and_return(current_user) + end + + it 'matches json schema' do + expect(entity.to_json).to match_schema('group_link/project_group_link') + end + + context 'when current user has `admin_project_member` permissions' do + before do + allow(entity).to receive(:can?).with(current_user, :admin_project_member, project_group_link.project).and_return(true) + end + + it 'exposes `can_update` and `can_remove` as `true`' do + json = entity.as_json + + expect(json[:can_update]).to be true + expect(json[:can_remove]).to be true + end + end +end diff --git a/spec/serializers/group_link/project_group_link_serializer_spec.rb b/spec/serializers/group_link/project_group_link_serializer_spec.rb new file mode 100644 index 00000000000..ecd5d4d70e4 --- /dev/null +++ b/spec/serializers/group_link/project_group_link_serializer_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GroupLink::ProjectGroupLinkSerializer do + let_it_be(:project_group_links) { create_list(:project_group_link, 1) } + + subject(:json) { described_class.new.represent(project_group_links).to_json } + + it 'matches json schema' do + expect(json).to match_schema('group_link/project_group_links') + end +end diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb index 63ed19bd556..1ec5237370f 100644 --- a/spec/services/system_hooks_service_spec.rb +++ b/spec/services/system_hooks_service_spec.rb @@ -45,15 +45,13 @@ RSpec.describe SystemHooksService do it do expect(event_data(group, :create)).to include( - :event_name, :name, :created_at, :updated_at, :path, :group_id, - :owner_name, :owner_email + :event_name, :name, :created_at, :updated_at, :path, :group_id ) end it do expect(event_data(group, :destroy)).to include( - :event_name, :name, :created_at, :updated_at, :path, :group_id, - :owner_name, :owner_email + :event_name, :name, :created_at, :updated_at, :path, :group_id ) end diff --git a/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb index 0338eb43f8d..4468af1a603 100644 --- a/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb +++ b/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb @@ -17,3 +17,78 @@ RSpec.shared_examples 'creating a new HTTP integration' do expect(integration_response['apiUrl']).to eq(nil) end end + +RSpec.shared_examples 'updating an existing HTTP integration' do + it 'updates the integration' do + post_graphql_mutation(mutation, current_user: current_user) + + integration_response = mutation_response['integration'] + + expect(response).to have_gitlab_http_status(:success) + expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s) + expect(integration_response['name']).to eq('Modified Name') + expect(integration_response['active']).to be_falsey + expect(integration_response['url']).to include('modified-name') + end +end + +RSpec.shared_examples 'validating the payload_example' do + context 'with invalid payloadExample attribute' do + let(:payload_example) { 'not a JSON' } + + it 'responds with errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect_graphql_errors_to_include(/was provided invalid value for payloadExample \(Invalid JSON string/) + end + end + + it 'validates the payload_example size' do + allow(::Gitlab::Utils::DeepSize) + .to receive(:new) + .with(Gitlab::Json.parse(payload_example)) + .and_return(double(valid?: false)) + + post_graphql_mutation(mutation, current_user: current_user) + + expect_graphql_errors_to_include(/payloadExample JSON is too big/) + end +end + +RSpec.shared_examples 'validating the payload_attribute_mappings' do + context 'with invalid payloadAttributeMapping attribute does not contain fieldName' do + let(:payload_attribute_mappings) do + [{ path: %w[alert name], type: 'STRING' }] + end + + it 'responds with errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect_graphql_errors_to_include(/was provided invalid value for payloadAttributeMappings\.0\.fieldName \(Expected value to not be null/) + end + end + + context 'with invalid payloadAttributeMapping attribute does not contain path' do + let(:payload_attribute_mappings) do + [{ fieldName: 'TITLE', type: 'STRING' }] + end + + it 'responds with errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect_graphql_errors_to_include(/was provided invalid value for payloadAttributeMappings\.0\.path \(Expected value to not be null/) + end + end + + context 'with invalid payloadAttributeMapping attribute does not contain type' do + let(:payload_attribute_mappings) do + [{ fieldName: 'TITLE', path: %w[alert name] }] + end + + it 'responds with errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect_graphql_errors_to_include(/was provided invalid value for payloadAttributeMappings\.0\.type \(Expected value to not be null/) + end + end +end |