Commit a14e2945 authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Bob Van Landuyt

Add GraphQL API to revert vulnerabilities to detected state

This change adds new GraphQL mutation to revert vulnerabilities to
detected state.
parent 12dd6301
......@@ -11521,6 +11521,7 @@ type Mutation {
pipelineRetry(input: PipelineRetryInput!): PipelineRetryPayload
removeAwardEmoji(input: RemoveAwardEmojiInput!): RemoveAwardEmojiPayload @deprecated(reason: "Use awardEmojiRemove. Deprecated in 13.2")
removeProjectFromSecurityDashboard(input: RemoveProjectFromSecurityDashboardInput!): RemoveProjectFromSecurityDashboardPayload
revertVulnerabilityToDetected(input: RevertVulnerabilityToDetectedInput!): RevertVulnerabilityToDetectedPayload
runDastScan(input: RunDASTScanInput!): RunDASTScanPayload @deprecated(reason: "Use DastOnDemandScanCreate. Deprecated in 13.4")
todoMarkDone(input: TodoMarkDoneInput!): TodoMarkDonePayload
todoRestore(input: TodoRestoreInput!): TodoRestorePayload
......@@ -15731,6 +15732,41 @@ interface ResolvableInterface {
resolvedBy: User
}
"""
Autogenerated input type of RevertVulnerabilityToDetected
"""
input RevertVulnerabilityToDetectedInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
ID of the vulnerability to be reverted
"""
id: VulnerabilityID!
}
"""
Autogenerated return type of RevertVulnerabilityToDetected
"""
type RevertVulnerabilityToDetectedPayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Errors encountered during execution of the mutation.
"""
errors: [String!]!
"""
The vulnerability after revert
"""
vulnerability: Vulnerability
}
type RootStorageStatistics {
"""
The CI artifacts size in bytes
......
......@@ -33593,6 +33593,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "revertVulnerabilityToDetected",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "RevertVulnerabilityToDetectedInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "RevertVulnerabilityToDetectedPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "runDastScan",
"description": null,
......@@ -45571,6 +45598,108 @@
}
]
},
{
"kind": "INPUT_OBJECT",
"name": "RevertVulnerabilityToDetectedInput",
"description": "Autogenerated input type of RevertVulnerabilityToDetected",
"fields": null,
"inputFields": [
{
"name": "id",
"description": "ID of the vulnerability to be reverted",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "VulnerabilityID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "RevertVulnerabilityToDetectedPayload",
"description": "Autogenerated return type of RevertVulnerabilityToDetected",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Errors encountered during execution of the mutation.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "vulnerability",
"description": "The vulnerability after revert",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Vulnerability",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "RootStorageStatistics",
......@@ -2141,6 +2141,16 @@ Counts of requirements by their state.
| `archived` | Int | Number of archived requirements |
| `opened` | Int | Number of opened requirements |
### RevertVulnerabilityToDetectedPayload
Autogenerated return type of RevertVulnerabilityToDetected.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `vulnerability` | Vulnerability | The vulnerability after revert |
### RootStorageStatistics
| Field | Type | Description |
......
......@@ -25,6 +25,7 @@ module EE
mount_mutation ::Mutations::Vulnerabilities::Dismiss
mount_mutation ::Mutations::Vulnerabilities::Resolve
mount_mutation ::Mutations::Vulnerabilities::Confirm
mount_mutation ::Mutations::Vulnerabilities::RevertToDetected
mount_mutation ::Mutations::Boards::Update
mount_mutation ::Mutations::Boards::Lists::UpdateLimitMetrics
mount_mutation ::Mutations::InstanceSecurityDashboard::AddProject
......
# frozen_string_literal: true
module Mutations
module Vulnerabilities
class RevertToDetected < BaseMutation
graphql_name 'RevertVulnerabilityToDetected'
authorize :admin_vulnerability
field :vulnerability, Types::VulnerabilityType,
null: true,
description: 'The vulnerability after revert'
argument :id,
::Types::GlobalIDType[::Vulnerability],
required: true,
description: 'ID of the vulnerability to be reverted'
def resolve(id:)
vulnerability = authorized_find!(id: id)
result = ::Vulnerabilities::RevertToDetectedService.new(current_user, vulnerability).execute
{
vulnerability: result,
errors: result.errors.full_messages || []
}
end
private
def find_object(id:)
GitlabSchema.object_from_id(id, expected_type: ::Vulnerability)
end
end
end
end
---
title: Add GraphQL API to revert vulnerabilities to detected state
merge_request: 41786
author:
type: added
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::Vulnerabilities::RevertToDetected do
let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
specify { expect(described_class).to require_graphql_authorizations(:admin_vulnerability) }
describe '#resolve' do
let_it_be(:vulnerability) { create(:vulnerability, :dismissed, :with_findings) }
let_it_be(:user) { create(:user) }
let(:mutated_vulnerability) { subject[:vulnerability] }
subject { mutation.resolve(id: GitlabSchema.id_from_object(vulnerability).to_s) }
context 'when the user can revert the vulnerability to detected' do
before do
stub_licensed_features(security_dashboard: true)
end
context 'when user does not have access to the project' do
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when user has access to the project' do
before do
vulnerability.project.add_developer(user)
end
it 'returns the vulnerability back in detected state' do
expect(mutated_vulnerability).to eq(vulnerability)
expect(mutated_vulnerability).to be_detected
expect(subject[:errors]).to be_empty
end
end
end
end
end
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