Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git_access_snippet.rb « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 5ae17dbbb91ad65a1de149ac066e412f7edb51f5 (plain)
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
# frozen_string_literal: true

module Gitlab
  class GitAccessSnippet < GitAccess
    extend ::Gitlab::Utils::Override

    ERROR_MESSAGES = {
      authentication_mechanism: 'The authentication mechanism is not supported.',
      read_snippet: 'You are not allowed to read this snippet.',
      update_snippet: 'You are not allowed to update this snippet.',
      snippet_not_found: 'The snippet you were looking for could not be found.',
      no_repo: 'The snippet repository you were looking for could not be found.'
    }.freeze

    alias_method :snippet, :container

    def initialize(actor, snippet, protocol, **kwargs)
      super(actor, snippet, protocol, **kwargs)

      @auth_result_type = nil
      @authentication_abilities &= [:download_code, :push_code]
    end

    override :project
    def project
      container.project if container.is_a?(ProjectSnippet)
    end

    override :check
    def check(cmd, changes)
      check_snippet_accessibility!

      super
    end

    override :download_ability
    def download_ability
      :read_snippet
    end

    override :push_ability
    def push_ability
      :update_snippet
    end

    private

    # TODO: Implement EE/Geo https://gitlab.com/gitlab-org/gitlab/issues/205629
    override :check_custom_action
    def check_custom_action
      # snippets never return custom actions, such as geo replication.
    end

    override :check_valid_actor!
    def check_valid_actor!
      # TODO: Investigate if expanding actor/authentication types are needed.
      # https://gitlab.com/gitlab-org/gitlab/issues/202190
      if actor && !allowed_actor?
        raise ForbiddenError, error_message(:authentication_mechanism)
      end

      super
    end

    def allowed_actor?
      actor.is_a?(User) || actor.instance_of?(Key)
    end

    override :check_push_access!
    def check_push_access!
      raise ForbiddenError, error_message(:update_snippet) unless user

      if snippet&.repository_read_only?
        raise ForbiddenError, error_message(:read_only)
      end

      check_change_access!
    end

    def check_snippet_accessibility!
      if snippet.blank?
        raise NotFoundError, error_message(:snippet_not_found)
      end
    end

    override :can_read_project?
    def can_read_project?
      return true if user&.migration_bot?

      super
    end

    override :check_download_access!
    def check_download_access!
      passed = guest_can_download_code? || user_can_download_code?

      unless passed
        raise ForbiddenError, error_message(:read_snippet)
      end
    end

    override :check_change_access!
    def check_change_access!
      unless user_can_push?
        raise ForbiddenError, error_message(:update_snippet)
      end

      check_size_before_push!
      check_access!
      check_push_size!
    end

    override :check_access!
    def check_access!
      changes_list.each do |change|
        # If user does not have access to make at least one change, cancel all
        # push by allowing the exception to bubble up
        Checks::SnippetCheck.new(change, default_branch: snippet.default_branch, root_ref: snippet.repository.root_ref, logger: logger).validate!
        Checks::PushFileCountCheck.new(change, repository: repository, limit: Snippet.max_file_limit, logger: logger).validate!
      end
    rescue Checks::TimedLogger::TimeoutError
      raise TimeoutError, logger.full_message
    end

    override :user_access
    def user_access
      @user_access ||= UserAccessSnippet.new(user, snippet: snippet)
    end

    override :check_size_limit?
    def check_size_limit?
      return false if user&.migration_bot?

      super
    end
  end
end

Gitlab::GitAccessSnippet.prepend_mod_with('Gitlab::GitAccessSnippet')