Commit d0d33e15 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '296752-dast-saved-scans-cleanup' into 'master'

Wire up DAST Saved Scans with the API

See merge request gitlab-org/gitlab!53501
parents 871ce6f5 d599e22b
---
filenames:
- ee/app/assets/javascripts/on_demand_scans/graphql/dast_scan_create.mutation.graphql
- ee/app/assets/javascripts/oncall_schedules/graphql/mutations/update_oncall_schedule_rotation.mutation.graphql
- ee/app/assets/javascripts/security_configuration/api_fuzzing/graphql/api_fuzzing_ci_configuration.query.graphql
- ee/app/assets/javascripts/on_demand_scans/graphql/dast_profile_update.mutation.graphql
......@@ -35,8 +35,8 @@ import {
TYPE_SITE_PROFILE,
TYPE_SCANNER_PROFILE,
} from '../settings';
import dastScanCreateMutation from '../graphql/dast_scan_create.mutation.graphql';
import dastScanUpdateMutation from '../graphql/dast_scan_update.mutation.graphql';
import dastProfileCreateMutation from '../graphql/dast_profile_create.mutation.graphql';
import dastProfileUpdateMutation from '../graphql/dast_profile_update.mutation.graphql';
import dastOnDemandScanCreateMutation from '../graphql/dast_on_demand_scan_create.mutation.graphql';
import ProfileSelectorSummaryCell from './profile_selector/summary_cell.vue';
import ScannerProfileSelector from './profile_selector/scanner_profile_selector.vue';
......@@ -252,15 +252,15 @@ export default {
this.loading = button;
this.hideErrors();
let mutation = dastOnDemandScanCreateMutation;
let reponseType = 'dastOnDemandScanCreate';
let responseType = 'dastOnDemandScanCreate';
let input = {
fullPath: this.projectPath,
dastScannerProfileId: this.selectedScannerProfile.id,
dastSiteProfileId: this.selectedSiteProfile.id,
};
if (this.glFeatures.dastSavedScans) {
mutation = this.isEdit ? dastScanUpdateMutation : dastScanCreateMutation;
reponseType = this.isEdit ? 'dastScanUpdate' : 'dastScanCreate';
mutation = this.isEdit ? dastProfileUpdateMutation : dastProfileCreateMutation;
responseType = this.isEdit ? 'dastProfileUpdate' : 'dastProfileCreate';
input = {
...input,
...(this.isEdit ? { id: this.dastScan.id } : {}),
......@@ -278,13 +278,13 @@ export default {
},
})
.then(({ data }) => {
const response = data[reponseType];
const response = data[responseType];
const { errors } = response;
if (errors?.length) {
this.showErrors(ERROR_RUN_SCAN, errors);
this.loading = false;
} else if (this.glFeatures.dastSavedScans && !runAfterCreate) {
redirectTo(response.dastScan.editPath);
redirectTo(response.dastProfile.editPath);
} else {
redirectTo(response.pipelineUrl);
}
......
mutation dastProfileCreate($input: DastProfileCreateInput!) {
dastProfileCreate(input: $input) {
dastProfile {
editPath
}
pipelineUrl
errors
}
}
mutation dastProfileUpdate($input: DastProfileUpdateInput!) {
dastProfileUpdate(input: $input) {
dastProfile {
editPath
}
pipelineUrl
errors
}
}
mutation dastScanCreate(
$fullPath: ID!
$name: String!
$description: String
$dastSiteProfileId: DastSiteProfileID!
$dastScannerProfileID: DastScannerProfileID!
$runAfterCreate: Boolean
) {
dastScanCreate(
input: {
fullPath: $fullPath
name: $name
description: $description
dastSiteProfileId: $dastSiteProfileId
dastScannerProfileID: $dastScannerProfileID
runAfterCreate: $runAfterCreate
}
) {
dastScan {
editPath
}
pipelineUrl
errors
}
}
mutation dastScanUpdate(
$id: DastScanID!
$fullPath: ID!
$name: String!
$description: String
$dastSiteProfileId: DastSiteProfileID!
$dastScannerProfileID: DastScannerProfileID!
$runAfterCreate: Boolean
) {
dastScanUpdate(
input: {
id: $id
fullPath: $fullPath
name: $name
description: $description
dastSiteProfileId: $dastSiteProfileId
dastScannerProfileID: $dastScannerProfileID
runAfterCreate: $runAfterCreate
}
) @client {
dastScan {
editPath
}
pipelineUrl
errors
}
}
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
query DastSavedScans($fullPath: ID!, $after: String, $before: String, $first: Int, $last: Int) {
project @client {
savedScans(after: $after, before: $before, first: $first, last: $last) {
query DastProfiles($fullPath: ID!, $after: String, $before: String, $first: Int, $last: Int) {
project(fullPath: $fullPath) {
dastProfiles(after: $after, before: $before, first: $first, last: $last) {
pageInfo {
...PageInfo
}
......
/* eslint-disable @gitlab/require-i18n-strings */
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { range } from 'lodash';
import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
// NOTE: We currently mock some fake DAST scans while the feature is feature-flagged and the
// backend is being worked on.
// This will be cleaned up as part of https://gitlab.com/gitlab-org/gitlab/-/issues/295248.
let id = 0;
const generateFakeDastScan = () => {
id += 1;
return {
node: {
id,
name: `My daily scan #${id}`,
description: 'Tests for SQL injection',
dastSiteProfile: {
id,
targetUrl: 'http://example.com ',
__typename: 'DastSiteProfile',
},
dastScannerProfile: {
id,
scanType: Math.random() < 0.5 ? 'PASSIVE' : 'ACTIVE',
__typename: 'DastScannerProfile',
},
editPath: '/on_demand_scans/1/edit',
__typename: 'DastSavedScan',
},
__typename: 'DastSavedScanEdge',
};
};
const resolvers = {
Query: {
project: () => ({
__typename: 'Project',
savedScans: {
pageInfo: {
hasNextPage: true,
hasPreviousPage: false,
startCursor: 'startCursor',
endCursor: 'endCursor',
__typename: 'PageInfo',
},
edges: range(10).map(generateFakeDastScan),
__typename: 'DastSavedScanConnection',
},
}),
},
};
export default new VueApollo({
defaultClient: createDefaultClient(resolvers, {
assumeImmutableResults: true,
}),
defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
});
import dastSavedScansQuery from 'ee/security_configuration/dast_profiles/graphql/dast_saved_scans.query.graphql';
import dastProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_profiles.query.graphql';
import dastSavedScansDelete from 'ee/security_configuration/dast_profiles/graphql/dast_saved_scans_delete.mutation.graphql';
import dastSiteProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql';
import dastSiteProfilesDelete from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles_delete.mutation.graphql';
......@@ -13,11 +13,11 @@ import { s__ } from '~/locale';
export const getProfileSettings = ({ createNewProfilePaths, isDastSavedScansEnabled }) => ({
...(isDastSavedScansEnabled
? {
savedScans: {
profileType: 'savedScans',
dastProfiles: {
profileType: 'dastProfiles',
createNewProfilePath: createNewProfilePaths.savedScan,
graphQL: {
query: dastSavedScansQuery,
query: dastProfilesQuery,
deletion: {
mutation: dastSavedScansDelete,
optimisticResponse: dastProfilesDeleteResponse({
......
......@@ -6,8 +6,8 @@ import createApolloProvider from 'helpers/mock_apollo_helper';
import OnDemandScansForm from 'ee/on_demand_scans/components/on_demand_scans_form.vue';
import ScannerProfileSelector from 'ee/on_demand_scans/components/profile_selector/scanner_profile_selector.vue';
import SiteProfileSelector from 'ee/on_demand_scans/components/profile_selector/site_profile_selector.vue';
import dastScanCreateMutation from 'ee/on_demand_scans/graphql/dast_scan_create.mutation.graphql';
import dastScanUpdateMutation from 'ee/on_demand_scans/graphql/dast_scan_update.mutation.graphql';
import dastProfileCreateMutation from 'ee/on_demand_scans/graphql/dast_profile_create.mutation.graphql';
import dastProfileUpdateMutation from 'ee/on_demand_scans/graphql/dast_profile_update.mutation.graphql';
import dastOnDemandScanCreateMutation from 'ee/on_demand_scans/graphql/dast_on_demand_scan_create.mutation.graphql';
import dastScannerProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_scanner_profiles.query.graphql';
import dastSiteProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql';
......@@ -79,8 +79,8 @@ describe('OnDemandScansForm', () => {
const setupSuccess = ({ edit = false } = {}) => {
jest.spyOn(subject.vm.$apollo, 'mutate').mockResolvedValue({
data: {
[edit ? 'dastScanUpdate' : 'dastScanCreate']: {
dastScan: { editPath },
[edit ? 'dastProfileUpdate' : 'dastProfileCreate']: {
dastProfile: { editPath },
pipelineUrl,
errors: [],
},
......@@ -265,9 +265,9 @@ describe('OnDemandScansForm', () => {
expect(saveButton.props('disabled')).toBe(!saveButtonLoading);
});
it(`triggers dastScanCreateMutation mutation with runAfterCreate set to ${runAfterCreate}`, async () => {
it(`triggers dastProfileCreateMutation mutation with runAfterCreate set to ${runAfterCreate}`, () => {
expect(subject.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: dastScanCreateMutation,
mutation: dastProfileCreateMutation,
variables: {
input: {
name: 'My daily scan',
......@@ -301,9 +301,9 @@ describe('OnDemandScansForm', () => {
actionFunction();
});
it(`triggers dastScanUpdateMutation mutation with runAfterCreate set to ${runAfterCreate}`, async () => {
it(`triggers dastProfileUpdateMutation mutation with runAfterCreate set to ${runAfterCreate}`, async () => {
expect(subject.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: dastScanUpdateMutation,
mutation: dastProfileUpdateMutation,
variables: {
input: {
id: 1,
......@@ -356,7 +356,7 @@ describe('OnDemandScansForm', () => {
mountShallowSubject();
jest
.spyOn(subject.vm.$apollo, 'mutate')
.mockResolvedValue({ data: { dastScanCreate: { pipelineUrl: null, errors } } });
.mockResolvedValue({ data: { dastProfileCreate: { pipelineUrl: null, errors } } });
await setValidFormData();
submitForm();
});
......
......@@ -26,7 +26,7 @@ describe('EE - DastProfiles', () => {
const defaultMocks = {
$apollo: {
queries: {
savedScans: {
dastProfiles: {
fetchMore: jest.fn().mockResolvedValue(),
},
siteProfiles: {
......@@ -139,7 +139,7 @@ describe('EE - DastProfiles', () => {
describe.each`
tabName | index | givenLocationHash
${'Saved Scans'} | ${0} | ${'saved-scans'}
${'Saved Scans'} | ${0} | ${'dast-profiles'}
${'Site Profiles'} | ${1} | ${'site-profiles'}
${'Scanner Profiles'} | ${2} | ${'scanner-profiles'}
`('with location hash set to "$givenLocationHash"', ({ tabName, index, givenLocationHash }) => {
......@@ -173,7 +173,7 @@ describe('EE - DastProfiles', () => {
describe.each`
description | profileType
${'Saved Scans List'} | ${'savedScans'}
${'Saved Scans List'} | ${'dastProfiles'}
${'Site Profiles List'} | ${'siteProfiles'}
${'Scanner Profiles List'} | ${'scannerProfiles'}
`('$description', ({ profileType }) => {
......
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