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: 3956fc8a483a05d5d42a3c3b3664c48e9bb94d98 (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
# 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.',
      project_not_found: 'The project you were looking for could not be found.',
      snippet_not_found: 'The snippet you were looking for could not be found.',
      repository_not_found: 'The snippet repository you were looking for could not be found.'
    }.freeze

    attr_reader :snippet

    def initialize(actor, snippet, protocol, **kwargs)
      @snippet = snippet

      super(actor, snippet&.project, protocol, **kwargs)

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

    def check(cmd, changes)
      # TODO: Investigate if expanding actor/authentication types are needed.
      # https://gitlab.com/gitlab-org/gitlab/issues/202190
      if actor && !actor.is_a?(User) && !actor.instance_of?(Key)
        raise ForbiddenError, ERROR_MESSAGES[:authentication_mechanism]
      end

      unless Feature.enabled?(:version_snippets, user)
        raise NotFoundError, ERROR_MESSAGES[:project_not_found]
      end

      check_snippet_accessibility!

      super
    end

    private

    override :check_project!
    def check_project!(cmd, changes)
      if snippet.is_a?(ProjectSnippet)
        check_namespace!
        check_project_accessibility!
        # TODO add add_project_moved_message! to handle non-project repo https://gitlab.com/gitlab-org/gitlab/issues/205646
      end
    end

    override :check_push_access!
    def check_push_access!
      raise ForbiddenError, ERROR_MESSAGES[:update_snippet] unless user

      check_change_access!
    end

    override :repository
    def repository
      snippet&.repository
    end

    def check_snippet_accessibility!
      if snippet.blank?
        raise NotFoundError, ERROR_MESSAGES[:snippet_not_found]
      end
    end

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

      unless passed
        raise ForbiddenError, ERROR_MESSAGES[:read_snippet]
      end
    end

    override :guest_can_download_code?
    def guest_can_download_code?
      Guest.can?(:read_snippet, snippet)
    end

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

    override :check_change_access!
    def check_change_access!
      unless user_access.can_do_action?(:update_snippet)
        raise ForbiddenError, ERROR_MESSAGES[:update_snippet]
      end

      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
        check_single_change_access(change)
      end
    end

    def check_single_change_access(change)
      change_access = Checks::SnippetCheck.new(change, logger: logger)

      change_access.exec
    rescue Checks::TimedLogger::TimeoutError
      raise TimeoutError, logger.full_message
    end

    override :check_repository_existence!
    def check_repository_existence!
      unless repository.exists?
        raise NotFoundError, ERROR_MESSAGES[:repository_not_found]
      end
    end

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

    # TODO: Implement EE/Geo https://gitlab.com/gitlab-org/gitlab/issues/205629
    override :check_custom_action
    def check_custom_action(cmd)
      nil
    end
  end
end