summaryrefslogtreecommitdiff
path: root/lib/gitlab_shell.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab_shell.rb')
-rw-r--r--lib/gitlab_shell.rb54
1 files changed, 37 insertions, 17 deletions
diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb
index 9644cf4..74af62a 100644
--- a/lib/gitlab_shell.rb
+++ b/lib/gitlab_shell.rb
@@ -17,6 +17,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
}.freeze
API_COMMANDS = %w(2fa_recovery_codes).freeze
GL_PROTOCOL = 'ssh'.freeze
+ HTTP_SUCCESS_CODES = %w{200 201}.freeze
attr_accessor :key_id, :gl_repository, :repo_name, :command, :git_access
attr_reader :repo_path
@@ -38,29 +39,29 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
args = Shellwords.shellwords(origin_cmd)
args = parse_cmd(args)
+ access_result = nil
if GIT_COMMANDS.include?(args.first)
- GitlabMetrics.measure('verify-access') { verify_access }
+ GitlabMetrics.measure('verify-access') { access_result = verify_access }
end
- process_cmd(args)
-
- true
+ process_cmd(access_result, args)
rescue GitlabNet::ApiUnreachableError
$stderr.puts "GitLab: Failed to authorize your Git request: internal API unreachable"
false
rescue AccessDeniedError => ex
$logger.warn('Access denied', command: origin_cmd, user: log_username)
-
$stderr.puts "GitLab: #{ex.message}"
false
rescue DisallowedCommandError
$logger.warn('Denied disallowed command', command: origin_cmd, user: log_username)
-
$stderr.puts "GitLab: Disallowed command"
false
rescue InvalidRepositoryPathError
$stderr.puts "GitLab: Invalid repository path"
false
+ rescue CustomActionStatus::UnsuccessfulError
+ $stderr.puts "GitLab: A custom action error has occurred"
+ false
end
protected
@@ -101,17 +102,13 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
end
def verify_access
- status = api.check_access(@git_access, nil, @repo_name, @key_id, '_any', GL_PROTOCOL)
+ result = api.check_access(@git_access, nil, @repo_name, @key_id, '_any', GL_PROTOCOL)
+ raise AccessDeniedError, result.message unless result.allowed?
- raise AccessDeniedError, status.message unless status.allowed?
-
- self.repo_path = status.repository_path
- @gl_repository = status.gl_repository
- @gitaly = status.gitaly
- @username = status.gl_username
+ result
end
- def process_cmd(args)
+ def process_cmd(access_result, args)
return send("api_#{@command}") if API_COMMANDS.include?(@command)
if @command == 'git-lfs-authenticate'
@@ -119,9 +116,23 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
$logger.info('Processing LFS authentication', user: log_username)
lfs_authenticate
end
- return
+ return true
end
+ case access_result
+ when GitAccessStatus
+ exec_cmd_for_gitaly(access_result, args)
+ when CustomActionStatus
+ exec_custom_action(access_result)
+ end
+ end
+
+ def exec_cmd_for_gitaly(access_result, args)
+ self.repo_path = access_result.repository_path
+ @gl_repository = access_result.gl_repository
+ @gitaly = access_result.gitaly
+ @username = access_result.gl_username
+
executable = @command
args = [repo_path]
@@ -147,6 +158,16 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
exec_cmd(executable, *args)
end
+ def exec_custom_action(access_result)
+ resp = access_result.execute(@key_id)
+
+ unless resp || HTTP_SUCCESS_CODES.include?(resp.code)
+ raise CustomActionStatus::UnsuccessfulError, resp.body
+ end
+
+ true
+ end
+
# This method is not covered by Rspec because it ends the current Ruby process.
def exec_cmd(*args)
# If you want to call a command without arguments, use
@@ -183,7 +204,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
end
def api
- GitlabNet.new
+ GitlabNet.new # TODO: Can this be memoised?
end
def user
@@ -213,7 +234,6 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
def lfs_authenticate
lfs_access = api.lfs_authenticate(@key_id, @repo_name)
-
return unless lfs_access
puts lfs_access.authentication_payload