1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
# frozen_string_literal: true
module Repositories
class GitHttpController < Repositories::GitHttpClientController
include WorkhorseRequest
before_action :access_check
prepend_before_action :deny_head_requests, only: [:info_refs]
rescue_from Gitlab::GitAccess::ForbiddenError, with: :render_403_with_exception
rescue_from JWT::DecodeError, with: :render_403_with_exception
rescue_from Gitlab::GitAccess::NotFoundError, with: :render_404_with_exception
rescue_from Gitlab::GitAccessProject::CreationError, with: :render_422_with_exception
rescue_from Gitlab::GitAccess::TimeoutError, with: :render_503_with_exception
rescue_from GRPC::Unavailable do |e|
render_503_with_exception(e, message: 'The git server, Gitaly, is not available at this time. Please contact your administrator.')
end
# 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
log_user_activity if upload_pack?
render_ok
end
# POST /foo/bar.git/git-upload-pack (git pull)
def git_upload_pack
update_fetch_statistics
render_ok
end
# POST /foo/bar.git/git-receive-pack" (git push)
def git_receive_pack
render_ok
end
# POST /foo/bar.git/ssh-upload-pack" (git pull via SSH)
def ssh_upload_pack
render plain: "Not found", status: :not_found
end
# POST /foo/bar.git/ssh-receive-pack" (git push via SSH)
def ssh_receive_pack
render plain: "Not found", status: :not_found
end
private
def deny_head_requests
head :forbidden if request.head?
end
def download_request?
upload_pack?
end
def upload_pack?
git_command == 'git-upload-pack'
end
def git_command
case action_name
when 'info_refs'
params[:service]
when 'ssh_upload_pack'
'git-upload-pack'
when 'ssh_receive_pack'
'git-receive-pack'
else
action_name.dasherize
end
end
def render_ok
set_workhorse_internal_api_content_type
render json: Gitlab::Workhorse.git_http_ok(repository, repo_type, user, action_name)
end
def render_403_with_exception(exception)
render plain: exception.message, status: :forbidden
end
def render_404_with_exception(exception)
render plain: exception.message, status: :not_found
end
def render_422_with_exception(exception)
render plain: exception.message, status: :unprocessable_entity
end
def render_503_with_exception(exception, message: nil)
render plain: message || exception.message, status: :service_unavailable
end
def update_fetch_statistics
return unless project
return if Gitlab::Database.read_only?
return unless repo_type.project?
return if Feature.enabled?(:disable_git_http_fetch_writes)
Projects::FetchStatisticsIncrementService.new(project).execute
end
def access
@access ||= access_klass.new(access_actor, container, 'http',
authentication_abilities: authentication_abilities,
repository_path: repository_path,
redirected_path: redirected_path,
auth_result_type: auth_result_type)
end
def access_actor
return user if user
:ci if ci?
end
def access_check
access.check(git_command, Gitlab::GitAccess::ANY)
@project = @container = access.container if repo_type.project? && !container
end
def access_klass
@access_klass ||= repo_type.access_checker_class
end
def log_user_activity
Users::ActivityService.new(author: user, project: project, namespace: project&.namespace).execute
return unless project && user
Gitlab::EventStore.publish(
Users::ActivityEvent.new(data: {
user_id: user.id,
namespace_id: project.root_ancestor.id
})
)
end
def append_info_to_payload(payload)
super
payload[:metadata] ||= {}
payload[:metadata][:repository_storage] = project&.repository_storage
end
end
end
Repositories::GitHttpController.prepend_mod_with('Repositories::GitHttpController')
|