Commit ec218553 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '280559-remove-dast-site-profile-validation' into 'master'

Remove validation from DAST site profile form

See merge request gitlab-org/gitlab!47701
parents f0b673bc d9cfd07d
<script>
import { isEqual } from 'lodash';
import {
GlAlert,
GlButton,
GlCollapse,
GlForm,
GlFormGroup,
GlFormInput,
GlModal,
GlToggle,
} from '@gitlab/ui';
import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput, GlModal } from '@gitlab/ui';
import { initFormField } from 'ee/security_configuration/utils';
import * as Sentry from '~/sentry/wrapper';
import { __, s__ } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
import { serializeFormObject } from '~/lib/utils/forms';
import { fetchPolicies } from '~/lib/graphql';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import validation from '~/vue_shared/directives/validation';
import DastSiteValidation from './dast_site_validation.vue';
import dastSiteProfileCreateMutation from '../graphql/dast_site_profile_create.mutation.graphql';
import dastSiteProfileUpdateMutation from '../graphql/dast_site_profile_update.mutation.graphql';
import dastSiteTokenCreateMutation from '../graphql/dast_site_token_create.mutation.graphql';
import dastSiteValidationQuery from '../graphql/dast_site_validation.query.graphql';
import { DAST_SITE_VALIDATION_STATUS, DAST_SITE_VALIDATION_POLL_INTERVAL } from '../constants';
const { PENDING, INPROGRESS, PASSED, FAILED } = DAST_SITE_VALIDATION_STATUS;
export default {
name: 'DastSiteProfileForm',
components: {
GlAlert,
GlButton,
GlCollapse,
GlForm,
GlFormGroup,
GlFormInput,
GlModal,
GlToggle,
DastSiteValidation,
},
directives: {
validation: validation(),
},
mixins: [glFeatureFlagsMixin()],
props: {
fullPath: {
type: String,
......@@ -72,18 +51,12 @@ export default {
};
return {
fetchValidationTimeout: null,
form,
initialFormValues: serializeFormObject(form.fields),
isFetchingValidationStatus: false,
isValidatingSite: false,
isLoading: false,
hasAlert: false,
tokenId: null,
token: null,
isSiteValidationActive: false,
isSiteValidationTouched: false,
validationStatus: null,
errorMessage: '',
errors: [],
};
......@@ -92,9 +65,6 @@ export default {
isEdit() {
return Boolean(this.siteProfile?.id);
},
isSiteValidationDisabled() {
return !this.form.fields.targetUrl.state || this.validationStatusMatches(INPROGRESS);
},
i18n() {
const { isEdit } = this;
return {
......@@ -111,163 +81,18 @@ export default {
okTitle: __('Discard'),
cancelTitle: __('Cancel'),
},
siteValidation: {
validationStatusFetchError: s__(
'DastProfiles|Could not retrieve site validation status. Please refresh the page, or try again later.',
),
createTokenError: s__(
'DastProfiles|Could not create site validation token. Please refresh the page, or try again later.',
),
},
};
},
formTouched() {
return !isEqual(serializeFormObject(this.form.fields), this.initialFormValues);
},
isSubmitDisabled() {
return (
this.validationStatusMatches(INPROGRESS) ||
(this.isSiteValidationActive && !this.validationStatusMatches(PASSED))
);
},
showValidationSection() {
return (
this.isSiteValidationActive &&
!this.isValidatingSite &&
![INPROGRESS, PASSED].some(this.validationStatusMatches)
);
},
siteValidationStatusDescription() {
const descriptions = {
[PENDING]: { text: s__('DastProfiles|Site must be validated to run an active scan.') },
[INPROGRESS]: {
text: s__('DastProfiles|Validation is in progress...'),
},
[PASSED]: {
text: s__(
'DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site.',
),
cssClass: 'gl-text-green-500',
},
[FAILED]: {
text: s__('DastProfiles|Validation failed. Please try again.'),
cssClass: 'gl-text-red-500',
dismissed: this.isSiteValidationTouched,
},
};
const defaultDescription = descriptions[PENDING];
const currentStatusDescription = descriptions[this.validationStatus];
return currentStatusDescription && !currentStatusDescription.dismissed
? currentStatusDescription
: defaultDescription;
},
},
async mounted() {
if (this.isEdit) {
this.form.showValidation = true;
if (this.glFeatures.securityOnDemandScansSiteValidation) {
await this.fetchValidationStatus();
this.isSiteValidationActive = this.validationStatusMatches(PASSED);
}
}
},
destroyed() {
clearTimeout(this.fetchValidationTimeout);
this.fetchValidationTimeout = null;
},
methods: {
async validateSite(validate) {
this.isSiteValidationActive = validate;
this.isSiteValidationTouched = true;
this.tokenId = null;
this.token = null;
if (!validate) {
this.validationStatus = null;
} else {
try {
this.isValidatingSite = true;
await this.fetchValidationStatus();
if (![PASSED, INPROGRESS].some(this.validationStatusMatches)) {
await this.createValidationToken();
}
} catch (exception) {
this.captureException(exception);
this.isSiteValidationActive = false;
} finally {
this.isValidatingSite = false;
}
}
},
validationStatusMatches(status) {
return this.validationStatus === status;
},
async fetchValidationStatus() {
this.isFetchingValidationStatus = true;
try {
const {
data: {
project: { dastSiteValidation },
},
} = await this.$apollo.query({
query: dastSiteValidationQuery,
variables: {
fullPath: this.fullPath,
targetUrl: this.form.fields.targetUrl.value,
},
fetchPolicy: fetchPolicies.NETWORK_ONLY,
});
this.validationStatus = dastSiteValidation?.status || null;
if (this.validationStatusMatches(INPROGRESS)) {
await new Promise(resolve => {
this.fetchValidationTimeout = setTimeout(resolve, DAST_SITE_VALIDATION_POLL_INTERVAL);
});
await this.fetchValidationStatus();
}
} catch (exception) {
this.showErrors({
message: this.i18n.siteValidation.validationStatusFetchError,
});
throw new Error(exception);
} finally {
this.isFetchingValidationStatus = false;
}
},
async createValidationToken() {
const errorMessage = this.i18n.siteValidation.createTokenError;
try {
const {
data: {
dastSiteTokenCreate: { id, token, errors = [] },
},
} = await this.$apollo.mutate({
mutation: dastSiteTokenCreateMutation,
variables: {
fullPath: this.fullPath,
targetUrl: this.form.fields.targetUrl.value,
},
});
if (errors.length) {
this.showErrors({ message: errorMessage, errors });
} else {
this.tokenId = id;
this.token = token;
}
} catch (exception) {
this.showErrors({ message: errorMessage });
throw new Error(exception);
}
},
onSubmit() {
this.form.showValidation = true;
......@@ -317,9 +142,6 @@ export default {
this.$refs[this.$options.modalId].show();
}
},
onValidationSuccess() {
this.validationStatus = PASSED;
},
discard() {
redirectTo(this.profilesLibraryPath);
},
......@@ -381,11 +203,6 @@ export default {
<gl-form-group
data-testid="target-url-input-group"
:invalid-feedback="form.fields.targetUrl.feedback"
:description="
isSiteValidationActive && !isValidatingSite
? s__('DastProfiles|Validation must be turned off to change the target URL')
: null
"
:label="s__('DastProfiles|Target URL')"
>
<gl-form-input
......@@ -397,44 +214,9 @@ export default {
required
type="url"
:state="form.fields.targetUrl.state"
:disabled="isSiteValidationActive"
/>
</gl-form-group>
<template v-if="glFeatures.securityOnDemandScansSiteValidation">
<gl-form-group :label="s__('DastProfiles|Validate target site')">
<template #description>
<p
v-if="siteValidationStatusDescription.text"
class="gl-mt-3"
:class="siteValidationStatusDescription.cssClass"
data-testid="siteValidationStatusDescription"
>
{{ siteValidationStatusDescription.text }}
</p>
</template>
<gl-toggle
data-testid="dast-site-validation-toggle"
:value="isSiteValidationActive"
:disabled="isSiteValidationDisabled"
:is-loading="
!isSiteValidationDisabled && (isFetchingValidationStatus || isValidatingSite)
"
@change="validateSite"
/>
</gl-form-group>
<gl-collapse :visible="showValidationSection">
<dast-site-validation
:full-path="fullPath"
:token-id="tokenId"
:token="token"
:target-url="form.fields.targetUrl.value"
@success="onValidationSuccess"
/>
</gl-collapse>
</template>
<hr />
<div class="gl-mt-6 gl-pt-6">
......@@ -443,7 +225,6 @@ export default {
variant="success"
class="js-no-auto-disable"
data-testid="dast-site-profile-form-submit-button"
:disabled="isSubmitDisabled"
:loading="isLoading"
>
{{ s__('DastProfiles|Save profile') }}
......
......@@ -8413,9 +8413,6 @@ msgstr ""
msgid "DastProfiles|Copy HTTP header to clipboard"
msgstr ""
msgid "DastProfiles|Could not create site validation token. Please refresh the page, or try again later."
msgstr ""
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
......@@ -8440,9 +8437,6 @@ msgstr ""
msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
msgstr ""
msgid "DastProfiles|Could not retrieve site validation status. Please refresh the page, or try again later."
msgstr ""
msgid "DastProfiles|Could not update the scanner profile. Please try again."
msgstr ""
......@@ -8557,9 +8551,6 @@ msgstr ""
msgid "DastProfiles|Site is not validated yet, please follow the steps."
msgstr ""
msgid "DastProfiles|Site must be validated to run an active scan."
msgstr ""
msgid "DastProfiles|Spider timeout"
msgstr ""
......@@ -8605,27 +8596,12 @@ msgstr ""
msgid "DastProfiles|Validate"
msgstr ""
msgid "DastProfiles|Validate target site"
msgstr ""
msgid "DastProfiles|Validating..."
msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the chosen method."
msgstr ""
msgid "DastProfiles|Validation failed. Please try again."
msgstr ""
msgid "DastProfiles|Validation is in progress..."
msgstr ""
msgid "DastProfiles|Validation must be turned off to change the target URL"
msgstr ""
msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
msgid "Data is still calculating..."
msgstr ""
......
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