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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/user_access.rb')
-rw-r--r--lib/gitlab/user_access.rb77
1 files changed, 48 insertions, 29 deletions
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 1551548d9b4..1c6ddc2e70f 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -5,15 +5,16 @@ module Gitlab
extend Gitlab::Cache::RequestCache
request_cache_key do
- [user&.id, project&.id]
+ [user&.id, container&.to_global_id]
end
- attr_reader :user
- attr_accessor :project
+ attr_reader :user, :push_ability
+ attr_accessor :container
- def initialize(user, project: nil)
+ def initialize(user, container: nil, push_ability: :push_code)
@user = user
- @project = project
+ @container = container
+ @push_ability = push_ability
end
def can_do_action?(action)
@@ -21,7 +22,7 @@ module Gitlab
permission_cache[action] =
permission_cache.fetch(action) do
- user.can?(action, project)
+ user.can?(action, container)
end
end
@@ -42,20 +43,20 @@ module Gitlab
request_cache def can_create_tag?(ref)
return false unless can_access_git?
- if protected?(ProtectedTag, project, ref)
+ if protected?(ProtectedTag, ref)
protected_tag_accessible_to?(ref, action: :create)
else
- user.can?(:admin_tag, project)
+ user.can?(:admin_tag, container)
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)
+ if protected?(ProtectedBranch, ref)
+ user.can?(:push_to_delete_protected_branch, container)
else
- user.can?(:push_code, project)
+ can_push?
end
end
@@ -64,36 +65,36 @@ module Gitlab
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
+ return false unless can_access_git? && container && can_collaborate?(ref)
+ return true unless protected?(ProtectedBranch, ref)
- if protected?(ProtectedBranch, project, ref)
- protected_branch_accessible_to?(ref, action: :push)
- else
- true
- end
+ protected_branch_accessible_to?(ref, action: :push)
end
request_cache def can_merge_to_branch?(ref)
return false unless can_access_git?
- if protected?(ProtectedBranch, project, ref)
+ if protected?(ProtectedBranch, ref)
protected_branch_accessible_to?(ref, action: :merge)
else
- user.can?(:push_code, project)
+ can_push?
end
end
private
+ def can_push?
+ user.can?(push_ability, container)
+ end
+
+ def can_collaborate?(ref)
+ assert_project!
+
+ # Checking for an internal project or group to prevent an infinite loop:
+ # https://gitlab.com/gitlab-org/gitlab/issues/36805
+ can_push? || (!project.internal? && project.branch_allows_collaboration?(user, ref))
+ end
+
def permission_cache
@permission_cache ||= {}
end
@@ -103,6 +104,8 @@ module Gitlab
end
def protected_branch_accessible_to?(ref, action:)
+ assert_project!
+
ProtectedBranch.protected_ref_accessible_to?(
ref, user,
project: project,
@@ -111,6 +114,8 @@ module Gitlab
end
def protected_tag_accessible_to?(ref, action:)
+ assert_project!
+
ProtectedTag.protected_ref_accessible_to?(
ref, user,
project: project,
@@ -118,8 +123,22 @@ module Gitlab
protected_refs: project.protected_tags)
end
- request_cache def protected?(kind, project, refs)
+ request_cache def protected?(kind, refs)
+ assert_project!
+
kind.protected?(project, refs)
end
+
+ def project
+ container
+ end
+
+ # Any method that assumes that it is operating on a project should make this
+ # explicit by calling `#assert_project!`.
+ # TODO: remove when we make this class polymorphic enough not to care about projects
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/227635
+ def assert_project!
+ raise "No project! #{project.inspect} is not a Project" unless project.is_a?(::Project)
+ end
end
end