Class: Gitlab::GitAccess

Inherits:
Object
  • Object
show all
Includes:
Utils::StrongMemoize
Defined in:
lib/gitlab/git_access.rb

Constant Summary collapse

ForbiddenError =
Class.new(StandardError)
NotFoundError =
Class.new(StandardError)
TimeoutError =
Class.new(StandardError)
ANY =

Use the magic string '_any' to indicate we do not know what the changes are. This is also what gitlab-shell does.

'_any'
ERROR_MESSAGES =
{
  upload: 'You are not allowed to upload code for this project.',
  download: 'You are not allowed to download code from this project.',
  auth_upload: 'You are not allowed to upload code.',
  auth_download: 'You are not allowed to download code.',
  deploy_key_upload: 'This deploy key does not have write access to this project.',
  no_repo: 'A repository for this project does not exist yet.',
  project_not_found: "The project you were looking for could not be found or you don't have permission to view it.",
  command_not_allowed: "The command you're trying to execute is not allowed.",
  upload_pack_disabled_over_http: 'Pulling over HTTP is not allowed.',
  receive_pack_disabled_over_http: 'Pushing over HTTP is not allowed.',
  read_only: 'The repository is temporarily read-only. Please try again later.',
  cannot_push_to_read_only: "You can't push code to a read-only GitLab instance.",
  push_code: 'You are not allowed to push code to this project.'
}.freeze
INTERNAL_TIMEOUT =
50.seconds.freeze
LOG_HEADER =
<<~MESSAGE
  Push operation timed out

  Timing information for debugging purposes:
MESSAGE
DOWNLOAD_COMMANDS =
%w{git-upload-pack git-upload-archive}.freeze
PUSH_COMMANDS =
%w{git-receive-pack}.freeze
ALL_COMMANDS =
DOWNLOAD_COMMANDS + PUSH_COMMANDS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils::StrongMemoize

#clear_memoization, #strong_memoize, #strong_memoized?

Constructor Details

#initialize(actor, container, protocol, authentication_abilities:, repository_path: nil, redirected_path: nil, auth_result_type: nil) ⇒ GitAccess

Returns a new instance of GitAccess.


59
60
61
62
63
64
65
66
67
# File 'lib/gitlab/git_access.rb', line 59

def initialize(actor, container, protocol, authentication_abilities:, repository_path: nil, redirected_path: nil, auth_result_type: nil)
  @actor     = actor
  @container = container
  @protocol  = protocol
  @authentication_abilities = Array(authentication_abilities)
  @repository_path = repository_path
  @redirected_path = redirected_path
  @auth_result_type = auth_result_type
end

Instance Attribute Details

#actorObject (readonly)

Returns the value of attribute actor.


44
45
46
# File 'lib/gitlab/git_access.rb', line 44

def actor
  @actor
end

#auth_result_typeObject (readonly)

Returns the value of attribute auth_result_type.


44
45
46
# File 'lib/gitlab/git_access.rb', line 44

def auth_result_type
  @auth_result_type
end

#authentication_abilitiesObject (readonly)

Returns the value of attribute authentication_abilities.


44
45
46
# File 'lib/gitlab/git_access.rb', line 44

def authentication_abilities
  @authentication_abilities
end

#changesObject (readonly)

Returns the value of attribute changes.


44
45
46
# File 'lib/gitlab/git_access.rb', line 44

def changes
  @changes
end

#cmdObject (readonly)

Returns the value of attribute cmd.


44
45
46
# File 'lib/gitlab/git_access.rb', line 44

def cmd
  @cmd
end

#containerObject

Returns the value of attribute container.


47
48
49
# File 'lib/gitlab/git_access.rb', line 47

def container
  @container
end

#protocolObject (readonly)

Returns the value of attribute protocol.


44
45
46
# File 'lib/gitlab/git_access.rb', line 44

def protocol
  @protocol
end

#redirected_pathObject (readonly)

Returns the value of attribute redirected_path.


44
45
46
# File 'lib/gitlab/git_access.rb', line 44

def redirected_path
  @redirected_path
end

#repository_pathObject (readonly)

Returns the value of attribute repository_path.


44
45
46
# File 'lib/gitlab/git_access.rb', line 44

def repository_path
  @repository_path
end

Class Method Details

.error_message(key) ⇒ Object

Raises:

  • (ArgumentError)

49
50
51
52
53
54
55
56
57
# File 'lib/gitlab/git_access.rb', line 49

def self.error_message(key)
  self.ancestors.each do |cls|
    return cls.const_get('ERROR_MESSAGES', false).fetch(key)
  rescue NameError, KeyError
    next
  end

  raise ArgumentError, "No error message defined for #{key}"
end

Instance Method Details

#build_can_download_code?Boolean

Returns:

  • (Boolean)

128
129
130
# File 'lib/gitlab/git_access.rb', line 128

def build_can_download_code?
  authentication_abilities.include?(:build_download_code) && user_access.can_do_action?(:build_download_code)
end

#check(cmd, changes) ⇒ Object


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
# File 'lib/gitlab/git_access.rb', line 69

def check(cmd, changes)
  @changes = changes
  @cmd = cmd

  check_protocol!
  check_valid_actor!
  check_active_user!
  check_authentication_abilities!
  check_command_disabled!
  check_command_existence!

  custom_action = check_custom_action
  return custom_action if custom_action

  check_db_accessibility!
  check_container!
  check_repository_existence!

  case cmd
  when *DOWNLOAD_COMMANDS
    check_download_access!
  when *PUSH_COMMANDS
    check_push_access!
  end
  check_additional_conditions!

  success_result
end

#deploy_key_can_download_code?Boolean

Returns:

  • (Boolean)

106
107
108
109
110
111
# File 'lib/gitlab/git_access.rb', line 106

def deploy_key_can_download_code?
  authentication_abilities.include?(:download_code) &&
    deploy_key? &&
    deploy_key.has_access_to?(container) &&
    (project? && project&.repository_access_level != ::Featurable::DISABLED)
end

#download_abilitySymbol

Returns the name of a Declarative Policy ability to check.

Returns:

  • (Symbol)

    the name of a Declarative Policy ability to check

Raises:

  • (NotImplementedError)

119
120
121
# File 'lib/gitlab/git_access.rb', line 119

def download_ability
  raise NotImplementedError
end

#guest_can_download_code?Boolean

Returns:

  • (Boolean)

102
103
104
# File 'lib/gitlab/git_access.rb', line 102

def guest_can_download_code?
  Guest.can?(download_ability, container)
end

#loggerObject


98
99
100
# File 'lib/gitlab/git_access.rb', line 98

def logger
  @logger ||= Checks::TimedLogger.new(timeout: INTERNAL_TIMEOUT, header: LOG_HEADER)
end

#protocol_allowed?Boolean

Returns:

  • (Boolean)

138
139
140
# File 'lib/gitlab/git_access.rb', line 138

def protocol_allowed?
  Gitlab::ProtocolAccess.allowed?(protocol)
end

#push_abilitySymbol

Returns the name of a Declarative Policy ability to check.

Returns:

  • (Symbol)

    the name of a Declarative Policy ability to check

Raises:

  • (NotImplementedError)

124
125
126
# File 'lib/gitlab/git_access.rb', line 124

def push_ability
  raise NotImplementedError
end

#request_from_ci_build?Boolean

Returns:

  • (Boolean)

132
133
134
135
136
# File 'lib/gitlab/git_access.rb', line 132

def request_from_ci_build?
  return false unless protocol == 'http'

  auth_result_type == :build || auth_result_type == :ci
end

#user_can_download_code?Boolean

Returns:

  • (Boolean)

113
114
115
116
# File 'lib/gitlab/git_access.rb', line 113

def user_can_download_code?
  authentication_abilities.include?(:download_code) &&
    user_access.can_do_action?(download_ability)
end