Commit 137e1e31 authored by Sean McGivern's avatar Sean McGivern

Merge branch '7532-allow-self-approvals-even-when-not-in-approvers-list' into 'master'

Allow self-approvals in fallback approval rules

Closes #7532

See merge request gitlab-org/gitlab-ee!10218
parents 3c26867a d277ec55
......@@ -133,15 +133,17 @@ class ApprovalState
def can_approve?(user)
return false unless user
# The check below considers authors being able to approve the MR.
# That is, they're included/excluded from that list accordingly.
return true if unactioned_approvers.include?(user)
# We can safely unauthorize author and committers if it reaches this guard clause.
return false if merge_request.author == user
return false if merge_request.committers.include?(user)
return false unless any_approver_allowed?
return false unless user.can?(:update_merge_request, merge_request)
# Users can only approve once.
return false if approvals.where(user: user).any?
# At this point, follow self-approval rules. Otherwise authors must
# have been in the list of unactioned_approvers to have been approved.
return committers_can_approve? if merge_request.committers.include?(user)
return authors_can_approve? if merge_request.author == user
any_approver_allowed? && merge_request.approvals.where(user: user).empty?
true
end
def has_approved?(user)
......@@ -154,6 +156,10 @@ class ApprovalState
project.merge_requests_author_approval?
end
def committers_can_approve?
!project.merge_requests_disable_committers_approval?
end
# TODO: remove after #1979 is closed
# This is a temporary method for backward compatibility
# before introduction of approval rules.
......
---
title: Allow self-approvals in fallback approval rules
merge_request: 10218
author:
type: changed
......@@ -43,28 +43,38 @@ describe ApprovableForRule do
end
context 'when the user is the author' do
context 'and user is an approver' do
context 'and author is an approver' do
before do
create(:approver, target: merge_request, user: author)
end
it 'return true when authors can approve' do
project.update(merge_requests_author_approval: true)
it 'returns true when authors can approve' do
project.update!(merge_requests_author_approval: true)
expect(merge_request.can_approve?(author)).to be true
end
it 'return false when authors cannot approve' do
project.update(merge_requests_author_approval: false)
it 'returns false when authors cannot approve' do
project.update!(merge_requests_author_approval: false)
expect(merge_request.can_approve?(author)).to be false
end
end
it 'returns false when user is not an approver' do
context 'and author is not an approver' do
it 'returns true when authors can approve' do
project.update!(merge_requests_author_approval: true)
expect(merge_request.can_approve?(author)).to be true
end
it 'returns false when authors cannot approve' do
project.update!(merge_requests_author_approval: false)
expect(merge_request.can_approve?(author)).to be false
end
end
end
context 'when user is a committer' do
let(:user) { create(:user, email: merge_request.commits.without_merge_commits.first.committer_email) }
......@@ -73,28 +83,38 @@ describe ApprovableForRule do
project.add_developer(user)
end
context 'and user is an approver' do
context 'and committer is an approver' do
before do
create(:approver, target: merge_request, user: user)
end
it 'return true when committers can approve' do
project.update(merge_requests_disable_committers_approval: false)
project.update!(merge_requests_disable_committers_approval: false)
expect(merge_request.can_approve?(user)).to be true
end
it 'return false when committers cannot approve' do
project.update(merge_requests_disable_committers_approval: true)
project.update!(merge_requests_disable_committers_approval: true)
expect(merge_request.can_approve?(user)).to be false
end
end
it 'returns false when user is not an approver' do
context 'and committer is not an approver' do
it 'return true when committers can approve' do
project.update!(merge_requests_disable_committers_approval: false)
expect(merge_request.can_approve?(user)).to be true
end
it 'return false when committers cannot approve' do
project.update!(merge_requests_disable_committers_approval: true)
expect(merge_request.can_approve?(user)).to be false
end
end
end
it 'returns false when user is unable to update the merge request' do
user = create(:user)
......@@ -105,7 +125,7 @@ describe ApprovableForRule do
context 'when approvals are required' do
before do
project.update(approvals_before_merge: 1)
project.update!(approvals_before_merge: 1)
end
it 'returns true when approvals are still accepted and user still has not approved' do
......
This diff is collapsed.
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