Read about our upcoming Code of Conduct on this issue

lfs_request.rb 2.42 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
# This concern assumes:
# - a `#project` accessor
# - a `#user` accessor
# - a `#authentication_result` accessor
# - a `#can?(object, action, subject)` method
# - a `#ci?` method
# - a `#download_request?` method
# - a `#upload_request?` method
# - a `#has_authentication_ability?(ability)` method
module LfsRequest
  extend ActiveSupport::Concern

13
14
  CONTENT_TYPE = 'application/vnd.git-lfs+json'.freeze

15
16
17
18
19
20
  included do
    before_action :require_lfs_enabled!
    before_action :lfs_check_access!
  end

  private
21

22
  def require_lfs_enabled!
Jacob Vosmaer's avatar
Jacob Vosmaer committed
23
24
25
26
27
    return if Gitlab.config.lfs.enabled

    render(
      json: {
        message: 'Git LFS is not enabled on this GitLab server, contact your admin.',
28
        documentation_url: help_url
Jacob Vosmaer's avatar
Jacob Vosmaer committed
29
30
31
32
33
34
35
36
37
      },
      status: 501
    )
  end

  def lfs_check_access!
    return if download_request? && lfs_download_access?
    return if upload_request? && lfs_upload_access?

38
39
    if project.public? || can?(user, :read_project, project)
      lfs_forbidden!
Jacob Vosmaer's avatar
Jacob Vosmaer committed
40
41
42
43
44
    else
      render_lfs_not_found
    end
  end

45
46
  def lfs_forbidden!
    render_lfs_forbidden
Jacob Vosmaer's avatar
Jacob Vosmaer committed
47
48
49
50
51
52
  end

  def render_lfs_forbidden
    render(
      json: {
        message: 'Access forbidden. Check your access level.',
53
        documentation_url: help_url
Jacob Vosmaer's avatar
Jacob Vosmaer committed
54
      },
55
      content_type: CONTENT_TYPE,
Jacob Vosmaer's avatar
Jacob Vosmaer committed
56
57
58
59
60
61
62
63
      status: 403
    )
  end

  def render_lfs_not_found
    render(
      json: {
        message: 'Not found.',
64
        documentation_url: help_url
Jacob Vosmaer's avatar
Jacob Vosmaer committed
65
      },
66
      content_type: CONTENT_TYPE,
Jacob Vosmaer's avatar
Jacob Vosmaer committed
67
68
69
70
      status: 404
    )
  end

71
72
73
74
75
76
77
78
  def lfs_download_access?
    return false unless project.lfs_enabled?

    ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code?
  end

  def lfs_upload_access?
    return false unless project.lfs_enabled?
79
    return false unless has_authentication_ability?(:push_code)
80

81
    lfs_deploy_token? || can?(user, :push_code, project)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  end

  def lfs_deploy_token?
    authentication_result.lfs_deploy_token?(project)
  end

  def user_can_download_code?
    has_authentication_ability?(:download_code) && can?(user, :download_code, project)
  end

  def build_can_download_code?
    has_authentication_ability?(:build_download_code) && can?(user, :build_download_code, project)
  end

Jacob Vosmaer's avatar
Jacob Vosmaer committed
96
  def storage_project
97
    @storage_project ||= project.lfs_storage_project
Jacob Vosmaer's avatar
Jacob Vosmaer committed
98
  end
99
100
101
102

  def objects
    @objects ||= (params[:objects] || []).to_a
  end
103
104
105
106

  def has_authentication_ability?(capability)
    (authentication_abilities || []).include?(capability)
  end
Jacob Vosmaer's avatar
Jacob Vosmaer committed
107
end