Skip to content
Snippets Groups Projects
Commit 324eefb4 authored by Harsimar Sandhu's avatar Harsimar Sandhu :three: Committed by Jessie Young
Browse files

Audit event for merge request merged deletion started

This commit adds audit event when a merged merge request
deletion is started.

EE: true
Changelog: added
parent fa951cc3
No related branches found
No related tags found
1 merge request!121594Audit event for merge request merged deletion started
......@@ -8,11 +8,15 @@ def initialize(container:, current_user: nil, params: {})
end
def execute(issuable)
before_destroy(issuable)
after_destroy(issuable) if issuable.destroy
end
private
# overriden in EE
def before_destroy(issuable); end
def after_destroy(issuable)
delete_associated_records(issuable)
issuable.update_project_counter_caches
......
......@@ -7,6 +7,13 @@ module DestroyService
private
override :before_destroy
def before_destroy(issuable)
return unless issuable.is_a?(MergeRequest)
::Audit::MergeRequestBeforeDestroyAuditor.new(issuable, current_user).execute
end
override :after_destroy
def after_destroy(issuable)
log_audit_event(issuable)
......
---
name: merged_merge_request_deletion_started
description: Audit event triggered when a merged merge request's deletion is started
introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/408288
introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118793
milestone: '16.1'
feature_category: source_code_management
saved_to_database: false
streamed: true
# frozen_string_literal: true
module Audit
class MergeRequestBeforeDestroyAuditor
attr_reader :merge_request, :current_user
def initialize(merge_request, current_user)
@merge_request = merge_request
@current_user = current_user
end
def execute
return unless current_user
return unless merge_request.merged?
audit_context = {
name: "merged_merge_request_deletion_started",
stream_only: true,
author: current_user,
target: merge_request,
scope: merge_request.resource_parent,
message: audit_event_message,
target_details: {
title: merge_request.title,
iid: merge_request.iid,
id: merge_request.id,
type: merge_request.class.name
}
}
::Gitlab::Audit::Auditor.audit(audit_context)
end
private
def audit_event_message
labels = merge_request.labels.pluck_titles.to_sentence
approvers = merge_request.approved_by_user_ids.to_sentence
merged_by_id = merge_request.metrics&.merged_by_id
committer_ids = merge_request.commits.committer_user_ids.to_sentence
message = "Removed MergeRequest(#{merge_request.title} with IID: #{merge_request.iid} " \
"and ID: #{merge_request.id})"
message += ", labels: #{labels}" unless labels.blank?
message += ", approved_by_user_ids: #{approvers}" unless approvers.blank?
message += ", committer_user_ids: #{committer_ids}"
message += ", merged_by_user_id: #{merged_by_id}" if merged_by_id.present?
message
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Audit::MergeRequestBeforeDestroyAuditor, feature_category: :audit_events do
let(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
subject { described_class.new(merge_request, current_user) }
before do
allow(Gitlab::Audit::Auditor).to receive(:audit)
end
describe '#execute' do
context 'when current_user is nil' do
let(:current_user) { nil }
it 'does not audit the event' do
subject.execute
expect(Gitlab::Audit::Auditor).not_to have_received(:audit)
end
end
context 'when merge request is not merged' do
before do
allow(merge_request).to receive(:merged?).and_return(false)
end
it 'does not audit the event' do
subject.execute
expect(Gitlab::Audit::Auditor).not_to have_received(:audit)
end
end
context 'when merge request is merged' do
before do
allow(merge_request).to receive(:merged?).and_return(true)
allow(merge_request).to receive_message_chain(:commits, :committer_user_ids).and_return([4, 5])
allow(merge_request).to receive_message_chain(:metrics, :merged_by_id).and_return(3)
end
it 'audits a merged_merge_request_deletion_started event' do
subject.execute
expect(Gitlab::Audit::Auditor).to have_received(:audit).with(
hash_including(name: 'merged_merge_request_deletion_started'))
end
context 'when labels and approvers are present' do
before do
allow(merge_request).to receive_message_chain(:labels, :pluck_titles).and_return(%w[label1 label2])
allow(merge_request).to receive(:approved_by_user_ids).and_return([1, 2])
end
it 'includes additional details in the message' do
subject.execute
expect(Gitlab::Audit::Auditor).to have_received(:audit) do |args|
expected_message = "Removed MergeRequest(#{merge_request.title} with IID: #{merge_request.iid} " \
"and ID: #{merge_request.id}), labels: label1 and label2, " \
"approved_by_user_ids: 1 and 2, " \
"committer_user_ids: 4 and 5, merged_by_user_id: 3"
expect(args[:message]).to eq(expected_message)
end
end
context 'when metrics is not present' do
before do
allow(merge_request).to receive(:metrics).and_return(nil)
end
it 'does not include merged_by_user_id in the message' do
subject.execute
expect(Gitlab::Audit::Auditor).to have_received(:audit) do |args|
expected_message = "Removed MergeRequest(#{merge_request.title} with IID: #{merge_request.iid} " \
"and ID: #{merge_request.id}), labels: label1 and label2, " \
"approved_by_user_ids: 1 and 2, " \
"committer_user_ids: 4 and 5"
expect(args[:message]).to eq(expected_message)
end
end
end
end
context 'when labels and approvers are not present' do
before do
allow(merge_request).to receive_message_chain(:labels, :pluck_titles).and_return([])
allow(merge_request).to receive(:approved_by_user_ids).and_return([])
end
it 'omits labels and approvers from the message' do
subject.execute
expect(Gitlab::Audit::Auditor).to have_received(:audit) do |args|
expected_message = "Removed MergeRequest(#{merge_request.title} with IID: #{merge_request.iid} " \
"and ID: #{merge_request.id}), committer_user_ids: 4 and 5, merged_by_user_id: 3" \
expect(args[:message]).to eq(expected_message)
end
end
end
end
end
end
......@@ -86,6 +86,14 @@
service.execute(issuable)
end
it 'calls MergeRequestBeforeDestroyAuditor with correct arguments' do
expect_next_instance_of(Audit::MergeRequestBeforeDestroyAuditor, issuable, user) do |instance|
expect(instance).to receive(:execute)
end
service.execute(issuable)
end
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