Commit 41a9166d authored by Clement Ho's avatar Clement Ho

Merge branch...

Merge branch '9215-promote-issue-to-epic-may-expose-confidential-information-warning-needs-explanation' into 'master'

Promote issue to epic "may expose confidential information" warning needs explanation

Closes #9215

See merge request gitlab-org/gitlab!21158
parents 2c57281a 4383b799
...@@ -107,8 +107,13 @@ class GfmAutoComplete { ...@@ -107,8 +107,13 @@ class GfmAutoComplete {
if (value.params.length > 0) { if (value.params.length > 0) {
tpl += ' <small class="params"><%- params.join(" ") %></small>'; tpl += ' <small class="params"><%- params.join(" ") %></small>';
} }
if (value.description !== '') { if (value.warning && value.icon && value.icon === 'confidential') {
tpl += '<small class="description"><i><%- description %> <%- warningText %></i></small>'; tpl +=
'<small class="description"><em><i class="fa fa-eye-slash" aria-hidden="true"/><%- warning %></em></small>';
} else if (value.warning) {
tpl += '<small class="description"><em><%- warning %></em></small>';
} else if (value.description !== '') {
tpl += '<small class="description"><em><%- description %></em></small>';
} }
tpl += '</li>'; tpl += '</li>';
...@@ -119,7 +124,6 @@ class GfmAutoComplete { ...@@ -119,7 +124,6 @@ class GfmAutoComplete {
return _.template(tpl)({ return _.template(tpl)({
...value, ...value,
className: cssClasses.join(' '), className: cssClasses.join(' '),
warningText: value.warning ? `(${value.warning})` : '',
}); });
}, },
insertTpl(value) { insertTpl(value) {
...@@ -150,6 +154,7 @@ class GfmAutoComplete { ...@@ -150,6 +154,7 @@ class GfmAutoComplete {
params: c.params, params: c.params,
description: c.description, description: c.description,
warning: c.warning, warning: c.warning,
icon: c.icon,
search, search,
}; };
}); });
......
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
} }
.has-warning { .has-warning {
.name,
.description { .description {
color: $orange-700; color: $orange-700;
background-color: $orange-100;
} }
} }
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
&.has-warning { &.has-warning {
color: $orange-700; color: $orange-700;
background-color: $orange-100;
} }
} }
......
---
title: Improve warning for Promote issue to epic
merge_request: 21158
author:
type: changed
...@@ -218,7 +218,9 @@ link in the issue sidebar. ...@@ -218,7 +218,9 @@ link in the issue sidebar.
If you have [permissions](../../permissions.md) to close an issue and create an If you have [permissions](../../permissions.md) to close an issue and create an
epic in the parent group, you can promote an issue to an epic with the `/promote` epic in the parent group, you can promote an issue to an epic with the `/promote`
[quick action](../../project/quick_actions.md#quick-actions-for-issues-merge-requests-and-epics). [quick action](../../project/quick_actions.md#quick-actions-for-issues-merge-requests-and-epics).
Only issues from projects that are in groups can be promoted. Only issues from projects that are in groups can be promoted. When attempting to promote a confidential
issue, a warning will display. Promoting a confidential issue to an epic will make all information
related to the issue public as epics are public to group members.
When the quick action is executed: When the quick action is executed:
......
...@@ -49,9 +49,23 @@ module EE ...@@ -49,9 +49,23 @@ module EE
@updates[:epic] = nil @updates[:epic] = nil
end end
desc _('Promote issue to an epic') promote_message = _('Promote issue to an epic')
explanation _('Promote issue to an epic.') promote_message_confidential = _('Promote confidential issue to a non-confidential epic')
warning _('may expose confidential information')
desc do
if quick_action_target.confidential?
promote_message_confidential
else
promote_message
end
end
explanation promote_message
warning do
if quick_action_target.confidential?
promote_message_confidential
end
end
icon 'confidential'
types Issue types Issue
condition do condition do
quick_action_target.persisted? && quick_action_target.persisted? &&
...@@ -60,7 +74,12 @@ module EE ...@@ -60,7 +74,12 @@ module EE
end end
command :promote do command :promote do
Epics::IssuePromoteService.new(quick_action_target.project, current_user).execute(quick_action_target) Epics::IssuePromoteService.new(quick_action_target.project, current_user).execute(quick_action_target)
@execution_message[:promote] = _('Promoted issue to an epic.')
@execution_message[:promote] = if quick_action_target.confidential?
_('Promoted confidential issue to a non-confidential epic. Information in this issue is no longer confidential as epics are public to group members.')
else
_('Promoted issue to an epic.')
end
end end
def extract_epic(params) def extract_epic(params)
......
...@@ -63,7 +63,7 @@ describe Groups::AutocompleteSourcesController do ...@@ -63,7 +63,7 @@ describe Groups::AutocompleteSourcesController do
expect(json_response).to include( expect(json_response).to include(
{ {
'name' => 'close', 'aliases' => [], 'description' => 'Close this epic', 'name' => 'close', 'aliases' => [], 'description' => 'Close this epic',
'params' => [], 'warning' => '' 'params' => [], 'warning' => '', 'icon' => ''
} }
) )
end end
......
...@@ -49,6 +49,15 @@ describe 'Issue promotion', :js do ...@@ -49,6 +49,15 @@ describe 'Issue promotion', :js do
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
end end
it 'displays warning' do
note = find('#note-body')
type(note, '/promote')
wait_for_requests
expect(page).to have_content 'Promote issue to an epic'
end
it 'promotes the issue' do it 'promotes the issue' do
add_note('/promote') add_note('/promote')
...@@ -63,5 +72,48 @@ describe 'Issue promotion', :js do ...@@ -63,5 +72,48 @@ describe 'Issue promotion', :js do
expect(epic.author).to eq(user) expect(epic.author).to eq(user)
end end
end end
context 'when issue is confidential' do
let(:confidential_issue) { create(:issue, :confidential, project: project) }
before do
group.add_developer(user)
visit project_issue_path(project, confidential_issue)
end
it 'displays warning' do
note = find('#note-body')
type(note, '/promote')
wait_for_requests
expect(page).to have_content 'Promote confidential issue to a non-confidential epic'
end
it 'promotes the issue' do
add_note('/promote')
wait_for_requests
epic = Epic.last
expect(page).to have_content 'Promoted confidential issue to a non-confidential epic. Information in this issue is no longer confidential as epics are public to group members.'
expect(confidential_issue.reload).to be_closed
expect(epic.title).to eq(confidential_issue.title)
expect(epic.description).to eq(confidential_issue.description)
expect(epic.author).to eq(user)
end
end
end
private
# `note` is a textarea where the given text should be typed.
# We don't want to find it each time this function gets called.
def type(note, text)
page.within('.timeline-content-form') do
note.set('')
note.native.send_keys(text)
end
end end
end end
...@@ -4,7 +4,7 @@ module Gitlab ...@@ -4,7 +4,7 @@ module Gitlab
module QuickActions module QuickActions
class CommandDefinition class CommandDefinition
attr_accessor :name, :aliases, :description, :explanation, :execution_message, attr_accessor :name, :aliases, :description, :explanation, :execution_message,
:params, :condition_block, :parse_params_block, :action_block, :warning, :types :params, :condition_block, :parse_params_block, :action_block, :warning, :icon, :types
def initialize(name, attributes = {}) def initialize(name, attributes = {})
@name = name @name = name
...@@ -12,6 +12,7 @@ module Gitlab ...@@ -12,6 +12,7 @@ module Gitlab
@aliases = attributes[:aliases] || [] @aliases = attributes[:aliases] || []
@description = attributes[:description] || '' @description = attributes[:description] || ''
@warning = attributes[:warning] || '' @warning = attributes[:warning] || ''
@icon = attributes[:icon] || ''
@explanation = attributes[:explanation] || '' @explanation = attributes[:explanation] || ''
@execution_message = attributes[:execution_message] || '' @execution_message = attributes[:execution_message] || ''
@params = attributes[:params] || [] @params = attributes[:params] || []
...@@ -45,7 +46,13 @@ module Gitlab ...@@ -45,7 +46,13 @@ module Gitlab
explanation explanation
end end
warning.empty? ? message : "#{message} (#{warning})" warning_text = if warning.respond_to?(:call)
execute_block(warning, context, arg)
else
warning
end
warning.empty? ? message : "#{message} (#{warning_text})"
end end
def execute(context, arg) def execute(context, arg)
...@@ -72,6 +79,11 @@ module Gitlab ...@@ -72,6 +79,11 @@ module Gitlab
desc = context.instance_exec(&desc) rescue '' desc = context.instance_exec(&desc) rescue ''
end end
warn = warning
if warn.respond_to?(:call)
warn = context.instance_exec(&warn) rescue ''
end
prms = params prms = params
if prms.respond_to?(:call) if prms.respond_to?(:call)
prms = Array(context.instance_exec(&prms)) rescue params prms = Array(context.instance_exec(&prms)) rescue params
...@@ -81,7 +93,8 @@ module Gitlab ...@@ -81,7 +93,8 @@ module Gitlab
name: name, name: name,
aliases: aliases, aliases: aliases,
description: desc, description: desc,
warning: warning, warning: warn,
icon: icon,
params: prms params: prms
} }
end end
......
...@@ -33,8 +33,12 @@ module Gitlab ...@@ -33,8 +33,12 @@ module Gitlab
@description = block_given? ? block : text @description = block_given? ? block : text
end end
def warning(message = '') def warning(text = '', &block)
@warning = message @warning = block_given? ? block : text
end
def icon(string = '')
@icon = string
end end
# Allows to define params for the next quick action. # Allows to define params for the next quick action.
...@@ -192,6 +196,7 @@ module Gitlab ...@@ -192,6 +196,7 @@ module Gitlab
aliases: aliases, aliases: aliases,
description: @description, description: @description,
warning: @warning, warning: @warning,
icon: @icon,
explanation: @explanation, explanation: @explanation,
execution_message: @execution_message, execution_message: @execution_message,
params: @params, params: @params,
...@@ -213,6 +218,7 @@ module Gitlab ...@@ -213,6 +218,7 @@ module Gitlab
@params = nil @params = nil
@condition_block = nil @condition_block = nil
@warning = nil @warning = nil
@icon = nil
@parse_params_block = nil @parse_params_block = nil
@types = nil @types = nil
end end
......
...@@ -14420,10 +14420,10 @@ msgstr "" ...@@ -14420,10 +14420,10 @@ msgstr ""
msgid "Promote" msgid "Promote"
msgstr "" msgstr ""
msgid "Promote issue to an epic" msgid "Promote confidential issue to a non-confidential epic"
msgstr "" msgstr ""
msgid "Promote issue to an epic." msgid "Promote issue to an epic"
msgstr "" msgstr ""
msgid "Promote these project milestones into a group milestone." msgid "Promote these project milestones into a group milestone."
...@@ -14444,6 +14444,9 @@ msgstr "" ...@@ -14444,6 +14444,9 @@ msgstr ""
msgid "PromoteMilestone|Promotion failed - %{message}" msgid "PromoteMilestone|Promotion failed - %{message}"
msgstr "" msgstr ""
msgid "Promoted confidential issue to a non-confidential epic. Information in this issue is no longer confidential as epics are public to group members."
msgstr ""
msgid "Promoted issue to an epic." msgid "Promoted issue to an epic."
msgstr "" msgstr ""
...@@ -21707,9 +21710,6 @@ msgstr "" ...@@ -21707,9 +21710,6 @@ msgstr ""
msgid "math|There was an error rendering this math block" msgid "math|There was an error rendering this math block"
msgstr "" msgstr ""
msgid "may expose confidential information"
msgstr ""
msgid "merge request" msgid "merge request"
msgid_plural "merge requests" msgid_plural "merge requests"
msgstr[0] "" msgstr[0] ""
......
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