lfs_api_controller.rb 2.52 KB
Newer Older
Jacob Vosmaer's avatar
Jacob Vosmaer committed
1
class Projects::LfsApiController < Projects::GitHttpClientController
2
  include LfsRequest
Jacob Vosmaer's avatar
Jacob Vosmaer committed
3

4
  skip_before_action :lfs_check_access!, only: [:deprecated]
5
  before_action :lfs_check_batch_operation!, only: [:batch]
Jacob Vosmaer's avatar
Jacob Vosmaer committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

  def batch
    unless objects.present?
      render_lfs_not_found
      return
    end

    if download_request?
      render json: { objects: download_objects! }
    elsif upload_request?
      render json: { objects: upload_objects! }
    else
      raise "Never reached"
    end
  end

  def deprecated
    render(
      json: {
        message: 'Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.',
26
        documentation_url: "#{Gitlab.config.gitlab.url}/help"
Jacob Vosmaer's avatar
Jacob Vosmaer committed
27 28 29 30 31 32 33
      },
      status: 501
    )
  end

  private

34 35 36 37 38 39 40 41
  def download_request?
    params[:operation] == 'download'
  end

  def upload_request?
    params[:operation] == 'upload'
  end

Jacob Vosmaer's avatar
Jacob Vosmaer committed
42 43 44 45 46 47 48 49 50 51
  def existing_oids
    @existing_oids ||= begin
      storage_project.lfs_objects.where(oid: objects.map { |o| o['oid'].to_s }).pluck(:oid)
    end
  end

  def download_objects!
    objects.each do |object|
      if existing_oids.include?(object[:oid])
        object[:actions] = download_actions(object)
52 53 54 55

        if Guest.can?(:download_code, project)
          object[:authenticated] = true
        end
Jacob Vosmaer's avatar
Jacob Vosmaer committed
56 57 58
      else
        object[:error] = {
          code: 404,
59
          message: "Object does not exist on the server or you don't have permissions to access it"
Jacob Vosmaer's avatar
Jacob Vosmaer committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
        }
      end
    end
    objects
  end

  def upload_objects!
    objects.each do |object|
      object[:actions] = upload_actions(object) unless existing_oids.include?(object[:oid])
    end
    objects
  end

  def download_actions(object)
    {
      download: {
        href: "#{project.http_url_to_repo}/gitlab-lfs/objects/#{object[:oid]}",
        header: {
          Authorization: request.headers['Authorization']
        }.compact
      }
    }
  end

  def upload_actions(object)
    {
      upload: {
        href: "#{project.http_url_to_repo}/gitlab-lfs/objects/#{object[:oid]}/#{object[:size]}",
        header: {
          Authorization: request.headers['Authorization']
        }.compact
      }
    }
  end
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

  def lfs_check_batch_operation!
    if upload_request? && Gitlab::Database.read_only?
      render(
        json: {
          message: lfs_read_only_message
        },
        content_type: 'application/vnd.git-lfs+json',
        status: 403
      )
    end
  end

  # Overridden in EE
  def lfs_read_only_message
    _('You cannot write to this read-only GitLab instance.')
  end
Jacob Vosmaer's avatar
Jacob Vosmaer committed
111
end