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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
require 'net/http'
require 'openssl'
require 'json'
require_relative 'gitlab_config'
require_relative 'gitlab_access'
require_relative 'gitlab_lfs_authentication'
require_relative 'http_helper'
class GitlabNet # rubocop:disable Metrics/ClassLength
include HTTPHelper
class ApiUnreachableError < StandardError; end
class NotFound < StandardError; end
CHECK_TIMEOUT = 5
API_INACCESSIBLE_MESSAGE = 'API is not accessible'.freeze
def check_access(cmd, gl_repository, repo, who, changes, protocol, env: {})
changes = changes.join("\n") unless changes.is_a?(String)
params = {
action: cmd,
changes: changes,
gl_repository: gl_repository,
project: sanitize_path(repo),
protocol: protocol,
env: env
}
who_sym, _, who_v = self.class.parse_who(who)
params[who_sym] = who_v
url = "#{internal_api_endpoint}/allowed"
resp = post(url, params)
case resp
when Net::HTTPSuccess, Net::HTTPMultipleChoices, Net::HTTPUnauthorized,
Net::HTTPNotFound
if resp.content_type == CONTENT_TYPE_JSON
return GitAccessStatus.create_from_json(resp.body, resp.code)
end
end
GitAccessStatus.new(false, resp.code, API_INACCESSIBLE_MESSAGE)
end
def discover(who)
_, who_k, who_v = self.class.parse_who(who)
resp = get("#{internal_api_endpoint}/discover?#{who_k}=#{who_v}")
JSON.parse(resp.body) rescue nil
end
def lfs_authenticate(gl_id, repo)
id_sym, _, id = self.class.parse_who(gl_id)
if id_sym == :key_id
params = {
project: sanitize_path(repo),
key_id: id
}
elsif id_sym == :user_id
params = {
project: sanitize_path(repo),
user_id: id
}
else
raise ArgumentError, "lfs_authenticate() got unsupported GL_ID='#{gl_id}'!"
end
resp = post("#{internal_api_endpoint}/lfs_authenticate", params)
if resp.code == '200'
GitlabLfsAuthentication.build_from_json(resp.body)
end
end
def broadcast_message
resp = get("#{internal_api_endpoint}/broadcast_message")
JSON.parse(resp.body) rescue {}
end
def merge_request_urls(gl_repository, repo_path, changes)
changes = changes.join("\n") unless changes.is_a?(String)
changes = changes.encode('UTF-8', 'ASCII', invalid: :replace, replace: '')
url = "#{internal_api_endpoint}/merge_request_urls?project=#{URI.escape(repo_path)}&changes=#{URI.escape(changes)}"
url += "&gl_repository=#{URI.escape(gl_repository)}" if gl_repository
resp = get(url)
if resp.code == '200'
JSON.parse(resp.body)
else
[]
end
rescue
[]
end
def check
get("#{internal_api_endpoint}/check", options: { read_timeout: CHECK_TIMEOUT })
end
def authorized_key(key)
resp = get("#{internal_api_endpoint}/authorized_keys?key=#{URI.escape(key, '+/=')}")
JSON.parse(resp.body) if resp.code == "200"
rescue
nil
end
def two_factor_recovery_codes(gl_id)
id_sym, _, id = self.class.parse_who(gl_id)
resp = post("#{internal_api_endpoint}/two_factor_recovery_codes", id_sym => id)
JSON.parse(resp.body) if resp.code == '200'
rescue
{}
end
def notify_post_receive(gl_repository, repo_path)
params = { gl_repository: gl_repository, project: repo_path }
resp = post("#{internal_api_endpoint}/notify_post_receive", params)
resp.code == '200'
rescue
false
end
def post_receive(gl_repository, identifier, changes)
params = {
gl_repository: gl_repository,
identifier: identifier,
changes: changes
}
resp = post("#{internal_api_endpoint}/post_receive", params)
raise NotFound if resp.code == '404'
JSON.parse(resp.body) if resp.code == '200'
end
def pre_receive(gl_repository)
resp = post("#{internal_api_endpoint}/pre_receive", gl_repository: gl_repository)
raise NotFound if resp.code == '404'
JSON.parse(resp.body) if resp.code == '200'
end
def self.parse_who(who)
if who.start_with?("key-")
value = who.gsub("key-", "")
raise ArgumentError, "who='#{who}' is invalid!" unless value =~ /\A[0-9]+\z/
[:key_id, 'key_id', value]
elsif who.start_with?("user-")
value = who.gsub("user-", "")
raise ArgumentError, "who='#{who}' is invalid!" unless value =~ /\A[0-9]+\z/
[:user_id, 'user_id', value]
elsif who.start_with?("username-")
[:username, 'username', who.gsub("username-", "")]
else
raise ArgumentError, "who='#{who}' is invalid!"
end
end
protected
def sanitize_path(repo)
repo.delete("'")
end
end
|