diff options
author | Douwe Maan <douwe@gitlab.com> | 2017-04-07 18:43:28 +0300 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2017-04-07 18:43:28 +0300 |
commit | 46aadc5c16150446840a26ea7199380830369326 (patch) | |
tree | fd41b11d20b3c6589b01d4500ad234d3582b5379 /lib | |
parent | 2d246df57dd8e7da8c2743fba38d31992bc7a3fc (diff) | |
parent | 6f15e89a6b83dcfef897dda414325b85090e2c40 (diff) |
Merge branch '18471-restrict-tag-pushes-protected-tags' into 'master'
Protected Tags
Closes #18471
See merge request !10356
Diffstat (limited to 'lib')
-rw-r--r-- | lib/api/entities.rb | 10 | ||||
-rw-r--r-- | lib/gitlab/checks/change_access.rb | 39 | ||||
-rw-r--r-- | lib/gitlab/import_export/import_export.yml | 2 | ||||
-rw-r--r-- | lib/gitlab/import_export/project_tree_restorer.rb | 6 | ||||
-rw-r--r-- | lib/gitlab/import_export/relation_factory.rb | 1 | ||||
-rw-r--r-- | lib/gitlab/user_access.rb | 20 |
6 files changed, 57 insertions, 21 deletions
diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 00d44821e3f..45625e00f7d 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -184,19 +184,15 @@ module API end expose :protected do |repo_branch, options| - options[:project].protected_branch?(repo_branch.name) + ProtectedBranch.protected?(options[:project], repo_branch.name) end expose :developers_can_push do |repo_branch, options| - project = options[:project] - access_levels = project.protected_branches.matching(repo_branch.name).map(&:push_access_levels).flatten - access_levels.any? { |access_level| access_level.access_level == Gitlab::Access::DEVELOPER } + options[:project].protected_branches.developers_can?(:push, repo_branch.name) end expose :developers_can_merge do |repo_branch, options| - project = options[:project] - access_levels = project.protected_branches.matching(repo_branch.name).map(&:merge_access_levels).flatten - access_levels.any? { |access_level| access_level.access_level == Gitlab::Access::DEVELOPER } + options[:project].protected_branches.developers_can?(:merge, repo_branch.name) end end diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb index c85f79127bc..eb2f2e144fd 100644 --- a/lib/gitlab/checks/change_access.rb +++ b/lib/gitlab/checks/change_access.rb @@ -10,6 +10,7 @@ module Gitlab ) @oldrev, @newrev, @ref = change.values_at(:oldrev, :newrev, :ref) @branch_name = Gitlab::Git.branch_name(@ref) + @tag_name = Gitlab::Git.tag_name(@ref) @user_access = user_access @project = project @env = env @@ -32,11 +33,11 @@ module Gitlab def protected_branch_checks return if skip_authorization return unless @branch_name - return unless project.protected_branch?(@branch_name) + return unless ProtectedBranch.protected?(project, @branch_name) if forced_push? return "You are not allowed to force push code to a protected branch on this project." - elsif Gitlab::Git.blank_ref?(@newrev) + elsif deletion? return "You are not allowed to delete protected branches from this project." end @@ -58,13 +59,29 @@ module Gitlab def tag_checks return if skip_authorization - tag_ref = Gitlab::Git.tag_name(@ref) + return unless @tag_name - if tag_ref && protected_tag?(tag_ref) && user_access.cannot_do_action?(:admin_project) - "You are not allowed to change existing tags on this project." + if tag_exists? && user_access.cannot_do_action?(:admin_project) + return "You are not allowed to change existing tags on this project." + end + + protected_tag_checks + end + + def protected_tag_checks + return unless tag_protected? + return "Protected tags cannot be updated." if update? + return "Protected tags cannot be deleted." if deletion? + + unless user_access.can_create_tag?(@tag_name) + return "You are not allowed to create this tag as it is protected." end end + def tag_protected? + ProtectedTag.protected?(project, @tag_name) + end + def push_checks return if skip_authorization @@ -75,14 +92,22 @@ module Gitlab private - def protected_tag?(tag_name) - project.repository.tag_exists?(tag_name) + def tag_exists? + project.repository.tag_exists?(@tag_name) end def forced_push? Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev, env: @env) end + def update? + !Gitlab::Git.blank_ref?(@oldrev) && !deletion? + end + + def deletion? + Gitlab::Git.blank_ref?(@newrev) + end + def matching_merge_request? Checks::MatchingMergeRequest.new(@newrev, @branch_name, @project).match? end diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index f5e1e385ff9..899a6567768 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -47,6 +47,8 @@ project_tree: - protected_branches: - :merge_access_levels - :push_access_levels + - protected_tags: + - :create_access_levels - :project_feature # Only include the following attributes for the models specified. diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index df21ff22216..2e349b5f9a9 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -52,7 +52,11 @@ module Gitlab create_sub_relations(relation, @tree_hash) if relation.is_a?(Hash) relation_key = relation.is_a?(Hash) ? relation.keys.first : relation - relation_hash = create_relation(relation_key, @tree_hash[relation_key.to_s]) + relation_hash_list = @tree_hash[relation_key.to_s] + + next unless relation_hash_list + + relation_hash = create_relation(relation_key, relation_hash_list) saved << restored_project.append_or_update_attribute(relation_key, relation_hash) end saved.all? diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 2ba12f5f924..71811be6f50 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -10,6 +10,7 @@ module Gitlab hooks: 'ProjectHook', merge_access_levels: 'ProtectedBranch::MergeAccessLevel', push_access_levels: 'ProtectedBranch::PushAccessLevel', + create_access_levels: 'ProtectedTag::CreateAccessLevel', labels: :project_labels, priorities: :label_priorities, label: :project_label }.freeze diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb index f260c0c535f..54728e5ff0e 100644 --- a/lib/gitlab/user_access.rb +++ b/lib/gitlab/user_access.rb @@ -28,14 +28,23 @@ module Gitlab true end + def can_create_tag?(ref) + return false unless can_access_git? + + if ProtectedTag.protected?(project, ref) + project.protected_tags.protected_ref_accessible_to?(ref, user, action: :create) + else + user.can?(:push_code, project) + end + end + def can_push_to_branch?(ref) return false unless can_access_git? - if project.protected_branch?(ref) + if ProtectedBranch.protected?(project, ref) return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user) - access_levels = project.protected_branches.matching(ref).map(&:push_access_levels).flatten - has_access = access_levels.any? { |access_level| access_level.check_access(user) } + has_access = project.protected_branches.protected_ref_accessible_to?(ref, user, action: :push) has_access || !project.repository.branch_exists?(ref) && can_merge_to_branch?(ref) else @@ -46,9 +55,8 @@ module Gitlab def can_merge_to_branch?(ref) return false unless can_access_git? - if project.protected_branch?(ref) - access_levels = project.protected_branches.matching(ref).map(&:merge_access_levels).flatten - access_levels.any? { |access_level| access_level.check_access(user) } + if ProtectedBranch.protected?(project, ref) + project.protected_branches.protected_ref_accessible_to?(ref, user, action: :merge) else user.can?(:push_code, project) end |