From 5525db8b33bf1f76c4a8023ea4fb571d73e41b0f Mon Sep 17 00:00:00 2001
From: Grzegorz Bizon <grzesiek.bizon@gmail.com>
Date: Thu, 6 Apr 2017 11:52:37 +0200
Subject: [PATCH] Check branch access when user triggers manual action

---
 app/models/ci/build.rb       | 10 ++++++
 spec/models/ci/build_spec.rb | 65 +++++++++++++++++++++++++++++-------
 2 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 8431c5f228c..159b3b2e101 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -115,7 +115,17 @@ module Ci
       commands.present?
     end
 
+    def can_play?(current_user)
+      ::Gitlab::UserAccess
+        .new(current_user, project: project)
+        .can_push_to_branch?(ref)
+    end
+
     def play(current_user)
+      unless can_play?(current_user)
+        raise Gitlab::Access::AccessDeniedError
+      end
+
       # Try to queue a current build
       if self.enqueue
         self.update(user: current_user)
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index ae390afbd80..8124d263fd4 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -925,6 +925,33 @@ describe Ci::Build, :models do
     end
   end
 
+  describe '#can_play?' do
+    before do
+      project.add_developer(user)
+    end
+
+    let(:build) do
+      create(:ci_build, ref: 'some-ref', pipeline: pipeline)
+    end
+
+    context 'when branch build is running for is protected' do
+      before do
+        create(:protected_branch, :no_one_can_push,
+               name: 'some-ref', project: project)
+      end
+
+      it 'indicates that user can not trigger an action' do
+        expect(build.can_play?(user)).to be_falsey
+      end
+    end
+
+    context 'when branch build is running for is not protected' do
+      it 'indicates that user can trigger an action' do
+        expect(build.can_play?(user)).to be_truthy
+      end
+    end
+  end
+
   describe '#play' do
     let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
 
@@ -932,25 +959,39 @@ describe Ci::Build, :models do
       project.add_developer(user)
     end
 
-    context 'when build is manual' do
-      it 'enqueues a build' do
-        new_build = build.play(user)
+    context 'when user does not have ability to trigger action' do
+      before do
+        create(:protected_branch, :no_one_can_push,
+               name: build.ref, project: project)
+      end
 
-        expect(new_build).to be_pending
-        expect(new_build).to eq(build)
+      it 'raises an error' do
+        expect { build.play(user) }
+          .to raise_error Gitlab::Access::AccessDeniedError
       end
     end
 
-    context 'when build is passed' do
-      before do
-        build.update(status: 'success')
+    context 'when user has ability to trigger manual action' do
+      context 'when build is manual' do
+        it 'enqueues a build' do
+          new_build = build.play(user)
+
+          expect(new_build).to be_pending
+          expect(new_build).to eq(build)
+        end
       end
 
-      it 'creates a new build' do
-        new_build = build.play(user)
+      context 'when build is not manual' do
+        before do
+          build.update(status: 'success')
+        end
+
+        it 'creates a new build' do
+          new_build = build.play(user)
 
-        expect(new_build).to be_pending
-        expect(new_build).not_to eq(build)
+          expect(new_build).to be_pending
+          expect(new_build).not_to eq(build)
+        end
       end
     end
   end
-- 
GitLab