git_http_controller.rb 2.5 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?
8 9
      log_user_activity

J
Jacob Vosmaer 已提交
10 11 12
      render_ok
    elsif receive_pack? && receive_pack_allowed?
      render_ok
13
    elsif http_blocked?
J
Jacob Vosmaer 已提交
14
      render_http_not_allowed
J
Jacob Vosmaer 已提交
15
    else
J
Jacob Vosmaer 已提交
16
      render_denied
J
Jacob Vosmaer 已提交
17 18
    end
  end
J
Jacob Vosmaer 已提交
19

20 21 22 23 24
  # 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 已提交
25
      render_denied
26 27 28 29 30 31 32 33
    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 已提交
34
      render_denied
35
    end
J
Jacob Vosmaer 已提交
36 37 38 39
  end

  private

J
Jacob Vosmaer 已提交
40 41
  def download_request?
    upload_pack?
J
Jacob Vosmaer 已提交
42 43 44
  end

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

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

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

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

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

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

78 79 80 81
  def access_denied_message
    'Access denied'
  end

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

85
    access_check.allowed? || ci?
J
Jacob Vosmaer 已提交
86
  end
J
Jacob Vosmaer 已提交
87

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

J
Jacob Vosmaer 已提交
92 93 94 95
  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 已提交
96 97
  end

98
  def http_blocked?
99
    !access.protocol_allowed?
100 101
  end

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

J
Jacob Vosmaer 已提交
105
    access_check.allowed?
J
Jacob Vosmaer 已提交
106
  end
107 108 109 110

  def access_klass
    @access_klass ||= wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess
  end
111 112 113 114

  def log_user_activity
    Users::ActivityService.new(user, 'pull').execute
  end
J
Jacob Vosmaer 已提交
115
end