From 50c2e538a9aa1cfd5adc18c3779c8b20f35cb624 Mon Sep 17 00:00:00 2001 From: Shubham Kumar Date: Mon, 28 Jul 2025 13:52:17 +0200 Subject: [PATCH 1/6] Add groups archive service audit events Changelog: added EE: true --- .../namespaces/groups/group_archived_event.rb | 18 ++++++++ .../groups/group_attributes_changed_event.rb | 30 +++++++++++++ .../namespaces/groups/archive_events.rb | 31 +++++++++++++ .../namespaces/groups/archive_service.rb | 10 +++++ .../namespaces/groups/unarchive_service.rb | 10 +++++ doc/user/compliance/audit_event_types.md | 2 + .../ee/namespaces/groups/archive_service.rb | 32 ++++++++++++++ .../ee/namespaces/groups/unarchive_service.rb | 32 ++++++++++++++ .../audit_events/types/group_archived.yml | 10 +++++ .../audit_events/types/group_unarchived.yml | 10 +++++ .../namespaces/groups/archive_service_spec.rb | 43 ++++++++++++++++++ .../groups/unarchive_service_spec.rb | 44 +++++++++++++++++++ 12 files changed, 272 insertions(+) create mode 100644 app/events/namespaces/groups/group_archived_event.rb create mode 100644 app/events/namespaces/groups/group_attributes_changed_event.rb create mode 100644 app/services/concerns/namespaces/groups/archive_events.rb create mode 100644 ee/app/services/ee/namespaces/groups/archive_service.rb create mode 100644 ee/app/services/ee/namespaces/groups/unarchive_service.rb create mode 100644 ee/config/audit_events/types/group_archived.yml create mode 100644 ee/config/audit_events/types/group_unarchived.yml create mode 100644 ee/spec/services/ee/namespaces/groups/archive_service_spec.rb create mode 100644 ee/spec/services/ee/namespaces/groups/unarchive_service_spec.rb diff --git a/app/events/namespaces/groups/group_archived_event.rb b/app/events/namespaces/groups/group_archived_event.rb new file mode 100644 index 00000000000000..90243d81d4662c --- /dev/null +++ b/app/events/namespaces/groups/group_archived_event.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Namespaces + module Groups + class GroupArchivedEvent < ::Gitlab::EventStore::Event + def schema + { + 'type' => 'object', + 'properties' => { + 'group_id' => { 'type' => 'integer' }, + 'root_namespace_id' => { 'type' => 'integer' } + }, + 'required' => %w[group_id root_namespace_id] + } + end + end + end +end diff --git a/app/events/namespaces/groups/group_attributes_changed_event.rb b/app/events/namespaces/groups/group_attributes_changed_event.rb new file mode 100644 index 00000000000000..8d57e5a5d9f152 --- /dev/null +++ b/app/events/namespaces/groups/group_attributes_changed_event.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module Namespaces + module Groups + class GroupAttributesChangedEvent < ::Gitlab::EventStore::Event + PAGES_RELATED_ATTRIBUTES = %w[ + pages_https_only + visibility_level + ].freeze + + def schema + { + 'type' => 'object', + 'properties' => { + 'group_id' => { 'type' => 'integer' }, + 'root_namespace_id' => { 'type' => 'integer' }, + 'attributes' => { 'type' => 'array' } + }, + 'required' => %w[group_id root_namespace_id attributes] + } + end + + def pages_related? + PAGES_RELATED_ATTRIBUTES.any? do |attribute| + data[:attributes].include?(attribute) + end + end + end + end +end diff --git a/app/services/concerns/namespaces/groups/archive_events.rb b/app/services/concerns/namespaces/groups/archive_events.rb new file mode 100644 index 00000000000000..3a771651f9f7b8 --- /dev/null +++ b/app/services/concerns/namespaces/groups/archive_events.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Namespaces + module Groups + module ArchiveEvents + def publish_events + publish_group_archived_event + publish_group_attributed_changed_event + end + + def publish_group_archived_event + event = Namespaces::Groups::GroupArchivedEvent.new(data: { + group_id: group.id, + root_namespace_id: group.root_ancestor&.id.to_i + }) + + Gitlab::EventStore.publish(event) + end + + def publish_group_attributed_changed_event + event = Namespaces::Groups::GroupAttributesChangedEvent.new(data: { + group_id: group.id, + root_namespace_id: group.root_ancestor&.id.to_i, + attributes: group.previous_changes.keys + }) + + Gitlab::EventStore.publish(event) + end + end + end +end diff --git a/app/services/namespaces/groups/archive_service.rb b/app/services/namespaces/groups/archive_service.rb index d1be2490ee9400..2e008b219dd147 100644 --- a/app/services/namespaces/groups/archive_service.rb +++ b/app/services/namespaces/groups/archive_service.rb @@ -3,6 +3,8 @@ module Namespaces module Groups class ArchiveService < ::Groups::BaseService + include ::Namespaces::Groups::ArchiveEvents + NotAuthorizedError = ServiceResponse.error( message: "You don't have permissions to archive this group!" ) @@ -25,14 +27,22 @@ def execute return AncestorAlreadyArchivedError if group.ancestors_archived? return ArchivingFailedError unless group.archive + after_archive ServiceResponse.success end private + def after_archive + system_hook_service.execute_hooks_for(group, :update) + publish_events + end + def error_response(message) ServiceResponse.error(message: message) end end end end + +Namespaces::Groups::ArchiveService.prepend_mod diff --git a/app/services/namespaces/groups/unarchive_service.rb b/app/services/namespaces/groups/unarchive_service.rb index 267c214596e25c..f253fda7ee0576 100644 --- a/app/services/namespaces/groups/unarchive_service.rb +++ b/app/services/namespaces/groups/unarchive_service.rb @@ -3,6 +3,8 @@ module Namespaces module Groups class UnarchiveService < ::Groups::BaseService + include ::Namespaces::Groups::ArchiveEvents + NotAuthorizedError = ServiceResponse.error( message: "You don't have permissions to unarchive this group!" ) @@ -25,14 +27,22 @@ def execute return AlreadyUnarchivedError unless group.archived return UnarchivingFailedError unless group.unarchive + after_unarchive ServiceResponse.success end private + def after_unarchive + system_hook_service.execute_hooks_for(group, :update) + publish_events + end + def error_response(message) ServiceResponse.error(message: message) end end end end + +Namespaces::Groups::UnarchiveService.prepend_mod diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 1818b441d3ad9b..53d93ab3d60575 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -358,6 +358,7 @@ Audit event types belong to the following product categories. | [`emails_enabled_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973) | Setting Enable email notifications is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | | [`enabled_git_access_protocol_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973) | Setting Enabled Git access protocols is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | | [`enforce_ssh_certificates_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973) | Setting Enforce SSH Certificates is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | +| [`group_archived`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199416) | A group is archived | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/520013) | Group | | [`group_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121005) | A group is created | {{< icon name="check-circle" >}} Yes | GitLab [16.3](https://gitlab.com/gitlab-org/gitlab/-/issues/411595) | Group | | [`group_deletion_marked`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/116986) | A group is marked for deletion | {{< icon name="check-circle" >}} Yes | GitLab [15.11](https://gitlab.com/gitlab-org/gitlab/-/issues/374106) | Group | | [`group_description_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973/) | Group description is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | @@ -374,6 +375,7 @@ Audit event types belong to the following product categories. | [`group_share_with_group_link_removed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719) | You remove a group from another group by using the group's membership page | {{< icon name="check-circle" >}} Yes | GitLab [15.10](https://gitlab.com/gitlab-org/gitlab/-/issues/327909) | Group | | [`group_share_with_group_link_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719) | You update a group's access settings to another group by using the group's membership page | {{< icon name="check-circle" >}} Yes | GitLab [15.10](https://gitlab.com/gitlab-org/gitlab/-/issues/327909) | Group | | [`group_shared_with_group_lock_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973/) | Group can be shared with other group setting is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | +| [`group_unarchived`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199416) | A group is unarchived | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/520013) | Group | | [`group_visibility_level_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106079) | A group's visibility level is updated | {{< icon name="check-circle" >}} Yes | GitLab [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/369322) | Group | | [`prevent_sharing_groups_outside_hierarchy_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973) | A group's setting to Members cannot invite groups outside of group and its subgroup updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | | [`project_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117543) | A project is created | {{< icon name="check-circle" >}} Yes | GitLab [16.0](https://gitlab.com/gitlab-org/gitlab/-/issues/374105) | Project | diff --git a/ee/app/services/ee/namespaces/groups/archive_service.rb b/ee/app/services/ee/namespaces/groups/archive_service.rb new file mode 100644 index 00000000000000..5a9c11b55104ab --- /dev/null +++ b/ee/app/services/ee/namespaces/groups/archive_service.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module EE + module Namespaces + module Groups + module ArchiveService + extend ::Gitlab::Utils::Override + + private + + override :after_archive + def after_archive + super + + log_audit_event + end + + def log_audit_event + audit_context = { + name: 'group_archived', + author: current_user, + target: group, + scope: group, + message: 'Group archived' + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + end + end + end +end diff --git a/ee/app/services/ee/namespaces/groups/unarchive_service.rb b/ee/app/services/ee/namespaces/groups/unarchive_service.rb new file mode 100644 index 00000000000000..28fb2a4dfdcadf --- /dev/null +++ b/ee/app/services/ee/namespaces/groups/unarchive_service.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module EE + module Namespaces + module Groups + module UnarchiveService + extend ::Gitlab::Utils::Override + + private + + override :after_unarchive + def after_unarchive + super + + log_audit_event + end + + def log_audit_event + audit_context = { + name: 'group_unarchived', + author: current_user, + target: group, + scope: group, + message: 'Group unarchived' + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + end + end + end +end diff --git a/ee/config/audit_events/types/group_archived.yml b/ee/config/audit_events/types/group_archived.yml new file mode 100644 index 00000000000000..5974fc77daca29 --- /dev/null +++ b/ee/config/audit_events/types/group_archived.yml @@ -0,0 +1,10 @@ +--- +name: group_archived +description: A group is archived +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/520013 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199416 +feature_category: groups_and_projects +milestone: '18.3' +saved_to_database: true +streamed: true +scope: [Group] diff --git a/ee/config/audit_events/types/group_unarchived.yml b/ee/config/audit_events/types/group_unarchived.yml new file mode 100644 index 00000000000000..349a1d940b0521 --- /dev/null +++ b/ee/config/audit_events/types/group_unarchived.yml @@ -0,0 +1,10 @@ +--- +name: group_unarchived +description: A group is unarchived +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/520013 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199416 +feature_category: groups_and_projects +milestone: '18.3' +saved_to_database: true +streamed: true +scope: [Group] diff --git a/ee/spec/services/ee/namespaces/groups/archive_service_spec.rb b/ee/spec/services/ee/namespaces/groups/archive_service_spec.rb new file mode 100644 index 00000000000000..734d195071440f --- /dev/null +++ b/ee/spec/services/ee/namespaces/groups/archive_service_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Namespaces::Groups::ArchiveService, feature_category: :groups_and_projects do + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + + let(:service) { described_class.new(group, user).execute } + + describe '#execute' do + context 'when group archiving fails' do + it 'does not log an audit event' do + expect { service }.not_to change { AuditEvent.count } + end + end + + context 'when group archiving succeeds' do + before_all do + group.add_owner(user) + end + + it 'logs an audit event' do + expect { service }.to change { AuditEvent.count }.by(1) + + audit_event = AuditEvent.last + expect(audit_event).to have_attributes( + author_id: user.id, + entity_type: 'Group', + target_type: "Group", + author_name: user.name + ) + expect(audit_event.details).to include( + event_name: "group_archived", + author_name: user.name, + author_class: "User", + target_type: "Group", + custom_message: "Group archived" + ) + end + end + end +end diff --git a/ee/spec/services/ee/namespaces/groups/unarchive_service_spec.rb b/ee/spec/services/ee/namespaces/groups/unarchive_service_spec.rb new file mode 100644 index 00000000000000..ad3fe121fbd81e --- /dev/null +++ b/ee/spec/services/ee/namespaces/groups/unarchive_service_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Namespaces::Groups::UnarchiveService, feature_category: :groups_and_projects do + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + + let(:service) { described_class.new(group, user).execute } + + describe '#execute' do + context 'when group unarchiving fails' do + it 'does not log an audit event' do + expect { service }.not_to change { AuditEvent.count } + end + end + + context 'when group unarchiving succeeds' do + before_all do + group.add_owner(user) + group.namespace_settings.update!(archived: true) + end + + it 'logs an audit event' do + expect { service }.to change { AuditEvent.count }.by(1) + + audit_event = AuditEvent.last + expect(audit_event).to have_attributes( + author_id: user.id, + entity_type: 'Group', + target_type: "Group", + author_name: user.name + ) + expect(audit_event.details).to include( + event_name: "group_unarchived", + author_name: user.name, + author_class: "User", + target_type: "Group", + custom_message: "Group unarchived" + ) + end + end + end +end -- GitLab From 3d361442c258af9dde8702f47a9345449e86b8a5 Mon Sep 17 00:00:00 2001 From: Shubham Kumar Date: Mon, 28 Jul 2025 13:57:57 +0200 Subject: [PATCH 2/6] Apply 2 suggestion(s) to 2 file(s) --- ee/config/audit_events/types/group_archived.yml | 2 +- ee/config/audit_events/types/group_unarchived.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ee/config/audit_events/types/group_archived.yml b/ee/config/audit_events/types/group_archived.yml index 5974fc77daca29..c530c4c6339eff 100644 --- a/ee/config/audit_events/types/group_archived.yml +++ b/ee/config/audit_events/types/group_archived.yml @@ -2,7 +2,7 @@ name: group_archived description: A group is archived introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/520013 -introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199416 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199419 feature_category: groups_and_projects milestone: '18.3' saved_to_database: true diff --git a/ee/config/audit_events/types/group_unarchived.yml b/ee/config/audit_events/types/group_unarchived.yml index 349a1d940b0521..b36778eb5168c6 100644 --- a/ee/config/audit_events/types/group_unarchived.yml +++ b/ee/config/audit_events/types/group_unarchived.yml @@ -2,7 +2,7 @@ name: group_unarchived description: A group is unarchived introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/520013 -introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199416 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199419 feature_category: groups_and_projects milestone: '18.3' saved_to_database: true -- GitLab From d417adc7f2f77bea3cc9ac6e1d3f65b48be2ca85 Mon Sep 17 00:00:00 2001 From: Shubham Kumar Date: Mon, 28 Jul 2025 14:17:08 +0200 Subject: [PATCH 3/6] Update groups api ee spec Changelog: fixed EE: true --- doc/user/compliance/audit_event_types.md | 4 +-- ee/spec/requests/api/groups_spec.rb | 36 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 53d93ab3d60575..cc19f27c427ea7 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -358,7 +358,7 @@ Audit event types belong to the following product categories. | [`emails_enabled_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973) | Setting Enable email notifications is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | | [`enabled_git_access_protocol_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973) | Setting Enabled Git access protocols is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | | [`enforce_ssh_certificates_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973) | Setting Enforce SSH Certificates is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | -| [`group_archived`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199416) | A group is archived | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/520013) | Group | +| [`group_archived`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199419) | A group is archived | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/520013) | Group | | [`group_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121005) | A group is created | {{< icon name="check-circle" >}} Yes | GitLab [16.3](https://gitlab.com/gitlab-org/gitlab/-/issues/411595) | Group | | [`group_deletion_marked`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/116986) | A group is marked for deletion | {{< icon name="check-circle" >}} Yes | GitLab [15.11](https://gitlab.com/gitlab-org/gitlab/-/issues/374106) | Group | | [`group_description_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973/) | Group description is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | @@ -375,7 +375,7 @@ Audit event types belong to the following product categories. | [`group_share_with_group_link_removed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719) | You remove a group from another group by using the group's membership page | {{< icon name="check-circle" >}} Yes | GitLab [15.10](https://gitlab.com/gitlab-org/gitlab/-/issues/327909) | Group | | [`group_share_with_group_link_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719) | You update a group's access settings to another group by using the group's membership page | {{< icon name="check-circle" >}} Yes | GitLab [15.10](https://gitlab.com/gitlab-org/gitlab/-/issues/327909) | Group | | [`group_shared_with_group_lock_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973/) | Group can be shared with other group setting is updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | -| [`group_unarchived`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199416) | A group is unarchived | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/520013) | Group | +| [`group_unarchived`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/199419) | A group is unarchived | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/520013) | Group | | [`group_visibility_level_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106079) | A group's visibility level is updated | {{< icon name="check-circle" >}} Yes | GitLab [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/369322) | Group | | [`prevent_sharing_groups_outside_hierarchy_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164973) | A group's setting to Members cannot invite groups outside of group and its subgroup updated | {{< icon name="check-circle" >}} Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/486532) | Group | | [`project_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117543) | A project is created | {{< icon name="check-circle" >}} Yes | GitLab [16.0](https://gitlab.com/gitlab-org/gitlab/-/issues/374105) | Project | diff --git a/ee/spec/requests/api/groups_spec.rb b/ee/spec/requests/api/groups_spec.rb index ab61d50309a484..ae10ec0eca3e41 100644 --- a/ee/spec/requests/api/groups_spec.rb +++ b/ee/spec/requests/api/groups_spec.rb @@ -223,6 +223,42 @@ end end + describe 'POST /groups/:id/archive' do + let(:path) { "/groups/#{group.id}/archive" } + + context 'when group archiving fails' do + it 'does not log an audit event' do + expect { post api(path, another_user) }.not_to change { AuditEvent.count } + end + end + + context 'when project archiving succeeds' do + it 'logs an audit event' do + expect { post api(path, user) }.to change { AuditEvent.count }.by(1) + end + end + end + + describe 'POST /groups/:id/unarchive' do + let(:path) { "/groups/#{group.id}/unarchive" } + + context 'when group unarchiving fails' do + it 'does not log an audit event' do + expect { post api(path, another_user) }.not_to change { AuditEvent.count } + end + end + + context 'when group unarchiving succeeds' do + before do + group.namespace_settings.update!(archived: true) + end + + it 'logs an audit event' do + expect { post api(path, user) }.to change { AuditEvent.count }.by(1) + end + end + end + describe 'PUT /groups/:id' do let_it_be(:admin_mode) { false } -- GitLab From 5d6ea7eaca58fff559b92150c92e3c0717b0a9c0 Mon Sep 17 00:00:00 2001 From: Shubham Kumar Date: Tue, 29 Jul 2025 13:05:35 +0200 Subject: [PATCH 4/6] Remove pages attributes Changelog: fixed --- .../groups/group_attributes_changed_event.rb | 30 ------------------- .../project_attributes_changed_event.rb | 6 ---- .../namespaces/groups/archive_events.rb | 13 +------- 3 files changed, 1 insertion(+), 48 deletions(-) delete mode 100644 app/events/namespaces/groups/group_attributes_changed_event.rb diff --git a/app/events/namespaces/groups/group_attributes_changed_event.rb b/app/events/namespaces/groups/group_attributes_changed_event.rb deleted file mode 100644 index 8d57e5a5d9f152..00000000000000 --- a/app/events/namespaces/groups/group_attributes_changed_event.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -module Namespaces - module Groups - class GroupAttributesChangedEvent < ::Gitlab::EventStore::Event - PAGES_RELATED_ATTRIBUTES = %w[ - pages_https_only - visibility_level - ].freeze - - def schema - { - 'type' => 'object', - 'properties' => { - 'group_id' => { 'type' => 'integer' }, - 'root_namespace_id' => { 'type' => 'integer' }, - 'attributes' => { 'type' => 'array' } - }, - 'required' => %w[group_id root_namespace_id attributes] - } - end - - def pages_related? - PAGES_RELATED_ATTRIBUTES.any? do |attribute| - data[:attributes].include?(attribute) - end - end - end - end -end diff --git a/app/events/projects/project_attributes_changed_event.rb b/app/events/projects/project_attributes_changed_event.rb index f7c27fa65e6486..c2f48a41948b9b 100644 --- a/app/events/projects/project_attributes_changed_event.rb +++ b/app/events/projects/project_attributes_changed_event.rb @@ -19,11 +19,5 @@ def schema 'required' => %w[project_id namespace_id root_namespace_id attributes] } end - - def pages_related? - PAGES_RELATED_ATTRIBUTES.any? do |attribute| - data[:attributes].include?(attribute) - end - end end end diff --git a/app/services/concerns/namespaces/groups/archive_events.rb b/app/services/concerns/namespaces/groups/archive_events.rb index 3a771651f9f7b8..ebb7de7db124ca 100644 --- a/app/services/concerns/namespaces/groups/archive_events.rb +++ b/app/services/concerns/namespaces/groups/archive_events.rb @@ -5,23 +5,12 @@ module Groups module ArchiveEvents def publish_events publish_group_archived_event - publish_group_attributed_changed_event end def publish_group_archived_event event = Namespaces::Groups::GroupArchivedEvent.new(data: { group_id: group.id, - root_namespace_id: group.root_ancestor&.id.to_i - }) - - Gitlab::EventStore.publish(event) - end - - def publish_group_attributed_changed_event - event = Namespaces::Groups::GroupAttributesChangedEvent.new(data: { - group_id: group.id, - root_namespace_id: group.root_ancestor&.id.to_i, - attributes: group.previous_changes.keys + root_namespace_id: group.root_ancestor.id }) Gitlab::EventStore.publish(event) -- GitLab From c75021d2e38a4ba745b4ca7d8d5fd93fea6e496e Mon Sep 17 00:00:00 2001 From: Shubham Kumar Date: Thu, 31 Jul 2025 13:46:24 +0200 Subject: [PATCH 5/6] Remove archive events subs Changelog: fixed --- .../namespaces/groups/group_archived_event.rb | 18 ----------------- .../project_attributes_changed_event.rb | 6 ++++++ .../namespaces/groups/archive_events.rb | 20 ------------------- .../namespaces/groups/archive_service.rb | 3 --- .../namespaces/groups/unarchive_service.rb | 3 --- 5 files changed, 6 insertions(+), 44 deletions(-) delete mode 100644 app/events/namespaces/groups/group_archived_event.rb delete mode 100644 app/services/concerns/namespaces/groups/archive_events.rb diff --git a/app/events/namespaces/groups/group_archived_event.rb b/app/events/namespaces/groups/group_archived_event.rb deleted file mode 100644 index 90243d81d4662c..00000000000000 --- a/app/events/namespaces/groups/group_archived_event.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module Namespaces - module Groups - class GroupArchivedEvent < ::Gitlab::EventStore::Event - def schema - { - 'type' => 'object', - 'properties' => { - 'group_id' => { 'type' => 'integer' }, - 'root_namespace_id' => { 'type' => 'integer' } - }, - 'required' => %w[group_id root_namespace_id] - } - end - end - end -end diff --git a/app/events/projects/project_attributes_changed_event.rb b/app/events/projects/project_attributes_changed_event.rb index c2f48a41948b9b..f7c27fa65e6486 100644 --- a/app/events/projects/project_attributes_changed_event.rb +++ b/app/events/projects/project_attributes_changed_event.rb @@ -19,5 +19,11 @@ def schema 'required' => %w[project_id namespace_id root_namespace_id attributes] } end + + def pages_related? + PAGES_RELATED_ATTRIBUTES.any? do |attribute| + data[:attributes].include?(attribute) + end + end end end diff --git a/app/services/concerns/namespaces/groups/archive_events.rb b/app/services/concerns/namespaces/groups/archive_events.rb deleted file mode 100644 index ebb7de7db124ca..00000000000000 --- a/app/services/concerns/namespaces/groups/archive_events.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -module Namespaces - module Groups - module ArchiveEvents - def publish_events - publish_group_archived_event - end - - def publish_group_archived_event - event = Namespaces::Groups::GroupArchivedEvent.new(data: { - group_id: group.id, - root_namespace_id: group.root_ancestor.id - }) - - Gitlab::EventStore.publish(event) - end - end - end -end diff --git a/app/services/namespaces/groups/archive_service.rb b/app/services/namespaces/groups/archive_service.rb index 2e008b219dd147..f0c15369902571 100644 --- a/app/services/namespaces/groups/archive_service.rb +++ b/app/services/namespaces/groups/archive_service.rb @@ -3,8 +3,6 @@ module Namespaces module Groups class ArchiveService < ::Groups::BaseService - include ::Namespaces::Groups::ArchiveEvents - NotAuthorizedError = ServiceResponse.error( message: "You don't have permissions to archive this group!" ) @@ -35,7 +33,6 @@ def execute def after_archive system_hook_service.execute_hooks_for(group, :update) - publish_events end def error_response(message) diff --git a/app/services/namespaces/groups/unarchive_service.rb b/app/services/namespaces/groups/unarchive_service.rb index f253fda7ee0576..05c67f2cd959bd 100644 --- a/app/services/namespaces/groups/unarchive_service.rb +++ b/app/services/namespaces/groups/unarchive_service.rb @@ -3,8 +3,6 @@ module Namespaces module Groups class UnarchiveService < ::Groups::BaseService - include ::Namespaces::Groups::ArchiveEvents - NotAuthorizedError = ServiceResponse.error( message: "You don't have permissions to unarchive this group!" ) @@ -35,7 +33,6 @@ def execute def after_unarchive system_hook_service.execute_hooks_for(group, :update) - publish_events end def error_response(message) -- GitLab From 1f296c98b1ebf24a7e7a5bbcb0b5e2236c571e51 Mon Sep 17 00:00:00 2001 From: Shubham Kumar Date: Thu, 31 Jul 2025 16:13:31 +0200 Subject: [PATCH 6/6] Refactor specs Changelog: fixed --- .../services/ee/namespaces/groups/archive_service_spec.rb | 6 +++--- .../services/ee/namespaces/groups/unarchive_service_spec.rb | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ee/spec/services/ee/namespaces/groups/archive_service_spec.rb b/ee/spec/services/ee/namespaces/groups/archive_service_spec.rb index 734d195071440f..acc8cbcceb2b55 100644 --- a/ee/spec/services/ee/namespaces/groups/archive_service_spec.rb +++ b/ee/spec/services/ee/namespaces/groups/archive_service_spec.rb @@ -6,12 +6,12 @@ let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group) } - let(:service) { described_class.new(group, user).execute } + let(:service) { described_class.new(group, user) } describe '#execute' do context 'when group archiving fails' do it 'does not log an audit event' do - expect { service }.not_to change { AuditEvent.count } + expect { service.execute }.not_to change { AuditEvent.count } end end @@ -21,7 +21,7 @@ end it 'logs an audit event' do - expect { service }.to change { AuditEvent.count }.by(1) + expect { service.execute }.to change { AuditEvent.count }.by(1) audit_event = AuditEvent.last expect(audit_event).to have_attributes( diff --git a/ee/spec/services/ee/namespaces/groups/unarchive_service_spec.rb b/ee/spec/services/ee/namespaces/groups/unarchive_service_spec.rb index ad3fe121fbd81e..77713c1cb4ea0b 100644 --- a/ee/spec/services/ee/namespaces/groups/unarchive_service_spec.rb +++ b/ee/spec/services/ee/namespaces/groups/unarchive_service_spec.rb @@ -6,12 +6,12 @@ let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group) } - let(:service) { described_class.new(group, user).execute } + let(:service) { described_class.new(group, user) } describe '#execute' do context 'when group unarchiving fails' do it 'does not log an audit event' do - expect { service }.not_to change { AuditEvent.count } + expect { service.execute }.not_to change { AuditEvent.count } end end @@ -22,7 +22,7 @@ end it 'logs an audit event' do - expect { service }.to change { AuditEvent.count }.by(1) + expect { service.execute }.to change { AuditEvent.count }.by(1) audit_event = AuditEvent.last expect(audit_event).to have_attributes( -- GitLab