Skip to content
Snippets Groups Projects
Commit cfce4f9c authored by Max Woolf's avatar Max Woolf
Browse files

Add auditEventsStreamingHeadersDestroy Mutation

Adds a new mutation that allows group owners
to destroy a custom HTTP header. Currently
behind a default-off feature flag.

EE: true
parent 9d57cbf4
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -730,6 +730,24 @@ Input type: `AuditEventsStreamingHeadersCreateInput`
| <a id="mutationauditeventsstreamingheaderscreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationauditeventsstreamingheaderscreateheader"></a>`header` | [`AuditEventStreamingHeader`](#auditeventstreamingheader) | Created header. |
 
### `Mutation.auditEventsStreamingHeadersDestroy`
Input type: `AuditEventsStreamingHeadersDestroyInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationauditeventsstreamingheadersdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationauditeventsstreamingheadersdestroyheaderid"></a>`headerId` | [`AuditEventsStreamingHeaderID!`](#auditeventsstreamingheaderid) | Header to delete. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationauditeventsstreamingheadersdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationauditeventsstreamingheadersdestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.awardEmojiAdd`
 
Input type: `AwardEmojiAddInput`
Loading
Loading
@@ -19699,6 +19717,12 @@ A `AuditEventsExternalAuditEventDestinationID` is a global ID. It is encoded as
 
An example `AuditEventsExternalAuditEventDestinationID` is: `"gid://gitlab/AuditEvents::ExternalAuditEventDestination/1"`.
 
### `AuditEventsStreamingHeaderID`
A `AuditEventsStreamingHeaderID` is a global ID. It is encoded as a string.
An example `AuditEventsStreamingHeaderID` is: `"gid://gitlab/AuditEvents::Streaming::Header/1"`.
### `AwardableID`
 
A `AwardableID` is a global ID. It is encoded as a string.
Loading
Loading
@@ -91,6 +91,7 @@ module MutationType
mount_mutation ::Mutations::AuditEvents::ExternalAuditEventDestinations::Update
mount_mutation ::Mutations::Ci::NamespaceCiCdSettingsUpdate
mount_mutation ::Mutations::AuditEvents::Streaming::Headers::Create
mount_mutation ::Mutations::AuditEvents::Streaming::Headers::Destroy
 
prepend(Types::DeprecatedMutations)
end
Loading
Loading
# frozen_string_literal: true
module Mutations
module AuditEvents
module Streaming
module Headers
class Destroy < BaseMutation
graphql_name 'AuditEventsStreamingHeadersDestroy'
authorize :admin_external_audit_events
argument :header_id, ::Types::GlobalIDType[::AuditEvents::Streaming::Header],
required: true,
description: 'Header to delete.'
def resolve(header_id:)
header = find_header(header_id)
authorize!(header.external_audit_event_destination)
unless Feature.enabled?(:streaming_audit_event_headers, header.external_audit_event_destination.group)
raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'feature disabled'
end
{ errors: Array(header.errors) } if header.destroy
end
private
def find_header(header_id)
header = GitlabSchema.object_from_id(header_id, expected_type: ::AuditEvents::Streaming::Header).sync
header.nil? ? raise(Gitlab::Graphql::Errors::ResourceNotAvailable, 'header does not exist') : header
end
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::AuditEvents::Streaming::Headers::Destroy do
let_it_be(:current_user) { create(:user) }
let_it_be(:header) { create(:audit_events_streaming_header) }
let(:destination) { header.external_audit_event_destination }
let(:group) { destination.group }
let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
subject { mutation.resolve(**{ header_id: header.to_gid }) }
describe '#resolve' do
context 'feature is unlicensed' do
before do
stub_licensed_features(external_audit_events: false)
end
it 'is not authorized' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'feature is licensed' do
before do
stub_licensed_features(external_audit_events: true)
end
context 'current_user is not group owner' do
it 'returns useful error messages' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'current_user is group owner' do
before do
group.add_owner(current_user)
stub_feature_flags(streaming_audit_event_headers: true)
end
it 'deletes the header' do
expect { subject }.to change { destination.headers.count }.by(-1)
end
context 'feature is disabled' do
before do
stub_feature_flags(streaming_audit_event_headers: false)
end
it 'is not authorized' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Destroy an external audit event destination header' do
include GraphqlHelpers
let_it_be(:destination) { create(:external_audit_event_destination) }
let_it_be(:owner) { create(:user) }
let_it_be(:header) { create(:audit_events_streaming_header, external_audit_event_destination: destination) }
let(:current_user) { owner }
let(:group) { destination.group }
let(:mutation) { graphql_mutation(:audit_events_streaming_headers_destroy, input) }
let(:mutation_response) { graphql_mutation_response(:audit_events_streaming_headers_destroy) }
let(:input) do
{ 'headerId': header.to_gid }
end
shared_examples 'a mutation that does not destroy a header' do
it 'does not destroy the destination' do
expect { post_graphql_mutation(mutation, current_user: owner) }
.not_to change { destination.headers.count }
end
end
context 'when feature is licensed' do
subject { post_graphql_mutation(mutation, current_user: owner) }
before do
stub_licensed_features(external_audit_events: true)
end
context 'when current user is a group owner' do
before do
group.add_owner(owner)
end
it 'destroys the header' do
expect { subject }
.to change { destination.headers.count }.by(-1)
end
context 'when header ID belongs to a different destination' do
let_it_be(:header) { create(:audit_events_streaming_header) }
it_behaves_like 'a mutation that does not destroy a header'
end
end
context 'when current user is a group maintainer' do
before do
group.add_maintainer(owner)
end
it_behaves_like 'a mutation that does not destroy a header'
end
context 'when current user is a group developer' do
before do
group.add_developer(owner)
end
it_behaves_like 'a mutation that does not destroy a header'
end
context 'when current user is a group guest' do
before do
group.add_guest(owner)
end
it_behaves_like 'a mutation that does not destroy a header'
end
end
context 'when feature is unlicensed' do
before do
stub_licensed_features(external_audit_events: false)
end
it_behaves_like 'a mutation on an unauthorized resource'
it 'does not destroy the header' do
expect { post_graphql_mutation(mutation, current_user: owner) }
.not_to change { destination.headers.count }
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment