Commit 8efa247b authored by Dheeraj Joshi's avatar Dheeraj Joshi Committed by David O'Regan

Improve UX for redacted fields in DAST Profiles

parent 42954bd5
...@@ -60,11 +60,6 @@ export default { ...@@ -60,11 +60,6 @@ export default {
isSensitiveFieldRequired: !isEditMode, isSensitiveFieldRequired: !isEditMode,
}; };
}, },
computed: {
passwordFieldPlaceholder() {
return this.isEditMode ? '••••••••' : '';
},
},
watch: { watch: {
form: { handler: 'emitUpdate', immediate: true, deep: true }, form: { handler: 'emitUpdate', immediate: true, deep: true },
}, },
...@@ -128,7 +123,6 @@ export default { ...@@ -128,7 +123,6 @@ export default {
autocomplete="off" autocomplete="off"
name="password" name="password"
type="password" type="password"
:placeholder="passwordFieldPlaceholder"
:required="isSensitiveFieldRequired" :required="isSensitiveFieldRequired"
:state="form.fields.password.state" :state="form.fields.password.state"
/> />
......
...@@ -21,6 +21,8 @@ import { ...@@ -21,6 +21,8 @@ import {
MAX_CHAR_LIMIT_EXCLUDED_URLS, MAX_CHAR_LIMIT_EXCLUDED_URLS,
MAX_CHAR_LIMIT_REQUEST_HEADERS, MAX_CHAR_LIMIT_REQUEST_HEADERS,
EXCLUDED_URLS_SEPARATOR, EXCLUDED_URLS_SEPARATOR,
REDACTED_PASSWORD,
REDACTED_REQUEST_HEADERS,
} from '../constants'; } from '../constants';
import dastSiteProfileCreateMutation from '../graphql/dast_site_profile_create.mutation.graphql'; import dastSiteProfileCreateMutation from '../graphql/dast_site_profile_create.mutation.graphql';
import dastSiteProfileUpdateMutation from '../graphql/dast_site_profile_update.mutation.graphql'; import dastSiteProfileUpdateMutation from '../graphql/dast_site_profile_update.mutation.graphql';
...@@ -61,7 +63,8 @@ export default { ...@@ -61,7 +63,8 @@ export default {
}, },
}, },
data() { data() {
const { name = '', targetUrl = '', excludedUrls = [], auth = {} } = this.siteProfile || {}; const { name = '', targetUrl = '', excludedUrls = [], requestHeaders = '', auth = {} } =
this.siteProfile || {};
const form = { const form = {
state: false, state: false,
...@@ -75,7 +78,7 @@ export default { ...@@ -75,7 +78,7 @@ export default {
skipValidation: true, skipValidation: true,
}), }),
requestHeaders: initFormField({ requestHeaders: initFormField({
value: '', value: requestHeaders || '',
required: false, required: false,
skipValidation: true, skipValidation: true,
}), }),
...@@ -131,10 +134,8 @@ export default { ...@@ -131,10 +134,8 @@ export default {
tooltip: s__( tooltip: s__(
'DastProfiles|Request header names and values. Headers are added to every request made by DAST.', 'DastProfiles|Request header names and values. Headers are added to every request made by DAST.',
), ),
placeholder: this.hasRequestHeaders // eslint-disable-next-line @gitlab/require-i18n-strings
? __('[Redacted]') placeholder: 'Cache-control: no-cache, User-Agent: DAST/1.0',
: // eslint-disable-next-line @gitlab/require-i18n-strings
'Cache-control: no-cache, User-Agent: DAST/1.0',
}, },
}; };
}, },
...@@ -149,6 +150,14 @@ export default { ...@@ -149,6 +150,14 @@ export default {
.split(EXCLUDED_URLS_SEPARATOR) .split(EXCLUDED_URLS_SEPARATOR)
.map((url) => url.trim()); .map((url) => url.trim());
}, },
serializedAuthFields() {
const authFields = serializeFormObject(this.authSection.fields);
// not to send password value if unchanged
if (authFields.password === REDACTED_PASSWORD) {
delete authFields.password;
}
return authFields;
},
}, },
methods: { methods: {
onSubmit() { onSubmit() {
...@@ -166,7 +175,9 @@ export default { ...@@ -166,7 +175,9 @@ export default {
this.hideErrors(); this.hideErrors();
const { errorMessage } = this.i18n; const { errorMessage } = this.i18n;
const { profileName, targetUrl, ...additionalFields } = serializeFormObject(this.form.fields); const { profileName, targetUrl, requestHeaders, excludedUrls } = serializeFormObject(
this.form.fields,
);
const variables = { const variables = {
input: { input: {
...@@ -175,11 +186,13 @@ export default { ...@@ -175,11 +186,13 @@ export default {
profileName, profileName,
targetUrl, targetUrl,
...(this.glFeatures.securityDastSiteProfilesAdditionalFields && { ...(this.glFeatures.securityDastSiteProfilesAdditionalFields && {
...additionalFields, auth: this.serializedAuthFields,
auth: serializeFormObject(this.authSection.fields), ...(excludedUrls && {
...(additionalFields.excludedUrls && {
excludedUrls: this.parsedExcludedUrls, excludedUrls: this.parsedExcludedUrls,
}), }),
...(requestHeaders !== REDACTED_REQUEST_HEADERS && {
requestHeaders,
}),
}), }),
}, },
}; };
......
export const MAX_CHAR_LIMIT_EXCLUDED_URLS = 2048; export const MAX_CHAR_LIMIT_EXCLUDED_URLS = 2048;
export const MAX_CHAR_LIMIT_REQUEST_HEADERS = 2048; export const MAX_CHAR_LIMIT_REQUEST_HEADERS = 2048;
export const EXCLUDED_URLS_SEPARATOR = ','; export const EXCLUDED_URLS_SEPARATOR = ',';
export const REDACTED_PASSWORD = '••••••••';
export const REDACTED_REQUEST_HEADERS = '••••••••';
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module Dast module Dast
class SiteProfilePresenter < Gitlab::View::Presenter::Delegated class SiteProfilePresenter < Gitlab::View::Presenter::Delegated
REDACTED_PASSWORD = '••••••••' REDACTED_PASSWORD = '••••••••'
REDACTED_REQUEST_HEADERS = '[Redacted]' REDACTED_REQUEST_HEADERS = '••••••••'
presents :site_profile presents :site_profile
......
...@@ -186,30 +186,34 @@ describe('DastSiteProfileForm', () => { ...@@ -186,30 +186,34 @@ describe('DastSiteProfileForm', () => {
expect(findRequestHeadersInput().attributes('maxlength')).toBe('2048'); expect(findRequestHeadersInput().attributes('maxlength')).toBe('2048');
}); });
describe('should have correct placeholders', () => { describe('request-headers and password fields renders correctly', () => {
const defaultPlaceholder = 'Cache-control: no-cache, User-Agent: DAST/1.0';
it('when creating a new profile', async () => { it('when creating a new profile', async () => {
expect(findRequestHeadersInput().attributes('placeholder')).toBe(defaultPlaceholder); expect(findRequestHeadersInput().attributes('placeholder')).toBe(
'Cache-control: no-cache, User-Agent: DAST/1.0',
);
expect(findRequestHeadersInput().element.value).toBe('');
expect(findByNameAttribute('password').exists()).toBe(false);
}); });
it('when updating an existing profile with no request headers set', () => { it('when updating an existing profile', () => {
createFullComponent({ createFullComponent({
propsData: { propsData: {
siteProfile: { ...siteProfileOne, requestHeaders: '' }, siteProfile: siteProfileOne,
}, },
}); });
expect(findRequestHeadersInput().attributes('placeholder')).toBe(defaultPlaceholder); expect(findRequestHeadersInput().element.value).toBe(siteProfileOne.requestHeaders);
expect(findByNameAttribute('password').element.value).toBe(siteProfileOne.auth.password);
}); });
it('when updating an existing profile', () => { it('when updating an existing profile with no request-header & password', () => {
createFullComponent({ createFullComponent({
propsData: { propsData: {
siteProfile: siteProfileOne, siteProfile: { ...siteProfileOne, requestHeaders: null, auth: { enabled: true } },
}, },
}); });
expect(findRequestHeadersInput().attributes('placeholder')).toBe('[Redacted]'); expect(findRequestHeadersInput().element.value).toBe('');
expect(findByNameAttribute('password').attributes('placeholder')).toBe('••••••••'); expect(findByNameAttribute('password').element.value).toBe('');
}); });
}); });
}); });
......
...@@ -99,7 +99,7 @@ RSpec.describe GitlabSchema.types['DastSiteProfile'] do ...@@ -99,7 +99,7 @@ RSpec.describe GitlabSchema.types['DastSiteProfile'] do
it 'is redacted' do it 'is redacted' do
create(:dast_site_profile_secret_variable, dast_site_profile: object, key: Dast::SiteProfileSecretVariable::REQUEST_HEADERS) create(:dast_site_profile_secret_variable, dast_site_profile: object, key: Dast::SiteProfileSecretVariable::REQUEST_HEADERS)
expect(resolve_field(:request_headers, object, current_user: user)).to eq('[Redacted]') expect(resolve_field(:request_headers, object, current_user: user)).to eq('••••••••')
end end
end end
end end
......
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