Commit 8c938b97 authored by Robert Speicher's avatar Robert Speicher

Revert "Merge branch '388-option-to-disallow-author-to-approve-merge-request' into 'master'

This reverts commit 09ab819e, reversing
changes made to 041f3c27.
parent 642b5485
...@@ -5,7 +5,6 @@ v 8.9.0 (unreleased) ...@@ -5,7 +5,6 @@ v 8.9.0 (unreleased)
- Fix nil user handling in UpdateMirrorService - Fix nil user handling in UpdateMirrorService
- Allow overriding the number of approvers for a merge request - Allow overriding the number of approvers for a merge request
- Allow LDAP to mark users as external based on their group membership. !432 - Allow LDAP to mark users as external based on their group membership. !432
- Forbid MR authors from approving their own MRs
- Instrument instance methods of Gitlab::InsecureKeyFingerprint class - Instrument instance methods of Gitlab::InsecureKeyFingerprint class
- Add API endpoint for Merge Request Approvals !449 - Add API endpoint for Merge Request Approvals !449
- Send notification email when merge request is approved - Send notification email when merge request is approved
......
...@@ -391,7 +391,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -391,7 +391,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def set_suggested_approvers def set_suggested_approvers
if @merge_request.requires_approve? if @merge_request.requires_approve?
@suggested_approvers = Gitlab::AuthorityAnalyzer.new( @suggested_approvers = Gitlab::AuthorityAnalyzer.new(
@merge_request @merge_request,
current_user
).calculate(@merge_request.approvals_required) ).calculate(@merge_request.approvals_required)
end end
end end
......
...@@ -492,7 +492,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -492,7 +492,8 @@ class MergeRequest < ActiveRecord::Base
end end
def approvers_left def approvers_left
User.where(id: overall_approvers.select(:user_id)).where.not(id: approvals.select(:user_id)) user_ids = overall_approvers.map(&:user_id) - approvals.map(&:user_id)
User.where id: user_ids
end end
def approvals_required def approvals_required
...@@ -524,10 +525,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -524,10 +525,8 @@ class MergeRequest < ActiveRecord::Base
end end
def can_approve?(user) def can_approve?(user)
return false if user == self.author
approvers_left.include?(user) || approvers_left.include?(user) ||
(any_approver_allowed? && !approved_by?(user)) (any_approver_allowed? && !approved_by?(user))
end end
def any_approver_allowed? def any_approver_allowed?
......
...@@ -33,7 +33,7 @@ independent of changes to the merge request. ...@@ -33,7 +33,7 @@ independent of changes to the merge request.
### Approvers ### Approvers
At approvers you can define the default set of users that need to approve a At approvers you can define the default set of users that need to approve a
merge request. The author of a merge request cannot approve that merge request. merge request.
If there are more approvers than required approvals, any subset of these users If there are more approvers than required approvals, any subset of these users
can approve the merge request. can approve the merge request.
...@@ -64,4 +64,4 @@ yet the process is still enforced. ...@@ -64,4 +64,4 @@ yet the process is still enforced.
To approve a merge request, simply press the button. To approve a merge request, simply press the button.
![Merge request approval](merge_request_approvals/2_approvals.png) ![Merge request approval](merge_request_approvals/2_approvals.png)
\ No newline at end of file
...@@ -327,6 +327,13 @@ Feature: Project Merge Requests ...@@ -327,6 +327,13 @@ Feature: Project Merge Requests
And I click link "Close" And I click link "Close"
Then I should see closed merge request "Bug NS-04" Then I should see closed merge request "Bug NS-04"
Scenario: I approve merge request
Given merge request 'Bug NS-04' must be approved
And I click link "Bug NS-04"
And I should not see merge button
When I click link "Approve"
Then I should see approved merge request "Bug NS-04"
Scenario: Reporter can approve merge request Scenario: Reporter can approve merge request
Given I am a "Shop" reporter Given I am a "Shop" reporter
And I visit project "Shop" merge requests page And I visit project "Shop" merge requests page
...@@ -336,12 +343,13 @@ Feature: Project Merge Requests ...@@ -336,12 +343,13 @@ Feature: Project Merge Requests
When I click link "Approve" When I click link "Approve"
Then I should see message that merge request can be merged Then I should see message that merge request can be merged
Scenario: I can not approve Merge request if I am the author Scenario: I approve merge request if I am an approver
Given merge request 'Bug NS-04' must be approved Given merge request 'Bug NS-04' must be approved by current user
And I click link "Bug NS-04" And I click link "Bug NS-04"
And I should not see merge button And I should not see merge button
When I should not see Approve button And I should see message that MR require an approval from me
And I should see message that MR require an approval When I click link "Approve"
Then I should see approved merge request "Bug NS-04"
Scenario: I can not approve merge request if I am not an approver Scenario: I can not approve merge request if I am not an approver
Given merge request 'Bug NS-04' must be approved by some user Given merge request 'Bug NS-04' must be approved by some user
......
...@@ -2,8 +2,9 @@ module Gitlab ...@@ -2,8 +2,9 @@ module Gitlab
class AuthorityAnalyzer class AuthorityAnalyzer
COMMITS_TO_CONSIDER = 5 COMMITS_TO_CONSIDER = 5
def initialize(merge_request) def initialize(merge_request, current_user)
@merge_request = merge_request @merge_request = merge_request
@current_user = current_user
@users = Hash.new(0) @users = Hash.new(0)
end end
...@@ -11,7 +12,7 @@ module Gitlab ...@@ -11,7 +12,7 @@ module Gitlab
involved_users involved_users
# Picks most active users from hash like: {user1: 2, user2: 6} # Picks most active users from hash like: {user1: 2, user2: 6}
@users.sort_by { |user, count| -count }.map(&:first).take(number_of_approvers) @users.sort_by { |user, count| count }.map(&:first).take(number_of_approvers)
end end
private private
...@@ -21,9 +22,7 @@ module Gitlab ...@@ -21,9 +22,7 @@ module Gitlab
list_of_involved_files.each do |path| list_of_involved_files.each do |path|
@repo.commits(@merge_request.target_branch, path: path, limit: COMMITS_TO_CONSIDER).each do |commit| @repo.commits(@merge_request.target_branch, path: path, limit: COMMITS_TO_CONSIDER).each do |commit|
if commit.author && commit.author != @merge_request.author @users[commit.author] += 1 if commit.author
@users[commit.author] += 1
end
end end
end end
end end
......
...@@ -335,49 +335,6 @@ describe Projects::MergeRequestsController do ...@@ -335,49 +335,6 @@ describe Projects::MergeRequestsController do
end end
end end
describe 'POST #approve' do
def approve(user)
post :approve, namespace_id: project.namespace.path, project_id: project.path, id: merge_request.iid, user: user
end
context 'when the user is the author of the MR' do
before { merge_request.approvers.create(user: merge_request.author) }
it "returns a 404" do
approve(merge_request.author)
expect(response).to have_http_status(404)
end
end
context 'when the user is not allowed to approve the MR' do
it "returns a 404" do
approve(user)
expect(response).to have_http_status(404)
end
end
context 'when the user is allowed to approve the MR' do
before { merge_request.approvers.create(user: user) }
it 'creates an approval' do
service = double(:approval_service)
expect(MergeRequests::ApprovalService).to receive(:new).with(project, anything).and_return(service)
expect(service).to receive(:execute).with(merge_request)
approve(user)
end
it 'redirects to the MR' do
approve(user)
expect(response).to redirect_to(namespace_project_merge_request_path)
end
end
end
describe "DELETE #destroy" do describe "DELETE #destroy" do
it "denies access to users unless they're admin or project owner" do it "denies access to users unless they're admin or project owner" do
delete :destroy, namespace_id: project.namespace.path, project_id: project.path, id: merge_request.iid delete :destroy, namespace_id: project.namespace.path, project_id: project.path, id: merge_request.iid
......
require 'spec_helper'
describe Gitlab::AuthorityAnalyzer, lib: true do
describe '#calculate' do
let(:project) { create(:project) }
let(:author) { create(:user) }
let(:user_a) { create(:user) }
let(:user_b) { create(:user) }
let(:merge_request) { create(:merge_request, target_project: project, source_project: project, author: author) }
let(:files) { [double(:file, deleted_file: true, old_path: 'foo')] }
let(:commits) do
[
double(:commit, author: author),
double(:commit, author: user_a),
double(:commit, author: user_a),
double(:commit, author: user_b),
double(:commit, author: author)
]
end
def calculate_approvers(count)
described_class.new(merge_request).calculate(count)
end
before do
merge_request.compare = double(:compare, diffs: files)
allow(merge_request.target_project.repository).to receive(:commits).and_return(commits)
end
context 'when the MR author is in the top contributors' do
it 'does not include the MR author' do
approvers = calculate_approvers(2)
expect(approvers).not_to include(author)
end
it 'returns the correct number of contributors' do
approvers = calculate_approvers(2)
expect(approvers.length).to eq(2)
end
end
context 'when there are fewer contributors than requested' do
it 'returns the full number of users' do
approvers = calculate_approvers(5)
expect(approvers.length).to eq(2)
end
end
context 'when there are more contributors than requested' do
it 'returns only the top n contributors' do
approvers = calculate_approvers(1)
expect(approvers).to contain_exactly(user_a)
end
end
end
end
...@@ -223,7 +223,7 @@ describe MergeRequest, models: true do ...@@ -223,7 +223,7 @@ describe MergeRequest, models: true do
end end
end end
describe "#approvers_left" do describe "approvers_left" do
let(:merge_request) {create :merge_request} let(:merge_request) {create :merge_request}
it "returns correct value" do it "returns correct value" do
...@@ -256,58 +256,6 @@ describe MergeRequest, models: true do ...@@ -256,58 +256,6 @@ describe MergeRequest, models: true do
end end
end end
describe "#can_approve?" do
let(:author) { create(:user) }
let(:user) { create(:user) }
let(:merge_request) { create(:merge_request, author: author) }
context "when the user is the MR author" do
it "returns false" do
expect(merge_request.can_approve?(author)).to eq(false)
end
end
context "when the user is not the MR author" do
context "when the user is in the approvers list" do
before { merge_request.approvers.create(user: user) }
context "when the user has not already approved the MR" do
it "returns true" do
expect(merge_request.can_approve?(user)).to eq(true)
end
end
context "when the user has already approved the MR" do
before { merge_request.approvals.create(user: user) }
it "returns false" do
expect(merge_request.can_approve?(user)).to eq(false)
end
end
end
context "when the user is not in the approvers list" do
context "when anyone is allowed to approve the MR" do
before { merge_request.target_project.update_attributes(approvals_before_merge: 1) }
context "when the user has not already approved the MR" do
it "returns true" do
expect(merge_request.can_approve?(user)).to eq(true)
end
end
context "when the user has already approved the MR" do
before { merge_request.approvals.create(user: user) }
it "returns false" do
expect(merge_request.can_approve?(user)).to eq(false)
end
end
end
end
end
end
describe '#can_remove_source_branch?' do describe '#can_remove_source_branch?' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:user2) { create(:user) } let(:user2) { create(:user) }
......
...@@ -695,24 +695,14 @@ describe API::API, api: true do ...@@ -695,24 +695,14 @@ describe API::API, api: true do
end end
describe 'POST :id/merge_requests/:merge_request_id/approve' do describe 'POST :id/merge_requests/:merge_request_id/approve' do
context 'when the user is an allowed approver' do it 'approves the merge request' do
it 'approves the merge request' do project.update_attribute(:approvals_before_merge, 2)
project.update_attribute(:approvals_before_merge, 2)
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/approve", admin)
expect(response.status).to eq(201)
expect(json_response['approvals_left']).to eq(1)
expect(json_response['approved_by'][0]['user']['username']).to eq(admin.username)
end
end
context 'when the user is the MR author' do post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/approve", user)
it 'returns a not authorised response' do
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/approve", user)
expect(response.status).to eq(401) expect(response.status).to eq(201)
end expect(json_response['approvals_left']).to eq(1)
expect(json_response['approved_by'][0]['user']['username']).to eq(user.username)
end end
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