From 65bb0c34066eef77647e1d60e6bac7a12993cd93 Mon Sep 17 00:00:00 2001
From: Douwe Maan <douwe@gitlab.com>
Date: Fri, 27 Mar 2015 12:19:48 +0100
Subject: [PATCH] Only allow users to cross-reference and close issues they
 have access to.

---
 app/models/commit.rb                  | 4 ++--
 app/models/concerns/mentionable.rb    | 6 +++---
 app/models/merge_request.rb           | 6 +++---
 app/services/git_push_service.rb      | 4 ++--
 lib/gitlab/closing_issue_extractor.rb | 4 ++--
 5 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/app/models/commit.rb b/app/models/commit.rb
index 481300171be..084cf420079 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -117,8 +117,8 @@ class Commit
 
   # Discover issues should be closed when this commit is pushed to a project's
   # default branch.
-  def closes_issues(project)
-    Gitlab::ClosingIssueExtractor.closed_by_message_in_project(safe_message, project)
+  def closes_issues(project, current_user = self.committer)
+    Gitlab::ClosingIssueExtractor.closed_by_message_in_project(safe_message, project, current_user)
   end
 
   # Mentionable override.
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 41bcfa6be21..bf0465728e7 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -51,10 +51,10 @@ module Mentionable
   end
 
   # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference.
-  def references(p = project, text = mentionable_text)
+  def references(p = project, current_user = self.author, text = mentionable_text)
     return [] if text.blank?
 
-    ext = Gitlab::ReferenceExtractor.new(p)
+    ext = Gitlab::ReferenceExtractor.new(p, current_user)
     ext.analyze(text)
 
     (ext.issues + ext.merge_requests + ext.commits).uniq - [local_reference]
@@ -83,7 +83,7 @@ module Mentionable
     # Only proceed if the saved changes actually include a chance to an attr_mentionable field.
     return unless mentionable_changed
 
-    preexisting = references(p, original)
+    preexisting = references(p, self.author, original)
     create_cross_references!(p, a, preexisting)
   end
 end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 5634f9a686e..167d7f9c71f 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -257,11 +257,11 @@ class MergeRequest < ActiveRecord::Base
   end
 
   # Return the set of issues that will be closed if this merge request is accepted.
-  def closes_issues
+  def closes_issues(current_user = self.author)
     if target_branch == project.default_branch
-      issues = commits.flat_map { |c| c.closes_issues(project) }
+      issues = commits.flat_map { |c| c.closes_issues(project, current_user) }
       issues.push(*Gitlab::ClosingIssueExtractor.
-                  closed_by_message_in_project(description, project))
+                  closed_by_message_in_project(description, project, current_user))
       issues.uniq.sort_by(&:id)
     else
       []
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index bb066e39f6b..31e0167d247 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -70,7 +70,7 @@ class GitPushService
       # Close issues if these commits were pushed to the project's default branch and the commit message matches the
       # closing regex. Exclude any mentioned Issues from cross-referencing even if the commits are being pushed to
       # a different branch.
-      issues_to_close = commit.closes_issues(project)
+      issues_to_close = commit.closes_issues(project, user)
 
       # Load commit author only if needed.
       # For push with 1k commits it prevents 900+ requests in database
@@ -87,7 +87,7 @@ class GitPushService
       # Create cross-reference notes for any other references. Omit any issues that were referenced in an
       # issue-closing phrase, or have already been mentioned from this commit (probably from this commit
       # being pushed to a different branch).
-      refs = commit.references(project) - issues_to_close
+      refs = commit.references(project, user) - issues_to_close
       refs.reject! { |r| commit.has_mentioned?(r) }
 
       if refs.present?
diff --git a/lib/gitlab/closing_issue_extractor.rb b/lib/gitlab/closing_issue_extractor.rb
index 5643d60c807..6425193d85f 100644
--- a/lib/gitlab/closing_issue_extractor.rb
+++ b/lib/gitlab/closing_issue_extractor.rb
@@ -2,14 +2,14 @@ module Gitlab
   module ClosingIssueExtractor
     ISSUE_CLOSING_REGEX = Regexp.new(Gitlab.config.gitlab.issue_closing_pattern)
 
-    def self.closed_by_message_in_project(message, project)
+    def self.closed_by_message_in_project(message, project, current_user = nil)
       issues = []
 
       unless message.nil?
         md = message.scan(ISSUE_CLOSING_REGEX)
 
         md.each do |ref|
-          extractor = Gitlab::ReferenceExtractor.new(project)
+          extractor = Gitlab::ReferenceExtractor.new(project, current_user)
           extractor.analyze(ref[0])
           issues += extractor.issues
         end
-- 
GitLab