87 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
class Projects::LfsStorageController < Projects::GitHttpClientController
 | 
						|
  include LfsRequest
 | 
						|
  include WorkhorseRequest
 | 
						|
 | 
						|
  skip_before_action :verify_workhorse_api!, only: [:download, :upload_finalize]
 | 
						|
 | 
						|
  def download
 | 
						|
    lfs_object = LfsObject.find_by_oid(oid)
 | 
						|
    unless lfs_object && lfs_object.file.exists?
 | 
						|
      render_lfs_not_found
 | 
						|
      return
 | 
						|
    end
 | 
						|
 | 
						|
    send_file lfs_object.file.path, content_type: "application/octet-stream"
 | 
						|
  end
 | 
						|
 | 
						|
  def upload_authorize
 | 
						|
    set_workhorse_internal_api_content_type
 | 
						|
    render json: Gitlab::Workhorse.lfs_upload_ok(oid, size)
 | 
						|
  end
 | 
						|
 | 
						|
  def upload_finalize
 | 
						|
    unless tmp_filename
 | 
						|
      render_lfs_forbidden
 | 
						|
      return
 | 
						|
    end
 | 
						|
 | 
						|
    if store_file(oid, size, tmp_filename)
 | 
						|
      head 200
 | 
						|
    else
 | 
						|
      render plain: 'Unprocessable entity', status: 422
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  private
 | 
						|
 | 
						|
  def download_request?
 | 
						|
    action_name == 'download'
 | 
						|
  end
 | 
						|
 | 
						|
  def upload_request?
 | 
						|
    %w[upload_authorize upload_finalize].include? action_name
 | 
						|
  end
 | 
						|
 | 
						|
  def oid
 | 
						|
    params[:oid].to_s
 | 
						|
  end
 | 
						|
 | 
						|
  def size
 | 
						|
    params[:size].to_i
 | 
						|
  end
 | 
						|
 | 
						|
  def tmp_filename
 | 
						|
    name = request.headers['X-Gitlab-Lfs-Tmp']
 | 
						|
    return if name.include?('/')
 | 
						|
    return unless oid.present? && name.start_with?(oid)
 | 
						|
    name
 | 
						|
  end
 | 
						|
 | 
						|
  def store_file(oid, size, tmp_file)
 | 
						|
    # Define tmp_file_path early because we use it in "ensure"
 | 
						|
    tmp_file_path = File.join("#{Gitlab.config.lfs.storage_path}/tmp/upload", tmp_file)
 | 
						|
 | 
						|
    object = LfsObject.find_or_create_by(oid: oid, size: size)
 | 
						|
    file_exists = object.file.exists? || move_tmp_file_to_storage(object, tmp_file_path)
 | 
						|
    file_exists && link_to_project(object)
 | 
						|
  ensure
 | 
						|
    FileUtils.rm_f(tmp_file_path)
 | 
						|
  end
 | 
						|
 | 
						|
  def move_tmp_file_to_storage(object, path)
 | 
						|
    File.open(path) do |f|
 | 
						|
      object.file = f
 | 
						|
    end
 | 
						|
 | 
						|
    object.file.store!
 | 
						|
    object.save
 | 
						|
  end
 | 
						|
 | 
						|
  def link_to_project(object)
 | 
						|
    if object && !object.projects.exists?(storage_project.id)
 | 
						|
      object.projects << storage_project
 | 
						|
      object.save
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |