From c3d897a9a382b0b3354d29726add5af8c322beb4 Mon Sep 17 00:00:00 2001
From: Kamil Trzcinski <ayufan@ayufan.eu>
Date: Wed, 3 Feb 2016 13:33:47 +0100
Subject: [PATCH] Properly handle commit status permissions (for a build)

---
 app/models/ability.rb                         | 22 +++++++++++++++++++
 .../commit_statuses/_commit_status.html.haml  |  8 +++----
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/app/models/ability.rb b/app/models/ability.rb
index a9246dd3dd5..bf24749b173 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -5,6 +5,12 @@ class Ability
       return [] unless user.is_a?(User)
       return [] if user.blocked?
 
+      if subject.is_a?(CommitStatus)
+        rules = project_abilities(user, subject)
+        rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build)
+        return rules
+      end
+
       case subject.class.name
       when "Project" then project_abilities(user, subject)
       when "Issue" then issue_abilities(user, subject)
@@ -25,6 +31,10 @@ class Ability
       case true
       when subject.is_a?(PersonalSnippet)
         anonymous_personal_snippet_abilities(subject)
+      when subject.is_a?(CommitStatus)
+        rules = anonymous_project_abilities(subject)
+        rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build)
+        rules
       when subject.is_a?(Project) || subject.respond_to?(:project)
         anonymous_project_abilities(subject)
       when subject.is_a?(Group) || subject.respond_to?(:group)
@@ -396,6 +406,18 @@ class Ability
       rules
     end
 
+    def filter_build_abilities(rules)
+      # If we can't read build we should also not have that
+      # ability when looking at this in context of commit_status
+      unless rules.include?(:read_build)
+        rules -= [:read_commit_status]
+      end
+      unless rules.include?(:update_build)
+        rules -= [:update_commit_status]
+      end
+      rules
+    end
+
     def abilities
       @abilities ||= begin
         abilities = Six.new
diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml
index fba4405cb7d..c02c5983ac8 100644
--- a/app/views/projects/commit_statuses/_commit_status.html.haml
+++ b/app/views/projects/commit_statuses/_commit_status.html.haml
@@ -1,6 +1,6 @@
 %tr.commit_status
   %td.status
-    - if commit_status.target_url
+    - if can?(current_user, :read_commit_status, commit_status) && commit_status.target_url
       = link_to commit_status.target_url, class: "ci-status ci-#{commit_status.status}" do
         = ci_icon_for_status(commit_status.status)
         = commit_status.status
@@ -8,7 +8,7 @@
       = ci_status_with_icon(commit_status.status)
 
   %td.commit_status-link
-    - if can?(current_user, :read_build, commit_status.project) && commit_status.target_url
+    - if can?(current_user, :read_commit_status, commit_status) && commit_status.target_url
       = link_to commit_status.target_url do
         %strong ##{commit_status.id}
     - else
@@ -66,10 +66,10 @@
 
   %td
     .pull-right
-      - if can?(current_user, :read_build, commit_status.project) && commit_status.artifacts_download_url
+      - if can?(current_user, :read_commit_status, commit_status) && commit_status.artifacts_download_url
         = link_to commit_status.artifacts_download_url, title: 'Download artifacts' do
           %i.fa.fa-download
-      - if can?(current_user, :update_build, commit_status.project)
+      - if can?(current_user, :update_commit_status, commit_status)
         - if commit_status.active?
           - if commit_status.cancel_url
             = link_to commit_status.cancel_url, method: :post, title: 'Cancel' do
-- 
GitLab