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: 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/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/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 { ...@@ -35,8 +35,8 @@ import {
TYPE_SITE_PROFILE, TYPE_SITE_PROFILE,
TYPE_SCANNER_PROFILE, TYPE_SCANNER_PROFILE,
} from '../settings'; } from '../settings';
import dastScanCreateMutation from '../graphql/dast_scan_create.mutation.graphql'; import dastProfileCreateMutation from '../graphql/dast_profile_create.mutation.graphql';
import dastScanUpdateMutation from '../graphql/dast_scan_update.mutation.graphql'; import dastProfileUpdateMutation from '../graphql/dast_profile_update.mutation.graphql';
import dastOnDemandScanCreateMutation from '../graphql/dast_on_demand_scan_create.mutation.graphql'; import dastOnDemandScanCreateMutation from '../graphql/dast_on_demand_scan_create.mutation.graphql';
import ProfileSelectorSummaryCell from './profile_selector/summary_cell.vue'; import ProfileSelectorSummaryCell from './profile_selector/summary_cell.vue';
import ScannerProfileSelector from './profile_selector/scanner_profile_selector.vue'; import ScannerProfileSelector from './profile_selector/scanner_profile_selector.vue';
...@@ -252,15 +252,15 @@ export default { ...@@ -252,15 +252,15 @@ export default {
this.loading = button; this.loading = button;
this.hideErrors(); this.hideErrors();
let mutation = dastOnDemandScanCreateMutation; let mutation = dastOnDemandScanCreateMutation;
let reponseType = 'dastOnDemandScanCreate'; let responseType = 'dastOnDemandScanCreate';
let input = { let input = {
fullPath: this.projectPath, fullPath: this.projectPath,
dastScannerProfileId: this.selectedScannerProfile.id, dastScannerProfileId: this.selectedScannerProfile.id,
dastSiteProfileId: this.selectedSiteProfile.id, dastSiteProfileId: this.selectedSiteProfile.id,
}; };
if (this.glFeatures.dastSavedScans) { if (this.glFeatures.dastSavedScans) {
mutation = this.isEdit ? dastScanUpdateMutation : dastScanCreateMutation; mutation = this.isEdit ? dastProfileUpdateMutation : dastProfileCreateMutation;
reponseType = this.isEdit ? 'dastScanUpdate' : 'dastScanCreate'; responseType = this.isEdit ? 'dastProfileUpdate' : 'dastProfileCreate';
input = { input = {
...input, ...input,
...(this.isEdit ? { id: this.dastScan.id } : {}), ...(this.isEdit ? { id: this.dastScan.id } : {}),
...@@ -278,13 +278,13 @@ export default { ...@@ -278,13 +278,13 @@ export default {
}, },
}) })
.then(({ data }) => { .then(({ data }) => {
const response = data[reponseType]; const response = data[responseType];
const { errors } = response; const { errors } = response;
if (errors?.length) { if (errors?.length) {
this.showErrors(ERROR_RUN_SCAN, errors); this.showErrors(ERROR_RUN_SCAN, errors);
this.loading = false; this.loading = false;
} else if (this.glFeatures.dastSavedScans && !runAfterCreate) { } else if (this.glFeatures.dastSavedScans && !runAfterCreate) {
redirectTo(response.dastScan.editPath); redirectTo(response.dastProfile.editPath);
} else { } else {
redirectTo(response.pipelineUrl); 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" #import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
query DastSavedScans($fullPath: ID!, $after: String, $before: String, $first: Int, $last: Int) { query DastProfiles($fullPath: ID!, $after: String, $before: String, $first: Int, $last: Int) {
project @client { project(fullPath: $fullPath) {
savedScans(after: $after, before: $before, first: $first, last: $last) { dastProfiles(after: $after, before: $before, first: $first, last: $last) {
pageInfo { pageInfo {
...PageInfo ...PageInfo
} }
......
/* eslint-disable @gitlab/require-i18n-strings */
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import { range } from 'lodash';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo); 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({ export default new VueApollo({
defaultClient: createDefaultClient(resolvers, { defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
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 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 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'; import dastSiteProfilesDelete from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles_delete.mutation.graphql';
...@@ -13,11 +13,11 @@ import { s__ } from '~/locale'; ...@@ -13,11 +13,11 @@ import { s__ } from '~/locale';
export const getProfileSettings = ({ createNewProfilePaths, isDastSavedScansEnabled }) => ({ export const getProfileSettings = ({ createNewProfilePaths, isDastSavedScansEnabled }) => ({
...(isDastSavedScansEnabled ...(isDastSavedScansEnabled
? { ? {
savedScans: { dastProfiles: {
profileType: 'savedScans', profileType: 'dastProfiles',
createNewProfilePath: createNewProfilePaths.savedScan, createNewProfilePath: createNewProfilePaths.savedScan,
graphQL: { graphQL: {
query: dastSavedScansQuery, query: dastProfilesQuery,
deletion: { deletion: {
mutation: dastSavedScansDelete, mutation: dastSavedScansDelete,
optimisticResponse: dastProfilesDeleteResponse({ optimisticResponse: dastProfilesDeleteResponse({
......
...@@ -6,8 +6,8 @@ import createApolloProvider from 'helpers/mock_apollo_helper'; ...@@ -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 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 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 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 dastProfileCreateMutation from 'ee/on_demand_scans/graphql/dast_profile_create.mutation.graphql';
import dastScanUpdateMutation from 'ee/on_demand_scans/graphql/dast_scan_update.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 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 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'; import dastSiteProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql';
...@@ -79,8 +79,8 @@ describe('OnDemandScansForm', () => { ...@@ -79,8 +79,8 @@ describe('OnDemandScansForm', () => {
const setupSuccess = ({ edit = false } = {}) => { const setupSuccess = ({ edit = false } = {}) => {
jest.spyOn(subject.vm.$apollo, 'mutate').mockResolvedValue({ jest.spyOn(subject.vm.$apollo, 'mutate').mockResolvedValue({
data: { data: {
[edit ? 'dastScanUpdate' : 'dastScanCreate']: { [edit ? 'dastProfileUpdate' : 'dastProfileCreate']: {
dastScan: { editPath }, dastProfile: { editPath },
pipelineUrl, pipelineUrl,
errors: [], errors: [],
}, },
...@@ -265,9 +265,9 @@ describe('OnDemandScansForm', () => { ...@@ -265,9 +265,9 @@ describe('OnDemandScansForm', () => {
expect(saveButton.props('disabled')).toBe(!saveButtonLoading); 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({ expect(subject.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: dastScanCreateMutation, mutation: dastProfileCreateMutation,
variables: { variables: {
input: { input: {
name: 'My daily scan', name: 'My daily scan',
...@@ -301,9 +301,9 @@ describe('OnDemandScansForm', () => { ...@@ -301,9 +301,9 @@ describe('OnDemandScansForm', () => {
actionFunction(); 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({ expect(subject.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: dastScanUpdateMutation, mutation: dastProfileUpdateMutation,
variables: { variables: {
input: { input: {
id: 1, id: 1,
...@@ -356,7 +356,7 @@ describe('OnDemandScansForm', () => { ...@@ -356,7 +356,7 @@ describe('OnDemandScansForm', () => {
mountShallowSubject(); mountShallowSubject();
jest jest
.spyOn(subject.vm.$apollo, 'mutate') .spyOn(subject.vm.$apollo, 'mutate')
.mockResolvedValue({ data: { dastScanCreate: { pipelineUrl: null, errors } } }); .mockResolvedValue({ data: { dastProfileCreate: { pipelineUrl: null, errors } } });
await setValidFormData(); await setValidFormData();
submitForm(); submitForm();
}); });
......
...@@ -26,7 +26,7 @@ describe('EE - DastProfiles', () => { ...@@ -26,7 +26,7 @@ describe('EE - DastProfiles', () => {
const defaultMocks = { const defaultMocks = {
$apollo: { $apollo: {
queries: { queries: {
savedScans: { dastProfiles: {
fetchMore: jest.fn().mockResolvedValue(), fetchMore: jest.fn().mockResolvedValue(),
}, },
siteProfiles: { siteProfiles: {
...@@ -139,7 +139,7 @@ describe('EE - DastProfiles', () => { ...@@ -139,7 +139,7 @@ describe('EE - DastProfiles', () => {
describe.each` describe.each`
tabName | index | givenLocationHash tabName | index | givenLocationHash
${'Saved Scans'} | ${0} | ${'saved-scans'} ${'Saved Scans'} | ${0} | ${'dast-profiles'}
${'Site Profiles'} | ${1} | ${'site-profiles'} ${'Site Profiles'} | ${1} | ${'site-profiles'}
${'Scanner Profiles'} | ${2} | ${'scanner-profiles'} ${'Scanner Profiles'} | ${2} | ${'scanner-profiles'}
`('with location hash set to "$givenLocationHash"', ({ tabName, index, givenLocationHash }) => { `('with location hash set to "$givenLocationHash"', ({ tabName, index, givenLocationHash }) => {
...@@ -173,7 +173,7 @@ describe('EE - DastProfiles', () => { ...@@ -173,7 +173,7 @@ describe('EE - DastProfiles', () => {
describe.each` describe.each`
description | profileType description | profileType
${'Saved Scans List'} | ${'savedScans'} ${'Saved Scans List'} | ${'dastProfiles'}
${'Site Profiles List'} | ${'siteProfiles'} ${'Site Profiles List'} | ${'siteProfiles'}
${'Scanner Profiles List'} | ${'scannerProfiles'} ${'Scanner Profiles List'} | ${'scannerProfiles'}
`('$description', ({ profileType }) => { `('$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