Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-30 18:09:03 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-30 18:09:03 +0300
commite7b262a4c5cf70fed6eb25ba7a0eb1336e6eb639 (patch)
tree4e1037d8fd8d93883e52d1fbd8b542dfc81a0436
parentb0139a824fba85e5b71e69f2c99d423700ff76cc (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/vendored-gems.gitlab-ci.yml9
-rw-r--r--.rubocop_todo/layout/line_length.yml7
-rw-r--r--.rubocop_todo/rspec/context_wording.yml1
-rw-r--r--.rubocop_todo/rspec/repeated_example_group_body.yml1
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock16
-rw-r--r--app/assets/javascripts/blob/3d_viewer/index.js4
-rw-r--r--app/assets/javascripts/blob/3d_viewer/mesh_object.js4
-rw-r--r--app/assets/javascripts/blob/stl_viewer.js8
-rw-r--r--app/assets/javascripts/graphql_shared/possible_types.json3
-rw-r--r--app/assets/javascripts/profile/account/index.js2
-rw-r--r--app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb3
-rw-r--r--app/graphql/types/work_items/widget_interface.rb5
-rw-r--r--app/graphql/types/work_items/widgets/weight_input_type.rb15
-rw-r--r--app/graphql/types/work_items/widgets/weight_type.rb21
-rw-r--r--app/models/ability.rb7
-rw-r--r--app/models/concerns/cache_markdown_field.rb9
-rw-r--r--app/models/concerns/participable.rb23
-rw-r--r--app/models/note.rb19
-rw-r--r--app/models/work_items/type.rb4
-rw-r--r--app/models/work_items/widgets/weight.rb9
-rw-r--r--app/services/work_items/widgets/weight_service/update_service.rb15
-rw-r--r--app/views/profiles/accounts/show.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_stl.html.haml8
-rw-r--r--config/feature_flags/development/fix_sliding_list_partitioning.yml2
-rw-r--r--config/routes/project.rb7
-rw-r--r--doc/administration/postgresql/replication_and_failover.md6
-rw-r--r--doc/api/graphql/reference/index.md23
-rw-r--r--doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md24
-rw-r--r--doc/development/integrations/secure.md2
-rw-r--r--doc/user/application_security/generate_test_vulnerabilities/index.md28
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml67
-rw-r--r--lib/sidebars/projects/menus/monitor_menu.rb16
-rw-r--r--locale/gitlab.pot12
-rw-r--r--package.json4
-rw-r--r--spec/features/incidents/incident_details_spec.rb77
-rw-r--r--spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap6
-rw-r--r--spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap1
-rw-r--r--spec/models/ability_spec.rb32
-rw-r--r--spec/models/concerns/participable_spec.rb10
-rw-r--r--spec/models/issue_spec.rb22
-rw-r--r--spec/models/work_item_spec.rb3
-rw-r--r--spec/models/work_items/type_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_spec.rb24
-rw-r--r--spec/requests/api/graphql/work_item_spec.rb28
-rw-r--r--spec/services/notification_service_spec.rb77
-rw-r--r--spec/services/work_items/widgets/weight_service/update_service_spec.rb36
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb1
-rw-r--r--spec/support/shared_examples/graphql/mutations/work_items/update_weight_widget_shared_examples.rb34
-rw-r--r--spec/support/shared_examples/models/issuable_participants_shared_examples.rb53
-rw-r--r--spec/support/shared_examples/models/mentionable_shared_examples.rb39
-rw-r--r--vendor/gems/omniauth-gitlab/.gitignore17
-rw-r--r--vendor/gems/omniauth-gitlab/.gitlab-ci.yml30
-rw-r--r--vendor/gems/omniauth-gitlab/Gemfile4
-rw-r--r--vendor/gems/omniauth-gitlab/Gemfile.lock73
-rw-r--r--vendor/gems/omniauth-gitlab/LICENSE.txt22
-rw-r--r--vendor/gems/omniauth-gitlab/README.md94
-rw-r--r--vendor/gems/omniauth-gitlab/Rakefile7
-rw-r--r--vendor/gems/omniauth-gitlab/lib/omniauth-gitlab.rb2
-rw-r--r--vendor/gems/omniauth-gitlab/lib/omniauth-gitlab/version.rb5
-rw-r--r--vendor/gems/omniauth-gitlab/lib/omniauth/strategies/gitlab.rb46
-rw-r--r--vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec25
-rw-r--r--vendor/gems/omniauth-gitlab/spec/omniauth/strategies/gitlab_spec.rb80
-rw-r--r--vendor/gems/omniauth-gitlab/spec/spec_helper.rb8
-rw-r--r--yarn.lock18
66 files changed, 1109 insertions, 164 deletions
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 4b7f60c1bac..e188475485b 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -1501,6 +1501,12 @@
changes: ["vendor/gems/ipynbdiff/**/*"]
- <<: *if-merge-request-labels-run-all-rspec
+.vendor:rules:omniauth-gitlab:
+ rules:
+ - <<: *if-merge-request
+ changes: ["vendor/gems/omniauth-gitlab/**/*"]
+ - <<: *if-merge-request-labels-run-all-rspec
+
##################
# Releases rules #
##################
diff --git a/.gitlab/ci/vendored-gems.gitlab-ci.yml b/.gitlab/ci/vendored-gems.gitlab-ci.yml
index ce71820100f..6dd6e19a818 100644
--- a/.gitlab/ci/vendored-gems.gitlab-ci.yml
+++ b/.gitlab/ci/vendored-gems.gitlab-ci.yml
@@ -5,6 +5,7 @@ vendor mail-smtp_pool:
trigger:
include: vendor/gems/mail-smtp_pool/.gitlab-ci.yml
strategy: depend
+
vendor ipynbdiff:
extends:
- .vendor:rules:ipynbdiff
@@ -12,3 +13,11 @@ vendor ipynbdiff:
trigger:
include: vendor/gems/ipynbdiff/.gitlab-ci.yml
strategy: depend
+
+vendor omniauth-gitlab:
+ extends:
+ - .vendor:rules:omniauth-gitlab
+ needs: []
+ trigger:
+ include: vendor/gems/omniauth-gitlab/.gitlab-ci.yml
+ strategy: depend
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index 9d3f426a228..c5c87040175 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -88,7 +88,6 @@ Layout/LineLength:
- 'app/controllers/projects/issues_controller.rb'
- 'app/controllers/projects/jobs_controller.rb'
- 'app/controllers/projects/labels_controller.rb'
- - 'app/controllers/projects/logs_controller.rb'
- 'app/controllers/projects/merge_requests/conflicts_controller.rb'
- 'app/controllers/projects/merge_requests/creations_controller.rb'
- 'app/controllers/projects/merge_requests/diffs_controller.rb'
@@ -696,8 +695,6 @@ Layout/LineLength:
- 'app/services/pages/migrate_legacy_storage_to_deployment_service.rb'
- 'app/services/personal_access_tokens/create_service.rb'
- 'app/services/personal_access_tokens/revoke_service.rb'
- - 'app/services/pod_logs/elasticsearch_service.rb'
- - 'app/services/pod_logs/kubernetes_service.rb'
- 'app/services/projects/branches_by_mode_service.rb'
- 'app/services/projects/container_repository/cleanup_tags_service.rb'
- 'app/services/projects/container_repository/gitlab/delete_tags_service.rb'
@@ -3485,7 +3482,6 @@ Layout/LineLength:
- 'lib/gitlab/diff/highlight_cache.rb'
- 'lib/gitlab/diff/parser.rb'
- 'lib/gitlab/diff/rendered/notebook/diff_file.rb'
- - 'lib/gitlab/elasticsearch/logs/lines.rb'
- 'lib/gitlab/email/failure_handler.rb'
- 'lib/gitlab/email/handler/create_issue_handler.rb'
- 'lib/gitlab/email/handler/create_merge_request_handler.rb'
@@ -5007,7 +5003,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/diff/position_tracer/image_strategy_spec.rb'
- 'spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb'
- 'spec/lib/gitlab/diff/suggestion_spec.rb'
- - 'spec/lib/gitlab/elasticsearch/logs/lines_spec.rb'
- 'spec/lib/gitlab/email/failure_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
@@ -6090,8 +6085,6 @@ Layout/LineLength:
- 'spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb'
- 'spec/services/personal_access_tokens/create_service_spec.rb'
- 'spec/services/personal_access_tokens/revoke_service_spec.rb'
- - 'spec/services/pod_logs/elasticsearch_service_spec.rb'
- - 'spec/services/pod_logs/kubernetes_service_spec.rb'
- 'spec/services/post_receive_service_spec.rb'
- 'spec/services/projects/apple_target_platform_detector_service_spec.rb'
- 'spec/services/projects/autocomplete_service_spec.rb'
diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index 0d517c6cd55..49968873ccb 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -1471,7 +1471,6 @@ RSpec/ContextWording:
- 'spec/features/ics/project_issues_spec.rb'
- 'spec/features/ide/clientside_preview_csp_spec.rb'
- 'spec/features/ide/static_object_external_storage_csp_spec.rb'
- - 'spec/features/incidents/incident_details_spec.rb'
- 'spec/features/incidents/user_creates_new_incident_spec.rb'
- 'spec/features/invites_spec.rb'
- 'spec/features/issuables/markdown_references/internal_references_spec.rb'
diff --git a/.rubocop_todo/rspec/repeated_example_group_body.yml b/.rubocop_todo/rspec/repeated_example_group_body.yml
index 87148442b08..e006396d0d6 100644
--- a/.rubocop_todo/rspec/repeated_example_group_body.yml
+++ b/.rubocop_todo/rspec/repeated_example_group_body.yml
@@ -23,7 +23,6 @@ RSpec/RepeatedExampleGroupBody:
- 'spec/controllers/projects/blob_controller_spec.rb'
- 'spec/controllers/projects/graphs_controller_spec.rb'
- 'spec/controllers/projects/registry/repositories_controller_spec.rb'
- - 'spec/features/incidents/incident_details_spec.rb'
- 'spec/features/issues/spam_akismet_issue_creation_spec.rb'
- 'spec/features/merge_request/user_sees_closing_issues_message_spec.rb'
- 'spec/features/projects/commit/cherry_pick_spec.rb'
diff --git a/Gemfile b/Gemfile
index e3eba484a15..a0f83cc93dd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -44,7 +44,7 @@ gem 'omniauth-dingtalk-oauth2', '~> 1.0'
gem 'omniauth-alicloud', '~> 1.0.1'
gem 'omniauth-facebook', '~> 4.0.0'
gem 'omniauth-github', '~> 1.4'
-gem 'omniauth-gitlab', '~> 1.0.2'
+gem 'omniauth-gitlab', '~> 4.0.0', path: 'vendor/gems/omniauth-gitlab' # See vendor/gems/omniauth-gitlab/README.md
gem 'omniauth-google-oauth2', '~> 0.6.0'
gem 'omniauth-oauth2-generic', '~> 0.2.2'
gem 'omniauth-saml', '~> 1.10'
@@ -407,7 +407,7 @@ group :development, :test do
end
group :development, :test, :danger do
- gem 'gitlab-dangerfiles', '~> 3.4.1', require: false
+ gem 'gitlab-dangerfiles', '~> 3.4.2', require: false
end
group :development, :test, :coverage do
diff --git a/Gemfile.lock b/Gemfile.lock
index aea6f448587..02068c3a243 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -12,6 +12,13 @@ PATH
connection_pool (~> 2.0)
mail (~> 2.7)
+PATH
+ remote: vendor/gems/omniauth-gitlab
+ specs:
+ omniauth-gitlab (4.0.0)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.7.1)
+
GEM
remote: https://rubygems.org/
specs:
@@ -482,7 +489,7 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-dangerfiles (3.4.1)
+ gitlab-dangerfiles (3.4.2)
danger (>= 8.4.5)
danger-gitlab (>= 8.0.0)
rake
@@ -872,9 +879,6 @@ GEM
omniauth-github (1.4.0)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0)
- omniauth-gitlab (1.0.3)
- omniauth (~> 1.0)
- omniauth-oauth2 (~> 1.0)
omniauth-google-oauth2 (0.6.0)
jwt (>= 2.0)
omniauth (>= 1.1.1)
@@ -1538,7 +1542,7 @@ DEPENDENCIES
gitaly (~> 15.1.0.pre.rc1)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-dangerfiles (~> 3.4.1)
+ gitlab-dangerfiles (~> 3.4.2)
gitlab-experiment (~> 0.7.1)
gitlab-fog-azure-rm (~> 1.3.0)
gitlab-labkit (~> 0.23.0)
@@ -1623,7 +1627,7 @@ DEPENDENCIES
omniauth-dingtalk-oauth2 (~> 1.0)
omniauth-facebook (~> 4.0.0)
omniauth-github (~> 1.4)
- omniauth-gitlab (~> 1.0.2)
+ omniauth-gitlab (~> 4.0.0)!
omniauth-google-oauth2 (~> 0.6.0)
omniauth-oauth2-generic (~> 0.2.2)
omniauth-salesforce (~> 1.0.5)
diff --git a/app/assets/javascripts/blob/3d_viewer/index.js b/app/assets/javascripts/blob/3d_viewer/index.js
index fd064e7ca8f..d4efe409fef 100644
--- a/app/assets/javascripts/blob/3d_viewer/index.js
+++ b/app/assets/javascripts/blob/3d_viewer/index.js
@@ -98,9 +98,9 @@ export default class Renderer {
requestAnimationFrame(this.renderWrapper);
}
- changeObjectMaterials(type) {
+ changeObjectMaterials(material) {
this.objects.forEach((obj) => {
- obj.changeMaterial(type);
+ obj.changeMaterial(material);
});
}
diff --git a/app/assets/javascripts/blob/3d_viewer/mesh_object.js b/app/assets/javascripts/blob/3d_viewer/mesh_object.js
index cb7fcff8674..c55a9ca8926 100644
--- a/app/assets/javascripts/blob/3d_viewer/mesh_object.js
+++ b/app/assets/javascripts/blob/3d_viewer/mesh_object.js
@@ -30,7 +30,7 @@ export default class MeshObject extends Mesh {
}
}
- changeMaterial(type) {
- this.material = materials[type];
+ changeMaterial(materialKey) {
+ this.material = materials[materialKey];
}
}
diff --git a/app/assets/javascripts/blob/stl_viewer.js b/app/assets/javascripts/blob/stl_viewer.js
index 0ea623a705a..768bbce9c57 100644
--- a/app/assets/javascripts/blob/stl_viewer.js
+++ b/app/assets/javascripts/blob/stl_viewer.js
@@ -5,15 +5,15 @@ export default () => {
[].slice.call(document.querySelectorAll('.js-material-changer')).forEach((el) => {
el.addEventListener('click', (e) => {
- const { target } = e;
+ const { currentTarget } = e;
e.preventDefault();
document.querySelector('.js-material-changer.selected').classList.remove('selected');
- target.classList.add('selected');
- target.blur();
+ currentTarget.classList.add('selected');
+ currentTarget.blur();
- viewer.changeObjectMaterials(target.dataset.type);
+ viewer.changeObjectMaterials(currentTarget.dataset.material);
});
});
};
diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json
index 1c0e27ac3ea..45c5cca68cc 100644
--- a/app/assets/javascripts/graphql_shared/possible_types.json
+++ b/app/assets/javascripts/graphql_shared/possible_types.json
@@ -133,6 +133,7 @@
"WorkItemWidget": [
"WorkItemWidgetAssignees",
"WorkItemWidgetDescription",
- "WorkItemWidgetHierarchy"
+ "WorkItemWidgetHierarchy",
+ "WorkItemWidgetWeight"
]
}
diff --git a/app/assets/javascripts/profile/account/index.js b/app/assets/javascripts/profile/account/index.js
index 00fe0bcf89b..f208280af27 100644
--- a/app/assets/javascripts/profile/account/index.js
+++ b/app/assets/javascripts/profile/account/index.js
@@ -30,7 +30,7 @@ export default () => {
deleteAccountModal,
},
mounted() {
- deleteAccountButton.classList.remove('disabled');
+ deleteAccountButton.disabled = false;
deleteAccountButton.addEventListener('click', () => {
this.$root.$emit(BV_SHOW_MODAL, 'delete-account-modal', '#delete-account-button');
});
diff --git a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
index 7af55d42f2a..cc15bff0916 100644
--- a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
+++ b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
@@ -18,6 +18,9 @@ module Mutations
argument :description_widget, ::Types::WorkItems::Widgets::DescriptionInputType,
required: false,
description: 'Input for description widget.'
+ argument :weight_widget, ::Types::WorkItems::Widgets::WeightInputType,
+ required: false,
+ description: 'Input for weight widget.'
end
end
end
diff --git a/app/graphql/types/work_items/widget_interface.rb b/app/graphql/types/work_items/widget_interface.rb
index 6520de39b7e..1b752393296 100644
--- a/app/graphql/types/work_items/widget_interface.rb
+++ b/app/graphql/types/work_items/widget_interface.rb
@@ -18,6 +18,8 @@ module Types
::Types::WorkItems::Widgets::HierarchyType
when ::WorkItems::Widgets::Assignees
::Types::WorkItems::Widgets::AssigneesType
+ when ::WorkItems::Widgets::Weight
+ ::Types::WorkItems::Widgets::WeightType
else
raise "Unknown GraphQL type for widget #{object}"
end
@@ -25,7 +27,8 @@ module Types
orphan_types ::Types::WorkItems::Widgets::DescriptionType,
::Types::WorkItems::Widgets::HierarchyType,
- ::Types::WorkItems::Widgets::AssigneesType
+ ::Types::WorkItems::Widgets::AssigneesType,
+ ::Types::WorkItems::Widgets::WeightType
end
end
end
diff --git a/app/graphql/types/work_items/widgets/weight_input_type.rb b/app/graphql/types/work_items/widgets/weight_input_type.rb
new file mode 100644
index 00000000000..a01c63222a5
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/weight_input_type.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ class WeightInputType < BaseInputObject
+ graphql_name 'WorkItemWidgetWeightInput'
+
+ argument :weight, GraphQL::Types::Int,
+ required: true,
+ description: 'Weight of the work item.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/work_items/widgets/weight_type.rb b/app/graphql/types/work_items/widgets/weight_type.rb
new file mode 100644
index 00000000000..c8eaf560268
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/weight_type.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ # Disabling widget level authorization as it might be too granular
+ # and we already authorize the parent work item
+ # rubocop:disable Graphql/AuthorizeTypes
+ class WeightType < BaseObject
+ graphql_name 'WorkItemWidgetWeight'
+ description 'Represents a weight widget'
+
+ implements Types::WorkItems::WidgetInterface
+
+ field :weight, GraphQL::Types::Int, null: true,
+ description: 'Weight of the work item.'
+ end
+ # rubocop:enable Graphql/AuthorizeTypes
+ end
+ end
+end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index a185448d5ea..b15143c8c9c 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -26,6 +26,13 @@ class Ability
end
end
+ # A list of users that can read confidential notes in a project
+ def users_that_can_read_internal_notes(users, note_parent)
+ DeclarativePolicy.subject_scope do
+ users.select { |u| allowed?(u, :reporter_access, note_parent) }
+ end
+ end
+
# Returns an Array of Issues that can be read by the given user.
#
# issues - The issues to reduce down to those readable by the user.
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index 99dbe464a7c..9ee0fd1db1d 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -172,7 +172,7 @@ module CacheMarkdownField
refs = all_references(self.author)
references = {}
- references[:mentioned_users_ids] = refs.mentioned_user_ids.presence
+ references[:mentioned_users_ids] = mentioned_filtered_user_ids_for(refs)
references[:mentioned_groups_ids] = refs.mentioned_group_ids.presence
references[:mentioned_projects_ids] = refs.mentioned_project_ids.presence
@@ -185,6 +185,13 @@ module CacheMarkdownField
true
end
+ # Overriden on objects that needs to filter
+ # mentioned users that cannot read them, for example,
+ # guest users that are referenced on a confidential note.
+ def mentioned_filtered_user_ids_for(refs)
+ refs.mentioned_user_ids.presence
+ end
+
def mentionable_attributes_changed?(changes = saved_changes)
return false unless is_a?(Mentionable)
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 20743ebcb52..f59b5d1ecc8 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -92,7 +92,13 @@ module Participable
end
def raw_participants(current_user = nil, verify_access: false)
- ext = Gitlab::ReferenceExtractor.new(project, current_user)
+ extractor = Gitlab::ReferenceExtractor.new(project, current_user)
+
+ # Used to extract references from confidential notes.
+ # Referenced users that cannot read confidential notes are
+ # later removed from participants array.
+ internal_notes_extractor = Gitlab::ReferenceExtractor.new(project, current_user)
+
participants = Set.new
process = [self]
@@ -107,6 +113,8 @@ module Participable
source.class.participant_attrs.each do |attr|
if attr.respond_to?(:call)
+ ext = use_internal_notes_extractor_for?(source) ? internal_notes_extractor : extractor
+
source.instance_exec(current_user, ext, &attr)
else
process << source.__send__(attr) # rubocop:disable GitlabSecurity/PublicSend
@@ -121,7 +129,18 @@ module Participable
end
end
- participants.merge(ext.users)
+ participants.merge(users_that_can_read_internal_notes(internal_notes_extractor))
+ participants.merge(extractor.users)
+ end
+
+ def use_internal_notes_extractor_for?(source)
+ source.is_a?(Note) && source.confidential?
+ end
+
+ def users_that_can_read_internal_notes(extractor)
+ return [] unless self.is_a?(Noteable) && self.try(:resource_parent)
+
+ Ability.users_that_can_read_internal_notes(extractor.users, self.resource_parent)
end
def source_visible_to_user?(source, user)
diff --git a/app/models/note.rb b/app/models/note.rb
index 41e45a8759f..f2ddf0efe47 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -665,6 +665,25 @@ class Note < ApplicationRecord
)
end
+ def mentioned_users(current_user = nil)
+ users = super
+
+ return users unless confidential?
+
+ Ability.users_that_can_read_internal_notes(users, resource_parent)
+ end
+
+ def mentioned_filtered_user_ids_for(references)
+ return super unless confidential?
+
+ user_ids = references.mentioned_user_ids.presence
+
+ return [] if user_ids.blank?
+
+ users = User.where(id: user_ids)
+ Ability.users_that_can_read_internal_notes(users, resource_parent).pluck(:id)
+ end
+
private
def system_note_viewable_by?(user)
diff --git a/app/models/work_items/type.rb b/app/models/work_items/type.rb
index 843e7a7fb32..c52565196a1 100644
--- a/app/models/work_items/type.rb
+++ b/app/models/work_items/type.rb
@@ -21,11 +21,11 @@ module WorkItems
}.freeze
WIDGETS_FOR_TYPE = {
- issue: [Widgets::Description, Widgets::Hierarchy, Widgets::Assignees],
+ issue: [Widgets::Assignees, Widgets::Description, Widgets::Hierarchy, Widgets::Weight],
incident: [Widgets::Description],
test_case: [Widgets::Description],
requirement: [Widgets::Description],
- task: [Widgets::Description, Widgets::Hierarchy, Widgets::Assignees]
+ task: [Widgets::Assignees, Widgets::Description, Widgets::Hierarchy, Widgets::Weight]
}.freeze
cache_markdown_field :description, pipeline: :single_line
diff --git a/app/models/work_items/widgets/weight.rb b/app/models/work_items/widgets/weight.rb
new file mode 100644
index 00000000000..f589378f307
--- /dev/null
+++ b/app/models/work_items/widgets/weight.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ class Weight < Base
+ delegate :weight, to: :work_item
+ end
+ end
+end
diff --git a/app/services/work_items/widgets/weight_service/update_service.rb b/app/services/work_items/widgets/weight_service/update_service.rb
new file mode 100644
index 00000000000..cd62a25358f
--- /dev/null
+++ b/app/services/work_items/widgets/weight_service/update_service.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ module WeightService
+ class UpdateService < WorkItems::Widgets::BaseService
+ def update(params: {})
+ return unless params.present? && params[:weight]
+
+ widget.work_item.weight = params[:weight]
+ end
+ end
+ end
+ end
+end
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index 745d3c62c5d..de09e78c695 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -68,7 +68,7 @@
= render 'users/deletion_guidance', user: current_user
-# Delete button here
- %button#delete-account-button.gl-button.btn.btn-danger.disabled{ data: { qa_selector: 'delete_account_button' } }
+ = render Pajamas::ButtonComponent.new(variant: :danger, button_options: { id: 'delete-account-button', disabled: true, data: { qa_selector: 'delete_account_button' }}) do
= s_('Profiles|Delete account')
#delete-account-modal{ data: { action_url: user_registration_path,
diff --git a/app/views/projects/blob/viewers/_stl.html.haml b/app/views/projects/blob/viewers/_stl.html.haml
index 8bf0339fc3c..7206a969fb7 100644
--- a/app/views/projects/blob/viewers/_stl.html.haml
+++ b/app/views/projects/blob/viewers/_stl.html.haml
@@ -3,7 +3,7 @@
= gl_loading_icon(size: "md", css_class: "gl-my-4")
.text-center.gl-mt-3.gl-mb-3.stl-controls
.btn-group
- %button.gl-button.btn.btn-default.btn-sm.js-material-changer{ data: { type: 'wireframe' } }
- Wireframe
- %button.gl-button.btn.btn-default.btn-sm.selected.js-material-changer{ data: { type: 'default' } }
- Solid
+ = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-material-changer', data: { material: 'wireframe' } }) do
+ = _('Wireframe')
+ = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-material-changer selected', data: { material: 'default' } }) do
+ = _('Solid')
diff --git a/config/feature_flags/development/fix_sliding_list_partitioning.yml b/config/feature_flags/development/fix_sliding_list_partitioning.yml
index 90b4bf87740..7d553ea938c 100644
--- a/config/feature_flags/development/fix_sliding_list_partitioning.yml
+++ b/config/feature_flags/development/fix_sliding_list_partitioning.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362246
milestone: '15.1'
type: development
group: group::sharding
-default_enabled: false
+default_enabled: true
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 6ecd002e970..f996cd1945f 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -238,13 +238,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :logs, only: [:index] do
- collection do
- get :k8s
- get :elasticsearch
- end
- end
-
resources :starrers, only: [:index]
resources :forks, only: [:index, :new, :create]
resources :group_links, only: [:update, :destroy], constraints: { id: /\d+|:id/ }
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index e9b607ad5d4..37471a4f491 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -996,7 +996,7 @@ You can switch an exiting database cluster to use Patroni instead of repmgr with
### Upgrading PostgreSQL major version in a Patroni cluster
-As of GitLab 13.3, PostgreSQL 11.7 and 12.3 are both shipped with Omnibus GitLab by default. As of GitLab 13.7, PostgreSQL 12 is the default. If you want to upgrade to PostgreSQL 12 in versions prior to GitLab 13.7, you must ask for it explicitly.
+As of GitLab 14.1, PostgreSQL 12.6 and 13.3 are both shipped with Omnibus GitLab by default. As of GitLab 15.0, PostgreSQL 13 is the default. If you want to upgrade to PostgreSQL 13 in versions prior to GitLab 15.0, you must ask for it explicitly.
WARNING:
The procedure for upgrading PostgreSQL in a Patroni cluster is different than when upgrading using repmgr.
@@ -1046,7 +1046,7 @@ Considering these, you should carefully plan your PostgreSQL upgrade:
1. Upgrade PostgreSQL on **the leader node** and make sure that the upgrade is completed successfully:
```shell
- sudo gitlab-ctl pg-upgrade -V 12
+ sudo gitlab-ctl pg-upgrade -V 13
```
NOTE:
@@ -1073,7 +1073,7 @@ Considering these, you should carefully plan your PostgreSQL upgrade:
1. Upgrade PostgreSQL **on replicas** (you can do this in parallel on all of them):
```shell
- sudo gitlab-ctl pg-upgrade -V 12
+ sudo gitlab-ctl pg-upgrade -V 13
```
NOTE:
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 5c179e18a4b..5b38f524ede 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -5655,6 +5655,7 @@ Input type: `WorkItemUpdateInput`
| <a id="mutationworkitemupdateid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
| <a id="mutationworkitemupdatestateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
| <a id="mutationworkitemupdatetitle"></a>`title` | [`String`](#string) | Title of the work item. |
+| <a id="mutationworkitemupdateweightwidget"></a>`weightWidget` | [`WorkItemWidgetWeightInput`](#workitemwidgetweightinput) | Input for weight widget. |
#### Fields
@@ -18518,6 +18519,17 @@ Represents a hierarchy widget.
| <a id="workitemwidgethierarchyparent"></a>`parent` | [`WorkItem`](#workitem) | Parent work item. |
| <a id="workitemwidgethierarchytype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
+### `WorkItemWidgetWeight`
+
+Represents a weight widget.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetweighttype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
+| <a id="workitemwidgetweightweight"></a>`weight` | [`Int`](#int) | Weight of the work item. |
+
## Enumeration types
Also called _Enums_, enumeration types are a special kind of scalar that
@@ -20372,6 +20384,7 @@ Type of a work item widget.
| <a id="workitemwidgettypeassignees"></a>`ASSIGNEES` | Assignees widget. |
| <a id="workitemwidgettypedescription"></a>`DESCRIPTION` | Description widget. |
| <a id="workitemwidgettypehierarchy"></a>`HIERARCHY` | Hierarchy widget. |
+| <a id="workitemwidgettypeweight"></a>`WEIGHT` | Weight widget. |
## Scalar types
@@ -21593,6 +21606,7 @@ Implementations:
- [`WorkItemWidgetAssignees`](#workitemwidgetassignees)
- [`WorkItemWidgetDescription`](#workitemwidgetdescription)
- [`WorkItemWidgetHierarchy`](#workitemwidgethierarchy)
+- [`WorkItemWidgetWeight`](#workitemwidgetweight)
##### Fields
@@ -22082,6 +22096,7 @@ A time-frame defined as a closed inclusive range of two dates.
| <a id="workitemupdatedtaskinputid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
| <a id="workitemupdatedtaskinputstateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
| <a id="workitemupdatedtaskinputtitle"></a>`title` | [`String`](#string) | Title of the work item. |
+| <a id="workitemupdatedtaskinputweightwidget"></a>`weightWidget` | [`WorkItemWidgetWeightInput`](#workitemwidgetweightinput) | Input for weight widget. |
### `WorkItemWidgetDescriptionInput`
@@ -22090,3 +22105,11 @@ A time-frame defined as a closed inclusive range of two dates.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="workitemwidgetdescriptioninputdescription"></a>`description` | [`String!`](#string) | Description of the work item. |
+
+### `WorkItemWidgetWeightInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetweightinputweight"></a>`weight` | [`Int!`](#int) | Weight of the work item. |
diff --git a/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md b/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
index 5356ebb84f1..5894efa95ab 100644
--- a/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
+++ b/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
@@ -248,9 +248,13 @@ set `CI_AWS_ECS_WAIT_FOR_ROLLOUT_COMPLETE_DISABLED` to a non-empty value.
## Set up Review Apps
-In order to use [Review Apps](../../../development/testing_guide/review_apps.md) with ECS, you should create another
-[service](#create-an-ecs-service) and specify its name using the `CI_AWS_ECS_SERVICE` variable scoped to `review/*`.
-Since this service is shared by all review apps, there is a limitation that only one Review App can be deployed at a time.
+To use [Review Apps](../../../development/testing_guide/review_apps.md) with ECS:
+
+1. Set up a new [service](#create-an-ecs-service).
+1. Use the `CI_AWS_ECS_SERVICE` variable to set the name.
+1. Set the environment scope to `review/*`.
+
+Only one Review App at a time can be deployed because this service is shared by all review apps.
## Set up Security Testing
@@ -275,6 +279,20 @@ include:
- template: Security/DAST.gitlab-ci.yml
```
+To use DAST on the default branch:
+
+1. Set up a new [service](#create-an-ecs-service). This service will be used to deploy a temporary
+DAST environment.
+1. Use the `CI_AWS_ECS_SERVICE` variable to set the name.
+1. Set the scope to the `dast-default` environment.
+1. Add the following to your `.gitlab-ci.yml` file:
+
+```yaml
+include:
+ - template: Security/DAST.gitlab-ci.yml
+ - template: Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+```
+
For more details and configuration options, see the [DAST documentation](../../../user/application_security/dast/index.md).
## Further reading
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index 1a51ee88c58..a68c0630b18 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -451,7 +451,7 @@ The `identifiers` array describes the detected vulnerability. An identifier obje
`value` fields are used to tell if two identifiers are the same. The user interface uses the
object's `name` and `url` fields to display the identifier.
-It is recommended to reuse the identifiers the GitLab scanners already define:
+We recommend that you use the identifiers the GitLab scanners already define:
| Identifier | Type | Example value |
|------------|------|---------------|
diff --git a/doc/user/application_security/generate_test_vulnerabilities/index.md b/doc/user/application_security/generate_test_vulnerabilities/index.md
new file mode 100644
index 00000000000..aafbebb91cd
--- /dev/null
+++ b/doc/user/application_security/generate_test_vulnerabilities/index.md
@@ -0,0 +1,28 @@
+---
+type: reference, howto
+stage: Secure
+group: Threat Insights
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Generate test vulnerabilities
+
+You can generate test vulnerabilities when you work on the [Vulnerability Report](../vulnerability_report/index.md).
+
+1. Go to `/-/profile/personal_access_tokens` and generate a personal access token with `api` permissions.
+1. Go to your project page and find the project ID. You can find the project ID below the project title.
+1. Open a terminal and go to the `gitlab/qa` directory.
+1. Run the following command:
+
+```shell
+GITLAB_QA_ACCESS_TOKEN=<your_personal_access_token> GITLAB_URL="http://localhost:3000" bundle exec rake vulnerabilities:setup\[<your_project_id>,<vulnerability_count>\] --trace
+```
+
+Make sure you do the following:
+
+- Replace `<your_personal_access_token>` with the token you generated in step one.
+- Double check the `GITLAB_URL`. It should point to the running local instance.
+- Replace `<your_project_id>` with the ID you obtained in step two.
+- Replace `<vulnerability_count>` with the number of vulnerabilities you'd like to generate.
+
+The script creates the specified amount of vulnerabilities in the project.
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index 8f1124373c4..b41e92e3a56 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -4,6 +4,14 @@ variables:
.dast-auto-deploy:
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
+.common_rules: &common_rules
+ - if: $CI_DEFAULT_BRANCH != $CI_COMMIT_REF_NAME
+ when: never
+ - if: $DAST_DISABLED || $DAST_DISABLED_FOR_DEFAULT_BRANCH
+ when: never
+ - if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
+ when: never
+
dast_environment_deploy:
extends: .dast-auto-deploy
stage: review
@@ -23,12 +31,7 @@ dast_environment_deploy:
artifacts:
paths: [environment_url.txt]
rules:
- - if: $CI_DEFAULT_BRANCH != $CI_COMMIT_REF_NAME
- when: never
- - if: $DAST_DISABLED || $DAST_DISABLED_FOR_DEFAULT_BRANCH
- when: never
- - if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
- when: never
+ - *common_rules
- if: $CI_COMMIT_BRANCH &&
($CI_KUBERNETES_ACTIVE || $KUBECONFIG) &&
$GITLAB_FEATURES =~ /\bdast\b/
@@ -47,13 +50,53 @@ stop_dast_environment:
action: stop
needs: ["dast"]
rules:
- - if: $CI_DEFAULT_BRANCH != $CI_COMMIT_REF_NAME
- when: never
- - if: $DAST_DISABLED || $DAST_DISABLED_FOR_DEFAULT_BRANCH
- when: never
- - if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
- when: never
+ - *common_rules
- if: $CI_COMMIT_BRANCH &&
($CI_KUBERNETES_ACTIVE || $KUBECONFIG) &&
$GITLAB_FEATURES =~ /\bdast\b/
when: always
+
+.ecs_image:
+ image: 'registry.gitlab.com/gitlab-org/cloud-deploy/aws-ecs:latest'
+
+.ecs_rules: &ecs_rules
+ - if: $AUTO_DEVOPS_PLATFORM_TARGET != "ECS"
+ when: never
+ - if: $CI_KUBERNETES_ACTIVE || $KUBECONFIG
+ when: never
+
+dast_ecs_environment_deploy:
+ extends: .ecs_image
+ stage: review
+ script:
+ - ecs update-task-definition
+ - echo "http://$(ecs get-task-hostname)" > environment_url.txt
+ environment:
+ name: dast-default
+ on_stop: stop_dast_ecs_environment
+ artifacts:
+ paths:
+ - environment_url.txt
+ rules:
+ - *common_rules
+ - *ecs_rules
+ - if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bdast\b/
+
+stop_dast_ecs_environment:
+ extends: .ecs_image
+ stage: cleanup
+ variables:
+ GIT_STRATEGY: none
+ script:
+ - ecs stop-task
+ allow_failure: true
+ environment:
+ name: dast-default
+ action: stop
+ needs:
+ - dast
+ rules:
+ - *common_rules
+ - *ecs_rules
+ - if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bdast\b/
+ when: always
diff --git a/lib/sidebars/projects/menus/monitor_menu.rb b/lib/sidebars/projects/menus/monitor_menu.rb
index 311c44f5f80..23e1a95c401 100644
--- a/lib/sidebars/projects/menus/monitor_menu.rb
+++ b/lib/sidebars/projects/menus/monitor_menu.rb
@@ -9,7 +9,6 @@ module Sidebars
return false unless context.project.feature_available?(:operations, context.current_user)
add_item(metrics_dashboard_menu_item)
- add_item(logs_menu_item)
add_item(error_tracking_menu_item)
add_item(alert_management_menu_item)
add_item(incidents_menu_item)
@@ -56,21 +55,6 @@ module Sidebars
)
end
- def logs_menu_item
- if !Feature.enabled?(:monitor_logging, context.project) ||
- !can?(context.current_user, :read_environment, context.project) ||
- !can?(context.current_user, :read_pod_logs, context.project)
- return ::Sidebars::NilMenuItem.new(item_id: :logs)
- end
-
- ::Sidebars::MenuItem.new(
- title: _('Logs'),
- link: project_logs_path(context.project),
- active_routes: { path: 'logs#index' },
- item_id: :logs
- )
- end
-
def error_tracking_menu_item
unless can?(context.current_user, :read_sentry_issue, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :error_tracking)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 258220d1366..8541420acc3 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6222,12 +6222,6 @@ msgstr ""
msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group. You can free up space for new members by removing those who no longer need access or toggling them to over-limit. To get an unlimited number of members, you can %{link_start}upgrade%{link_end} to a paid tier."
-msgstr ""
-
msgid "Bitbucket Server Import"
msgstr ""
@@ -36098,6 +36092,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Solid"
+msgstr ""
+
msgid "Solution"
msgstr ""
@@ -43551,6 +43548,9 @@ msgstr ""
msgid "Will deploy to"
msgstr ""
+msgid "Wireframe"
+msgstr ""
+
msgid "With requirements, you can set criteria to check your products against."
msgstr ""
diff --git a/package.json b/package.json
index 75e58835f6d..e33699b0402 100644
--- a/package.json
+++ b/package.json
@@ -52,8 +52,8 @@
"@babel/preset-env": "^7.18.2",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "2.21.0",
- "@gitlab/ui": "42.9.0",
+ "@gitlab/svgs": "2.22.0",
+ "@gitlab/ui": "42.11.0",
"@gitlab/visual-review-tools": "1.7.3",
"@rails/actioncable": "6.1.4-7",
"@rails/ujs": "6.1.4-7",
diff --git a/spec/features/incidents/incident_details_spec.rb b/spec/features/incidents/incident_details_spec.rb
index dad3dfd3440..7c24943eb6f 100644
--- a/spec/features/incidents/incident_details_spec.rb
+++ b/spec/features/incidents/incident_details_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Incident details', :js do
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user) }
let_it_be(:incident) { create(:incident, project: project, author: developer, description: 'description') }
+ let_it_be(:issue) { create(:issue, project: project, author: developer, description: 'Issue description') }
let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, issue: incident) }
before_all do
@@ -14,23 +15,24 @@ RSpec.describe 'Incident details', :js do
before do
sign_in(developer)
-
- visit project_issues_incident_path(project, incident)
- wait_for_requests
end
context 'when a developer+ displays the incident' do
- it 'shows the incident' do
+ before do
+ visit project_issues_incident_path(project, incident)
+ wait_for_requests
+ end
+
+ it 'shows correct elements on the page', :aggregate_failures do
+ # shows the incident
page.within('.issuable-details') do
expect(find('h1')).to have_content(incident.title)
end
- end
- it 'does not show design management' do
+ # does not show design management
expect(page).not_to have_selector('.js-design-management')
- end
- it 'shows the incident tabs' do
+ # shows the incident tabs
page.within('.issuable-details') do
incident_tabs = find('[data-testid="incident-tabs"]')
@@ -38,9 +40,8 @@ RSpec.describe 'Incident details', :js do
expect(incident_tabs).to have_content('Summary')
expect(incident_tabs).to have_content(incident.description)
end
- end
- it 'shows the right sidebar mounted with type issue' do
+ # shows the right sidebar mounted with type issue
page.within('.layout-page') do
sidebar = find('.right-sidebar')
@@ -51,12 +52,12 @@ RSpec.describe 'Incident details', :js do
end
end
- context 'escalation status' do
+ describe 'escalation status' do
let(:sidebar) { page.find('.right-sidebar') }
let(:widget) { sidebar.find('[data-testid="escalation_status_container"]') }
let(:expected_dropdown_options) { escalation_status.class::STATUSES.keys.take(3).map { |key| key.to_s.titleize } }
- it 'has an interactable escalation status widget' do
+ it 'has an interactable escalation status widget', :aggregate_failures do
expect(current_status).to have_text(escalation_status.status_name.to_s.titleize)
# list the available statuses
@@ -87,41 +88,41 @@ RSpec.describe 'Incident details', :js do
end
end
- context 'when an incident `issue_type` is edited by a signed in user' do
- it 'routes the user to the incident details page when the `issue_type` is set to incident' do
- wait_for_requests
- project_path = "/#{project.full_path}"
- click_button 'Edit title and description'
- wait_for_requests
+ it 'routes the user to the incident details page when the `issue_type` is set to incident' do
+ visit project_issue_path(project, issue)
+ wait_for_requests
+
+ project_path = "/#{project.full_path}"
+ click_button 'Edit title and description'
+ wait_for_requests
- page.within('[data-testid="issuable-form"]') do
- click_button 'Incident'
- click_button 'Issue'
- click_button 'Save changes'
+ page.within('[data-testid="issuable-form"]') do
+ click_button 'Issue'
+ click_button 'Incident'
+ click_button 'Save changes'
- wait_for_requests
+ wait_for_requests
- expect(page).to have_current_path("#{project_path}/-/issues/#{incident.iid}")
- end
+ expect(page).to have_current_path("#{project_path}/-/issues/incident/#{issue.iid}")
end
end
- context 'when incident details are edited by a signed in user' do
- it 'routes the user to the incident details page when the `issue_type` is set to incident' do
- wait_for_requests
- project_path = "/#{project.full_path}"
- click_button 'Edit title and description'
- wait_for_requests
+ it 'routes the user to the issue details page when the `issue_type` is set to issue' do
+ visit project_issues_incident_path(project, incident)
+ wait_for_requests
- page.within('[data-testid="issuable-form"]') do
- click_button 'Incident'
- click_button 'Issue'
- click_button 'Save changes'
+ project_path = "/#{project.full_path}"
+ click_button 'Edit title and description'
+ wait_for_requests
- wait_for_requests
+ page.within('[data-testid="issuable-form"]') do
+ click_button 'Incident'
+ click_button 'Issue'
+ click_button 'Save changes'
- expect(page).to have_current_path("#{project_path}/-/issues/#{incident.iid}")
- end
+ wait_for_requests
+
+ expect(page).to have_current_path("#{project_path}/-/issues/#{incident.iid}")
end
end
end
diff --git a/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap b/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
index ec5b6a5597b..4693d5a47e4 100644
--- a/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
+++ b/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
@@ -17,6 +17,7 @@ exports[`Alert integration settings form default state should match the default
<gl-form-checkbox-stub
checked="true"
data-qa-selector="create_issue_checkbox"
+ id="2"
>
<span>
Create an incident. Incidents are created for each alert triggered.
@@ -87,7 +88,9 @@ exports[`Alert integration settings form default state should match the default
labeldescription=""
optionaltext="(optional)"
>
- <gl-form-checkbox-stub>
+ <gl-form-checkbox-stub
+ id="3"
+ >
<span>
Send a single email notification to Owners and Maintainers for new alerts.
</span>
@@ -101,6 +104,7 @@ exports[`Alert integration settings form default state should match the default
>
<gl-form-checkbox-stub
checked="true"
+ id="4"
>
<span>
Automatically close associated incident when a recovery alert notification resolves an alert
diff --git a/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap b/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap
index 2691e11e616..ba8215f4e00 100644
--- a/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap
+++ b/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap
@@ -7,6 +7,7 @@ exports[`Keep latest artifact checkbox when application keep latest artifact set
<b-form-checkbox-stub
checked="true"
class="gl-form-checkbox"
+ id="4"
value="true"
>
<strong
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index 5bd69ad9fad..422dd9a463b 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -151,6 +151,38 @@ RSpec.describe Ability do
end
end
+ describe '.users_that_can_read_internal_note' do
+ shared_examples 'filtering users that can read internal note' do
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+
+ let(:users) { [reporter, guest] }
+
+ before do
+ parent.add_guest(guest)
+ parent.add_reporter(reporter)
+ end
+
+ it 'returns users that can read internal notes' do
+ result = described_class.users_that_can_read_internal_notes(users, parent)
+
+ expect(result).to match_array([reporter])
+ end
+ end
+
+ context 'for groups' do
+ it_behaves_like 'filtering users that can read internal note' do
+ let(:parent) { create(:group) }
+ end
+ end
+
+ context 'for projects' do
+ it_behaves_like 'filtering users that can read internal note' do
+ let(:parent) { create(:project) }
+ end
+ end
+ end
+
describe '.merge_requests_readable_by_user' do
context 'with an admin when admin mode is enabled', :enable_admin_mode do
it 'returns all merge requests' do
diff --git a/spec/models/concerns/participable_spec.rb b/spec/models/concerns/participable_spec.rb
index 99a3a0fb79a..b92c7c52f0b 100644
--- a/spec/models/concerns/participable_spec.rb
+++ b/spec/models/concerns/participable_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Participable do
expect(instance).to receive(:foo).and_return(user2)
expect(instance).to receive(:bar).and_return(user3)
- expect(instance).to receive(:project).twice.and_return(project)
+ expect(instance).to receive(:project).thrice.and_return(project)
participants = instance.participants(user1)
@@ -66,7 +66,7 @@ RSpec.describe Participable do
expect(instance).to receive(:foo).and_return(other)
expect(other).to receive(:bar).and_return(user2)
- expect(instance).to receive(:project).twice.and_return(project)
+ expect(instance).to receive(:project).thrice.and_return(project)
expect(instance.participants(user1)).to eq([user2])
end
@@ -86,7 +86,7 @@ RSpec.describe Participable do
instance = model.new
- expect(instance).to receive(:project).twice.and_return(project)
+ expect(instance).to receive(:project).thrice.and_return(project)
instance.participants(user1)
@@ -138,7 +138,7 @@ RSpec.describe Participable do
allow(instance).to receive_message_chain(:model_name, :element) { 'class' }
expect(instance).to receive(:foo).and_return(user2)
expect(instance).to receive(:bar).and_return(user3)
- expect(instance).to receive(:project).twice.and_return(project)
+ expect(instance).to receive(:project).thrice.and_return(project)
participants = instance.visible_participants(user1)
@@ -159,7 +159,7 @@ RSpec.describe Participable do
allow(instance).to receive_message_chain(:model_name, :element) { 'class' }
allow(instance).to receive(:bar).and_return(user2)
- expect(instance).to receive(:project).twice.and_return(project)
+ expect(instance).to receive(:project).thrice.and_return(project)
expect(instance.visible_participants(user1)).to be_empty
end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index d45a23a7ef8..9f864afc213 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -744,25 +744,11 @@ RSpec.describe Issue do
end
describe '#participants' do
- context 'using a public project' do
- let_it_be(:public_project) { create(:project, :public) }
- let_it_be(:issue) { create(:issue, project: public_project) }
-
- let!(:note1) do
- create(:note_on_issue, noteable: issue, project: public_project, note: 'a')
- end
-
- let!(:note2) do
- create(:note_on_issue, noteable: issue, project: public_project, note: 'b')
- end
-
- it 'includes the issue author' do
- expect(issue.participants).to include(issue.author)
- end
+ it_behaves_like 'issuable participants' do
+ let_it_be(:issuable_parent) { create(:project, :public) }
+ let_it_be_with_refind(:issuable) { create(:issue, project: issuable_parent) }
- it 'includes the authors of the notes' do
- expect(issue.participants).to include(note1.author, note2.author)
- end
+ let(:params) { { noteable: issuable, project: issuable_parent } }
end
context 'using a private project' do
diff --git a/spec/models/work_item_spec.rb b/spec/models/work_item_spec.rb
index d49c7452421..f3874155dd1 100644
--- a/spec/models/work_item_spec.rb
+++ b/spec/models/work_item_spec.rb
@@ -39,7 +39,8 @@ RSpec.describe WorkItem do
it 'returns instances of supported widgets' do
is_expected.to match_array([instance_of(WorkItems::Widgets::Description),
instance_of(WorkItems::Widgets::Hierarchy),
- instance_of(WorkItems::Widgets::Assignees)])
+ instance_of(WorkItems::Widgets::Assignees),
+ instance_of(WorkItems::Widgets::Weight)])
end
end
diff --git a/spec/models/work_items/type_spec.rb b/spec/models/work_items/type_spec.rb
index 342c1eb5f50..e91617effc0 100644
--- a/spec/models/work_items/type_spec.rb
+++ b/spec/models/work_items/type_spec.rb
@@ -66,7 +66,8 @@ RSpec.describe WorkItems::Type do
it 'returns list of all possible widgets' do
is_expected.to match_array([::WorkItems::Widgets::Description,
::WorkItems::Widgets::Hierarchy,
- ::WorkItems::Widgets::Assignees])
+ ::WorkItems::Widgets::Assignees,
+ ::WorkItems::Widgets::Weight])
end
end
diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
index 7a160819a41..8e801eec74d 100644
--- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
@@ -113,5 +113,29 @@ RSpec.describe 'Update a work item' do
end
end
end
+
+ context 'with weight widget input' do
+ let(:fields) do
+ <<~FIELDS
+ workItem {
+ widgets {
+ type
+ ... on WorkItemWidgetWeight {
+ weight
+ }
+ }
+ }
+ errors
+ FIELDS
+ end
+
+ it_behaves_like 'update work item weight widget' do
+ let(:new_weight) { 2 }
+
+ let(:input) do
+ { 'weightWidget' => { 'weight' => new_weight } }
+ end
+ end
+ end
end
end
diff --git a/spec/requests/api/graphql/work_item_spec.rb b/spec/requests/api/graphql/work_item_spec.rb
index a7edfc6ee2d..70fa8100411 100644
--- a/spec/requests/api/graphql/work_item_spec.rb
+++ b/spec/requests/api/graphql/work_item_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Query.work_item(id)' do
let_it_be(:developer) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:project) { create(:project, :private) }
- let_it_be(:work_item) { create(:work_item, project: project, description: '- List item') }
+ let_it_be(:work_item) { create(:work_item, project: project, description: '- List item', weight: 1) }
let_it_be(:child_item1) { create(:work_item, :task, project: project) }
let_it_be(:child_item2) { create(:work_item, :task, confidential: true, project: project) }
let_it_be(:child_link1) { create(:parent_link, work_item_parent: work_item, work_item: child_item1) }
@@ -163,6 +163,32 @@ RSpec.describe 'Query.work_item(id)' do
end
end
+ describe 'weight widget' do
+ let(:work_item_fields) do
+ <<~GRAPHQL
+ id
+ widgets {
+ type
+ ... on WorkItemWidgetWeight {
+ weight
+ }
+ }
+ GRAPHQL
+ end
+
+ it 'returns widget information' do
+ expect(work_item_data).to include(
+ 'id' => work_item.to_gid.to_s,
+ 'widgets' => include(
+ hash_including(
+ 'type' => 'WEIGHT',
+ 'weight' => work_item.weight
+ )
+ )
+ )
+ end
+ end
+
describe 'assignees widget' do
let(:assignees) { create_list(:user, 2) }
let(:work_item) { create(:work_item, project: project, assignees: assignees) }
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 032f35cfc29..8e0f964d965 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -147,6 +147,34 @@ RSpec.describe NotificationService, :mailer do
end
end
+ shared_examples 'participating by confidential note notification' do
+ context 'when user is mentioned on confidential note' do
+ let_it_be(:guest_1) { create(:user) }
+ let_it_be(:guest_2) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+
+ before do
+ issuable.resource_parent.add_guest(guest_1)
+ issuable.resource_parent.add_guest(guest_2)
+ issuable.resource_parent.add_reporter(reporter)
+ end
+
+ it 'only emails authorized users' do
+ confidential_note_text = "#{guest_1.to_reference} and #{guest_2.to_reference} and #{reporter.to_reference}"
+ note_text = "Mentions #{guest_2.to_reference}"
+ create(:note_on_issue, noteable: issuable, project_id: project.id, note: confidential_note_text, confidential: true)
+ create(:note_on_issue, noteable: issuable, project_id: project.id, note: note_text)
+ reset_delivered_emails!
+
+ notification_trigger
+
+ should_not_email(guest_1)
+ should_email(guest_2)
+ should_email(reporter)
+ end
+ end
+ end
+
shared_examples 'participating by assignee notification' do
it 'emails the participant' do
issuable.assignees << participant
@@ -736,6 +764,20 @@ RSpec.describe NotificationService, :mailer do
let(:notification_target) { note }
let(:notification_trigger) { notification.new_note(note) }
end
+
+ context 'when note is confidential' do
+ let(:note) { create(:note_on_issue, author: author, noteable: issue, project_id: issue.project_id, note: '@all mentioned', confidential: true) }
+ let(:guest) { create(:user) }
+
+ it 'does not notify users that cannot read note' do
+ project.add_guest(guest)
+ reset_delivered_emails!
+
+ notification.new_note(note)
+
+ should_not_email(guest)
+ end
+ end
end
end
@@ -1376,6 +1418,11 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.reassigned_issue(issue, @u_disabled, [assignee]) }
end
+ it_behaves_like 'participating by confidential note notification' do
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.reassigned_issue(issue, @u_disabled, [assignee]) }
+ end
+
it_behaves_like 'project emails are disabled' do
let(:notification_target) { issue }
let(:notification_trigger) { notification.reassigned_issue(issue, @u_disabled, [assignee]) }
@@ -1494,6 +1541,11 @@ RSpec.describe NotificationService, :mailer do
let(:notification_target) { issue }
let(:notification_trigger) { notification.removed_milestone_issue(issue, issue.author) }
end
+
+ it_behaves_like 'participating by confidential note notification' do
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.removed_milestone_issue(issue, issue.author) }
+ end
end
context 'confidential issues' do
@@ -1616,6 +1668,11 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.close_issue(issue, @u_disabled) }
end
+ it_behaves_like 'participating by confidential note notification' do
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.close_issue(issue, @u_disabled) }
+ end
+
it 'adds "subscribed" reason to subscriber emails' do
user_1 = create(:user)
issue.subscribe(user_1)
@@ -1658,6 +1715,11 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.reopen_issue(issue, @u_disabled) }
end
+ it_behaves_like 'participating by confidential note notification' do
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.reopen_issue(issue, @u_disabled) }
+ end
+
it_behaves_like 'project emails are disabled' do
let(:notification_target) { issue }
let(:notification_trigger) { notification.reopen_issue(issue, @u_disabled) }
@@ -1689,6 +1751,11 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.issue_moved(issue, new_issue, @u_disabled) }
end
+ it_behaves_like 'participating by confidential note notification' do
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.issue_moved(issue, new_issue, @u_disabled) }
+ end
+
it_behaves_like 'project emails are disabled' do
let(:notification_target) { issue }
let(:notification_trigger) { notification.issue_moved(issue, new_issue, @u_disabled) }
@@ -1720,6 +1787,11 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.issue_cloned(issue, new_issue, @u_disabled) }
end
+ it_behaves_like 'participating by confidential note notification' do
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.issue_cloned(issue, new_issue, @u_disabled) }
+ end
+
it_behaves_like 'project emails are disabled' do
let(:notification_target) { issue }
let(:notification_trigger) { notification.issue_cloned(issue, new_issue, @u_disabled) }
@@ -1765,6 +1837,11 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.issue_due(issue) }
end
+ it_behaves_like 'participating by confidential note notification' do
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.issue_due(issue) }
+ end
+
it_behaves_like 'project emails are disabled' do
let(:notification_target) { issue }
let(:notification_trigger) { notification.issue_due(issue) }
diff --git a/spec/services/work_items/widgets/weight_service/update_service_spec.rb b/spec/services/work_items/widgets/weight_service/update_service_spec.rb
new file mode 100644
index 00000000000..97e17f1c526
--- /dev/null
+++ b/spec/services/work_items/widgets/weight_service/update_service_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::Widgets::WeightService::UpdateService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:work_item) { create(:work_item, project: project, weight: 1) }
+
+ let(:widget) { work_item.widgets.find {|widget| widget.is_a?(WorkItems::Widgets::Weight) } }
+
+ describe '#update' do
+ subject { described_class.new(widget: widget, current_user: user).update(params: params) } # rubocop:disable Rails/SaveBang
+
+ context 'when weight param is present' do
+ let(:params) { { weight: 2 } }
+
+ it 'correctly sets work item weight value' do
+ subject
+
+ expect(work_item.weight).to eq(2)
+ end
+ end
+
+ context 'when weight param is not present' do
+ let(:params) { {} }
+
+ it 'does not change work item weight value', :aggregate_failures do
+ expect { subject }
+ .to not_change { work_item.weight }
+
+ expect(work_item.weight).to eq(1)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 50e6d4aad1b..b523af385f4 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -83,7 +83,6 @@ RSpec.shared_context 'project navbar structure' do
nav_item: _('Monitor'),
nav_sub_items: [
_('Metrics'),
- _('Logs'),
_('Error Tracking'),
_('Alerts'),
_('Incidents'),
diff --git a/spec/support/shared_examples/graphql/mutations/work_items/update_weight_widget_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/work_items/update_weight_widget_shared_examples.rb
new file mode 100644
index 00000000000..3c32b7e0310
--- /dev/null
+++ b/spec/support/shared_examples/graphql/mutations/work_items/update_weight_widget_shared_examples.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'update work item weight widget' do
+ it 'updates the weight widget' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :weight).from(nil).to(new_weight)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']['widgets']).to include(
+ {
+ 'weight' => new_weight,
+ 'type' => 'WEIGHT'
+ }
+ )
+ end
+
+ context 'when the updated work item is not valid' do
+ it 'returns validation errors without the work item' do
+ errors = ActiveModel::Errors.new(work_item).tap { |e| e.add(:weight, 'error message') }
+
+ allow_next_found_instance_of(::WorkItem) do |instance|
+ allow(instance).to receive(:valid?).and_return(false)
+ allow(instance).to receive(:errors).and_return(errors)
+ end
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(mutation_response['workItem']).to be_nil
+ expect(mutation_response['errors']).to match_array(['Weight error message'])
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/issuable_participants_shared_examples.rb b/spec/support/shared_examples/models/issuable_participants_shared_examples.rb
new file mode 100644
index 00000000000..c3eaae0ace2
--- /dev/null
+++ b/spec/support/shared_examples/models/issuable_participants_shared_examples.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'issuable participants' do
+ context 'when resource parent is public' do
+ context 'and users are referenced on notes' do
+ let_it_be(:notes_author) { create(:user) }
+
+ let(:note_params) { params.merge(author: notes_author) }
+
+ before do
+ create(:note, note_params)
+ end
+
+ it 'includes the issue author' do
+ expect(issuable.participants).to include(issuable.author)
+ end
+
+ it 'includes the authors of the notes' do
+ expect(issuable.participants).to include(notes_author)
+ end
+
+ context 'and note is confidential' do
+ context 'and mentions users' do
+ let_it_be(:guest_1) { create(:user) }
+ let_it_be(:guest_2) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+
+ before do
+ issuable_parent.add_guest(guest_1)
+ issuable_parent.add_guest(guest_2)
+ issuable_parent.add_reporter(reporter)
+
+ confidential_note_params =
+ note_params.merge(
+ confidential: true,
+ note: "mentions #{guest_1.to_reference} and #{guest_2.to_reference} and #{reporter.to_reference}"
+ )
+
+ regular_note_params =
+ note_params.merge(note: "Mentions #{guest_2.to_reference}")
+
+ create(:note, confidential_note_params)
+ create(:note, regular_note_params)
+ end
+
+ it 'only includes users that can read the note as participants' do
+ expect(issuable.participants).to contain_exactly(issuable.author, notes_author, reporter, guest_2)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/mentionable_shared_examples.rb b/spec/support/shared_examples/models/mentionable_shared_examples.rb
index e23658d1774..f9612dd61be 100644
--- a/spec/support/shared_examples/models/mentionable_shared_examples.rb
+++ b/spec/support/shared_examples/models/mentionable_shared_examples.rb
@@ -260,6 +260,25 @@ RSpec.shared_examples 'mentions in notes' do |mentionable_type|
expect(mentionable.referenced_projects(user)).to eq [mentionable.project].compact # epic.project is nil, and we want empty []
expect(mentionable.referenced_groups(user)).to eq [group]
end
+
+ if [:epic, :issue].include?(mentionable_type)
+ context 'and note is confidential' do
+ let_it_be(:guest) { create(:user) }
+
+ let(:note_desc) { "#{guest.to_reference} and #{user2.to_reference} and #{user.to_reference}" }
+
+ before do
+ note.resource_parent.add_reporter(user2)
+ note.resource_parent.add_guest(guest)
+ # Bypass :confidential update model validation for testing purposes
+ note.update_attribute(:confidential, true)
+ end
+
+ it 'returns only mentioned users that has permissions' do
+ expect(note.mentioned_users).to contain_exactly(user, user2)
+ end
+ end
+ end
end
end
@@ -294,6 +313,26 @@ RSpec.shared_examples 'load mentions from DB' do |mentionable_type|
end
end
+ if [:epic, :issue].include?(mentionable_type)
+ context 'and note is confidential' do
+ let_it_be(:guest) { create(:user) }
+
+ let(:note_desc) { "#{guest.to_reference} and #{mentioned_user.to_reference}" }
+
+ before do
+ note.resource_parent.add_reporter(mentioned_user)
+ note.resource_parent.add_guest(guest)
+ # Bypass :confidential update model validation for testing purposes
+ note.update_attribute(:confidential, true)
+ note.store_mentions!
+ end
+
+ it 'stores only mentioned users that has permissions' do
+ expect(mentionable.referenced_users).to contain_exactly(mentioned_user)
+ end
+ end
+ end
+
context 'when private projects and groups are mentioned' do
let(:mega_user) { create(:user) }
let(:private_project) { create(:project, :private) }
diff --git a/vendor/gems/omniauth-gitlab/.gitignore b/vendor/gems/omniauth-gitlab/.gitignore
new file mode 100644
index 00000000000..062d4acf0a9
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/.gitignore
@@ -0,0 +1,17 @@
+*.gem
+*.rbc
+.bundle
+.config
+.yardoc
+.rvmrc
+InstalledFiles
+_yardoc
+coverage
+doc/
+lib/bundler/man
+pkg
+rdoc
+spec/reports
+test/tmp
+test/version_tmp
+tmp
diff --git a/vendor/gems/omniauth-gitlab/.gitlab-ci.yml b/vendor/gems/omniauth-gitlab/.gitlab-ci.yml
new file mode 100644
index 00000000000..ad9545e2998
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/.gitlab-ci.yml
@@ -0,0 +1,30 @@
+workflow:
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
+
+.rspec:
+ cache:
+ key: omniauth-gitlab-ruby
+ paths:
+ - vendor/gems/omniauth-gitlab/vendor/ruby
+ before_script:
+ - cd vendor/gems/omniauth-gitlab
+ - ruby -v # Print out ruby version for debugging
+ - gem install bundler --no-document # Bundler is not installed with the image
+ - bundle config set --local path 'vendor' # Install dependencies into ./vendor/ruby
+ - bundle config set with 'development'
+ - bundle install -j $(nproc)
+ script:
+ - bundle exec rspec
+
+rspec-2.6:
+ image: "ruby:2.6"
+ extends: .rspec
+
+rspec-2.7:
+ image: "ruby:2.7"
+ extends: .rspec
+
+rspec-3.0:
+ image: "ruby:3.0"
+ extends: .rspec \ No newline at end of file
diff --git a/vendor/gems/omniauth-gitlab/Gemfile b/vendor/gems/omniauth-gitlab/Gemfile
new file mode 100644
index 00000000000..ad0c84b6ac8
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/Gemfile
@@ -0,0 +1,4 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in omniauth-gitlab.gemspec
+gemspec
diff --git a/vendor/gems/omniauth-gitlab/Gemfile.lock b/vendor/gems/omniauth-gitlab/Gemfile.lock
new file mode 100644
index 00000000000..b5979104080
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/Gemfile.lock
@@ -0,0 +1,73 @@
+PATH
+ remote: .
+ specs:
+ omniauth-gitlab (4.0.0)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.7.1)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ diff-lcs (1.5.0)
+ docile (1.4.0)
+ faraday (2.3.0)
+ faraday-net_http (~> 2.0)
+ ruby2_keywords (>= 0.0.4)
+ faraday-net_http (2.0.3)
+ hashie (5.0.0)
+ jwt (2.4.1)
+ multi_xml (0.6.0)
+ oauth2 (2.0.1)
+ faraday (>= 0.17.3, < 3.0)
+ jwt (>= 1.0, < 3.0)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 3)
+ rash_alt (>= 0.4, < 1)
+ version_gem (~> 1.0)
+ omniauth (1.9.1)
+ hashie (>= 3.4.6)
+ rack (>= 1.6.2, < 3)
+ omniauth-oauth2 (1.7.3)
+ oauth2 (>= 1.4, < 3)
+ omniauth (>= 1.9, < 3)
+ rack (2.2.3.1)
+ rake (13.0.6)
+ rash_alt (0.4.12)
+ hashie (>= 3.4)
+ rspec (3.11.0)
+ rspec-core (~> 3.11.0)
+ rspec-expectations (~> 3.11.0)
+ rspec-mocks (~> 3.11.0)
+ rspec-core (3.11.0)
+ rspec-support (~> 3.11.0)
+ rspec-expectations (3.11.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.11.0)
+ rspec-its (1.3.0)
+ rspec-core (>= 3.0.0)
+ rspec-expectations (>= 3.0.0)
+ rspec-mocks (3.11.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.11.0)
+ rspec-support (3.11.0)
+ ruby2_keywords (0.0.5)
+ simplecov (0.21.2)
+ docile (~> 1.1)
+ simplecov-html (~> 0.11)
+ simplecov_json_formatter (~> 0.1)
+ simplecov-html (0.12.3)
+ simplecov_json_formatter (0.1.4)
+ version_gem (1.0.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ omniauth-gitlab!
+ rake (>= 12.0)
+ rspec (~> 3.1)
+ rspec-its (~> 1.0)
+ simplecov
+
+BUNDLED WITH
+ 2.3.15
diff --git a/vendor/gems/omniauth-gitlab/LICENSE.txt b/vendor/gems/omniauth-gitlab/LICENSE.txt
new file mode 100644
index 00000000000..ccdae5ea15c
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2013 ssein
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/vendor/gems/omniauth-gitlab/README.md b/vendor/gems/omniauth-gitlab/README.md
new file mode 100644
index 00000000000..f22f14266f6
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/README.md
@@ -0,0 +1,94 @@
+# Omniauth::Gitlab
+
+This is fork of [omniauth-gitlab](https://github.com/linchus/omniauth-gitlab) to support:
+
+1. OmniAuth v1 and v2. OmniAuth v2 disables GET requests by default
+ and defaults to POST. GitLab already has patched v1 to use POST,
+ but other dependencies need to be updated:
+ https://gitlab.com/gitlab-org/gitlab/-/issues/30073.
+
+2. [`oauth2`](https://github.com/oauth-xx/oauth2) v1.4.9 and up.
+ [v1.4.9 fixed relative URL handling](https://github.com/oauth-xx/oauth2/pull/469).
+
+ However, this breaks the default GitLab.com configuration and
+ existing configurations that use the `/api/v4` suffix in the `site`
+ parameter.
+ [omniauth-gitlab v4.0.0 fixed the first issue](https://github.com/linchus/omniauth-gitlab/pull/22),
+ but the second issue requires an admin to update `site` to drop the suffix.
+
+ This fork restores backwards compatibility that was removed in omniauth-gitlab v2.0.0:
+ https://github.com/linchus/omniauth-gitlab/commit/bb4cec2c9f8f067fdfe1f9aa219973e5d8e4a0a3
+
+[![Join the chat at https://gitter.im/linchus/omniauth-gitlab](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/linchus/omniauth-gitlab?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+This is the OAuth2 strategy for authenticating to your GitLab service.
+
+## Requirements
+
+Gitlab 7.7.0+
+
+## Installation
+
+Add this line to your application's Gemfile:
+
+ gem 'omniauth-gitlab'
+
+And then execute:
+
+ $ bundle
+
+Or install it yourself as:
+
+ $ gem install omniauth-gitlab
+
+## Basic Usage
+
+ use OmniAuth::Builder do
+ provider :gitlab, ENV['GITLAB_KEY'], ENV['GITLAB_SECRET']
+ end
+
+## Standalone Usage
+
+ use OmniAuth::Builder do
+ provider :gitlab, ENV['GITLAB_KEY'], ENV['GITLAB_SECRET'],
+ {
+ client_options: {
+ site: 'https://gitlab.YOURDOMAIN.com/api/v4'
+ }
+ }
+ end
+
+## Custom scopes
+
+By default, the `api` scope is requested and must be allowed in GitLab's application configuration. To use different scopes:
+
+ use OmniAuth::Builder do
+ provider :gitlab, ENV['GITLAB_KEY'], ENV['GITLAB_SECRET'], scope: 'read_user openid'
+ end
+
+Requesting a scope that is not configured will result the error "The requested scope is invalid, unknown, or malformed.".
+
+## Old API version
+
+API V3 will be unsupported from GitLab 9.5 and will be removed in GitLab 9.5 or later.
+
+[https://gitlab.com/help/api/v3_to_v4.md](https://gitlab.com/help/api/v3_to_v4.md)
+
+If you use GitLab 9.0 and below you could configure V3 API:
+
+ use OmniAuth::Builder do
+ provider :gitlab, ENV['GITLAB_KEY'], ENV['GITLAB_SECRET'],
+ {
+ client_options: {
+ site: 'https://gitlab.YOURDOMAIN.com/api/v3'
+ }
+ }
+ end
+
+## Contributing
+
+1. Fork it
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Commit your changes (`git commit -am 'Add some feature'`)
+4. Push to the branch (`git push origin my-new-feature`)
+5. Create new Pull Request
diff --git a/vendor/gems/omniauth-gitlab/Rakefile b/vendor/gems/omniauth-gitlab/Rakefile
new file mode 100644
index 00000000000..db953c9a1c5
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/Rakefile
@@ -0,0 +1,7 @@
+require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new
+
+desc 'Run specs'
+task default: :spec
diff --git a/vendor/gems/omniauth-gitlab/lib/omniauth-gitlab.rb b/vendor/gems/omniauth-gitlab/lib/omniauth-gitlab.rb
new file mode 100644
index 00000000000..dfe9d2131c9
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/lib/omniauth-gitlab.rb
@@ -0,0 +1,2 @@
+require 'omniauth-gitlab/version'
+require 'omniauth/strategies/gitlab'
diff --git a/vendor/gems/omniauth-gitlab/lib/omniauth-gitlab/version.rb b/vendor/gems/omniauth-gitlab/lib/omniauth-gitlab/version.rb
new file mode 100644
index 00000000000..6465d4ca199
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/lib/omniauth-gitlab/version.rb
@@ -0,0 +1,5 @@
+module Omniauth
+ module Gitlab
+ VERSION = '4.0.0'
+ end
+end
diff --git a/vendor/gems/omniauth-gitlab/lib/omniauth/strategies/gitlab.rb b/vendor/gems/omniauth-gitlab/lib/omniauth/strategies/gitlab.rb
new file mode 100644
index 00000000000..19ee02e78c4
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/lib/omniauth/strategies/gitlab.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'omniauth-oauth2'
+
+module OmniAuth
+ module Strategies
+ class GitLab < OmniAuth::Strategies::OAuth2
+ API_SUFFIX_REGEX = %r{/api/v(\d+)/?$}.freeze
+
+ option :client_options, site: 'https://gitlab.com'
+
+ option :redirect_url
+
+ uid { raw_info['id'].to_s }
+
+ info do
+ {
+ name: raw_info['name'],
+ username: raw_info['username'],
+ email: raw_info['email'],
+ image: raw_info['avatar_url']
+ }
+ end
+
+ extra do
+ { raw_info: raw_info }
+ end
+
+ def raw_info
+ @raw_info ||= access_token.get(user_endpoint_url).parsed
+ end
+
+ private
+
+ def user_endpoint_url
+ options.client_options.site.match(API_SUFFIX_REGEX) ? 'user' : 'api/v4/user'
+ end
+
+ def callback_url
+ options.redirect_url || (full_host + script_name + callback_path)
+ end
+ end
+ end
+end
+
+OmniAuth.config.add_camelization 'gitlab', 'GitLab'
diff --git a/vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec b/vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec
new file mode 100644
index 00000000000..be25cb50af6
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require 'omniauth-gitlab/version'
+
+Gem::Specification.new do |gem|
+ gem.name = 'omniauth-gitlab'
+ gem.version = Omniauth::Gitlab::VERSION
+ gem.authors = ['Sergey Sein']
+ gem.email = ['linchus@gmail.com']
+ gem.description = 'This is the strategy for authenticating to your GitLab service'
+ gem.summary = 'This is the strategy for authenticating to your GitLab service'
+ gem.homepage = 'https://github.com/linchus/omniauth-gitlab'
+
+ gem.files = Dir['lib/**/*.rb']
+ gem.test_files = Dir['spec/**/*.rb']
+ gem.require_paths = ['lib']
+
+ gem.add_dependency 'omniauth', '~> 1.0'
+ gem.add_dependency 'omniauth-oauth2', '~> 1.7.1'
+ gem.add_development_dependency 'rspec', '~> 3.1'
+ gem.add_development_dependency 'rspec-its', '~> 1.0'
+ gem.add_development_dependency 'simplecov'
+ gem.add_development_dependency 'rake', '>= 12.0'
+end
diff --git a/vendor/gems/omniauth-gitlab/spec/omniauth/strategies/gitlab_spec.rb b/vendor/gems/omniauth-gitlab/spec/omniauth/strategies/gitlab_spec.rb
new file mode 100644
index 00000000000..a599386b26c
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/spec/omniauth/strategies/gitlab_spec.rb
@@ -0,0 +1,80 @@
+require 'spec_helper'
+
+describe OmniAuth::Strategies::GitLab do
+ let(:access_token) { double('AccessToken') }
+ let(:parsed_response) { double('ParsedResponse') }
+ let(:response) { double('Response', parsed: parsed_response) }
+
+ let(:enterprise_site) { 'https://some.other.site.com' }
+
+ let(:gitlab_service) { OmniAuth::Strategies::GitLab.new({}) }
+ let(:enterprise) do
+ OmniAuth::Strategies::GitLab.new(
+ 'GITLAB_KEY',
+ 'GITLAB_SECRET',
+ client_options: { site: enterprise_site },
+ redirect_url: 'http://localhost:9292/callback_url'
+ )
+ end
+
+ subject { gitlab_service }
+
+ before(:each) do
+ allow(subject).to receive(:access_token).and_return(access_token)
+ end
+
+ describe 'client options' do
+ context 'with defaults' do
+ subject { gitlab_service.options.client_options }
+
+ its(:site) { is_expected.to eq 'https://gitlab.com' }
+ end
+
+ context 'with override' do
+ subject { enterprise.options.client_options }
+
+ its(:site) { is_expected.to eq enterprise_site }
+ end
+ end
+
+ describe 'redirect_url' do
+ context 'with defaults' do
+ subject { gitlab_service.options }
+ its(:redirect_url) { is_expected.to be_nil }
+ end
+
+ context 'with customs' do
+ subject { enterprise.options }
+ its(:redirect_url) { is_expected.to eq 'http://localhost:9292/callback_url' }
+ end
+ end
+
+ describe '#raw_info' do
+ context 'with new configuration' do
+ it 'sent request to current user endpoint' do
+ expect(access_token).to receive(:get).with('api/v4/user').and_return(response)
+ expect(subject.raw_info).to eq(parsed_response)
+ end
+ end
+
+ context 'with old style configuration' do
+ let(:enterprise_site) { 'https://some.other.site.com/api/v4' }
+
+ subject { enterprise }
+
+ it 'sent request to current user endpoint' do
+ expect(access_token).to receive(:get).with('user').and_return(response)
+ expect(subject.raw_info).to eq(parsed_response)
+ end
+
+ context 'with a trailing slash' do
+ let(:enterprise_site) { 'https://some.other.site.com/api/v4/' }
+
+ it 'sent request to current user endpoint' do
+ expect(access_token).to receive(:get).with('user').and_return(response)
+ expect(subject.raw_info).to eq(parsed_response)
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/gems/omniauth-gitlab/spec/spec_helper.rb b/vendor/gems/omniauth-gitlab/spec/spec_helper.rb
new file mode 100644
index 00000000000..38553547e98
--- /dev/null
+++ b/vendor/gems/omniauth-gitlab/spec/spec_helper.rb
@@ -0,0 +1,8 @@
+$LOAD_PATH.unshift File.expand_path('..', __FILE__)
+$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
+require 'simplecov'
+SimpleCov.start
+require 'rspec'
+require 'rspec/its'
+require 'omniauth'
+require 'omniauth-gitlab'
diff --git a/yarn.lock b/yarn.lock
index 60129b671c9..e5b5cf166ca 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1048,15 +1048,15 @@
stylelint-declaration-strict-value "1.8.0"
stylelint-scss "4.2.0"
-"@gitlab/svgs@2.21.0":
- version "2.21.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.21.0.tgz#bc71951dc35a61647fb2c0267cca6fb55a04d317"
- integrity sha512-cVa5cgvVmY2MsRdV61id+rLTsY/tAGPq7Og9ETblUuZXl06ciw8H/g7cYPMxN39DdEfDklzbUnS98OJlMmD9TQ==
-
-"@gitlab/ui@42.9.0":
- version "42.9.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-42.9.0.tgz#506a642b9bef9eb5d363684c8ef81129a9b284ef"
- integrity sha512-i575fmHOXYPGWdaaSqt7cdgpfhPvnbIwhavslgbj9g9LNzffH7fea4P6BobKakb1AZuOfahJfarqfOJ2pYuRSQ==
+"@gitlab/svgs@2.22.0":
+ version "2.22.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.22.0.tgz#66211ba26418b8dfb3ac796d795a0e3392d22ada"
+ integrity sha512-9Es97o/VByIsCNNfSF28oTYW5XIJ2dZSK0YjSpyy5yBF0QPwEjzRhxapYGz2c8YBFVC9WkoGHjp5PJ9tJgmmuA==
+
+"@gitlab/ui@42.11.0":
+ version "42.11.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-42.11.0.tgz#68b1cca7414a9f8e6d7e18ab8325daac000588f8"
+ integrity sha512-IxawSvXyL4ysvriOcQ+2TpdEzZxDumj9H/K3MTxmvKYtrFEygNE7wCPasQa3/jxmdfn6sYuPDHVg1tk1ziXyVQ==
dependencies:
"@popperjs/core" "^2.11.2"
bootstrap-vue "2.20.1"