Automatically select DAST profile

When there is only a single profile available in an on-demand scan's
profile selector, it is automatically selected to save the user some
clicks and to prevent potential confusion.
parent f64a7c35
...@@ -30,7 +30,7 @@ import ProfileSelectorSummaryCell from './profile_selector/summary_cell.vue'; ...@@ -30,7 +30,7 @@ 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';
import SiteProfileSelector from './profile_selector/site_profile_selector.vue'; import SiteProfileSelector from './profile_selector/site_profile_selector.vue';
const createProfilesApolloOptions = (name, { fetchQuery, fetchError }) => ({ const createProfilesApolloOptions = (name, field, { fetchQuery, fetchError }) => ({
query: fetchQuery, query: fetchQuery,
variables() { variables() {
return { return {
...@@ -39,6 +39,9 @@ const createProfilesApolloOptions = (name, { fetchQuery, fetchError }) => ({ ...@@ -39,6 +39,9 @@ const createProfilesApolloOptions = (name, { fetchQuery, fetchError }) => ({
}, },
update(data) { update(data) {
const edges = data?.project?.[name]?.edges ?? []; const edges = data?.project?.[name]?.edges ?? [];
if (edges.length === 1) {
this[field] = edges[0].node.id;
}
return edges.map(({ node }) => node); return edges.map(({ node }) => node);
}, },
error(e) { error(e) {
...@@ -66,8 +69,16 @@ export default { ...@@ -66,8 +69,16 @@ export default {
}, },
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
apollo: { apollo: {
scannerProfiles: createProfilesApolloOptions('scannerProfiles', SCANNER_PROFILES_QUERY), scannerProfiles: createProfilesApolloOptions(
siteProfiles: createProfilesApolloOptions('siteProfiles', SITE_PROFILES_QUERY), 'scannerProfiles',
'selectedScannerProfileId',
SCANNER_PROFILES_QUERY,
),
siteProfiles: createProfilesApolloOptions(
'siteProfiles',
'selectedSiteProfileId',
SITE_PROFILES_QUERY,
),
}, },
props: { props: {
helpPagePath: { helpPagePath: {
...@@ -104,8 +115,8 @@ export default { ...@@ -104,8 +115,8 @@ export default {
return { return {
scannerProfiles: [], scannerProfiles: [],
siteProfiles: [], siteProfiles: [],
selectedScannerProfile: null, selectedScannerProfileId: null,
selectedSiteProfile: null, selectedSiteProfileId: null,
loading: false, loading: false,
errorType: null, errorType: null,
errors: [], errors: [],
...@@ -113,6 +124,16 @@ export default { ...@@ -113,6 +124,16 @@ export default {
}; };
}, },
computed: { computed: {
selectedScannerProfile() {
return this.selectedScannerProfileId
? this.scannerProfiles.find(({ id }) => id === this.selectedScannerProfileId)
: null;
},
selectedSiteProfile() {
return this.selectedSiteProfileId
? this.siteProfiles.find(({ id }) => id === this.selectedSiteProfileId)
: null;
},
errorMessage() { errorMessage() {
return ERROR_MESSAGES[this.errorType] || null; return ERROR_MESSAGES[this.errorType] || null;
}, },
...@@ -238,37 +259,37 @@ export default { ...@@ -238,37 +259,37 @@ export default {
</template> </template>
<template v-else-if="!failedToLoadProfiles"> <template v-else-if="!failedToLoadProfiles">
<scanner-profile-selector <scanner-profile-selector
v-model="selectedScannerProfile" v-model="selectedScannerProfileId"
class="gl-mb-5" class="gl-mb-5"
:profiles="scannerProfiles" :profiles="scannerProfiles"
> >
<template #summary="{ profile }"> <template v-if="selectedScannerProfile" #summary>
<div class="row"> <div class="row">
<profile-selector-summary-cell <profile-selector-summary-cell
:class="{ 'gl-text-red-500': hasProfilesConflict }" :class="{ 'gl-text-red-500': hasProfilesConflict }"
:label="s__('DastProfiles|Scan mode')" :label="s__('DastProfiles|Scan mode')"
:value="$options.SCAN_TYPE_LABEL[profile.scanType]" :value="$options.SCAN_TYPE_LABEL[selectedScannerProfile.scanType]"
/> />
</div> </div>
<div class="row"> <div class="row">
<profile-selector-summary-cell <profile-selector-summary-cell
:label="s__('DastProfiles|Spider timeout')" :label="s__('DastProfiles|Spider timeout')"
:value="n__('%d minute', '%d minutes', profile.spiderTimeout)" :value="n__('%d minute', '%d minutes', selectedScannerProfile.spiderTimeout)"
/> />
<profile-selector-summary-cell <profile-selector-summary-cell
:label="s__('DastProfiles|Target timeout')" :label="s__('DastProfiles|Target timeout')"
:value="n__('%d second', '%d seconds', profile.targetTimeout)" :value="n__('%d second', '%d seconds', selectedScannerProfile.targetTimeout)"
/> />
</div> </div>
<div class="row"> <div class="row">
<profile-selector-summary-cell <profile-selector-summary-cell
:label="s__('DastProfiles|AJAX spider')" :label="s__('DastProfiles|AJAX spider')"
:value="profile.useAjaxSpider ? __('On') : __('Off')" :value="selectedScannerProfile.useAjaxSpider ? __('On') : __('Off')"
/> />
<profile-selector-summary-cell <profile-selector-summary-cell
:label="s__('DastProfiles|Debug messages')" :label="s__('DastProfiles|Debug messages')"
:value=" :value="
profile.showDebugMessages selectedScannerProfile.showDebugMessages
? s__('DastProfiles|Show debug messages') ? s__('DastProfiles|Show debug messages')
: s__('DastProfiles|Hide debug messages') : s__('DastProfiles|Hide debug messages')
" "
...@@ -276,13 +297,17 @@ export default { ...@@ -276,13 +297,17 @@ export default {
</div> </div>
</template> </template>
</scanner-profile-selector> </scanner-profile-selector>
<site-profile-selector v-model="selectedSiteProfile" class="gl-mb-5" :profiles="siteProfiles"> <site-profile-selector
<template #summary="{ profile }"> v-model="selectedSiteProfileId"
class="gl-mb-5"
:profiles="siteProfiles"
>
<template v-if="selectedSiteProfile" #summary>
<div class="row"> <div class="row">
<profile-selector-summary-cell <profile-selector-summary-cell
:class="{ 'gl-text-red-500': hasProfilesConflict }" :class="{ 'gl-text-red-500': hasProfilesConflict }"
:label="s__('DastProfiles|Target URL')" :label="s__('DastProfiles|Target URL')"
:value="profile.targetUrl" :value="selectedSiteProfile.targetUrl"
/> />
</div> </div>
</template> </template>
......
...@@ -25,14 +25,14 @@ export default { ...@@ -25,14 +25,14 @@ export default {
default: () => [], default: () => [],
}, },
value: { value: {
type: Object, type: String,
required: false, required: false,
default: null, default: null,
}, },
}, },
methods: { computed: {
isChecked({ id }) { selectedProfile() {
return this.value?.id === id; return this.value ? this.profiles.find(({ id }) => this.value === id) : null;
}, },
}, },
}; };
...@@ -67,7 +67,9 @@ export default { ...@@ -67,7 +67,9 @@ export default {
</template> </template>
<gl-dropdown <gl-dropdown
:text=" :text="
value ? value.dropdownLabel : s__('OnDemandScans|Select one of the existing profiles') selectedProfile
? selectedProfile.dropdownLabel
: s__('OnDemandScans|Select one of the existing profiles')
" "
class="mw-460" class="mw-460"
data-testid="profiles-dropdown" data-testid="profiles-dropdown"
...@@ -75,9 +77,9 @@ export default { ...@@ -75,9 +77,9 @@ export default {
<gl-dropdown-item <gl-dropdown-item
v-for="profile in profiles" v-for="profile in profiles"
:key="profile.id" :key="profile.id"
:is-checked="isChecked(profile)" :is-checked="value === profile.id"
is-check-item is-check-item
@click="$emit('input', profile)" @click="$emit('input', profile.id)"
> >
{{ profile.profileName }} {{ profile.profileName }}
</gl-dropdown-item> </gl-dropdown-item>
...@@ -87,7 +89,7 @@ export default { ...@@ -87,7 +89,7 @@ export default {
data-testid="selected-profile-summary" data-testid="selected-profile-summary"
class="gl-mt-6 gl-pt-6 gl-border-t-solid gl-border-gray-100 gl-border-t-1" class="gl-mt-6 gl-pt-6 gl-border-t-solid gl-border-gray-100 gl-border-t-1"
> >
<slot name="summary" :profile="value"></slot> <slot name="summary"></slot>
</div> </div>
</gl-form-group> </gl-form-group>
<template v-else> <template v-else>
......
...@@ -57,8 +57,8 @@ export default { ...@@ -57,8 +57,8 @@ export default {
) )
}}</template> }}</template>
<template #new-profile>{{ s__('OnDemandScans|Create a new scanner profile') }}</template> <template #new-profile>{{ s__('OnDemandScans|Create a new scanner profile') }}</template>
<template #summary="{ profile }"> <template #summary>
<slot name="summary" :profile="profile"></slot> <slot name="summary"></slot>
</template> </template>
</profile-selector> </profile-selector>
</template> </template>
...@@ -60,8 +60,8 @@ export default { ...@@ -60,8 +60,8 @@ export default {
) )
}}</template> }}</template>
<template #new-profile>{{ s__('OnDemandScans|Create a new site profile') }}</template> <template #new-profile>{{ s__('OnDemandScans|Create a new site profile') }}</template>
<template #summary="{ profile }"> <template #summary>
<slot name="summary" :profile="profile"></slot> <slot name="summary"></slot>
</template> </template>
</profile-selector> </profile-selector>
</template> </template>
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