Commit d599e22b authored by Paul Gascou-Vaillancourt's avatar Paul Gascou-Vaillancourt Committed by Natalia Tepluhina

Wire up DAST Saved Scans with the API

This updates the frontend so that the following queries and mutations
hit the actual API rather than local mocks:

- dastProfileCreate mutation
- dastProfileUpdate mutation
- dastProfiles query
parent 1b7335b4
--- ---
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