From 0a081e7eff9730beebd4bea1eb40873d907b6293 Mon Sep 17 00:00:00 2001
From: Marin Jankovski <maxlazio@gmail.com>
Date: Thu, 3 Dec 2015 14:59:10 +0100
Subject: [PATCH] If a user clicks on the LFS object, it should be served if
 the user has access to the object.

---
 app/controllers/projects/blob_controller.rb | 17 +++++++++++++++++
 app/models/lfs_object.rb                    | 10 ++++++++++
 2 files changed, 27 insertions(+)

diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 31a33bfd237..d0108c823a9 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -17,6 +17,7 @@ class Projects::BlobController < Projects::ApplicationController
   before_action :require_branch_head, only: [:edit, :update]
   before_action :editor_variables, except: [:show, :preview, :diff]
   before_action :after_edit_path, only: [:edit, :update]
+  before_action :show_lfs_object, only: :show
 
   def new
     commit unless @repository.empty?
@@ -193,4 +194,20 @@ class Projects::BlobController < Projects::ApplicationController
       file_content_encoding: params[:encoding]
     }
   end
+
+  def show_lfs_object
+    return unless @blob && @blob.text? && @blob.data.present?
+
+    if @blob.data.starts_with?("version https://git-lfs.github.com/spec")
+      oid = @blob.data.match(/#{LfsObject::MATCH_FROM_POINTER_REGEX}/)
+      if oid && oid[1]
+        lfs_object = LfsObject.find_by_oid(oid[1])
+        return nil unless lfs_object && lfs_object.file.exists?
+
+        if lfs_object.projects.exists?(lfs_object.storage_project(@project).id)
+          send_file lfs_object.file.path, filename: @blob.name, disposition: 'attachment'
+        end
+      end
+    end
+  end
 end
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index 3c1426f59d0..f087d07b5b2 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -5,4 +5,14 @@ class LfsObject < ActiveRecord::Base
   validates :oid, presence: true, uniqueness: true
 
   mount_uploader :file, LfsObjectUploader
+
+  MATCH_FROM_POINTER_REGEX = "(?<=sha256:)([0-9a-f]{64})"
+
+  def storage_project(project)
+    if project && project.forked?
+      project.forked_from_project
+    else
+      project
+    end
+  end
 end
-- 
2.30.9