Commit e8ea70d8 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch '230558-add-graphql-api-to-reverting-vulnerabilities-to-detected' into 'master'

Add GraphQL API to revert vulnerabilities to detected state

See merge request gitlab-org/gitlab!41786
parents 99e44606 a14e2945
...@@ -11521,6 +11521,7 @@ type Mutation { ...@@ -11521,6 +11521,7 @@ type Mutation {
pipelineRetry(input: PipelineRetryInput!): PipelineRetryPayload pipelineRetry(input: PipelineRetryInput!): PipelineRetryPayload
removeAwardEmoji(input: RemoveAwardEmojiInput!): RemoveAwardEmojiPayload @deprecated(reason: "Use awardEmojiRemove. Deprecated in 13.2") removeAwardEmoji(input: RemoveAwardEmojiInput!): RemoveAwardEmojiPayload @deprecated(reason: "Use awardEmojiRemove. Deprecated in 13.2")
removeProjectFromSecurityDashboard(input: RemoveProjectFromSecurityDashboardInput!): RemoveProjectFromSecurityDashboardPayload removeProjectFromSecurityDashboard(input: RemoveProjectFromSecurityDashboardInput!): RemoveProjectFromSecurityDashboardPayload
revertVulnerabilityToDetected(input: RevertVulnerabilityToDetectedInput!): RevertVulnerabilityToDetectedPayload
runDastScan(input: RunDASTScanInput!): RunDASTScanPayload @deprecated(reason: "Use DastOnDemandScanCreate. Deprecated in 13.4") runDastScan(input: RunDASTScanInput!): RunDASTScanPayload @deprecated(reason: "Use DastOnDemandScanCreate. Deprecated in 13.4")
todoMarkDone(input: TodoMarkDoneInput!): TodoMarkDonePayload todoMarkDone(input: TodoMarkDoneInput!): TodoMarkDonePayload
todoRestore(input: TodoRestoreInput!): TodoRestorePayload todoRestore(input: TodoRestoreInput!): TodoRestorePayload
...@@ -15731,6 +15732,41 @@ interface ResolvableInterface { ...@@ -15731,6 +15732,41 @@ interface ResolvableInterface {
resolvedBy: User 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 { type RootStorageStatistics {
""" """
The CI artifacts size in bytes The CI artifacts size in bytes
......
...@@ -33593,6 +33593,33 @@ ...@@ -33593,6 +33593,33 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "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", "name": "runDastScan",
"description": null, "description": null,
...@@ -45571,6 +45598,108 @@ ...@@ -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", "kind": "OBJECT",
"name": "RootStorageStatistics", "name": "RootStorageStatistics",
...@@ -2141,6 +2141,16 @@ Counts of requirements by their state. ...@@ -2141,6 +2141,16 @@ Counts of requirements by their state.
| `archived` | Int | Number of archived requirements | | `archived` | Int | Number of archived requirements |
| `opened` | Int | Number of opened 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 ### RootStorageStatistics
| Field | Type | Description | | Field | Type | Description |
......
...@@ -25,6 +25,7 @@ module EE ...@@ -25,6 +25,7 @@ module EE
mount_mutation ::Mutations::Vulnerabilities::Dismiss mount_mutation ::Mutations::Vulnerabilities::Dismiss
mount_mutation ::Mutations::Vulnerabilities::Resolve mount_mutation ::Mutations::Vulnerabilities::Resolve
mount_mutation ::Mutations::Vulnerabilities::Confirm mount_mutation ::Mutations::Vulnerabilities::Confirm
mount_mutation ::Mutations::Vulnerabilities::RevertToDetected
mount_mutation ::Mutations::Boards::Update mount_mutation ::Mutations::Boards::Update
mount_mutation ::Mutations::Boards::Lists::UpdateLimitMetrics mount_mutation ::Mutations::Boards::Lists::UpdateLimitMetrics
mount_mutation ::Mutations::InstanceSecurityDashboard::AddProject 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