summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/models/issue_email_participant.rb2
-rw-r--r--app/serializers/issue_entity.rb5
-rw-r--r--app/services/issues/move_service.rb13
-rw-r--r--config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml6
-rw-r--r--config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml6
-rw-r--r--config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml6
-rw-r--r--config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml6
-rw-r--r--config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml6
-rw-r--r--doc/user/application_security/dast_api/index.md57
-rw-r--r--doc/user/project/releases/index.md14
-rw-r--r--doc/user/project/service_desk.md7
-rw-r--r--lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb2
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb34
-rw-r--r--spec/features/projects/issues/email_participants_spec.rb50
-rw-r--r--spec/serializers/issue_entity_spec.rb20
-rw-r--r--spec/services/issues/move_service_spec.rb21
18 files changed, 198 insertions, 66 deletions
diff --git a/app/models/issue_email_participant.rb b/app/models/issue_email_participant.rb
index 76a96151350..dd963bc9e7e 100644
--- a/app/models/issue_email_participant.rb
+++ b/app/models/issue_email_participant.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class IssueEmailParticipant < ApplicationRecord
+ include BulkInsertSafe
+
belongs_to :issue
validates :email, uniqueness: { scope: [:issue_id], case_sensitive: false }
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index 3d94d2e2e9d..82eef55205a 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -85,6 +85,11 @@ class IssueEntity < IssuableEntity
end
expose :issue_email_participants do |issue|
+ # TODO - This is a Temporary solution to avoid leaking participants' emails
+ # on public/internal projects when issue is not confidential.
+ # Should be removed when https://gitlab.com/gitlab-org/gitlab/-/issues/383448 is implemented.
+ next [] unless issue.confidential?
+
issue.issue_email_participants.map { |x| { email: x.email } }
end
diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb
index 6366ff4076b..f7f7d85611b 100644
--- a/app/services/issues/move_service.rb
+++ b/app/services/issues/move_service.rb
@@ -19,6 +19,7 @@ module Issues
# to receive service desk emails on the new moved issue.
update_service_desk_sent_notifications
+ copy_email_participants
queue_copy_designs
new_entity
@@ -49,6 +50,18 @@ module Issues
.sent_notifications.update_all(project_id: new_entity.project_id, noteable_id: new_entity.id)
end
+ def copy_email_participants
+ new_attributes = { id: nil, issue_id: new_entity.id }
+
+ new_participants = original_entity.issue_email_participants.dup
+
+ new_participants.each do |participant|
+ participant.assign_attributes(new_attributes)
+ end
+
+ IssueEmailParticipant.bulk_insert!(new_participants)
+ end
+
override :update_old_entity
def update_old_entity
super
diff --git a/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
index d4d8158f25d..e7eb6a01f82 100644
--- a/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
@@ -75,12 +75,6 @@ options:
- i_code_review_merge_request_widget_license_compliance_warning
- i_code_review_merge_request_widget_license_compliance_full_report_clicked
- i_code_review_merge_request_widget_license_compliance_view
- - i_code_review_merge_request_widget_load_performance_expand
- - i_code_review_merge_request_widget_load_performance_expand_failed
- - i_code_review_merge_request_widget_load_performance_expand_success
- - i_code_review_merge_request_widget_load_performance_warning
- - i_code_review_merge_request_widget_load_performance_full_report_clicked
- - i_code_review_merge_request_widget_load_performance_view
- i_code_review_mr_diffs
- i_code_review_mr_single_file_diffs
- i_code_review_mr_with_invalid_approvers
diff --git a/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml b/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
index be5a1acc826..6f7b82ec793 100644
--- a/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
+++ b/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
@@ -132,9 +132,3 @@ options:
- 'i_code_review_merge_request_widget_license_compliance_expand_success'
- 'i_code_review_merge_request_widget_license_compliance_expand_warning'
- 'i_code_review_merge_request_widget_license_compliance_expand_failed'
- - 'i_code_review_merge_request_widget_load_performance_view'
- - 'i_code_review_merge_request_widget_load_performance_full_report_clicked'
- - 'i_code_review_merge_request_widget_load_performance_expand'
- - 'i_code_review_merge_request_widget_load_performance_expand_success'
- - 'i_code_review_merge_request_widget_load_performance_expand_warning'
- - 'i_code_review_merge_request_widget_load_performance_expand_failed'
diff --git a/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml b/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
index 2761eb0fe7c..ce14aa19f9c 100644
--- a/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
+++ b/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
@@ -136,9 +136,3 @@ options:
- 'i_code_review_merge_request_widget_license_compliance_expand_success'
- 'i_code_review_merge_request_widget_license_compliance_expand_warning'
- 'i_code_review_merge_request_widget_license_compliance_expand_failed'
- - 'i_code_review_merge_request_widget_load_performance_view'
- - 'i_code_review_merge_request_widget_load_performance_full_report_clicked'
- - 'i_code_review_merge_request_widget_load_performance_expand'
- - 'i_code_review_merge_request_widget_load_performance_expand_success'
- - 'i_code_review_merge_request_widget_load_performance_expand_warning'
- - 'i_code_review_merge_request_widget_load_performance_expand_failed'
diff --git a/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
index d82545a035f..420926c825c 100644
--- a/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
@@ -75,12 +75,6 @@ options:
- i_code_review_merge_request_widget_license_compliance_warning
- i_code_review_merge_request_widget_license_compliance_full_report_clicked
- i_code_review_merge_request_widget_license_compliance_view
- - i_code_review_merge_request_widget_load_performance_expand
- - i_code_review_merge_request_widget_load_performance_expand_failed
- - i_code_review_merge_request_widget_load_performance_expand_success
- - i_code_review_merge_request_widget_load_performance_warning
- - i_code_review_merge_request_widget_load_performance_full_report_clicked
- - i_code_review_merge_request_widget_load_performance_view
- i_code_review_mr_diffs
- i_code_review_mr_single_file_diffs
- i_code_review_mr_with_invalid_approvers
diff --git a/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml b/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
index 465664d0f8c..f29f4d0cf28 100644
--- a/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
+++ b/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
@@ -134,9 +134,3 @@ options:
- 'i_code_review_merge_request_widget_license_compliance_expand_success'
- 'i_code_review_merge_request_widget_license_compliance_expand_warning'
- 'i_code_review_merge_request_widget_license_compliance_expand_failed'
- - 'i_code_review_merge_request_widget_load_performance_view'
- - 'i_code_review_merge_request_widget_load_performance_full_report_clicked'
- - 'i_code_review_merge_request_widget_load_performance_expand'
- - 'i_code_review_merge_request_widget_load_performance_expand_success'
- - 'i_code_review_merge_request_widget_load_performance_expand_warning'
- - 'i_code_review_merge_request_widget_load_performance_expand_failed'
diff --git a/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml b/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
index 984cdb976ba..e40e7c7f19a 100644
--- a/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
+++ b/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
@@ -132,9 +132,3 @@ options:
- 'i_code_review_merge_request_widget_license_compliance_expand_success'
- 'i_code_review_merge_request_widget_license_compliance_expand_warning'
- 'i_code_review_merge_request_widget_license_compliance_expand_failed'
- - 'i_code_review_merge_request_widget_load_performance_view'
- - 'i_code_review_merge_request_widget_load_performance_full_report_clicked'
- - 'i_code_review_merge_request_widget_load_performance_expand'
- - 'i_code_review_merge_request_widget_load_performance_expand_success'
- - 'i_code_review_merge_request_widget_load_performance_expand_warning'
- - 'i_code_review_merge_request_widget_load_performance_expand_failed'
diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md
index 996338d54c4..9e0d174e8ee 100644
--- a/doc/user/application_security/dast_api/index.md
+++ b/doc/user/application_security/dast_api/index.md
@@ -1046,6 +1046,8 @@ can be added, removed, and modified by creating a custom configuration.
|[`DAST_API_EXCLUDE_URLS`](#exclude-urls) | Exclude API URL from testing. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/357195) in GitLab 14.10. |
|[`DAST_API_EXCLUDE_PARAMETER_ENV`](#exclude-parameters) | JSON string containing excluded parameters. |
|[`DAST_API_EXCLUDE_PARAMETER_FILE`](#exclude-parameters) | Path to a JSON file containing excluded parameters. |
+|[`DAST_API_REQUEST_HEADERS`](#request-headers) | A comma-separated (`,`) list of headers to include on each scan request. Consider using `DAST_API_REQUEST_HEADERS_BASE64` when storing secret header values in a [masked variable](../../../ci/variables/index.md#mask-a-cicd-variable), which has character set restrictions. |
+|[`DAST_API_REQUEST_HEADERS_BASE64`](#request-headers) | A comma-separated (`,`) list of headers to include on each scan request, Base64-encoded. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/378440) in GitLab 15.6. |
|[`DAST_API_OPENAPI`](#openapi-specification) | OpenAPI specification file or URL. |
|[`DAST_API_OPENAPI_RELAXED_VALIDATION`](#openapi-specification) | Relax document validation. Default is disabled. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345950) in GitLab 14.7. |
|[`DAST_API_OPENAPI_ALL_MEDIA_TYPES`](#openapi-specification) | Use all supported media types instead of one when generating requests. Causes test duration to be longer. Default is disabled. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/333304) in GitLab 14.10. |
@@ -1488,6 +1490,61 @@ variables:
In the previous sample, you could use the script `user-pre-scan-set-up.sh` to also install new runtimes or applications that later on you could use in our overrides command.
+## Request Headers
+
+The request headers feature lets you specify fixed values for the headers during the scan session. For example, you can use the configuration variable `DAST_API_REQUEST_HEADERS` to set a fixed value in the `Cache-Control` header. If the headers you need to set include sensitive values like the `Authorization` header, use the [masked variable](../../../ci/variables/index.md#mask-a-cicd-variable) feature along with the [variable `DAST_API_REQUEST_HEADERS_BASE64`](#base64).
+
+Note that if the `Authorization` header or any other header needs to get updated while the scan is in progress, consider using the [overrides](#overrides) feature.
+
+The variable `DAST_API_REQUEST_HEADERS` lets you specify a comma-separated (`,`) list of headers. These headers are included on each request that the scanner performs. Each header entry in the list consists of a name followed by a colon (`:`) and then by its value. Whitespace before the key or value is ignored. For example, to declare a header name `Cache-Control` with the value `max-age=604800`, the header entry is `Cache-Control: max-age=604800`. To use two headers, `Cache-Control: max-age=604800` and `Age: 100`, set `DAST_API_REQUEST_HEADERS` variable to `Cache-Control: max-age=604800, Age: 100`.
+
+The order in which the different headers are provided into the variable `DAST_API_REQUEST_HEADERS` does not affect the result. Setting `DAST_API_REQUEST_HEADERS` to `Cache-Control: max-age=604800, Age: 100` produces the same result as setting it to `Age: 100, Cache-Control: max-age=604800`.
+
+### Base64
+
+The `DAST_API_REQUEST_HEADERS_BASE64` variable accepts the same list of headers as `DAST_API_REQUEST_HEADERS`, with the only difference that the entire value of the variable must be Base64-encoded. For example, to set `DAST_API_REQUEST_HEADERS_BASE64` variable to `Authorization: QmVhcmVyIFRPS0VO, Cache-control: bm8tY2FjaGU=`, ensure you convert the list to its Base64 equivalent: `QXV0aG9yaXphdGlvbjogUW1WaGNtVnlJRlJQUzBWTywgQ2FjaGUtY29udHJvbDogYm04dFkyRmphR1U9`, and the Base64-encoded value must be used. This is useful when storing secret header values in a [masked variable](../../../ci/variables/index.md#mask-a-cicd-variable), which has character set restrictions.
+
+WARNING:
+Base64 is used to support the [masked variable](../../../ci/variables/index.md#mask-a-cicd-variable) feature. Base64 encoding is not by itself a security measure, because sensitive values can be easily decoded.
+
+### Example: Adding a list of headers on each request using plain text
+
+In the following example of a `.gitlab-ci.yml`, `DAST_API_REQUEST_HEADERS` configuration variable is set to provide two header values as explained in [request headers](#request-headers).
+
+```yaml
+stages:
+ - dast
+
+include:
+ - template: DAST-API.gitlab-ci.yml
+
+variables:
+ DAST_API_PROFILE: Quick
+ DAST_API_OPENAPI: test-api-specification.json
+ DAST_API_TARGET_URL: http://test-deployment/
+ DAST_API_REQUEST_HEADERS: 'Cache-control: no-cache, Save-Data: on'
+```
+
+### Example: Using a masked CI/CD variable
+
+The following `.gitlab-ci.yml` sample assumes the [masked variable](../../../ci/variables/index.md#mask-a-cicd-variable) `SECRET_REQUEST_HEADERS_BASE64` is defined as a [group or instance level CI/CD variable defined in the UI](../../../ci/variables/index.md#add-a-cicd-variable-to-an-instance). The value of `SECRET_REQUEST_HEADERS_BASE64` is set to `WC1BQ01FLVNlY3JldDogc31jcnt0ISwgWC1BQ01FLVRva2VuOiA3MDVkMTZmNWUzZmI=`, which is the Base64-encoded text version of `X-ACME-Secret: s3cr3t!, X-ACME-Token: 705d16f5e3fb`. Then, it can be used as follows:
+
+```yaml
+stages:
+ - dast
+
+include:
+ - template: DAST-API.gitlab-ci.yml
+
+variables:
+ DAST_API_PROFILE: Quick
+ DAST_API_OPENAPI: test-api-specification.json
+ DAST_API_TARGET_URL: http://test-deployment/
+ DAST_API_REQUEST_HEADERS_BASE64: $SECRET_REQUEST_HEADERS_BASE64
+```
+
+Consider using `DAST_API_REQUEST_HEADERS_BASE64` when storing secret header values in a [masked variable](../../../ci/variables/index.md#mask-a-cicd-variable), which has character set restrictions.
+
## Exclude Paths
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211892) in GitLab 14.0.
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index da00be361f3..34cb8e9e092 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -184,20 +184,20 @@ is not available.
## Edit a release
-Only users with at least the Developer role can edit releases.
-Read more about [Release permissions](#release-permissions).
+To edit the details of a release after it's created, you can use the
+[Update a release API](../../../api/releases/index.md#update-a-release) or the UI.
-To edit the details of a release:
+Prerequisites:
+
+- You must have at least the Developer role.
+
+In the UI:
1. On the left sidebar, select **Deployments > Releases**.
1. In the top-right corner of the release you want to modify, select **Edit this release** (the pencil icon).
1. On the **Edit Release** page, change the release's details.
1. Select **Save changes**.
-You can edit the release title, notes, associated milestones, and asset links.
-To change the release date use the
-[Releases API](../../../api/releases/index.md#update-a-release).
-
## Delete a release
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213862) in GitLab 15.2
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index 199f25f1122..968a419ab52 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -360,12 +360,17 @@ does not count toward the license limit count.
### Moving a Service Desk issue
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/372246) in GitLab 15.7: customers continue receiving notifications when a Service Desk issue is moved.
+
Service Desk issues can be moved like any other issue in GitLab.
You can move a Service Desk issue the same way you
[move a regular issue](issues/managing_issues.md#move-an-issue) in GitLab.
-If a Service Desk issue is moved to a different project the customer who created the issue stops receiving emails.
+If a Service Desk issue is moved to a different project with Service Desk enabled,
+the customer who created the issue continues to receive email notifications.
+Because a moved issue is first closed, then copied, the customer is considered to be a participant
+in both issues. They continue to receive any notifications in the old issue and the new one.
## Troubleshooting Service Desk
diff --git a/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb b/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb
index 93b7b7dd749..f88bbc41c70 100644
--- a/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb
+++ b/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb
@@ -5,8 +5,7 @@ module Gitlab
class MergeRequestWidgetExtensionCounter < BaseCounter
KNOWN_EVENTS = %w[view full_report_clicked expand expand_success expand_warning expand_failed].freeze
PREFIX = 'i_code_review_merge_request_widget'
- WIDGETS = %w[accessibility code_quality license_compliance load_performance status_checks terraform test_summary
- metrics].freeze
+ WIDGETS = %w[accessibility code_quality license_compliance status_checks terraform test_summary metrics].freeze
class << self
private
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index 330cae575e4..236af93716f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -27,7 +27,7 @@ module QA
merge_request.visit!
Page::MergeRequest::Show.perform do |mr_page|
- expect(mr_page).to have_content('Merge blocked: the source branch must be rebased onto the target branch.')
+ expect(mr_page).to have_content('Merge blocked: the source branch must be rebased onto the target branch.', wait: 20)
expect(mr_page).to be_fast_forward_not_possible
expect(mr_page).not_to have_merge_button
expect(merge_request.project.commits.size).to eq(2)
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index a7996c5266c..31e297e5773 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -141,18 +141,32 @@ RSpec.describe Projects::IssuesController do
project.add_developer(user)
end
- it "returns issue attributes" do
- participants = create_list(:issue_email_participant, 2, issue: issue)
+ context 'issue email participants' do
+ context 'when issue is confidential' do
+ let(:issue) { create(:issue, project: project, confidential: true) }
+ let!(:participants) { create_list(:issue_email_participant, 2, issue: issue) }
- get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }, format: :json
+ it "returns issue email participants" do
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }, format: :json
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to include(
- 'issue_email_participants' => contain_exactly(
- { "email" => participants[0].email }, { "email" => participants[1].email }
- ),
- 'type' => 'ISSUE'
- )
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include(
+ 'issue_email_participants' => contain_exactly(
+ { "email" => participants[0].email }, { "email" => participants[1].email }
+ ),
+ 'type' => 'ISSUE'
+ )
+ end
+ end
+
+ context 'when issue is not confidential' do
+ it "returns empty email participants" do
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }, format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include('issue_email_participants' => [])
+ end
+ end
end
context 'when issue is not a task and work items feature flag is enabled' do
diff --git a/spec/features/projects/issues/email_participants_spec.rb b/spec/features/projects/issues/email_participants_spec.rb
index 3ffe0a5ced8..4dedbff608e 100644
--- a/spec/features/projects/issues/email_participants_spec.rb
+++ b/spec/features/projects/issues/email_participants_spec.rb
@@ -2,16 +2,15 @@
require 'spec_helper'
-RSpec.describe 'viewing an issue', :js do
+RSpec.describe 'viewing an issue', :js, feature_category: :issue_email_participants do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) }
- let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be_with_refind(:issue) { create(:issue, project: project) }
let_it_be(:note) { create(:note_on_issue, project: project, noteable: issue) }
let_it_be(:participants) { create_list(:issue_email_participant, 4, issue: issue) }
before do
- sign_in(user)
- visit project_issue_path(project, issue)
+ project.add_reporter(user)
end
shared_examples 'email participants warning' do |selector|
@@ -20,15 +19,48 @@ RSpec.describe 'viewing an issue', :js do
end
end
- context 'for a new note' do
- it_behaves_like 'email participants warning', '.new-note'
+ shared_examples 'no email participants warning' do |selector|
+ it 'does not show email participants warning' do
+ expect(find(selector)).not_to have_content(", and 1 more will be notified of your comment")
+ end
+ end
+
+ context 'when issue is confidential' do
+ before do
+ issue.update!(confidential: true)
+ sign_in(user)
+ visit project_issue_path(project, issue)
+ end
+
+ context 'for a new note' do
+ it_behaves_like 'email participants warning', '.new-note'
+ end
+
+ context 'for a reply form' do
+ before do
+ find('.js-reply-button').click
+ end
+
+ it_behaves_like 'email participants warning', '.note-edit-form'
+ end
end
- context 'for a reply form' do
+ context 'when issue is not confidential' do
before do
- find('.js-reply-button').click
+ sign_in(user)
+ visit project_issue_path(project, issue)
end
- it_behaves_like 'email participants warning', '.note-edit-form'
+ context 'for a new note' do
+ it_behaves_like 'no email participants warning', '.new-note'
+ end
+
+ context 'for a reply form' do
+ before do
+ find('.js-reply-button').click
+ end
+
+ it_behaves_like 'no email participants warning', '.note-edit-form'
+ end
end
end
diff --git a/spec/serializers/issue_entity_spec.rb b/spec/serializers/issue_entity_spec.rb
index 6161d4d7ec2..9d53d8bb235 100644
--- a/spec/serializers/issue_entity_spec.rb
+++ b/spec/serializers/issue_entity_spec.rb
@@ -162,4 +162,24 @@ RSpec.describe IssueEntity do
end
it_behaves_like 'issuable entity current_user properties'
+
+ context 'when issue has email participants' do
+ before do
+ resource.issue_email_participants.create!(email: 'any@email.com')
+ end
+
+ context 'when issue is confidential' do
+ it 'returns email participants' do
+ resource.update!(confidential: true)
+
+ expect(subject[:issue_email_participants]).to match_array([{ email: "any@email.com" }])
+ end
+ end
+
+ context 'when issue is not confidential' do
+ it 'returns empty array' do
+ expect(subject[:issue_email_participants]).to be_empty
+ end
+ end
+ end
end
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index 655c5085fdc..324b2aa9fe2 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -508,4 +508,25 @@ RSpec.describe Issues::MoveService do
end
end
end
+
+ context 'copying email participants' do
+ let!(:participant1) { create(:issue_email_participant, email: 'user1@example.com', issue: old_issue) }
+ let!(:participant2) { create(:issue_email_participant, email: 'user2@example.com', issue: old_issue) }
+ let!(:participant3) { create(:issue_email_participant, email: 'other_project_customer@example.com') }
+
+ include_context 'user can move issue'
+
+ subject(:new_issue) do
+ move_service.execute(old_issue, new_project)
+ end
+
+ it 'copies moved issue email participants' do
+ new_issue
+
+ expect(participant1.reload.issue).to eq(old_issue)
+ expect(participant2.reload.issue).to eq(old_issue)
+ expect(new_issue.issue_email_participants.pluck(:email))
+ .to match_array([participant1.email, participant2.email])
+ end
+ end
end