diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json index 81b0fad47a0408d0f65562f282808ca1394affe9..d72ad6694340939e43c6c3103d42f6f4858e82ea 100644 --- a/app/assets/javascripts/graphql_shared/possible_types.json +++ b/app/assets/javascripts/graphql_shared/possible_types.json @@ -179,6 +179,7 @@ "MergeRequest", "Namespace", "Project", + "Vulnerability", "WorkItem" ], "User": [ diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 933910880c5517675d559baf299496b17800a70b..9d39ad712e792c218b6e5100af18b73363ad8702 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -34399,6 +34399,7 @@ Represents a vulnerability. | <a id="vulnerabilitylinks"></a>`links` | [`[VulnerabilityLink!]!`](#vulnerabilitylink) | List of links associated with the vulnerability. | | <a id="vulnerabilitylocation"></a>`location` | [`VulnerabilityLocation`](#vulnerabilitylocation) | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability. | | <a id="vulnerabilitymergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request that fixes the vulnerability. | +| <a id="vulnerabilityname"></a>`name` | [`String`](#string) | Name or title of this object. | | <a id="vulnerabilitypresentondefaultbranch"></a>`presentOnDefaultBranch` | [`Boolean!`](#boolean) | Indicates whether the vulnerability is present on the default branch or not. | | <a id="vulnerabilityprimaryidentifier"></a>`primaryIdentifier` | [`VulnerabilityIdentifier`](#vulnerabilityidentifier) | Primary identifier of the vulnerability. | | <a id="vulnerabilityproject"></a>`project` | [`Project`](#project) | Project on which the vulnerability was found. | @@ -38672,6 +38673,7 @@ Sort options for todos. | <a id="todotargetenummergerequest"></a>`MERGEREQUEST` | Merge request. | | <a id="todotargetenumnamespace"></a>`NAMESPACE` | Namespace. | | <a id="todotargetenumproject"></a>`PROJECT` | Project. | +| <a id="todotargetenumvulnerability"></a>`VULNERABILITY` | Vulnerability. | | <a id="todotargetenumworkitem"></a>`WORKITEM` | Work item. | ### `TrainingUrlRequestStatus` @@ -40855,6 +40857,7 @@ Implementations: - [`MergeRequest`](#mergerequest) - [`Namespace`](#namespace) - [`Project`](#project) +- [`Vulnerability`](#vulnerability) - [`WorkItem`](#workitem) ##### Fields diff --git a/doc/api/todos.md b/doc/api/todos.md index bd49128f1873ee47372d8f4333813db6417f1e60..f84084c8a986f1af773c4d223bba468eb6708f1e 100644 --- a/doc/api/todos.md +++ b/doc/api/todos.md @@ -31,7 +31,7 @@ Parameters: | `project_id` | integer | no | The ID of a project | | `group_id` | integer | no | The ID of a group | | `state` | string | no | The state of the to-do item. Can be either `pending` or `done` | -| `type` | string | no | The type of to-do item. Can be either `Issue`, `MergeRequest`, `Commit`, `Epic`, `DesignManagement::Design` or `AlertManagement::Alert` | +| `type` | string | no | The type of to-do item. Can be either `Issue`, `MergeRequest`, `Commit`, `Epic`, `DesignManagement::Design`, `AlertManagement::Alert`, `Project`, `Namespace` or `Vulnerability` | ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/todos" diff --git a/ee/app/finders/ee/todos_finder.rb b/ee/app/finders/ee/todos_finder.rb index eece83c6e97965f4b4a2089d6ff09c4e9cadbd52..25f0af4a4b5bf63c995571c6bc4cca1019adccf2 100644 --- a/ee/app/finders/ee/todos_finder.rb +++ b/ee/app/finders/ee/todos_finder.rb @@ -4,7 +4,7 @@ module EE module TodosFinder extend ActiveSupport::Concern - EE_TODO_TYPES = (::TodosFinder::TODO_TYPES + %w[Epic]).freeze + EE_TODO_TYPES = (::TodosFinder::TODO_TYPES + %w[Epic Vulnerability]).freeze class_methods do extend ::Gitlab::Utils::Override diff --git a/ee/app/graphql/ee/types/todo_target_enum.rb b/ee/app/graphql/ee/types/todo_target_enum.rb index 6f3ff5926ebceae4f5942eac01e7d0b7a05d33e7..52422d2e448ad230d2463c092a9a2ec606026541 100644 --- a/ee/app/graphql/ee/types/todo_target_enum.rb +++ b/ee/app/graphql/ee/types/todo_target_enum.rb @@ -7,6 +7,7 @@ module TodoTargetEnum prepended do value 'EPIC', value: 'Epic', description: 'An Epic.' + value 'VULNERABILITY', value: 'Vulnerability', description: 'Vulnerability.' end end end diff --git a/ee/app/graphql/ee/types/todoable_interface.rb b/ee/app/graphql/ee/types/todoable_interface.rb index dcf3480c61246a6f8fda463302608f8d54fa9fe1..ea46754e16c15e2870f835931ef23f728e2ab23e 100644 --- a/ee/app/graphql/ee/types/todoable_interface.rb +++ b/ee/app/graphql/ee/types/todoable_interface.rb @@ -10,9 +10,14 @@ module TodoableInterface override :resolve_type def resolve_type(object, *) - return ::Types::EpicType if Epic === object - - super + case object + when Epic + ::Types::EpicType + when Vulnerability + ::Types::VulnerabilityType + else + super + end end end end diff --git a/ee/app/graphql/types/vulnerability_type.rb b/ee/app/graphql/types/vulnerability_type.rb index 12c4e0d77c53142464eec53a199adc1c4b41cdd0..286017e16170540cf4d70dd05097a25d4ecc309b 100644 --- a/ee/app/graphql/types/vulnerability_type.rb +++ b/ee/app/graphql/types/vulnerability_type.rb @@ -6,6 +6,7 @@ class VulnerabilityType < BaseObject description 'Represents a vulnerability' implements Types::Notes::NoteableInterface + implements Types::TodoableInterface authorize :read_vulnerability diff --git a/ee/app/models/ee/todo.rb b/ee/app/models/ee/todo.rb index 85655f318fb79ef44ba41fb4c69ca72de2c2497a..3cc49b1fb4b26e74f63d006d9f02bf8a43614526 100644 --- a/ee/app/models/ee/todo.rb +++ b/ee/app/models/ee/todo.rb @@ -14,7 +14,7 @@ def target_url return if target.nil? case target - when Epic + when Vulnerability, Epic ::Gitlab::UrlBuilder.build( target, anchor: note.present? ? ActionView::RecordIdentifier.dom_id(note) : nil diff --git a/ee/app/models/ee/vulnerability.rb b/ee/app/models/ee/vulnerability.rb index a0142ce56840e005f119c94a2da484c17f81b87f..61e552840b0e524fb1a5fe930440d4b114b39db1 100644 --- a/ee/app/models/ee/vulnerability.rb +++ b/ee/app/models/ee/vulnerability.rb @@ -3,6 +3,7 @@ module EE module Vulnerability include ::Gitlab::Utils::StrongMemoize + include Todoable extend ActiveSupport::Concern prepended do diff --git a/ee/spec/graphql/ee/types/todoable_interface_spec.rb b/ee/spec/graphql/ee/types/todoable_interface_spec.rb index 2ec1f7ba095741ff2ee29987735bf345e356457a..d4d64e2c107c21cc5fb26be8f782f39aae9afb16 100644 --- a/ee/spec/graphql/ee/types/todoable_interface_spec.rb +++ b/ee/spec/graphql/ee/types/todoable_interface_spec.rb @@ -2,12 +2,13 @@ require 'spec_helper' -RSpec.describe Types::TodoableInterface do +RSpec.describe Types::TodoableInterface, feature_category: :notifications do let(:extended_class) { described_class } describe ".resolve_type" do it 'knows the correct type for EE-only objects' do expect(extended_class.resolve_type(build(:epic), {})).to eq(Types::EpicType) + expect(extended_class.resolve_type(build(:vulnerability), {})).to eq(Types::VulnerabilityType) end end end diff --git a/ee/spec/graphql/types/vulnerability_type_spec.rb b/ee/spec/graphql/types/vulnerability_type_spec.rb index bd0ec90a32a5ba75863b97e911ed3a454c1865cc..7165a37f0652eca494339f85f78b9a625146d1c2 100644 --- a/ee/spec/graphql/types/vulnerability_type_spec.rb +++ b/ee/spec/graphql/types/vulnerability_type_spec.rb @@ -37,6 +37,7 @@ report_type resolved_on_default_branch vulnerability_path + name web_url location scanner @@ -93,6 +94,7 @@ subject(:graphql_response) { GitlabSchema.execute(query, context: { current_user: user }).as_json } + it { expect(described_class.interfaces).to include(Types::TodoableInterface) } it { expect(described_class).to have_graphql_fields(fields) } it { expect(described_class).to require_graphql_authorizations(:read_vulnerability) } diff --git a/ee/spec/models/todo_spec.rb b/ee/spec/models/todo_spec.rb index 9c10bb4e3849ed0294dac7868a02af5820a8d452..151bc175c3c4a4a6d5fbbf7b99d6220be2d3f3a9 100644 --- a/ee/spec/models/todo_spec.rb +++ b/ee/spec/models/todo_spec.rb @@ -2,15 +2,16 @@ require 'spec_helper' -RSpec.describe Todo, feature_category: :team_planning do +RSpec.describe Todo, feature_category: :notifications do let_it_be(:current_user) { create(:user) } - let_it_be(:group) { create(:group, developers: current_user) } - let_it_be(:epic) { create(:epic, group: group) } describe '#target_url' do subject { todo.target_url } context 'when the todo is coming from an epic' do + let_it_be(:group) { create(:group, developers: current_user) } + let_it_be(:epic) { create(:epic, group: group) } + context 'when coming from the epic itself' do let_it_be(:todo) { create(:todo, project: nil, group: group, user: current_user, target: epic) } @@ -28,5 +29,31 @@ end end end + + context 'when the todo is coming from a vulnerability' do + let_it_be(:project) { create(:project) } + let_it_be(:vulnerability) { create(:vulnerability, project: project) } + + context 'when coming from the vulnerability itself' do + let_it_be(:todo) do + create(:todo, project: project, group: project.group, user: current_user, target: vulnerability) + end + + it 'returns the work item web path' do + is_expected.to eq("http://localhost/#{project.full_path}/-/security/vulnerabilities/#{vulnerability.id}") + end + end + + context 'when coming from a note on the vulnerability' do + let_it_be(:note) { create(:note, noteable: vulnerability, project: project) } + let_it_be(:todo) do + create(:todo, project: project, group: project.group, user: current_user, note: note, target: vulnerability) + end + + it 'returns the work item web path with an anchor to the note' do + is_expected.to eq("http://localhost/#{project.full_path}/-/security/vulnerabilities/#{vulnerability.id}#note_#{note.id}") + end + end + end end end diff --git a/spec/finders/todos_finder_spec.rb b/spec/finders/todos_finder_spec.rb index ef47c66e8b251c13344f7e1ef9d1737e5556bafe..1284dbe3394483eeb9d2ed4cc8754991223b8160 100644 --- a/spec/finders/todos_finder_spec.rb +++ b/spec/finders/todos_finder_spec.rb @@ -340,11 +340,12 @@ describe '.todo_types' do it 'returns the expected types' do + shared_types = %w[Commit Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert Namespace Project] expected_result = if Gitlab.ee? - %w[Epic Commit Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert Namespace Project] + %w[Epic Vulnerability] + shared_types else - %w[Commit Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert Namespace Project] + shared_types end expect(described_class.todo_types).to contain_exactly(*expected_result)