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
|
# frozen_string_literal: true
module Repositories
class GitHttpController < Repositories::GitHttpClientController
include WorkhorseRequest
before_action :snippet_request_allowed?
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 Gitlab::GitAccess::NotFoundError, with: :render_404_with_exception
rescue_from Gitlab::GitAccess::ProjectCreationError, with: :render_422_with_exception
rescue_from Gitlab::GitAccess::TimeoutError, with: :render_503_with_exception
# 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
enqueue_fetch_statistics_update
render_ok
end
# POST /foo/bar.git/git-receive-pack" (git push)
def git_receive_pack
render_ok
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
if action_name == 'info_refs'
params[:service]
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)
render plain: exception.message, status: :service_unavailable
end
def enqueue_fetch_statistics_update
return if Gitlab::Database.read_only?
return unless repo_type.project?
return unless project&.daily_statistics_enabled?
ProjectDailyStatisticsWorker.perform_async(project.id) # rubocop:disable CodeReuse/Worker
end
def access
@access ||= access_klass.new(access_actor, container, 'http',
authentication_abilities: authentication_abilities,
namespace_path: params[:namespace_id],
repository_path: repository_path,
redirected_path: redirected_path,
auth_result_type: auth_result_type)
end
def access_actor
return user if user
return :ci if ci?
end
def access_check
access.check(git_command, Gitlab::GitAccess::ANY)
if repo_type.project? && !container
@project = @container = access.project
end
end
def access_klass
@access_klass ||= repo_type.access_checker_class
end
def repository_path
@repository_path ||= params[:repository_id].sub(/\.git$/, '')
end
def log_user_activity
Users::ActivityService.new(user).execute
end
def snippet_request_allowed?
if repo_type.snippet? && Feature.disabled?(:version_snippets, user)
Gitlab::AppLogger.info('Snippet access attempt with feature disabled')
render plain: 'Snippet git access is disabled.', status: :forbidden
end
end
end
end
Repositories::GitHttpController.prepend_if_ee('EE::Repositories::GitHttpController')
|