git_http_controller.rb 2.4 KB
Newer Older
J
Jacob Vosmaer 已提交
1
class Projects::GitHttpController < Projects::GitHttpClientController
2
  include WorkhorseRequest
3

4 5 6
  # GET /foo/bar.git/info/refs?service=git-upload-pack (git pull)
  # GET /foo/bar.git/info/refs?service=git-receive-pack (git push)
  def info_refs
J
Jacob Vosmaer 已提交
7
    if upload_pack? && upload_pack_allowed?
J
Jacob Vosmaer 已提交
8 9 10
      render_ok
    elsif receive_pack? && receive_pack_allowed?
      render_ok
11
    elsif http_blocked?
J
Jacob Vosmaer 已提交
12
      render_http_not_allowed
J
Jacob Vosmaer 已提交
13
    else
J
Jacob Vosmaer 已提交
14
      render_denied
J
Jacob Vosmaer 已提交
15 16
    end
  end
J
Jacob Vosmaer 已提交
17

18 19 20 21 22
  # POST /foo/bar.git/git-upload-pack (git pull)
  def git_upload_pack
    if upload_pack? && upload_pack_allowed?
      render_ok
    else
J
Jacob Vosmaer 已提交
23
      render_denied
24 25 26 27 28 29 30 31
    end
  end

  # POST /foo/bar.git/git-receive-pack" (git push)
  def git_receive_pack
    if receive_pack? && receive_pack_allowed?
      render_ok
    else
J
Jacob Vosmaer 已提交
32
      render_denied
33
    end
J
Jacob Vosmaer 已提交
34 35 36 37
  end

  private

J
Jacob Vosmaer 已提交
38 39
  def download_request?
    upload_pack?
J
Jacob Vosmaer 已提交
40 41 42
  end

  def upload_pack?
43
    git_command == 'git-upload-pack'
J
Jacob Vosmaer 已提交
44 45 46
  end

  def receive_pack?
47
    git_command == 'git-receive-pack'
J
Jacob Vosmaer 已提交
48 49
  end

50
  def git_command
J
Jacob Vosmaer 已提交
51
    if action_name == 'info_refs'
J
Jacob Vosmaer 已提交
52
      params[:service]
J
Jacob Vosmaer 已提交
53
    else
54
      action_name.dasherize
J
Jacob Vosmaer 已提交
55 56
    end
  end
J
Jacob Vosmaer 已提交
57

J
Jacob Vosmaer 已提交
58
  def render_ok
59
    set_workhorse_internal_api_content_type
60
    render json: Gitlab::Workhorse.git_http_ok(repository, user, action_name)
J
Jacob Vosmaer 已提交
61
  end
J
Jacob Vosmaer 已提交
62

J
Jacob Vosmaer 已提交
63 64 65 66 67
  def render_http_not_allowed
    render plain: access_check.message, status: :forbidden
  end

  def render_denied
68 69
    if user && can?(user, :read_project, project)
      render plain: access_denied_message, status: :forbidden
J
Jacob Vosmaer 已提交
70 71 72 73
    else
      # Do not leak information about project existence
      render_not_found
    end
74 75
  end

76 77 78 79
  def access_denied_message
    'Access denied'
  end

J
Jacob Vosmaer 已提交
80
  def upload_pack_allowed?
81 82
    return false unless Gitlab.config.gitlab_shell.upload_pack

83
    access_check.allowed? || ci?
J
Jacob Vosmaer 已提交
84
  end
J
Jacob Vosmaer 已提交
85

86
  def access
87
    @access ||= access_klass.new(user, project, 'http', authentication_abilities: authentication_abilities)
88 89
  end

J
Jacob Vosmaer 已提交
90 91 92 93
  def access_check
    # Use the magic string '_any' to indicate we do not know what the
    # changes are. This is also what gitlab-shell does.
    @access_check ||= access.check(git_command, '_any')
P
Patricio Cano 已提交
94 95
  end

96
  def http_blocked?
97
    !access.protocol_allowed?
98 99
  end

J
Jacob Vosmaer 已提交
100
  def receive_pack_allowed?
101 102
    return false unless Gitlab.config.gitlab_shell.receive_pack

J
Jacob Vosmaer 已提交
103
    access_check.allowed?
J
Jacob Vosmaer 已提交
104
  end
105 106 107 108

  def access_klass
    @access_klass ||= wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess
  end
J
Jacob Vosmaer 已提交
109
end