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
|