Commit 830c9f63 authored by Jonathan Schafer's avatar Jonathan Schafer Committed by Enrique Alcántara

Add vulnerability activity filters in GraphQL

Filters added for hasIssues and hasResolution

Changelog: changed
EE: true
parent 11750512
......@@ -9548,6 +9548,8 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="groupvulnerabilityseveritiescounthasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have issues. |
| <a id="groupvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
| <a id="groupvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="groupvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="groupvulnerabilityseveritiescountscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by scanner. |
......@@ -9717,6 +9719,8 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="instancesecuritydashboardvulnerabilityseveritiescounthasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have issues. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescountscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by scanner. |
......@@ -11954,6 +11958,8 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectvulnerabilityseveritiescounthasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have issues. |
| <a id="projectvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
| <a id="projectvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="projectvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="projectvulnerabilityseveritiescountscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by scanner. |
......
......@@ -8,6 +8,8 @@ query vulnerabilitySeveritiesCount(
$scanner: [String!]
$state: [VulnerabilityState!]
$scannerId: [VulnerabilitiesScannerID!]
$hasIssues: Boolean
$hasResolution: Boolean
$isGroup: Boolean = false
$isProject: Boolean = false
$isInstance: Boolean = false
......@@ -20,6 +22,8 @@ query vulnerabilitySeveritiesCount(
scanner: $scanner
state: $state
scannerId: $scannerId
hasIssues: $hasIssues
hasResolution: $hasResolution
) {
...VulnerabilitySeveritiesCount
}
......@@ -32,6 +36,8 @@ query vulnerabilitySeveritiesCount(
scanner: $scanner
state: $state
scannerId: $scannerId
hasIssues: $hasIssues
hasResolution: $hasResolution
) {
...VulnerabilitySeveritiesCount
}
......@@ -43,6 +49,8 @@ query vulnerabilitySeveritiesCount(
scanner: $scanner
state: $state
scannerId: $scannerId
hasIssues: $hasIssues
hasResolution: $hasResolution
) {
...VulnerabilitySeveritiesCount
}
......
......@@ -33,6 +33,14 @@ module Resolvers
required: false,
description: 'Filter vulnerabilities by scanner ID.'
argument :has_issues, GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Filter vulnerabilities that do or do not have issues.'
argument :has_resolution, GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Filter vulnerabilities that do or do not have a resolution.'
def resolve(**args)
return Vulnerability.none unless vulnerable
......
......@@ -20,7 +20,7 @@ RSpec.describe Resolvers::VulnerabilitySeveritiesCountResolver do
end
let_it_be(:high_vulnerability) do
create(:vulnerability, :with_findings, :dismissed, :high, :container_scanning, project: project)
create(:vulnerability, :with_findings, :dismissed, :high, :container_scanning, :with_issue_links, resolved_on_default_branch: true, project: project)
end
let(:current_user) { user }
......@@ -84,6 +84,38 @@ RSpec.describe Resolvers::VulnerabilitySeveritiesCountResolver do
is_expected.to eq('critical' => 1, 'high' => 1, 'low' => 1)
end
end
context 'when filtering vulnerabilities with issues' do
let(:filters) { { has_issues: true } }
it 'only returns count for vulnerabilities with issues' do
is_expected.to eq('high' => 1)
end
end
context 'when filtering vulnerabilities with issues' do
let(:filters) { { has_issues: false } }
it 'only returns count for vulnerabilities with issues' do
is_expected.to eq('critical' => 1, 'low' => 1)
end
end
context 'when filtering resolved vulnerabilities' do
let(:filters) { { has_resolution: true } }
it 'only returns count for resolved vulnerabilities' do
is_expected.to eq('high' => 1)
end
end
context 'when filtering resolved vulnerabilities' do
let(:filters) { { has_resolution: false } }
it 'only returns count for resolved vulnerabilities' do
is_expected.to eq('critical' => 1, 'low' => 1)
end
end
end
context 'when resolving vulnerabilities for an instance security dashboard' do
......
......@@ -22,6 +22,8 @@ RSpec.describe 'Query.project(fullPath).vulnerabilitySeveritiesCount' do
before do
stub_licensed_features(security_dashboard: true)
create_list(:vulnerability, 2, :high, :with_issue_links, resolved_on_default_branch: true, project: project)
project.add_developer(user)
end
......@@ -30,7 +32,71 @@ RSpec.describe 'Query.project(fullPath).vulnerabilitySeveritiesCount' do
it "returns counts for each severity of the project's detected or confirmed vulnerabilities" do
high_count = subject.dig('data', 'project', 'vulnerabilitySeveritiesCount', 'high')
expect(high_count).to eq(1)
expect(high_count).to eq(3)
end
context 'with hasIssues filter' do
let(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
vulnerabilitySeveritiesCount(hasIssues: #{has_issues}) {
high
}
}
}
)
end
context 'when counting vulnerabilities without issues' do
let(:has_issues) { false }
it 'counts vulnerabilities with issues' do
expect(count_issues).to eq(1)
end
end
context 'when counting vulnerabilities with issues' do
let(:has_issues) { true }
it 'counts vulnerabilities with issues' do
expect(count_issues).to eq(2)
end
end
end
context 'with hasResolution filter' do
let(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
vulnerabilitySeveritiesCount(hasResolution: #{has_resolution}) {
high
}
}
}
)
end
context 'when counting vulnerabilities without resolution' do
let(:has_resolution) { false }
it 'counts vulnerabilities with resolution' do
expect(count_issues).to eq(1)
end
end
context 'when counting vulnerabilities with resolution' do
let(:has_resolution) { true }
it 'counts vulnerabilities with resolution' do
expect(count_issues).to eq(2)
end
end
end
def count_issues
subject.dig('data', 'project', 'vulnerabilitySeveritiesCount', 'high')
end
context 'with scannerId filter' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment