Read about our upcoming Code of Conduct on this issue

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]
Toon Claes's avatar
Toon Claes committed
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
Toon Claes's avatar
Toon Claes committed
94
95
96
97
98
99
100

  def lfs_check_batch_operation!
    if upload_request? && Gitlab::Database.read_only?
      render(
        json: {
          message: lfs_read_only_message
        },
101
        content_type: LfsRequest::CONTENT_TYPE,
Toon Claes's avatar
Toon Claes committed
102
103
104
105
106
107
108
109
110
        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