From 6baaa8a98e10ff93ba3f481052bb68fdafb6e2c1 Mon Sep 17 00:00:00 2001
From: Grzegorz Bizon <grzesiek.bizon@gmail.com>
Date: Mon, 1 May 2017 13:38:57 +0200
Subject: [PATCH] Add new ability check for stopping environment

---
 app/policies/environment_policy.rb           | 13 ++++-
 app/services/ci/stop_environments_service.rb |  9 +---
 spec/policies/environment_policy_spec.rb     | 57 ++++++++++++++++++++
 3 files changed, 71 insertions(+), 8 deletions(-)
 create mode 100644 spec/policies/environment_policy_spec.rb

diff --git a/app/policies/environment_policy.rb b/app/policies/environment_policy.rb
index f4219569161..0b976e5664d 100644
--- a/app/policies/environment_policy.rb
+++ b/app/policies/environment_policy.rb
@@ -1,5 +1,16 @@
 class EnvironmentPolicy < BasePolicy
+
+  alias_method :environment, :subject
+
   def rules
-    delegate! @subject.project
+    delegate! environment.project
+
+    if environment.stop_action?
+      delegate! environment.stop_action
+    end
+
+    if can?(:create_deployment) && can?(:play_build)
+      can! :stop_environment
+    end
   end
 end
diff --git a/app/services/ci/stop_environments_service.rb b/app/services/ci/stop_environments_service.rb
index bd9735fc0ac..43c9a065fcf 100644
--- a/app/services/ci/stop_environments_service.rb
+++ b/app/services/ci/stop_environments_service.rb
@@ -5,12 +5,11 @@ module Ci
     def execute(branch_name)
       @ref = branch_name
 
-      return unless has_ref?
-      return unless can?(current_user, :create_deployment, project)
+      return unless @ref.present?
 
       environments.each do |environment|
         next unless environment.stop_action?
-        next unless can?(current_user, :play_build, environment.stop_action)
+        next unless can?(current_user, :stop_environment, environment)
 
         environment.stop_with_action!(current_user)
       end
@@ -18,10 +17,6 @@ module Ci
 
     private
 
-    def has_ref?
-      @ref.present?
-    end
-
     def environments
       @environments ||= EnvironmentsFinder
         .new(project, current_user, ref: @ref, recently_updated: true)
diff --git a/spec/policies/environment_policy_spec.rb b/spec/policies/environment_policy_spec.rb
new file mode 100644
index 00000000000..f43caffa946
--- /dev/null
+++ b/spec/policies/environment_policy_spec.rb
@@ -0,0 +1,57 @@
+require 'spec_helper'
+
+describe Ci::EnvironmentPolicy do
+  let(:user) { create(:user) }
+  let(:project) { create(:project) }
+
+  let(:environment) do
+    create(:environment, :with_review_app, project: project)
+  end
+
+  let(:policies) do
+    described_class.abilities(user, environment).to_set
+  end
+
+  describe '#rules' do
+    context 'when user does not have access to the project' do
+      let(:project) { create(:project, :private) }
+
+      it 'does not include ability to stop environment' do
+        expect(policies).not_to include :stop_environment
+      end
+    end
+
+    context 'when anonymous user has access to the project' do
+      let(:project) { create(:project, :public) }
+
+      it 'does not include ability to stop environment' do
+        expect(policies).not_to include :stop_environment
+      end
+    end
+
+    context 'when team member has access to the project' do
+      let(:project) { create(:project, :public) }
+
+      before do
+        project.add_master(user)
+      end
+
+      context 'when team member has ability to stop environment' do
+        it 'does includes ability to stop environment' do
+          expect(policies).to include :stop_environment
+        end
+      end
+
+      context 'when team member has no ability to stop environment' do
+        before do
+          create(:protected_branch, :no_one_can_push,
+                 name: 'master', project: project)
+        end
+
+        it 'does not include ability to stop environment' do
+          expect(policies).not_to include :stop_environment
+        end
+      end
+    end
+  end
+end
-- 
GitLab