Commit e5c867c5 authored by Kerri Miller's avatar Kerri Miller

Merge branch '268361-delete-escalation-policy-graphql' into 'master'

Add delete escalation policy GraphQL mutation

See merge request gitlab-org/gitlab!62009
parents 7f6d004b 64f1ae7c
...@@ -2175,6 +2175,25 @@ Input type: `EscalationPolicyCreateInput` ...@@ -2175,6 +2175,25 @@ Input type: `EscalationPolicyCreateInput`
| <a id="mutationescalationpolicycreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | | <a id="mutationescalationpolicycreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationescalationpolicycreateescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. | | <a id="mutationescalationpolicycreateescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. |
### `Mutation.escalationPolicyDestroy`
Input type: `EscalationPolicyDestroyInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationescalationpolicydestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationescalationpolicydestroyid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | The escalation policy internal ID to remove. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationescalationpolicydestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationescalationpolicydestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationescalationpolicydestroyescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. |
### `Mutation.exportRequirements` ### `Mutation.exportRequirements`
Input type: `ExportRequirementsInput` Input type: `ExportRequirementsInput`
......
...@@ -76,6 +76,7 @@ module EE ...@@ -76,6 +76,7 @@ module EE
mount_mutation ::Mutations::IncidentManagement::OncallRotation::Update mount_mutation ::Mutations::IncidentManagement::OncallRotation::Update
mount_mutation ::Mutations::IncidentManagement::OncallRotation::Destroy mount_mutation ::Mutations::IncidentManagement::OncallRotation::Destroy
mount_mutation ::Mutations::IncidentManagement::EscalationPolicy::Create mount_mutation ::Mutations::IncidentManagement::EscalationPolicy::Create
mount_mutation ::Mutations::IncidentManagement::EscalationPolicy::Destroy
mount_mutation ::Mutations::AppSec::Fuzzing::Api::CiConfiguration::Create mount_mutation ::Mutations::AppSec::Fuzzing::Api::CiConfiguration::Create
prepend(Types::DeprecatedMutations) prepend(Types::DeprecatedMutations)
......
# frozen_string_literal: true
module Mutations
module IncidentManagement
module EscalationPolicy
class Base < BaseMutation
field :escalation_policy,
::Types::IncidentManagement::EscalationPolicyType,
null: true,
description: 'The escalation policy.'
authorize :admin_incident_management_escalation_policy
private
def response(result)
{
escalation_policy: result.payload[:escalation_policy],
errors: result.errors
}
end
def find_object(id:)
GitlabSchema.object_from_id(id, expected_type: ::IncidentManagement::EscalationPolicy)
end
end
end
end
end
# frozen_string_literal: true
module Mutations
module IncidentManagement
module EscalationPolicy
class Destroy < Base
graphql_name 'EscalationPolicyDestroy'
argument :id, Types::GlobalIDType[::IncidentManagement::EscalationPolicy],
required: true,
description: 'The escalation policy internal ID to remove.'
def resolve(id:)
escalation_policy = authorized_find!(id: id)
response ::IncidentManagement::EscalationPolicies::DestroyService.new(
escalation_policy,
current_user
).execute
end
end
end
end
end
# frozen_string_literal: true
module IncidentManagement
module EscalationPolicies
class DestroyService < EscalationPolicies::BaseService
# @param escalation_policy [IncidentManagement::EscalationPolicy]
# @param user [User]
def initialize(escalation_policy, user)
@escalation_policy = escalation_policy
@user = user
@project = escalation_policy.project
end
def execute
return error_no_license unless available?
return error_no_permissions unless allowed?
if escalation_policy.destroy
success(escalation_policy)
else
error(escalation_policy.errors.full_messages.to_sentence)
end
end
private
attr_reader :escalation_policy, :user, :project
def error_no_permissions
error(_('You have insufficient permissions to remove an escalation policy from this project'))
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::IncidentManagement::EscalationPolicy::Destroy do
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let(:escalation_policy) { create(:incident_management_escalation_policy, project: project) }
let(:args) { { id: escalation_policy.to_global_id } }
specify { expect(described_class).to require_graphql_authorizations(:admin_incident_management_escalation_policy) }
before do
stub_licensed_features(oncall_schedules: true, escalation_policies: true)
stub_feature_flags(escalation_policies_mvc: project)
end
describe '#resolve' do
subject(:resolve) { mutation_for(project, current_user).resolve(**args) }
context 'user has access to project' do
before do
project.add_maintainer(current_user)
end
context 'when EscalationPolicies::DestroyService responds with success' do
it 'returns the escalation policy with no errors' do
expect(resolve).to eq(
escalation_policy: escalation_policy,
errors: []
)
end
end
context 'when EscalationPolicies::DestroyService responds with an error' do
before do
allow_next_instance_of(::IncidentManagement::EscalationPolicies::DestroyService) do |service|
allow(service)
.to receive(:execute)
.and_return(ServiceResponse.error(payload: { escalation_policy: nil }, message: 'An error has occurred'))
end
end
it 'returns errors' do
expect(resolve).to eq(
escalation_policy: nil,
errors: ['An error has occurred']
)
end
end
end
context 'when resource is not accessible to the user' do
it 'raises an error' do
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
private
def mutation_for(project, user)
described_class.new(object: project, context: { current_user: user }, field: nil)
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Removing an escalation policy' do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:escalation_policy) { create(:incident_management_escalation_policy, project: project) }
let(:variables) { { id: escalation_policy.to_global_id.to_s } }
let(:mutation) do
graphql_mutation(:escalation_policy_destroy, variables) do
<<~QL
clientMutationId
errors
escalationPolicy {
id
name
description
}
QL
end
end
let(:mutation_response) { graphql_mutation_response(:escalation_policy_destroy) }
before do
stub_licensed_features(oncall_schedules: true, escalation_policies: true)
stub_feature_flags(escalation_policies_mvc: project)
project.add_maintainer(user)
end
it 'removes the escalation policy' do
post_graphql_mutation(mutation, current_user: user)
escalation_policy_response = mutation_response['escalationPolicy']
expect(response).to have_gitlab_http_status(:success)
expect(escalation_policy_response.slice(*%w[id name description])).to eq(
'id' => escalation_policy.to_global_id.to_s,
'name' => escalation_policy.name,
'description' => escalation_policy.description
)
expect { escalation_policy.reload }.to raise_error ActiveRecord::RecordNotFound
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IncidentManagement::EscalationPolicies::DestroyService do
let_it_be(:user_with_permissions) { create(:user) }
let_it_be(:user_without_permissions) { create(:user) }
let_it_be_with_refind(:project) { create(:project) }
let!(:escalation_policy) { create(:incident_management_escalation_policy, project: project) }
let(:current_user) { user_with_permissions }
let(:params) { {} }
let(:service) { described_class.new(escalation_policy, current_user) }
before do
stub_licensed_features(oncall_schedules: true, escalation_policies: true)
stub_feature_flags(escalation_policies_mvc: project)
end
before_all do
project.add_maintainer(user_with_permissions)
end
describe '#execute' do
shared_examples 'error response' do |message|
it 'has an informative message' do
expect(execute).to be_error
expect(execute.message).to eq(message)
end
end
subject(:execute) { service.execute }
context 'when the current_user is anonymous' do
let(:current_user) { nil }
it_behaves_like 'error response', 'You have insufficient permissions to remove an escalation policy from this project'
end
context 'when the current_user does not have permissions to remove escalation policies' do
let(:current_user) { user_without_permissions }
it_behaves_like 'error response', 'You have insufficient permissions to remove an escalation policy from this project'
end
context 'when license is not enabled' do
before do
stub_licensed_features(oncall_schedules: true, escalation_policies: false)
end
it_behaves_like 'error response', 'Escalation policies are not supported for this project'
end
context 'when feature is not available' do
before do
stub_feature_flags(escalation_policies_mvc: false)
end
it_behaves_like 'error response', 'Escalation policies are not supported for this project'
end
context 'when an error occurs during removal' do
before do
allow(escalation_policy).to receive(:destroy).and_return(false)
escalation_policy.errors.add(:name, 'cannot be removed')
end
it_behaves_like 'error response', 'Name cannot be removed'
end
it 'successfully returns the escalation policy' do
expect(execute).to be_success
escalation_policy_result = execute.payload[:escalation_policy]
expect(escalation_policy_result).to be_a(::IncidentManagement::EscalationPolicy)
expect(escalation_policy_result.name).to eq(escalation_policy.name)
expect(escalation_policy_result.description).to eq(escalation_policy.description)
end
end
end
...@@ -37506,6 +37506,9 @@ msgstr "" ...@@ -37506,6 +37506,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project" msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr "" msgstr ""
msgid "You have insufficient permissions to remove an escalation policy from this project"
msgstr ""
msgid "You have insufficient permissions to remove an on-call rotation from this project" msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr "" msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment