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

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

module Gitlab
  class UserAccess
    extend Gitlab::Cache::RequestCache

    request_cache_key do
      [user&.id, project&.id]
    end

    attr_reader :user
    attr_accessor :project

    def initialize(user, project: nil)
      @user = user
      @project = project
    end

    def can_do_action?(action)
      return false unless can_access_git?

      permission_cache[action] =
        permission_cache.fetch(action) do
          user.can?(action, project)
        end
    end

    def cannot_do_action?(action)
      !can_do_action?(action)
    end

    def allowed?
      return false unless can_access_git?

      if user.requires_ldap_check? && user.try_obtain_ldap_lease
        return false unless Gitlab::Auth::Ldap::Access.allowed?(user)
      end

      true
    end

    request_cache def can_create_tag?(ref)
      return false unless can_access_git?

      if protected?(ProtectedTag, project, ref)
        protected_tag_accessible_to?(ref, action: :create)
      else
        user.can?(:admin_tag, project)
      end
    end

    request_cache def can_delete_branch?(ref)
      return false unless can_access_git?

      if protected?(ProtectedBranch, project, ref)
        user.can?(:push_to_delete_protected_branch, project)
      else
        user.can?(:push_code, project)
      end
    end

    def can_update_branch?(ref)
      can_push_to_branch?(ref) || can_merge_to_branch?(ref)
    end

    request_cache def can_push_to_branch?(ref)
      return false unless can_access_git?
      return false unless project

      # Checking for an internal project to prevent an infinite loop:
      # https://gitlab.com/gitlab-org/gitlab/issues/36805
      if project.internal?
        return false unless user.can?(:push_code, project)
      else
        return false if !user.can?(:push_code, project) && !project.branch_allows_collaboration?(user, ref)
      end

      if protected?(ProtectedBranch, project, ref)
        protected_branch_accessible_to?(ref, action: :push)
      else
        true
      end
    end

    request_cache def can_merge_to_branch?(ref)
      return false unless can_access_git?

      if protected?(ProtectedBranch, project, ref)
        protected_branch_accessible_to?(ref, action: :merge)
      else
        user.can?(:push_code, project)
      end
    end

    def can_read_project?
      return false unless can_access_git?

      user.can?(:read_project, project)
    end

    private

    def permission_cache
      @permission_cache ||= {}
    end

    request_cache def can_access_git?
      user && user.can?(:access_git)
    end

    def protected_branch_accessible_to?(ref, action:)
      ProtectedBranch.protected_ref_accessible_to?(
        ref, user,
        project: project,
        action: action,
        protected_refs: project.protected_branches)
    end

    def protected_tag_accessible_to?(ref, action:)
      ProtectedTag.protected_ref_accessible_to?(
        ref, user,
        project: project,
        action: action,
        protected_refs: project.protected_tags)
    end

    request_cache def protected?(kind, project, refs)
      kind.protected?(project, refs)
    end
  end
end