From b636efde37316bb7c2331fd79272f8dd563e66c4 Mon Sep 17 00:00:00 2001 From: Michael Becker <11881043-wandering_person@users.noreply.gitlab.com> Date: Wed, 22 Feb 2023 18:32:49 +0100 Subject: [PATCH 1/2] Add audit events for sharing a group membership to another group There is currently no audit event triggered when you share membership to a group (group A) to another group (group B) via group A's membership page This commit adds audit events for create/update/delete actions Changelog: changed EE: true --- .../groups/group_links_controller.rb | 2 +- .../groups/group_links/create_service.rb | 2 + .../groups/group_links/destroy_service.rb | 4 ++ .../groups/group_links/update_service.rb | 4 ++ .../ee/groups/group_links/create_service.rb | 32 ++++++++++ .../ee/groups/group_links/destroy_service.rb | 42 +++++++++++++ .../ee/groups/group_links/update_service.rb | 63 +++++++++++++++++++ .../group_share_with_group_link_created.yml | 10 +++ .../group_share_with_group_link_removed.yml | 10 +++ .../group_share_with_group_link_updated.yml | 10 +++ .../groups/group_links/create_service_spec.rb | 40 ++++++++++++ .../group_links/destroy_service_spec.rb | 58 +++++++++++++++++ .../groups/group_links/update_service_spec.rb | 46 ++++++++++++++ .../groups/group_links/create_service_spec.rb | 2 +- .../group_links/destroy_service_spec.rb | 2 +- .../groups/group_links/update_service_spec.rb | 4 +- 16 files changed, 326 insertions(+), 5 deletions(-) create mode 100644 ee/app/services/ee/groups/group_links/create_service.rb create mode 100644 ee/app/services/ee/groups/group_links/destroy_service.rb create mode 100644 ee/app/services/ee/groups/group_links/update_service.rb create mode 100644 ee/config/audit_events/types/group_share_with_group_link_created.yml create mode 100644 ee/config/audit_events/types/group_share_with_group_link_removed.yml create mode 100644 ee/config/audit_events/types/group_share_with_group_link_updated.yml create mode 100644 ee/spec/services/ee/groups/group_links/create_service_spec.rb create mode 100644 ee/spec/services/ee/groups/group_links/destroy_service_spec.rb create mode 100644 ee/spec/services/ee/groups/group_links/update_service_spec.rb diff --git a/app/controllers/groups/group_links_controller.rb b/app/controllers/groups/group_links_controller.rb index cc2ca728592367..c74c48a960d576 100644 --- a/app/controllers/groups/group_links_controller.rb +++ b/app/controllers/groups/group_links_controller.rb @@ -7,7 +7,7 @@ class Groups::GroupLinksController < Groups::ApplicationController feature_category :subgroups def update - Groups::GroupLinks::UpdateService.new(@group_link).execute(group_link_params) + Groups::GroupLinks::UpdateService.new(@group_link, current_user).execute(group_link_params) if @group_link.expires? render json: { diff --git a/app/services/groups/group_links/create_service.rb b/app/services/groups/group_links/create_service.rb index 9c1a003ff36317..a6e2c0b952e77d 100644 --- a/app/services/groups/group_links/create_service.rb +++ b/app/services/groups/group_links/create_service.rb @@ -36,3 +36,5 @@ def setup_authorizations end end end + +Groups::GroupLinks::CreateService.prepend_mod diff --git a/app/services/groups/group_links/destroy_service.rb b/app/services/groups/group_links/destroy_service.rb index dc3cab927be54d..8eed46b28ca28b 100644 --- a/app/services/groups/group_links/destroy_service.rb +++ b/app/services/groups/group_links/destroy_service.rb @@ -24,7 +24,11 @@ def execute(one_or_more_links, skip_authorization: false) Gitlab::AppLogger.info( "Failed to delete GroupGroupLinks with ids: #{links.map(&:id)}.") end + + links end end end end + +Groups::GroupLinks::DestroyService.prepend_mod diff --git a/app/services/groups/group_links/update_service.rb b/app/services/groups/group_links/update_service.rb index 66d0d63cb9b8d7..913bf2bfce7aa7 100644 --- a/app/services/groups/group_links/update_service.rb +++ b/app/services/groups/group_links/update_service.rb @@ -15,6 +15,8 @@ def execute(group_link_params) if requires_authorization_refresh?(group_link_params) group_link.shared_with_group.refresh_members_authorized_projects(direct_members_only: true) end + + group_link end private @@ -27,3 +29,5 @@ def requires_authorization_refresh?(params) end end end + +Groups::GroupLinks::UpdateService.prepend_mod diff --git a/ee/app/services/ee/groups/group_links/create_service.rb b/ee/app/services/ee/groups/group_links/create_service.rb new file mode 100644 index 00000000000000..b420f48e751604 --- /dev/null +++ b/ee/app/services/ee/groups/group_links/create_service.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module EE + module Groups + module GroupLinks + module CreateService + extend ::Gitlab::Utils::Override + + override :after_successful_save + def after_successful_save + super + + log_audit_event + end + + def log_audit_event + audit_context = { + name: "group_share_with_group_link_created", + author: current_user, + scope: link.shared_group, + target: link.shared_with_group, + stream_only: false, + message: "Invited #{link.shared_with_group.name} " \ + "to the group #{link.shared_group.name}" + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + end + end + end +end diff --git a/ee/app/services/ee/groups/group_links/destroy_service.rb b/ee/app/services/ee/groups/group_links/destroy_service.rb new file mode 100644 index 00000000000000..edff33b18e3f24 --- /dev/null +++ b/ee/app/services/ee/groups/group_links/destroy_service.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module EE + module Groups + module GroupLinks + module DestroyService + extend ::Gitlab::Utils::Override + + override :execute + def execute(one_or_more_links, skip_authorization: false) + super.tap do |links| + log_audit_events(links) + end + end + + private + + def log_audit_events(links) + return unless links.is_a?(Array) + + links.each do |link| + log_audit_event(link.shared_group, link.shared_with_group) + end + end + + def log_audit_event(group, shared_with_group) + audit_context = { + name: "group_share_with_group_link_removed", + author: current_user, + scope: group, + target: shared_with_group, + stream_only: false, + message: "Removed #{shared_with_group.name} " \ + "from the group #{group.name}" + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + end + end + end +end diff --git a/ee/app/services/ee/groups/group_links/update_service.rb b/ee/app/services/ee/groups/group_links/update_service.rb new file mode 100644 index 00000000000000..1172c81d59e96d --- /dev/null +++ b/ee/app/services/ee/groups/group_links/update_service.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +module EE + module Groups + module GroupLinks + module UpdateService + extend ::Gitlab::Utils::Override + + override :execute + def execute(group_link_params) + super.tap do |group_link| + log_audit_event(group_link) + end + end + + private + + def log_audit_event(group_link) + changes = group_link.previous_changes.symbolize_keys.except(:updated_at) + return unless changes.present? + + audit_context = { + name: "group_share_with_group_link_updated", + author: current_user, + scope: group_link.shared_group, + target: group_link.shared_with_group, + stream_only: false, + message: "Updated #{group_link.shared_with_group.name}'s " \ + "access params for the group #{group_link.shared_group.name}", + additional_details: { + changes: [ + access_change(changes[:group_access]), + expiry_change(changes[:expires_at]) + ].compact + }.compact + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + + def access_change(change = nil) + return if change.blank? + + { + change: :group_access, + from: ::Gitlab::Access.human_access(change.first), + to: ::Gitlab::Access.human_access(change.last) + } + end + + def expiry_change(change = nil) + return if change.blank? + + { + change: :expires_at, + from: change.first.to_s, + to: change.last.to_s + } + end + end + end + end +end diff --git a/ee/config/audit_events/types/group_share_with_group_link_created.yml b/ee/config/audit_events/types/group_share_with_group_link_created.yml new file mode 100644 index 00000000000000..c4f8ed8ea3a627 --- /dev/null +++ b/ee/config/audit_events/types/group_share_with_group_link_created.yml @@ -0,0 +1,10 @@ +--- +name: group_share_with_group_link_created +description: This event is triggered when you proceed to invite a group to another + group via the 'invite group' tab on the group's membership page +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/327909 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719 +feature_category: system_access +milestone: '15.10' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/group_share_with_group_link_removed.yml b/ee/config/audit_events/types/group_share_with_group_link_removed.yml new file mode 100644 index 00000000000000..f2a44118acd72b --- /dev/null +++ b/ee/config/audit_events/types/group_share_with_group_link_removed.yml @@ -0,0 +1,10 @@ +--- +name: group_share_with_group_link_removed +description: This event is triggered when you proceed to invite a group to another + group via the 'invite group' tab on the group's membership page +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/327909 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719 +feature_category: system_access +milestone: '15.10' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/group_share_with_group_link_updated.yml b/ee/config/audit_events/types/group_share_with_group_link_updated.yml new file mode 100644 index 00000000000000..a4aaf142d48fa1 --- /dev/null +++ b/ee/config/audit_events/types/group_share_with_group_link_updated.yml @@ -0,0 +1,10 @@ +--- +name: group_share_with_group_link_updated +description: This event is triggered when you proceed to invite a group to another + group via the 'invite group' tab on the group's membership page +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/327909 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719 +feature_category: system_access +milestone: '15.10' +saved_to_database: true +streamed: true diff --git a/ee/spec/services/ee/groups/group_links/create_service_spec.rb b/ee/spec/services/ee/groups/group_links/create_service_spec.rb new file mode 100644 index 00000000000000..227f2c788d82e0 --- /dev/null +++ b/ee/spec/services/ee/groups/group_links/create_service_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Groups::GroupLinks::CreateService, '#execute', feature_category: :system_access do + subject { described_class.new(group, shared_with_group, user, opts) } + + let_it_be(:shared_with_group) { create(:group, :private) } + let_it_be(:user) { create(:user) } + + let(:group) { create(:group, :private) } + let(:opts) do + { + shared_group_access: Gitlab::Access::DEVELOPER, + expires_at: nil + } + end + + let(:audit_context) do + { + name: 'group_share_with_group_link_created', + stream_only: false, + author: user, + scope: group, + target: shared_with_group, + message: "Invited #{shared_with_group.name} to the group #{group.name}" + } + end + + before do + shared_with_group.add_guest(user) + group.add_owner(user) + end + + it 'sends an audit event' do + expect(::Gitlab::Audit::Auditor).to receive(:audit).with(audit_context).once + + subject.execute + end +end diff --git a/ee/spec/services/ee/groups/group_links/destroy_service_spec.rb b/ee/spec/services/ee/groups/group_links/destroy_service_spec.rb new file mode 100644 index 00000000000000..ae1421aecbce39 --- /dev/null +++ b/ee/spec/services/ee/groups/group_links/destroy_service_spec.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Groups::GroupLinks::DestroyService, '#execute', feature_category: :system_access do + subject { described_class.new(shared_group, owner) } + + let_it_be(:group) { create(:group, :private) } + let_it_be(:shared_group) { create(:group, :private) } + let_it_be(:owner) { create(:user) } + + before do + group.add_developer(owner) + shared_group.add_owner(owner) + end + + context 'with a single link' do + let!(:link) { create(:group_group_link, shared_group: shared_group, shared_with_group: group) } + let(:audit_context) do + { + name: 'group_share_with_group_link_removed', + stream_only: false, + author: owner, + scope: shared_group, + target: group, + message: "Removed #{group.name} from the group #{shared_group.name}" + } + end + + it 'sends an audit event' do + expect(::Gitlab::Audit::Auditor).to receive(:audit).with(hash_including(audit_context)).once + + subject.execute(link) + end + end + + context 'with multiple links' do + let_it_be(:another_group) { create(:group, :private) } + let_it_be(:another_shared_group) { create(:group, :private) } + + let!(:links) do + [ + create(:group_group_link, shared_group: shared_group, shared_with_group: group), + create(:group_group_link, shared_group: shared_group, shared_with_group: another_group), + create(:group_group_link, shared_group: another_shared_group, shared_with_group: group), + create(:group_group_link, shared_group: another_shared_group, shared_with_group: another_group) + ] + end + + it 'sends multiple audit events' do + expect(::Gitlab::Audit::Auditor).to receive(:audit).with( + hash_including({ name: 'group_share_with_group_link_removed' }) + ).exactly(links.size).times + + subject.execute(links) + end + end +end diff --git a/ee/spec/services/ee/groups/group_links/update_service_spec.rb b/ee/spec/services/ee/groups/group_links/update_service_spec.rb new file mode 100644 index 00000000000000..87d8a10c46bd21 --- /dev/null +++ b/ee/spec/services/ee/groups/group_links/update_service_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Groups::GroupLinks::UpdateService, '#execute', feature_category: :system_access do + subject { described_class.new(link, user).execute(group_link_params) } + + let_it_be(:group) { create(:group, :private) } + let_it_be(:shared_group) { create(:group, :private) } + let_it_be(:user) { create(:user) } + + let(:link) { create(:group_group_link, shared_group: shared_group, shared_with_group: group) } + let(:expiry_date) { 1.month.from_now.to_date } + let(:group_link_params) do + { group_access: Gitlab::Access::GUEST, + expires_at: expiry_date } + end + + let(:audit_context) do + { + name: 'group_share_with_group_link_updated', + stream_only: false, + author: user, + scope: shared_group, + target: group, + message: "Updated #{group.name}'s " \ + "access params for the group #{shared_group.name}", + additional_details: { + changes: [ + { change: :group_access, from: 'Developer', to: 'Guest' }, + { change: :expires_at, from: '', to: expiry_date.to_s } + ] + } + } + end + + before do + group.add_developer(user) + end + + it 'sends an audit event' do + expect(::Gitlab::Audit::Auditor).to receive(:audit).with(hash_including(audit_context)).once + + subject + end +end diff --git a/spec/services/groups/group_links/create_service_spec.rb b/spec/services/groups/group_links/create_service_spec.rb index ced8742185845d..4d4915c7bb5720 100644 --- a/spec/services/groups/group_links/create_service_spec.rb +++ b/spec/services/groups/group_links/create_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::CreateService, '#execute', feature_category: :subgroups do +RSpec.describe Groups::GroupLinks::CreateService, '#execute', feature_category: :system_access do let_it_be(:shared_with_group_parent) { create(:group, :private) } let_it_be(:shared_with_group) { create(:group, :private, parent: shared_with_group_parent) } let_it_be(:shared_with_group_child) { create(:group, :private, parent: shared_with_group) } diff --git a/spec/services/groups/group_links/destroy_service_spec.rb b/spec/services/groups/group_links/destroy_service_spec.rb index 5821ec44192086..f02edc151d0d16 100644 --- a/spec/services/groups/group_links/destroy_service_spec.rb +++ b/spec/services/groups/group_links/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::DestroyService, '#execute', feature_category: :subgroups do +RSpec.describe Groups::GroupLinks::DestroyService, '#execute', feature_category: :system_access do let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group, :private) } let_it_be(:shared_group) { create(:group, :private) } diff --git a/spec/services/groups/group_links/update_service_spec.rb b/spec/services/groups/group_links/update_service_spec.rb index 42f622811d4c78..36d01429957567 100644 --- a/spec/services/groups/group_links/update_service_spec.rb +++ b/spec/services/groups/group_links/update_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::UpdateService, '#execute', feature_category: :subgroups do +RSpec.describe Groups::GroupLinks::UpdateService, '#execute', feature_category: :system_access do let(:user) { create(:user) } let_it_be(:group) { create(:group, :private) } @@ -18,7 +18,7 @@ expires_at: expiry_date } end - subject { described_class.new(link).execute(group_link_params) } + subject { described_class.new(link, user).execute(group_link_params) } before do group.add_developer(group_member_user) -- GitLab From 05e0f93548c1abe3827621b058eebd50e1828152 Mon Sep 17 00:00:00 2001 From: Michael Becker <11881043-wandering_person@users.noreply.gitlab.com> Date: Thu, 9 Mar 2023 12:58:24 -0800 Subject: [PATCH 2/2] Update `feature_category` assignment --- .../audit_events/types/group_share_with_group_link_created.yml | 2 +- .../audit_events/types/group_share_with_group_link_removed.yml | 2 +- .../audit_events/types/group_share_with_group_link_updated.yml | 2 +- ee/spec/services/ee/groups/group_links/create_service_spec.rb | 2 +- ee/spec/services/ee/groups/group_links/destroy_service_spec.rb | 2 +- ee/spec/services/ee/groups/group_links/update_service_spec.rb | 2 +- spec/services/groups/group_links/create_service_spec.rb | 2 +- spec/services/groups/group_links/destroy_service_spec.rb | 2 +- spec/services/groups/group_links/update_service_spec.rb | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ee/config/audit_events/types/group_share_with_group_link_created.yml b/ee/config/audit_events/types/group_share_with_group_link_created.yml index c4f8ed8ea3a627..f1a306854279b6 100644 --- a/ee/config/audit_events/types/group_share_with_group_link_created.yml +++ b/ee/config/audit_events/types/group_share_with_group_link_created.yml @@ -4,7 +4,7 @@ description: This event is triggered when you proceed to invite a group to anoth group via the 'invite group' tab on the group's membership page introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/327909 introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719 -feature_category: system_access +feature_category: subgroups milestone: '15.10' saved_to_database: true streamed: true diff --git a/ee/config/audit_events/types/group_share_with_group_link_removed.yml b/ee/config/audit_events/types/group_share_with_group_link_removed.yml index f2a44118acd72b..3d036601e2b8de 100644 --- a/ee/config/audit_events/types/group_share_with_group_link_removed.yml +++ b/ee/config/audit_events/types/group_share_with_group_link_removed.yml @@ -4,7 +4,7 @@ description: This event is triggered when you proceed to invite a group to anoth group via the 'invite group' tab on the group's membership page introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/327909 introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719 -feature_category: system_access +feature_category: subgroups milestone: '15.10' saved_to_database: true streamed: true diff --git a/ee/config/audit_events/types/group_share_with_group_link_updated.yml b/ee/config/audit_events/types/group_share_with_group_link_updated.yml index a4aaf142d48fa1..a9526224315802 100644 --- a/ee/config/audit_events/types/group_share_with_group_link_updated.yml +++ b/ee/config/audit_events/types/group_share_with_group_link_updated.yml @@ -4,7 +4,7 @@ description: This event is triggered when you proceed to invite a group to anoth group via the 'invite group' tab on the group's membership page introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/327909 introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112719 -feature_category: system_access +feature_category: subgroups milestone: '15.10' saved_to_database: true streamed: true diff --git a/ee/spec/services/ee/groups/group_links/create_service_spec.rb b/ee/spec/services/ee/groups/group_links/create_service_spec.rb index 227f2c788d82e0..58f32ac48dce64 100644 --- a/ee/spec/services/ee/groups/group_links/create_service_spec.rb +++ b/ee/spec/services/ee/groups/group_links/create_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::CreateService, '#execute', feature_category: :system_access do +RSpec.describe Groups::GroupLinks::CreateService, '#execute', feature_category: :subgroups do subject { described_class.new(group, shared_with_group, user, opts) } let_it_be(:shared_with_group) { create(:group, :private) } diff --git a/ee/spec/services/ee/groups/group_links/destroy_service_spec.rb b/ee/spec/services/ee/groups/group_links/destroy_service_spec.rb index ae1421aecbce39..7bd9f9364011d2 100644 --- a/ee/spec/services/ee/groups/group_links/destroy_service_spec.rb +++ b/ee/spec/services/ee/groups/group_links/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::DestroyService, '#execute', feature_category: :system_access do +RSpec.describe Groups::GroupLinks::DestroyService, '#execute', feature_category: :subgroups do subject { described_class.new(shared_group, owner) } let_it_be(:group) { create(:group, :private) } diff --git a/ee/spec/services/ee/groups/group_links/update_service_spec.rb b/ee/spec/services/ee/groups/group_links/update_service_spec.rb index 87d8a10c46bd21..4281b1ccad2c85 100644 --- a/ee/spec/services/ee/groups/group_links/update_service_spec.rb +++ b/ee/spec/services/ee/groups/group_links/update_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::UpdateService, '#execute', feature_category: :system_access do +RSpec.describe Groups::GroupLinks::UpdateService, '#execute', feature_category: :subgroups do subject { described_class.new(link, user).execute(group_link_params) } let_it_be(:group) { create(:group, :private) } diff --git a/spec/services/groups/group_links/create_service_spec.rb b/spec/services/groups/group_links/create_service_spec.rb index 4d4915c7bb5720..ced8742185845d 100644 --- a/spec/services/groups/group_links/create_service_spec.rb +++ b/spec/services/groups/group_links/create_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::CreateService, '#execute', feature_category: :system_access do +RSpec.describe Groups::GroupLinks::CreateService, '#execute', feature_category: :subgroups do let_it_be(:shared_with_group_parent) { create(:group, :private) } let_it_be(:shared_with_group) { create(:group, :private, parent: shared_with_group_parent) } let_it_be(:shared_with_group_child) { create(:group, :private, parent: shared_with_group) } diff --git a/spec/services/groups/group_links/destroy_service_spec.rb b/spec/services/groups/group_links/destroy_service_spec.rb index f02edc151d0d16..5821ec44192086 100644 --- a/spec/services/groups/group_links/destroy_service_spec.rb +++ b/spec/services/groups/group_links/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::DestroyService, '#execute', feature_category: :system_access do +RSpec.describe Groups::GroupLinks::DestroyService, '#execute', feature_category: :subgroups do let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group, :private) } let_it_be(:shared_group) { create(:group, :private) } diff --git a/spec/services/groups/group_links/update_service_spec.rb b/spec/services/groups/group_links/update_service_spec.rb index 36d01429957567..f17d2f50a02604 100644 --- a/spec/services/groups/group_links/update_service_spec.rb +++ b/spec/services/groups/group_links/update_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::GroupLinks::UpdateService, '#execute', feature_category: :system_access do +RSpec.describe Groups::GroupLinks::UpdateService, '#execute', feature_category: :subgroups do let(:user) { create(:user) } let_it_be(:group) { create(:group, :private) } -- GitLab