Add documentation and tests
This commit adds - feature specs - to test the ability of a user with "developer" permission to delete tags in repositories. - documentation
This commit is contained in:
parent
69e1bd389f
commit
53b17f0301
|
@ -8,8 +8,7 @@ class Projects::TagsController < Projects::ApplicationController
|
|||
# Authorize
|
||||
before_action :require_non_empty_project
|
||||
before_action :authorize_download_code!
|
||||
before_action :authorize_push_code!, only: [:new, :create]
|
||||
before_action :authorize_admin_project!, only: [:destroy]
|
||||
before_action :authorize_admin_tag!, only: [:new, :create, :destroy]
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def index
|
||||
|
|
|
@ -297,6 +297,7 @@ class ProjectPolicy < BasePolicy
|
|||
end
|
||||
|
||||
rule { (mirror_available & can?(:admin_project)) | admin }.enable :admin_remote_mirror
|
||||
rule { can?(:push_code) }.enable :admin_tag
|
||||
|
||||
rule { archived }.policy do
|
||||
prevent :push_code
|
||||
|
|
|
@ -26,10 +26,8 @@
|
|||
.row-fixed-content.controls.flex-row
|
||||
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
|
||||
|
||||
- if can?(current_user, :push_code, @project)
|
||||
- if can?(current_user, :admin_tag, @project)
|
||||
= link_to edit_project_tag_release_path(@project, tag.name), class: 'btn btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
|
||||
= icon("pencil")
|
||||
|
||||
- if can?(current_user, :admin_project, @project)
|
||||
= link_to project_tag_path(@project, tag.name), class: "btn btn-remove remove-row has-tooltip prepend-left-10 #{protected_tag?(@project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: tag.name }, container: 'body' }, remote: true do
|
||||
= icon("trash-o")
|
||||
= link_to project_tag_path(@project, tag.name), class: "btn btn-remove remove-row has-tooltip prepend-left-10 #{protected_tag?(@project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: tag.name }, container: 'body' }, remote: true do
|
||||
= icon("trash-o")
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
- tags_sort_options_hash.each do |value, title|
|
||||
%li
|
||||
= link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value)
|
||||
- if can?(current_user, :push_code, @project)
|
||||
- if can?(current_user, :admin_tag, @project)
|
||||
= link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn' do
|
||||
= s_('TagsPage|New tag')
|
||||
= link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn d-none d-sm-inline-block has-tooltip' do
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
= s_("TagsPage|Can't find HEAD commit for this tag")
|
||||
|
||||
.nav-controls
|
||||
- if can?(current_user, :push_code, @project)
|
||||
- if can?(current_user, :admin_tag, @project)
|
||||
= link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
|
||||
= icon("pencil")
|
||||
= link_to project_tree_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse files') do
|
||||
|
@ -28,7 +28,7 @@
|
|||
= icon('history')
|
||||
.btn-container.controls-item
|
||||
= render 'projects/buttons/download', project: @project, ref: @tag.name
|
||||
- if can?(current_user, :push_code, @project) && can?(current_user, :admin_project, @project)
|
||||
- if can?(current_user, :admin_tag, @project)
|
||||
.btn-container.controls-item-full
|
||||
= link_to project_tag_path(@project, @tag.name), class: "btn btn-remove remove-row has-tooltip #{protected_tag?(@project, @tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: @tag.name } } do
|
||||
%i.fa.fa-trash-o
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Allow developers to delete tags
|
||||
merge_request: 29668
|
||||
author:
|
||||
type: changed
|
|
@ -95,6 +95,7 @@ The following table depicts the various user permission levels in a project.
|
|||
| Dismiss vulnerability **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
|
||||
| Apply code change suggestions | | | ✓ | ✓ | ✓ |
|
||||
| Create and edit wiki pages | | | ✓ | ✓ | ✓ |
|
||||
| Rewrite/remove Git tags | | | ✓ | ✓ | ✓ |
|
||||
| Use environment terminals | | | | ✓ | ✓ |
|
||||
| Run Web IDE's Interactive Web Terminals **[ULTIMATE ONLY]** | | | | ✓ | ✓ |
|
||||
| Add new team members | | | | ✓ | ✓ |
|
||||
|
@ -102,7 +103,6 @@ The following table depicts the various user permission levels in a project.
|
|||
| Push to protected branches | | | | ✓ | ✓ |
|
||||
| Turn on/off protected branch push for devs | | | | ✓ | ✓ |
|
||||
| Enable/disable tag protections | | | | ✓ | ✓ |
|
||||
| Rewrite/remove Git tags | | | | ✓ | ✓ |
|
||||
| Edit project | | | | ✓ | ✓ |
|
||||
| Add deploy keys to project | | | | ✓ | ✓ |
|
||||
| Configure project hooks | | | | ✓ | ✓ |
|
||||
|
|
|
@ -235,6 +235,10 @@ module API
|
|||
authorize! :push_code, user_project
|
||||
end
|
||||
|
||||
def authorize_admin_tag
|
||||
authorize! :admin_tag, user_project
|
||||
end
|
||||
|
||||
def authorize_admin_project
|
||||
authorize! :admin_project, user_project
|
||||
end
|
||||
|
|
|
@ -55,7 +55,7 @@ module API
|
|||
optional :release_description, type: String, desc: 'Specifying release notes stored in the GitLab database (deprecated in GitLab 11.7)'
|
||||
end
|
||||
post ':id/repository/tags' do
|
||||
authorize_push_project
|
||||
authorize_admin_tag
|
||||
|
||||
result = ::Tags::CreateService.new(user_project, current_user)
|
||||
.execute(params[:tag_name], params[:ref], params[:message])
|
||||
|
@ -87,7 +87,7 @@ module API
|
|||
requires :tag_name, type: String, desc: 'The name of the tag'
|
||||
end
|
||||
delete ':id/repository/tags/:tag_name', requirements: TAG_ENDPOINT_REQUIREMENTS do
|
||||
authorize_push_project
|
||||
authorize_admin_tag
|
||||
|
||||
tag = user_project.repository.find_tag(params[:tag_name])
|
||||
not_found!('Tag') unless tag
|
||||
|
|
|
@ -19,7 +19,7 @@ module Gitlab
|
|||
return unless tag_name
|
||||
|
||||
logger.log_timed(LOG_MESSAGES[:tag_checks]) do
|
||||
if tag_exists? && user_access.cannot_do_action?(:admin_project)
|
||||
if tag_exists? && user_access.cannot_do_action?(:admin_tag)
|
||||
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:change_existing_tags]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,7 +45,7 @@ module Gitlab
|
|||
if protected?(ProtectedTag, project, ref)
|
||||
protected_tag_accessible_to?(ref, action: :create)
|
||||
else
|
||||
user.can?(:push_code, project)
|
||||
user.can?(:admin_tag, project)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Maintainer creates tag' do
|
||||
describe 'Developer creates tag' do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository, namespace: user.namespace) }
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:project, :repository, namespace: group) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
project.add_developer(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Maintainer deletes tag' do
|
||||
describe 'Developer deletes tag' do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository, namespace: user.namespace) }
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:project, :repository, namespace: group) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
project.add_developer(user)
|
||||
sign_in(user)
|
||||
visit project_tags_path(project)
|
||||
end
|
|
@ -1,11 +1,12 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Maintainer updates tag' do
|
||||
describe 'Developer updates tag' do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository, namespace: user.namespace) }
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:project, :repository, namespace: group) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
project.add_developer(user)
|
||||
sign_in(user)
|
||||
visit project_tags_path(project)
|
||||
end
|
|
@ -1,7 +1,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Maintainer views tags' do
|
||||
describe 'Developer views tags' do
|
||||
let(:user) { create(:user) }
|
||||
let(:group) { create(:group) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
|
@ -9,7 +10,7 @@ describe 'Maintainer views tags' do
|
|||
end
|
||||
|
||||
context 'when project has no tags' do
|
||||
let(:project) { create(:project_empty_repo) }
|
||||
let(:project) { create(:project_empty_repo, namespace: group) }
|
||||
|
||||
before do
|
||||
visit project_path(project)
|
||||
|
@ -25,7 +26,7 @@ describe 'Maintainer views tags' do
|
|||
end
|
||||
|
||||
context 'when project has tags' do
|
||||
let(:project) { create(:project, :repository, namespace: user.namespace) }
|
||||
let(:project) { create(:project, :repository, namespace: group) }
|
||||
let(:repository) { project.repository }
|
||||
|
||||
before do
|
|
@ -8,9 +8,8 @@ describe Gitlab::Checks::TagCheck do
|
|||
describe '#validate!' do
|
||||
let(:ref) { 'refs/tags/v1.0.0' }
|
||||
|
||||
it 'raises an error' do
|
||||
allow(user_access).to receive(:can_do_action?).with(:push_code).and_return(true)
|
||||
expect(user_access).to receive(:can_do_action?).with(:admin_project).and_return(false)
|
||||
it 'raises an error when user does not have access' do
|
||||
allow(user_access).to receive(:can_do_action?).with(:admin_tag).and_return(false)
|
||||
|
||||
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to change existing tags on this project.')
|
||||
end
|
||||
|
|
|
@ -831,7 +831,7 @@ describe Gitlab::GitAccess do
|
|||
push_master: true,
|
||||
push_protected_branch: false,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: false,
|
||||
push_tag: true,
|
||||
push_new_tag: true,
|
||||
push_all: false,
|
||||
merge_into_protected_branch: false
|
||||
|
|
|
@ -36,7 +36,7 @@ describe ProjectPolicy do
|
|||
|
||||
let(:developer_permissions) do
|
||||
%i[
|
||||
admin_milestone admin_merge_request update_merge_request create_commit_status
|
||||
admin_tag admin_milestone admin_merge_request update_merge_request create_commit_status
|
||||
update_commit_status create_build update_build create_pipeline
|
||||
update_pipeline create_merge_request_from create_wiki push_code
|
||||
resolve_note create_container_image update_container_image destroy_container_image
|
||||
|
|
|
@ -10,7 +10,7 @@ describe API::Tags do
|
|||
let(:current_user) { nil }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
project.add_developer(user)
|
||||
end
|
||||
|
||||
describe 'GET /projects/:id/repository/tags' do
|
||||
|
|
|
@ -17,6 +17,7 @@ RSpec.shared_examples 'archived project policies' do
|
|||
upload_file
|
||||
resolve_note
|
||||
award_emoji
|
||||
admin_tag
|
||||
]
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue