Commit 08a35292 authored by Mark Chao's avatar Mark Chao

Add ApprovalRules services

Handles both project and MR rules
parent d641d25d
# frozen_string_literal: true
module ApprovalRules
class BaseService < ::BaseService
def execute
return error(['Prohibited']) unless can_edit?
filter_eligible_users!
filter_eligible_groups!
if rule.update(params)
rule.reload
success
else
error(rule.errors.messages)
end
end
private
attr_reader :rule
def can_edit?
can?(current_user, :edit_approval_rule, rule)
end
def success(*args, &blk)
super.tap { |hsh| hsh[:rule] = rule }
end
def filter_eligible_users!
return unless params.key?(:user_ids)
params[:users] = project.members_among(User.id_in(params.delete(:user_ids)))
end
def filter_eligible_groups!
return unless params.key?(:group_ids)
params[:groups] = Group.id_in(params.delete(:group_ids)).public_or_visible_to_user(current_user)
end
end
end
# frozen_string_literal: true
module ApprovalRules
class CreateService < ::ApprovalRules::BaseService
# @param target [Project, MergeRequest]
def initialize(target, user, params)
@rule = target.approval_rules.build
super(@rule.project, user, params)
end
end
end
# frozen_string_literal: true
module ApprovalRules
class UpdateService < ::ApprovalRules::BaseService
attr_reader :rule
def initialize(approval_rule, user, params)
@rule = approval_rule
super(@rule.project, user, params)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe ApprovalRules::CreateService do
let(:project) { create(:project) }
let(:user) { project.creator }
shared_examples 'creatable' do
let(:new_approvers) { create_list(:user, 2) }
let(:new_groups) { create_list(:group, 2, :private) }
it 'creates approval, excluding non-eligible users and groups' do
result = described_class.new(target, user, {
name: 'security',
approvals_required: 1,
user_ids: new_approvers.map(&:id),
group_ids: new_groups.map(&:id)
}).execute
expect(result[:status]).to eq(:success)
rule = result[:rule]
expect(rule.name).to eq('security')
expect(rule.approvals_required).to eq(1)
expect(rule.users).to be_empty
expect(rule.groups).to be_empty
end
context 'when some users and groups are eligible' do
before do
project.add_reporter new_approvers.first
new_groups.first.add_guest(user)
end
it 'creates and includes eligible users and groups' do
result = described_class.new(target, user, {
name: 'security',
approvals_required: 1,
user_ids: new_approvers.map(&:id),
group_ids: new_groups.map(&:id)
}).execute
expect(result[:status]).to eq(:success)
rule = result[:rule]
expect(rule.name).to eq('security')
expect(rule.approvals_required).to eq(1)
expect(rule.users).to contain_exactly(new_approvers.first)
expect(rule.groups).to contain_exactly(new_groups.first)
end
end
context 'when validation fails' do
it 'returns error message' do
result = described_class.new(target, user, {
name: nil,
approvals_required: 1
}).execute
expect(result[:status]).to eq(:error)
end
end
context 'when user does not have right to admin project' do
let(:user) { create(:user) }
it 'returns error message' do
result = described_class.new(target, user, {
approvals_required: 1
}).execute
expect(result[:status]).to eq(:error)
expect(result[:message]).to include('Prohibited')
end
end
end
context 'when target is project' do
let(:target) { project }
it_behaves_like "creatable"
end
context 'when target is merge request' do
let(:target) { create(:merge_request, source_project: project, target_project: project) }
it_behaves_like "creatable"
end
end
# frozen_string_literal: true
require 'spec_helper'
describe ApprovalRules::UpdateService do
let(:project) { create(:project) }
let(:user) { project.creator }
shared_examples 'editable' do
let(:approval_rule) { target.approval_rules.create(name: 'foo') }
let(:new_approvers) { create_list(:user, 2) }
let(:new_groups) { create_list(:group, 2, :private) }
it 'updates approval, excluding non-eligible users and groups' do
result = described_class.new(approval_rule, user, {
name: 'security',
approvals_required: 1,
user_ids: new_approvers.map(&:id),
group_ids: new_groups.map(&:id)
}).execute
expect(result[:status]).to eq(:success)
rule = result[:rule]
expect(rule.name).to eq('security')
expect(rule.approvals_required).to eq(1)
expect(rule.users).to be_empty
expect(rule.groups).to be_empty
end
context 'when some users and groups are eligible' do
before do
project.add_reporter new_approvers.first
new_groups.first.add_guest user
end
it 'creates and includes eligible users and groups' do
result = described_class.new(approval_rule, user, {
name: 'security',
approvals_required: 1,
user_ids: new_approvers.map(&:id),
group_ids: new_groups.map(&:id)
}).execute
expect(result[:status]).to eq(:success)
rule = result[:rule]
expect(rule.name).to eq('security')
expect(rule.approvals_required).to eq(1)
expect(rule.users).to contain_exactly(new_approvers.first)
expect(rule.groups).to contain_exactly(new_groups.first)
end
end
context 'when validation fails' do
it 'returns error message' do
result = described_class.new(approval_rule, user, {
name: nil,
approvals_required: 1
}).execute
expect(result[:status]).to eq(:error)
end
end
context 'when user does not have right to edit' do
let(:user) { create(:user) }
it 'returns error message' do
result = described_class.new(approval_rule, user, {
approvals_required: 1
}).execute
expect(result[:status]).to eq(:error)
expect(result[:message]).to include('Prohibited')
end
end
end
context 'when target is project' do
let(:target) { project }
it_behaves_like "editable"
end
context 'when target is merge request' do
let(:target) { create(:merge_request, source_project: project, target_project: project) }
it_behaves_like "editable"
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment