summaryrefslogtreecommitdiff
path: root/lib/gitlab_net.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab_net.rb')
-rw-r--r--lib/gitlab_net.rb149
1 files changed, 55 insertions, 94 deletions
diff --git a/lib/gitlab_net.rb b/lib/gitlab_net.rb
index 9cb7e56..9ea18aa 100644
--- a/lib/gitlab_net.rb
+++ b/lib/gitlab_net.rb
@@ -1,23 +1,20 @@
-require 'net/http'
-require 'openssl'
require 'json'
-require_relative 'gitlab_config'
+require_relative 'errors'
require_relative 'gitlab_logger'
require_relative 'gitlab_access'
require_relative 'gitlab_lfs_authentication'
-require_relative 'httpunix'
require_relative 'http_helper'
+require_relative 'action'
-class GitlabNet # rubocop:disable Metrics/ClassLength
+class GitlabNet
include HTTPHelper
- class ApiUnreachableError < StandardError; end
- class NotFound < StandardError; end
-
CHECK_TIMEOUT = 5
+ GL_PROTOCOL = 'ssh'.freeze
+ API_INACCESSIBLE_ERROR = 'API is not accessible'.freeze
- def check_access(cmd, gl_repository, repo, who, changes, protocol, env: {})
+ def check_access(cmd, gl_repository, repo, actor, changes, protocol = GL_PROTOCOL, env: {})
changes = changes.join("\n") unless changes.is_a?(String)
params = {
@@ -29,56 +26,27 @@ class GitlabNet # rubocop:disable Metrics/ClassLength
env: env
}
- who_sym, _, who_v = self.class.parse_who(who)
- params[who_sym] = who_v
+ params[actor.identifier_key.to_sym] = actor.id
- url = "#{internal_api_endpoint}/allowed"
- resp = post(url, params)
+ resp = post("#{internal_api_endpoint}/allowed", params)
- if resp.code == '200'
- GitAccessStatus.create_from_json(resp.body)
- else
- GitAccessStatus.new(false,
- 'API is not accessible',
- gl_repository: nil,
- gl_id: nil,
- gl_username: nil,
- repository_path: nil,
- gitaly: nil,
- git_protocol: nil)
- end
+ determine_action(actor, resp)
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
+ def discover(actor)
+ resp = get("#{internal_api_endpoint}/discover?#{actor.identifier_key}=#{actor.id}")
+ JSON.parse(resp.body) if resp.code == HTTP_SUCCESS
+ rescue JSON::ParserError, ApiUnreachableError
+ 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
+ def lfs_authenticate(actor, repo)
+ params = { project: sanitize_path(repo) }
+ params[actor.identifier_key.to_sym] = actor.id
resp = post("#{internal_api_endpoint}/lfs_authenticate", params)
- if resp.code == '200'
- GitlabLfsAuthentication.build_from_json(resp.body)
- end
+ GitlabLfsAuthentication.build_from_json(resp.body) if resp.code == HTTP_SUCCESS
end
def broadcast_message
@@ -93,11 +61,7 @@ class GitlabNet # rubocop:disable Metrics/ClassLength
url += "&gl_repository=#{URI.escape(gl_repository)}" if gl_repository
resp = get(url)
- if resp.code == '200'
- JSON.parse(resp.body)
- else
- []
- end
+ resp.code == HTTP_SUCCESS ? JSON.parse(resp.body) : []
rescue
[]
end
@@ -106,19 +70,17 @@ class GitlabNet # rubocop:disable Metrics/ClassLength
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"
+ def authorized_key(full_key)
+ resp = get("#{internal_api_endpoint}/authorized_keys?key=#{URI.escape(full_key, '+/=')}")
+ JSON.parse(resp.body) if resp.code == HTTP_SUCCESS
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'
+ def two_factor_recovery_codes(actor)
+ params = { actor.identifier_key.to_sym => actor.id }
+ resp = post("#{internal_api_endpoint}/two_factor_recovery_codes", params)
+ JSON.parse(resp.body) if resp.code == HTTP_SUCCESS
rescue
{}
end
@@ -127,51 +89,50 @@ class GitlabNet # rubocop:disable Metrics/ClassLength
params = { gl_repository: gl_repository, project: repo_path }
resp = post("#{internal_api_endpoint}/notify_post_receive", params)
- resp.code == '200'
+ resp.code == HTTP_SUCCESS
rescue
false
end
- def post_receive(gl_repository, identifier, changes)
- params = {
- gl_repository: gl_repository,
- identifier: identifier,
- changes: changes
- }
+ def post_receive(gl_repository, actor, changes)
+ params = { gl_repository: gl_repository, identifier: actor.identifier, changes: changes }
resp = post("#{internal_api_endpoint}/post_receive", params)
+ raise NotFoundError if resp.code == HTTP_NOT_FOUND
- raise NotFound if resp.code == '404'
-
- JSON.parse(resp.body) if resp.code == '200'
+ JSON.parse(resp.body) if resp.code == HTTP_SUCCESS
end
def pre_receive(gl_repository)
resp = post("#{internal_api_endpoint}/pre_receive", gl_repository: gl_repository)
+ raise NotFoundError if resp.code == HTTP_NOT_FOUND
- 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
+ JSON.parse(resp.body) if resp.code == HTTP_SUCCESS
end
- protected
+ private
def sanitize_path(repo)
repo.delete("'")
end
+
+ def determine_action(actor, resp)
+ json = JSON.parse(resp.body)
+ message = json['message']
+
+ case resp.code
+ when HTTP_SUCCESS
+ # TODO: This raise can be removed once internal API can respond with correct
+ # HTTP status codes, instead of relying upon parsing the body and
+ # accessing the 'status' key.
+ raise AccessDeniedError, message unless json['status']
+
+ Action::Gitaly.create_from_json(actor, json)
+ when HTTP_UNAUTHORIZED, HTTP_NOT_FOUND
+ raise AccessDeniedError, message
+ else
+ raise UnknownError, "#{API_INACCESSIBLE_ERROR}: #{message}"
+ end
+ rescue JSON::ParserError
+ raise UnknownError, API_INACCESSIBLE_ERROR
+ end
end