aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWouter Admiraal <wouter.admiraal@sonarsource.com>2021-01-04 11:42:25 +0100
committersonartech <sonartech@sonarsource.com>2021-01-11 20:20:39 +0000
commit16d235022a4711857cde9d0953be3a864b1bfb83 (patch)
treef005208b8deb8fecbce1d89852bcc81cfa4afe24
parentfc6cecacf8b26c016bceddf5e34185af368555d0 (diff)
downloadsonarqube-16d235022a4711857cde9d0953be3a864b1bfb83.tar.gz
sonarqube-16d235022a4711857cde9d0953be3a864b1bfb83.zip
SONAR-12840 Toggle private field visibility on update
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx29
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx13
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap28
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap4
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap2
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties2
12 files changed, 82 insertions, 5 deletions
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx
index 33e6912b5ed..b86c8209f8f 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx
@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { ButtonLink } from 'sonar-ui-common/components/controls/buttons';
import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { AlmBindingDefinition } from '../../../../types/alm-settings';
@@ -30,6 +31,7 @@ export interface AlmBindingDefinitionFormFieldProps<B extends AlmBindingDefiniti
maxLength?: number;
onFieldChange: (id: keyof B, value: string) => void;
optional?: boolean;
+ overwriteOnly?: boolean;
propKey: keyof B;
readOnly?: boolean;
value: string;
@@ -44,12 +46,13 @@ export function AlmBindingDefinitionFormField<B extends AlmBindingDefinition>(
id,
isTextArea,
maxLength,
- onFieldChange,
optional,
+ overwriteOnly = false,
propKey,
readOnly = false,
value
} = props;
+ const [showField, setShowField] = React.useState(!overwriteOnly);
return (
<div className="modal-field">
@@ -58,18 +61,34 @@ export function AlmBindingDefinitionFormField<B extends AlmBindingDefinition>(
{!optional && <em className="mandatory">*</em>}
{help && <HelpTooltip className="spacer-left" overlay={help} placement="right" />}
</label>
- {isTextArea ? (
+
+ {!showField && overwriteOnly && (
+ <div>
+ <p>{translate('settings.almintegration.form.secret_field')}</p>
+ <ButtonLink
+ onClick={() => {
+ props.onFieldChange(propKey, '');
+ setShowField(true);
+ }}>
+ {translate('settings.almintegration.form.update_secret_field')}
+ </ButtonLink>
+ </div>
+ )}
+
+ {showField && isTextArea && (
<textarea
className="settings-large-input"
disabled={readOnly}
id={id}
maxLength={maxLength || 2000}
- onChange={e => onFieldChange(propKey, e.currentTarget.value)}
+ onChange={e => props.onFieldChange(propKey, e.currentTarget.value)}
required={!optional}
rows={5}
value={value}
/>
- ) : (
+ )}
+
+ {showField && !isTextArea && (
<input
autoFocus={autoFocus}
className="input-super-large"
@@ -77,7 +96,7 @@ export function AlmBindingDefinitionFormField<B extends AlmBindingDefinition>(
id={id}
maxLength={maxLength || 100}
name={id}
- onChange={e => onFieldChange(propKey, e.currentTarget.value)}
+ onChange={e => props.onFieldChange(propKey, e.currentTarget.value)}
size={50}
type="text"
value={value}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx
index d9256003073..182a44de178 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx
@@ -65,6 +65,7 @@ export default function AzureForm(props: AzureFormProps) {
id="personal_access_token"
isTextArea={true}
onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
propKey="personalAccessToken"
readOnly={readOnly}
value={formData.personalAccessToken}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx
index b0ad59b927e..504222cbdca 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx
@@ -66,6 +66,7 @@ export default function BitbucketForm(props: BitbucketFormProps) {
id="personal_access_token"
isTextArea={true}
onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
propKey="personalAccessToken"
readOnly={readOnly}
value={formData.personalAccessToken}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx
index 69bb366ef17..fe097ae0d60 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx
@@ -85,6 +85,7 @@ export default function GithubForm(props: GithubFormProps) {
id="client_secret"
maxLength={80}
onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
propKey="clientSecret"
readOnly={readOnly}
value={formData.clientSecret}
@@ -93,6 +94,7 @@ export default function GithubForm(props: GithubFormProps) {
id="private_key"
isTextArea={true}
onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
propKey="privateKey"
readOnly={readOnly}
value={formData.privateKey}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx
index 0c96f708b93..2ef0b83a92a 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx
@@ -65,6 +65,7 @@ export default function GitlabForm(props: GitlabFormProps) {
id="personal_access_token"
isTextArea={true}
onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
propKey="personalAccessToken"
readOnly={readOnly}
value={formData.personalAccessToken}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx
index e7dc957f134..1137b35be28 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx
@@ -19,6 +19,8 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { ButtonLink } from 'sonar-ui-common/components/controls/buttons';
+import { click } from 'sonar-ui-common/helpers/testUtils';
import { AlmBindingDefinition } from '../../../../../types/alm-settings';
import {
AlmBindingDefinitionFormField,
@@ -30,6 +32,7 @@ it('should render correctly', () => {
expect(shallowRender({ help: 'help' })).toMatchSnapshot('with help');
expect(shallowRender({ isTextArea: true })).toMatchSnapshot('textarea');
expect(shallowRender({ optional: true })).toMatchSnapshot('optional');
+ expect(shallowRender({ overwriteOnly: true })).toMatchSnapshot('secret');
});
it('should call onFieldChange', () => {
@@ -46,6 +49,16 @@ it('should call onFieldChange', () => {
expect(onTextAreaChange).toBeCalled();
});
+it('should correctly toggle visibility for secret fields', () => {
+ const onFieldChange = jest.fn();
+ const wrapper = shallowRender({ onFieldChange, overwriteOnly: true });
+ expect(wrapper.find('input').exists()).toBe(false);
+
+ click(wrapper.find(ButtonLink));
+ expect(onFieldChange).toHaveBeenCalledWith('key', '');
+ expect(wrapper.find('input').exists()).toBe(true);
+});
+
function shallowRender(
props: Partial<AlmBindingDefinitionFormFieldProps<AlmBindingDefinition>> = {}
) {
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap
index df0e1be514e..246cfcb1745 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap
@@ -53,6 +53,34 @@ exports[`should render correctly: optional 1`] = `
</div>
`;
+exports[`should render correctly: secret 1`] = `
+<div
+ className="modal-field"
+>
+ <label
+ className="display-flex-center"
+ htmlFor="key"
+ >
+ settings.almintegration.form.key
+ <em
+ className="mandatory"
+ >
+ *
+ </em>
+ </label>
+ <div>
+ <p>
+ settings.almintegration.form.secret_field
+ </p>
+ <ButtonLink
+ onClick={[Function]}
+ >
+ settings.almintegration.form.update_secret_field
+ </ButtonLink>
+ </div>
+</div>
+`;
+
exports[`should render correctly: textarea 1`] = `
<div
className="modal-field"
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap
index 48b2949cad4..e12787f70fd 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap
@@ -31,6 +31,7 @@ exports[`should render correctly: create 1`] = `
id="personal_access_token"
isTextArea={true}
onFieldChange={[MockFunction]}
+ overwriteOnly={false}
propKey="personalAccessToken"
value=""
/>
@@ -68,6 +69,7 @@ exports[`should render correctly: edit 1`] = `
id="personal_access_token"
isTextArea={true}
onFieldChange={[MockFunction]}
+ overwriteOnly={true}
propKey="personalAccessToken"
value="asdf1234"
/>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap
index b936abc487c..e19b6f4af80 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap
@@ -33,6 +33,7 @@ exports[`should render correctly 1`] = `
id="personal_access_token"
isTextArea={true}
onFieldChange={[MockFunction]}
+ overwriteOnly={false}
propKey="personalAccessToken"
value=""
/>
@@ -72,6 +73,7 @@ exports[`should render correctly 2`] = `
id="personal_access_token"
isTextArea={true}
onFieldChange={[MockFunction]}
+ overwriteOnly={true}
propKey="personalAccessToken"
value="asdf1234"
/>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap
index e64c54eb136..6ae40e3ac21 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap
@@ -51,6 +51,7 @@ exports[`should render correctly 1`] = `
id="client_secret"
maxLength={80}
onFieldChange={[MockFunction]}
+ overwriteOnly={false}
propKey="clientSecret"
value=""
/>
@@ -58,6 +59,7 @@ exports[`should render correctly 1`] = `
id="private_key"
isTextArea={true}
onFieldChange={[MockFunction]}
+ overwriteOnly={false}
propKey="privateKey"
value=""
/>
@@ -115,6 +117,7 @@ exports[`should render correctly 2`] = `
id="client_secret"
maxLength={80}
onFieldChange={[MockFunction]}
+ overwriteOnly={true}
propKey="clientSecret"
value="**clientsecret**"
/>
@@ -122,6 +125,7 @@ exports[`should render correctly 2`] = `
id="private_key"
isTextArea={true}
onFieldChange={[MockFunction]}
+ overwriteOnly={true}
propKey="privateKey"
value="asdf1234"
/>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap
index b3c74682498..10b9473011a 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap
@@ -31,6 +31,7 @@ exports[`should render correctly 1`] = `
id="personal_access_token"
isTextArea={true}
onFieldChange={[MockFunction]}
+ overwriteOnly={false}
propKey="personalAccessToken"
value=""
/>
@@ -68,6 +69,7 @@ exports[`should render correctly 2`] = `
id="personal_access_token"
isTextArea={true}
onFieldChange={[MockFunction]}
+ overwriteOnly={true}
propKey="personalAccessToken"
value="foobar"
/>
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index 881cf90af17..5e02164729c 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -1118,6 +1118,8 @@ settings.almintegration.form.personal_access_token.azure.help=Token of the user
settings.almintegration.form.personal_access_token.gitlab.help=Token of the user that will be used to decorate the Merge Requests. Needs API scope authorization.
settings.almintegration.form.save=Save configuration
settings.almintegration.form.cancel=Cancel
+settings.almintegration.form.secret_field=This field is hidden for security reasons.
+settings.almintegration.form.update_secret_field=Update field value
settings.almintegration.feature.pr_decoration.title=Pull Request Decoration
settings.almintegration.feature.pr_decoration.description=Add analysis and a Quality Gate to your Pull Requests directly in your ALM provider's interface.
settings.almintegration.feature.mr_decoration.title=Merge Request Decoration