Commit 231497bb authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch 'issue_337189-block_move_and_clone_of_requirement_issues' into 'master'

Block move and clone of requirement issues

See merge request gitlab-org/gitlab!70439
parents a0e8e0c7 3c18b544
......@@ -12,7 +12,8 @@ module IssueAvailableFeatures
{
assignee: %w(issue incident),
confidentiality: %w(issue incident),
time_tracking: %w(issue incident)
time_tracking: %w(issue incident),
move_and_clone: %w(issue incident)
}.with_indifferent_access
end
end
......
......@@ -542,6 +542,10 @@ class Issue < ApplicationRecord
issue_type_supports?(:time_tracking)
end
def supports_move_and_clone?
issue_type_supports?(:move_and_clone)
end
def email_participants_emails
issue_email_participants.pluck(:email)
end
......
......@@ -8,13 +8,7 @@ module Issues
@target_project = target_project
@with_notes = with_notes
unless issue.can_clone?(current_user, target_project)
raise CloneError, s_('CloneIssue|Cannot clone issue due to insufficient permissions!')
end
if target_project.pending_delete?
raise CloneError, s_('CloneIssue|Cannot clone issue to target project as it is pending deletion.')
end
verify_can_clone_issue!(issue, target_project)
super(issue, target_project)
......@@ -30,6 +24,20 @@ module Issues
attr_reader :target_project
attr_reader :with_notes
def verify_can_clone_issue!(issue, target_project)
unless issue.supports_move_and_clone?
raise CloneError, s_('CloneIssue|Cannot clone issues of \'%{issue_type}\' type.') % { issue_type: issue.issue_type }
end
unless issue.can_clone?(current_user, target_project)
raise CloneError, s_('CloneIssue|Cannot clone issue due to insufficient permissions!')
end
if target_project.pending_delete?
raise CloneError, s_('CloneIssue|Cannot clone issue to target project as it is pending deletion.')
end
end
def update_new_entity
# we don't call `super` because we want to be able to decide whether or not to copy all comments over.
update_new_entity_description
......
......@@ -7,13 +7,7 @@ module Issues
def execute(issue, target_project)
@target_project = target_project
unless issue.can_move?(current_user, @target_project)
raise MoveError, s_('MoveIssue|Cannot move issue due to insufficient permissions!')
end
if @project == @target_project
raise MoveError, s_('MoveIssue|Cannot move issue to project it originates from!')
end
verify_can_move_issue!(issue, target_project)
super
......@@ -32,6 +26,20 @@ module Issues
attr_reader :target_project
def verify_can_move_issue!(issue, target_project)
unless issue.supports_move_and_clone?
raise MoveError, s_('MoveIssue|Cannot move issues of \'%{issue_type}\' type.') % { issue_type: issue.issue_type }
end
unless issue.can_move?(current_user, @target_project)
raise MoveError, s_('MoveIssue|Cannot move issue due to insufficient permissions!')
end
if @project == @target_project
raise MoveError, s_('MoveIssue|Cannot move issue to project it originates from!')
end
end
def update_service_desk_sent_notifications
return unless original_entity.from_service_desk?
......
......@@ -15,6 +15,7 @@ module EE
available_features[:epics] = %w(issue)
available_features[:sla] = %w(incident)
available_features[:confidentiality] += %w(test_case)
available_features[:move_and_clone] += %w(test_case)
end
end
end
......
......@@ -1048,6 +1048,26 @@ RSpec.describe Issue do
end
end
describe '#supports_move_and_clone?' do
let_it_be(:project) { create(:project) }
let_it_be_with_refind(:issue) { create(:incident, project: project) }
where(:issue_type, :supports_move_and_clone) do
:requirement | false
:test_case | true
end
with_them do
before do
issue.update!(issue_type: issue_type)
end
it do
expect(issue.supports_move_and_clone?).to eq(supports_move_and_clone)
end
end
end
describe '#related_feature_flags' do
let_it_be(:user) { create(:user) }
......
......@@ -48,6 +48,15 @@ RSpec.describe Issues::CloneService do
end
end
context 'when it is not allowed to clone issues of given type' do
it 'throws error' do
requirement_issue = create(:issue, issue_type: :requirement, project: old_project)
expect { clone_service.execute(requirement_issue, new_project) }
.to raise_error(StandardError, 'Cannot clone issues of \'requirement\' type.')
end
end
context 'epics' do
context 'issue assigned to epic' do
let_it_be(:epic) { create(:epic, group: group) }
......
......@@ -46,6 +46,15 @@ RSpec.describe Issues::MoveService do
move_service.execute(old_issue, new_project)
end
end
context 'when it is not allowed to move issues of given type' do
it 'throws error' do
requirement_issue = create(:issue, issue_type: :requirement, project: old_project)
expect { move_service.execute(requirement_issue, new_project) }
.to raise_error(StandardError, 'Cannot move issues of \'requirement\' type.')
end
end
end
context 'resource weight events' do
......
......@@ -7106,6 +7106,9 @@ msgstr ""
msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
msgstr ""
msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
msgstr ""
msgid "Cloned this issue to %{path_to_project}."
msgstr ""
......@@ -22168,6 +22171,9 @@ msgstr ""
msgid "MoveIssue|Cannot move issue to project it originates from!"
msgstr ""
msgid "MoveIssue|Cannot move issues of '%{issue_type}' type."
msgstr ""
msgid "Moved issue to %{label} column in the board."
msgstr ""
......
......@@ -1505,6 +1505,26 @@ RSpec.describe Issue do
end
end
describe '#supports_move_and_clone?' do
let_it_be(:project) { create(:project) }
let_it_be_with_refind(:issue) { create(:incident, project: project) }
where(:issue_type, :supports_move_and_clone) do
:issue | true
:incident | true
end
with_them do
before do
issue.update!(issue_type: issue_type)
end
it do
expect(issue.supports_move_and_clone?).to eq(supports_move_and_clone)
end
end
end
describe '#email_participants_emails' do
let_it_be(:issue) { create(:issue) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment