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)
ProjectMovedError =
Class.new(NotFoundError)
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.',
  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

Instance Method Summary collapse

Methods included from Utils::StrongMemoize

#clear_memoization, #strong_memoize, #strong_memoized?

Constructor Details

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

Returns a new instance of GitAccess.


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

def initialize(actor, container, protocol, authentication_abilities:, namespace_path: nil, repository_path: nil, redirected_path: nil, auth_result_type: nil)
  @actor     = actor
  @container = container
  @protocol  = protocol
  @authentication_abilities = Array(authentication_abilities)
  @namespace_path = namespace_path
  @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


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

def actor
  @actor
end

#auth_result_typeObject (readonly)

Returns the value of attribute auth_result_type


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

def auth_result_type
  @auth_result_type
end

#authentication_abilitiesObject (readonly)

Returns the value of attribute authentication_abilities


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

def authentication_abilities
  @authentication_abilities
end

#changesObject (readonly)

Returns the value of attribute changes


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

def changes
  @changes
end

#cmdObject (readonly)

Returns the value of attribute cmd


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

def cmd
  @cmd
end

#containerObject

Returns the value of attribute container


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

def container
  @container
end

#namespace_pathObject (readonly)

Returns the value of attribute namespace_path


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

def namespace_path
  @namespace_path
end

#protocolObject (readonly)

Returns the value of attribute protocol


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

def protocol
  @protocol
end

#redirected_pathObject (readonly)

Returns the value of attribute redirected_path


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

def redirected_path
  @redirected_path
end

Instance Method Details

#build_can_download_code?Boolean

Returns:

  • (Boolean)

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

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

#check(cmd, changes) ⇒ Object


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

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

  success_result
end

#deploy_key_can_download_code?Boolean

Returns:

  • (Boolean)

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

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)

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

def download_ability
  raise NotImplementedError
end

#guest_can_download_code?Boolean

Returns:

  • (Boolean)

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

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

#loggerObject


93
94
95
# File 'lib/gitlab/git_access.rb', line 93

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

#protocol_allowed?Boolean

Returns:

  • (Boolean)

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

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)

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

def push_ability
  raise NotImplementedError
end

#repository_pathObject


61
62
63
# File 'lib/gitlab/git_access.rb', line 61

def repository_path
  @repository_path ||= project&.path
end

#request_from_ci_build?Boolean

Returns:

  • (Boolean)

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

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)

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

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