diff --git a/ee/app/services/security/security_orchestration_policies/fetch_policy_approvers_service.rb b/ee/app/services/security/security_orchestration_policies/fetch_policy_approvers_service.rb index 6e95f7c741a372b15aab75cc4378971135e91dbf..222cd51c56e5201f8b0bf5cbf0652a2e454ff165 100644 --- a/ee/app/services/security/security_orchestration_policies/fetch_policy_approvers_service.rb +++ b/ee/app/services/security/security_orchestration_policies/fetch_policy_approvers_service.rb @@ -35,12 +35,27 @@ def user_approvers(action) when Project container.team.users.by_ids_or_usernames(user_ids, user_names) when Group - container.users.by_ids_or_usernames(user_ids, user_names) + authorizable_users_in_group_hierarchy_by_ids_or_usernames(user_ids, user_names) else [] end end + # rubocop: disable CodeReuse/ActiveRecord + def authorizable_users_in_group_hierarchy_by_ids_or_usernames(user_ids, user_names) + User + .by_ids_or_usernames(user_ids, user_names) + .where( + container + .authorizable_members_with_parents + .merge(Member.where(Member.arel_table[:user_id].eq(User.arel_table[:id])), rewhere: true) + .select(1) + .arel + .exists + ) + end + # rubocop: enable CodeReuse/ActiveRecord + def group_approvers(action) return [] unless action[:group_approvers] || action[:group_approvers_ids] diff --git a/ee/spec/services/security/security_orchestration_policies/fetch_policy_approvers_service_spec.rb b/ee/spec/services/security/security_orchestration_policies/fetch_policy_approvers_service_spec.rb index cab6a06620d509f63ae24fc9a888927ca07b3992..dbb88cd45d6ff2f4df05c65a4ab43b39c347e0ec 100644 --- a/ee/spec/services/security/security_orchestration_policies/fetch_policy_approvers_service_spec.rb +++ b/ee/spec/services/security/security_orchestration_policies/fetch_policy_approvers_service_spec.rb @@ -52,6 +52,21 @@ expect(response[:users]).to match_array([user]) expect(response[:groups]).to be_empty end + + context 'with user approvers inherited from parent group' do + let(:action) { { type: "require_approval", approvals_required: 1, user_approvers: [user.username] } } + + let_it_be(:child) { create(:group, parent: group) } + let(:container) { child } + + it 'returns user approvers' do + response = service.execute + + expect(response[:status]).to eq(:success) + expect(response[:users]).to match_array([user]) + expect(response[:groups]).to be_empty + end + end end context 'with container of any other type' do