Commit db6a6603 authored by Ash McKenzie's avatar Ash McKenzie

Merge branch 'issue_208974_2' into 'master'

Prevent issues of being promoted twice

See merge request gitlab-org/gitlab!27837
parents 9db74f5b 57e102b8
...@@ -5,15 +5,10 @@ module Epics ...@@ -5,15 +5,10 @@ module Epics
PromoteError = Class.new(StandardError) PromoteError = Class.new(StandardError)
def execute(issue) def execute(issue)
@group = issue.project.group @issue = issue
@parent_group = issue.project.group
unless @group validate_promotion!
raise PromoteError, 'Cannot promote issue because it does not belong to a group!'
end
unless current_user.can?(:admin_issue, issue) && current_user.can?(:create_epic, @group)
raise PromoteError, 'Cannot promote issue due to insufficient permissions!'
end
super super
...@@ -23,6 +18,18 @@ module Epics ...@@ -23,6 +18,18 @@ module Epics
private private
attr_reader :issue, :parent_group
def validate_promotion!
raise PromoteError, _('Cannot promote issue because it does not belong to a group.') if parent_group.nil?
raise PromoteError, _('Cannot promote issue due to insufficient permissions.') unless can_promote?
raise PromoteError, _('Issue already promoted to epic.') if issue.promoted?
end
def can_promote?
current_user.can?(:admin_issue, issue) && current_user.can?(:create_epic, parent_group)
end
def track_event def track_event
::Gitlab::Tracking.event( ::Gitlab::Tracking.event(
'epics', 'promote', property: 'issue_id', value: original_entity.id 'epics', 'promote', property: 'issue_id', value: original_entity.id
...@@ -30,7 +37,7 @@ module Epics ...@@ -30,7 +37,7 @@ module Epics
end end
def create_new_entity def create_new_entity
@new_entity = Epics::CreateService.new(@group, current_user, params).execute @new_entity = Epics::CreateService.new(parent_group, current_user, params).execute
end end
def update_old_entity def update_old_entity
......
---
title: Prevent issues from being promoted twice
merge_request: 27837
author:
type: fixed
...@@ -69,6 +69,7 @@ module EE ...@@ -69,6 +69,7 @@ module EE
types Issue types Issue
condition do condition do
quick_action_target.persisted? && quick_action_target.persisted? &&
!quick_action_target.promoted? &&
current_user.can?(:admin_issue, project) && current_user.can?(:admin_issue, project) &&
current_user.can?(:create_epic, project.group) current_user.can?(:create_epic, project.group)
end end
......
...@@ -393,6 +393,14 @@ describe Notes::QuickActionsService do ...@@ -393,6 +393,14 @@ describe Notes::QuickActionsService do
end end
end end
context 'when issue was already promoted' do
it 'does not promote issue' do
issue.update(promoted_to_epic_id: epic.id)
expect { execute(note) }.not_to change { Epic.count }
end
end
context 'when an issue belongs to a project without group' do context 'when an issue belongs to a project without group' do
let(:user_project) { create(:project) } let(:user_project) { create(:project) }
let(:issue) { create(:issue, project: user_project) } let(:issue) { create(:issue, project: user_project) }
......
...@@ -54,7 +54,7 @@ describe Epics::IssuePromoteService do ...@@ -54,7 +54,7 @@ describe Epics::IssuePromoteService do
end end
end end
context 'when issue is promoted' do context 'when promoting issue' do
let!(:issue_mentionable_note) { create(:note, noteable: issue, author: user, project: project, note: "note with mention #{user.to_reference}") } let!(:issue_mentionable_note) { create(:note, noteable: issue, author: user, project: project, note: "note with mention #{user.to_reference}") }
let!(:issue_note) { create(:note, noteable: issue, author: user, project: project, note: "note without mention") } let!(:issue_note) { create(:note, noteable: issue, author: user, project: project, note: "note without mention") }
...@@ -104,6 +104,16 @@ describe Epics::IssuePromoteService do ...@@ -104,6 +104,16 @@ describe Epics::IssuePromoteService do
end end
end end
context 'when issue was already promoted' do
it 'raises error' do
epic = create(:epic, group: group)
issue.update(promoted_to_epic_id: epic.id)
expect { subject.execute(issue) }
.to raise_error(Epics::IssuePromoteService::PromoteError, /already promoted/)
end
end
context 'when promoted issue has notes' do context 'when promoted issue has notes' do
let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) } let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
......
...@@ -3333,6 +3333,12 @@ msgstr "" ...@@ -3333,6 +3333,12 @@ msgstr ""
msgid "Cannot modify provider during creation" msgid "Cannot modify provider during creation"
msgstr "" msgstr ""
msgid "Cannot promote issue because it does not belong to a group."
msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
msgid "Cannot refer to a group milestone by an internal id!" msgid "Cannot refer to a group milestone by an internal id!"
msgstr "" msgstr ""
...@@ -11149,6 +11155,9 @@ msgstr "" ...@@ -11149,6 +11155,9 @@ msgstr ""
msgid "Issue Boards" msgid "Issue Boards"
msgstr "" msgstr ""
msgid "Issue already promoted to epic."
msgstr ""
msgid "Issue board focus mode" msgid "Issue board focus mode"
msgstr "" msgstr ""
......
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