From de1e0eade13ed77b6d003e91437cfa5d46abf8b7 Mon Sep 17 00:00:00 2001 From: Jerry Seto <jseto@gitlab.com> Date: Fri, 10 May 2024 20:49:40 +0000 Subject: [PATCH] Fix error on deleting exclusions and limit creating exclusions --- .../integrations/exclusions/create.rb | 9 +++++-- .../integrations/exclusions/delete.rb | 2 +- .../exclusions/destroy_service.rb | 5 +++- doc/api/graphql/reference/index.md | 4 ++-- .../integrations/exclusions/create_spec.rb | 16 +++++++++++++ .../integrations/exclusions/delete_spec.rb | 24 ++++++++++++------- 6 files changed, 46 insertions(+), 14 deletions(-) diff --git a/app/graphql/mutations/integrations/exclusions/create.rb b/app/graphql/mutations/integrations/exclusions/create.rb index 7949b2a267bc..483e3b0fba8d 100644 --- a/app/graphql/mutations/integrations/exclusions/create.rb +++ b/app/graphql/mutations/integrations/exclusions/create.rb @@ -6,6 +6,7 @@ module Exclusions class Create < BaseMutation graphql_name 'IntegrationExclusionCreate' include ResolvesIds + MAX_PROJECT_IDS = 100 field :exclusions, [::Types::Integrations::ExclusionType], null: true, @@ -19,14 +20,18 @@ class Create < BaseMutation argument :project_ids, [::Types::GlobalIDType[::Project]], required: true, - description: 'Ids of projects to exclude.' + description: "IDs of projects to exclude up to a maximum of #{MAX_PROJECT_IDS}." authorize :admin_all_resources def resolve(integration_name:, project_ids:) authorize!(:global) - projects = Project.id_in(resolve_ids(project_ids)) + if project_ids.length > MAX_PROJECT_IDS + raise Gitlab::Graphql::Errors::ArgumentError, "Count of projectIds should be less than #{MAX_PROJECT_IDS}" + end + + projects = Project.id_in(resolve_ids(project_ids)).limit(MAX_PROJECT_IDS) result = ::Integrations::Exclusions::CreateService.new( current_user: current_user, diff --git a/app/graphql/mutations/integrations/exclusions/delete.rb b/app/graphql/mutations/integrations/exclusions/delete.rb index d01d8c6776ed..bf76c07a1508 100644 --- a/app/graphql/mutations/integrations/exclusions/delete.rb +++ b/app/graphql/mutations/integrations/exclusions/delete.rb @@ -19,7 +19,7 @@ class Delete < BaseMutation argument :project_ids, [::Types::GlobalIDType[::Project]], required: true, - description: 'Id of excluded project.' + description: 'IDs of excluded projects.' authorize :admin_all_resources diff --git a/app/services/integrations/exclusions/destroy_service.rb b/app/services/integrations/exclusions/destroy_service.rb index cee0af8f9c88..6fd1fd201617 100644 --- a/app/services/integrations/exclusions/destroy_service.rb +++ b/app/services/integrations/exclusions/destroy_service.rb @@ -19,7 +19,10 @@ def destroy_exclusions instance_integration = integration_class.for_instance.first - return ServiceResponse.success(payload: exclusions.destroy_all) unless instance_integration # rubocop: disable Cop/DestroyAll -- We load exclusions so we can have the deleted exclusions in the response + unless instance_integration + integration_class.id_in(exclusions.map(&:id)).delete_all + return ServiceResponse.success(payload: exclusions) + end ::Integrations::Propagation::BulkUpdateService.new(instance_integration, exclusions).execute ServiceResponse.success(payload: exclusions) diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 561f34b80461..61bb881aeb4c 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -5460,7 +5460,7 @@ Input type: `IntegrationExclusionCreateInput` | ---- | ---- | ----------- | | <a id="mutationintegrationexclusioncreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | <a id="mutationintegrationexclusioncreateintegrationname"></a>`integrationName` | [`IntegrationType!`](#integrationtype) | Type of integration to exclude. | -| <a id="mutationintegrationexclusioncreateprojectids"></a>`projectIds` | [`[ProjectID!]!`](#projectid) | Ids of projects to exclude. | +| <a id="mutationintegrationexclusioncreateprojectids"></a>`projectIds` | [`[ProjectID!]!`](#projectid) | IDs of projects to exclude up to a maximum of 100. | #### Fields @@ -5484,7 +5484,7 @@ Input type: `IntegrationExclusionDeleteInput` | ---- | ---- | ----------- | | <a id="mutationintegrationexclusiondeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | <a id="mutationintegrationexclusiondeleteintegrationname"></a>`integrationName` | [`IntegrationType!`](#integrationtype) | Type of integration. | -| <a id="mutationintegrationexclusiondeleteprojectids"></a>`projectIds` | [`[ProjectID!]!`](#projectid) | Id of excluded project. | +| <a id="mutationintegrationexclusiondeleteprojectids"></a>`projectIds` | [`[ProjectID!]!`](#projectid) | IDs of excluded projects. | #### Fields diff --git a/spec/requests/api/graphql/mutations/integrations/exclusions/create_spec.rb b/spec/requests/api/graphql/mutations/integrations/exclusions/create_spec.rb index 5d3e19c100df..153a5ef51e5d 100644 --- a/spec/requests/api/graphql/mutations/integrations/exclusions/create_spec.rb +++ b/spec/requests/api/graphql/mutations/integrations/exclusions/create_spec.rb @@ -56,5 +56,21 @@ expect(existing_exclusion.inherit_from_id).to be_nil end end + + context 'and the number of project ids exceeds the maximum' do + let(:stubbed_limit) { 1 } + let(:project_ids) { [project, project2].map { |p| p.to_global_id.to_s } } + + before do + stub_const("#{described_class.name}::MAX_PROJECT_IDS", stubbed_limit) + end + + it 'responds with an error' do + resolve_mutation + expect(graphql_errors.first['message']).to eq( + "Count of projectIds should be less than #{stubbed_limit}" + ) + end + end end end diff --git a/spec/requests/api/graphql/mutations/integrations/exclusions/delete_spec.rb b/spec/requests/api/graphql/mutations/integrations/exclusions/delete_spec.rb index 2e4dce2e4d08..2b1e41ff56b4 100644 --- a/spec/requests/api/graphql/mutations/integrations/exclusions/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/integrations/exclusions/delete_spec.rb @@ -41,20 +41,28 @@ end context 'and there are integrations' do - let!(:instance_integration) { create(:beyond_identity_integration) } let!(:existing_exclusion) do create(:beyond_identity_integration, project: project, active: false, inherit_from_id: nil, instance: false) end - it 'enables the integration for the specified project' do - resolve_mutation + context 'and the integration is active for the instance' do + let!(:instance_integration) { create(:beyond_identity_integration) } - existing_exclusion.reload - expect(existing_exclusion).to be_activated - expect(existing_exclusion.inherit_from_id).to eq(instance_integration.id) - exclusion_response = graphql_data['integrationExclusionDelete']['exclusions'][0] - expect(exclusion_response['project']['id']).to eq(project.to_global_id.to_s) + it 'enables the integration for the specified project' do + resolve_mutation + + existing_exclusion.reload + expect(existing_exclusion).to be_activated + expect(existing_exclusion.inherit_from_id).to eq(instance_integration.id) + exclusion_response = graphql_data['integrationExclusionDelete']['exclusions'][0] + expect(exclusion_response['project']['id']).to eq(project.to_global_id.to_s) + end + end + + it 'deletes the integration' do + expect { resolve_mutation }.to change { Integration.count }.from(1).to(0) + expect(graphql_errors).to be_nil end end end -- GitLab