]> source.dussan.org Git - sonarqube.git/commitdiff
Rewrite settings encryption app to TS
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Tue, 13 Nov 2018 09:38:17 +0000 (10:38 +0100)
committerSonarTech <sonartech@sonarsource.com>
Thu, 15 Nov 2018 19:20:59 +0000 (20:20 +0100)
15 files changed:
server/sonar-web/src/main/js/api/settings.ts
server/sonar-web/src/main/js/app/styles/init/forms.css
server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js [deleted file]
server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/settings/encryption/EncryptionAppContainer.js [deleted file]
server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js [deleted file]
server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js [deleted file]
server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/settings/routes.ts
server/sonar-web/src/main/js/apps/settings/store/encryptionPage/actions.js [deleted file]
server/sonar-web/src/main/js/apps/settings/store/encryptionPage/reducer.js [deleted file]
server/sonar-web/src/main/js/apps/settings/store/rootReducer.js
server/sonar-web/src/main/js/store/rootReducer.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 6df408faa6b48d8b90918df5d0c48b24bd278298..2c0ad2d72104e7d1d2abe986c01d446e9469eac5 100644 (file)
@@ -41,7 +41,7 @@ export interface Definition {
   type: string;
 }
 
-export function getDefinitions(component?: string): Promise<any> {
+export function getDefinitions(component?: string): Promise<{ definitions: Definition[] }> {
   return getJSON('/api/settings/list_definitions', { component }).then(r => r.definitions);
 }
 
@@ -93,14 +93,14 @@ export function sendTestEmail(to: string, subject: string, message: string): Pro
   return post('/api/emails/send', { to, subject, message });
 }
 
-export function checkSecretKey(): Promise<any> {
-  return getJSON('/api/settings/check_secret_key');
+export function checkSecretKey(): Promise<{ secretKeyAvailable: boolean }> {
+  return getJSON('/api/settings/check_secret_key').catch(throwGlobalError);
 }
 
-export function generateSecretKey(): Promise<any> {
-  return postJSON('/api/settings/generate_secret_key');
+export function generateSecretKey(): Promise<{ secretKey: string }> {
+  return postJSON('/api/settings/generate_secret_key').catch(throwGlobalError);
 }
 
-export function encryptValue(value: string): Promise<any> {
-  return postJSON('/api/settings/encrypt', { value });
+export function encryptValue(value: string): Promise<{ encryptedValue: string }> {
+  return postJSON('/api/settings/encrypt', { value }).catch(throwGlobalError);
 }
index 4d9d83329fd5dfbc4636503dfb4e1879b31ac438..d68a4eb42d8d71209b4e1cb0ddb8ed2e71f0c849 100644 (file)
@@ -171,6 +171,10 @@ textarea.input-super-large {
   background-color: transparent !important;
 }
 
+.input-clear {
+  background-color: transparent !important;
+}
+
 .input-code {
   font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
   font-size: var(--smallFontSize);
diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js
deleted file mode 100644 (file)
index 89f918d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import Helmet from 'react-helmet';
-import GenerateSecretKeyForm from './GenerateSecretKeyForm';
-import EncryptionForm from './EncryptionForm';
-import { translate } from '../../../helpers/l10n';
-
-export default class EncryptionApp extends React.PureComponent {
-  static propTypes = {
-    loading: PropTypes.bool.isRequired,
-    secretKeyAvailable: PropTypes.bool,
-    secretKey: PropTypes.string,
-    encryptedValue: PropTypes.string,
-
-    checkSecretKey: PropTypes.func.isRequired,
-    generateSecretKey: PropTypes.func.isRequired,
-    encryptValue: PropTypes.func.isRequired,
-    startGeneration: PropTypes.func.isRequired
-  };
-
-  componentDidMount() {
-    this.props.checkSecretKey();
-  }
-
-  render() {
-    return (
-      <div className="page page-limited" id="encryption-page">
-        <Helmet title={translate('property.category.security.encryption')} />
-        <header className="page-header">
-          <h1 className="page-title">{translate('property.category.security.encryption')}</h1>
-          {this.props.loading && <i className="spinner" />}
-        </header>
-
-        {!this.props.loading &&
-          !this.props.secretKeyAvailable && (
-            <GenerateSecretKeyForm
-              generateSecretKey={this.props.generateSecretKey}
-              secretKey={this.props.secretKey}
-            />
-          )}
-
-        {this.props.secretKeyAvailable && (
-          <EncryptionForm
-            encryptedValue={this.props.encryptedValue}
-            encryptValue={this.props.encryptValue}
-            generateSecretKey={this.props.startGeneration}
-          />
-        )}
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.tsx b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.tsx
new file mode 100644 (file)
index 0000000..441cecf
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import Helmet from 'react-helmet';
+import EncryptionForm from './EncryptionForm';
+import GenerateSecretKeyForm from './GenerateSecretKeyForm';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
+import { checkSecretKey, generateSecretKey } from '../../../api/settings';
+import { translate } from '../../../helpers/l10n';
+
+interface State {
+  loading: boolean;
+  secretKey?: string;
+  secretKeyAvailable?: boolean;
+}
+
+export default class EncryptionApp extends React.PureComponent<{}, State> {
+  state: State = { loading: true };
+  mounted = false;
+
+  componentDidMount() {
+    this.mounted = true;
+    this.checkSecretKey();
+  }
+
+  componentWillUnmount() {
+    this.mounted = false;
+  }
+
+  checkSecretKey = () => {
+    checkSecretKey().then(
+      ({ secretKeyAvailable }) => {
+        if (this.mounted) {
+          this.setState({ loading: false, secretKeyAvailable });
+        }
+      },
+      () => {
+        if (this.mounted) {
+          this.setState({ loading: false });
+        }
+      }
+    );
+  };
+
+  generateSecretKey = () => {
+    return generateSecretKey().then(({ secretKey }) => {
+      if (this.mounted) {
+        this.setState({ secretKey, secretKeyAvailable: false });
+      }
+    });
+  };
+
+  render() {
+    const { loading, secretKey, secretKeyAvailable } = this.state;
+    return (
+      <div className="page page-limited" id="encryption-page">
+        <Helmet title={translate('property.category.security.encryption')} />
+        <header className="page-header">
+          <h1 className="page-title">{translate('property.category.security.encryption')}</h1>
+          <DeferredSpinner loading={loading} />
+        </header>
+
+        {!loading &&
+          !secretKeyAvailable && (
+            <GenerateSecretKeyForm
+              generateSecretKey={this.generateSecretKey}
+              secretKey={secretKey}
+            />
+          )}
+
+        {secretKeyAvailable && <EncryptionForm generateSecretKey={this.generateSecretKey} />}
+      </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionAppContainer.js b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionAppContainer.js
deleted file mode 100644 (file)
index 80c24b3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { connect } from 'react-redux';
-import EncryptionApp from './EncryptionApp';
-import {
-  checkSecretKey,
-  generateSecretKey,
-  encryptValue,
-  startGeneration
-} from '../store/encryptionPage/actions';
-import { getSettingsAppEncryptionState } from '../../../store/rootReducer';
-
-export default connect(
-  state => getSettingsAppEncryptionState(state),
-  {
-    checkSecretKey,
-    generateSecretKey,
-    encryptValue,
-    startGeneration
-  }
-)(EncryptionApp);
diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js
deleted file mode 100644 (file)
index fef8d68..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import { translate } from '../../../helpers/l10n';
-import { SubmitButton } from '../../../components/ui/buttons';
-
-export default class EncryptionForm extends React.PureComponent {
-  static propTypes = {
-    encryptedValue: PropTypes.string,
-    encryptValue: PropTypes.func.isRequired,
-    generateSecretKey: PropTypes.func.isRequired
-  };
-
-  state = { value: '' };
-
-  handleEncrypt(e) {
-    e.preventDefault();
-    this.props.encryptValue(this.state.value);
-  }
-
-  handleGenerateNewKey(e) {
-    e.preventDefault();
-    this.props.generateSecretKey();
-  }
-
-  render() {
-    return (
-      <div id="encryption-form-container">
-        <div className="spacer-bottom">{translate('encryption.form_intro')}</div>
-
-        <form
-          className="big-spacer-bottom"
-          id="encryption-form"
-          onSubmit={e => this.handleEncrypt(e)}>
-          <textarea
-            autoFocus={true}
-            className="input-super-large"
-            id="encryption-form-value"
-            onChange={e => this.setState({ value: e.target.value })}
-            required={true}
-            rows={3}
-            value={this.state.value}
-          />
-          <div className="spacer-top">
-            <SubmitButton>{translate('encryption.encrypt')}</SubmitButton>
-          </div>
-        </form>
-
-        {this.props.encryptedValue != null && (
-          <div>
-            {translate('encryption.encrypted_value')}
-            {': '}
-            <input
-              className="input-clear input-code input-super-large"
-              id="encrypted-value"
-              readOnly={true}
-              type="text"
-              value={this.props.encryptedValue}
-            />
-          </div>
-        )}
-
-        <div className="huge-spacer-top bordered-top">
-          <div
-            className="big-spacer-top spacer-bottom"
-            dangerouslySetInnerHTML={{ __html: translate('encryption.form_note') }}
-          />
-          <form id="encryption-new-key-form" onSubmit={e => this.handleGenerateNewKey(e)}>
-            <SubmitButton>{translate('encryption.generate_new_secret_key')}</SubmitButton>
-          </form>
-        </div>
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx
new file mode 100644 (file)
index 0000000..2348e9b
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import ClipboardButton from '../../../components/controls/ClipboardButton';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
+import { SubmitButton } from '../../../components/ui/buttons';
+import { encryptValue } from '../../../api/settings';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+  generateSecretKey: () => Promise<void>;
+}
+
+interface State {
+  encryptedValue?: string;
+  encrypting: boolean;
+  generating: boolean;
+  value: string;
+}
+
+export default class EncryptionForm extends React.PureComponent<Props, State> {
+  mounted = false;
+  state: State = { encrypting: false, generating: false, value: '' };
+
+  componentDidMount() {
+    this.mounted = true;
+  }
+
+  componentWillUnmount() {
+    this.mounted = false;
+  }
+
+  handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
+    this.setState({ value: event.currentTarget.value });
+  };
+
+  handleEncrypt = (event: React.FormEvent) => {
+    event.preventDefault();
+    this.setState({ encrypting: true });
+    encryptValue(this.state.value).then(
+      ({ encryptedValue }) => {
+        if (this.mounted) {
+          this.setState({ encryptedValue, encrypting: false });
+        }
+      },
+      () => {
+        if (this.mounted) {
+          this.setState({ encrypting: false });
+        }
+      }
+    );
+  };
+
+  handleGenerateSecretKey = (event: React.FormEvent) => {
+    event.preventDefault();
+    this.setState({ generating: true });
+    this.props.generateSecretKey().then(this.stopGenerating, this.stopGenerating);
+  };
+
+  stopGenerating = () => {
+    if (this.mounted) {
+      this.setState({ generating: false });
+    }
+  };
+
+  render() {
+    const { encryptedValue, encrypting, generating } = this.state;
+    return (
+      <div id="encryption-form-container">
+        <div className="spacer-bottom">{translate('encryption.form_intro')}</div>
+        <form className="big-spacer-bottom" id="encryption-form" onSubmit={this.handleEncrypt}>
+          <textarea
+            autoFocus={true}
+            className="input-super-large"
+            id="encryption-form-value"
+            onChange={this.handleChange}
+            required={true}
+            rows={3}
+            value={this.state.value}
+          />
+          <div className="spacer-top">
+            <SubmitButton disabled={encrypting || generating}>
+              {translate('encryption.encrypt')}
+            </SubmitButton>
+            <DeferredSpinner className="spacer-left" loading={encrypting} />
+          </div>
+        </form>
+
+        {encryptedValue && (
+          <div>
+            <span className="little-spacer-right">{translate('encryption.encrypted_value')}</span>
+            <input
+              className="input-clear input-code input-super-large"
+              id="encrypted-value"
+              readOnly={true}
+              type="text"
+              value={encryptedValue}
+            />
+            <ClipboardButton className="little-spacer-left" copyValue={encryptedValue} />
+          </div>
+        )}
+
+        <form
+          className="huge-spacer-top bordered-top"
+          id="encryption-new-key-form"
+          onSubmit={this.handleGenerateSecretKey}>
+          <p className="big-spacer-top spacer-bottom">
+            <FormattedMessage
+              defaultMessage={translate('encryption.form_note')}
+              id="encryption.form_note"
+              values={{
+                moreInformationLink: (
+                  <a
+                    href="https://redirect.sonarsource.com/doc/settings-encryption.html"
+                    rel="noopener noreferrer"
+                    target="_blank">
+                    {translate('more_information')}
+                  </a>
+                )
+              }}
+            />
+          </p>
+
+          <SubmitButton disabled={generating || encrypting}>
+            {translate('encryption.generate_new_secret_key')}{' '}
+          </SubmitButton>
+          <DeferredSpinner className="spacer-left" loading={generating} />
+        </form>
+      </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js
deleted file mode 100644 (file)
index bec7d66..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import { translate } from '../../../helpers/l10n';
-import { SubmitButton } from '../../../components/ui/buttons';
-
-export default class GenerateSecretKeyForm extends React.PureComponent {
-  static propTypes = {
-    secretKey: PropTypes.string,
-    generateSecretKey: PropTypes.func.isRequired
-  };
-
-  handleSubmit = e => {
-    e.preventDefault();
-    this.props.generateSecretKey();
-  };
-
-  render() {
-    return (
-      <div id="generate-secret-key-form-container">
-        {this.props.secretKey != null ? (
-          <div>
-            <div className="big-spacer-bottom">
-              <h3 className="spacer-bottom">{translate('encryption.secret_key')}</h3>
-              <input
-                className="input-large"
-                id="secret-key"
-                readOnly={true}
-                type="text"
-                value={this.props.secretKey}
-              />
-            </div>
-
-            <h3 className="spacer-bottom">{translate('encryption.how_to_use')}</h3>
-
-            <div
-              className="markdown"
-              dangerouslySetInnerHTML={{ __html: translate('encryption.how_to_use.content') }}
-            />
-          </div>
-        ) : (
-          <div>
-            <p
-              className="spacer-bottom"
-              dangerouslySetInnerHTML={{ __html: translate('ecryption.secret_key_description') }}
-            />
-
-            <form id="generate-secret-key-form" onSubmit={this.handleSubmit}>
-              <SubmitButton>{translate('encryption.generate_secret_key')}</SubmitButton>
-            </form>
-          </div>
-        )}
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx
new file mode 100644 (file)
index 0000000..1855fe2
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import ClipboardButton from '../../../components/controls/ClipboardButton';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
+import { SubmitButton } from '../../../components/ui/buttons';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+  generateSecretKey: () => Promise<void>;
+  secretKey?: string;
+}
+
+interface State {
+  submitting: boolean;
+}
+
+export default class GenerateSecretKeyForm extends React.PureComponent<Props, State> {
+  mounted = false;
+  state: State = { submitting: false };
+
+  componentDidMount() {
+    this.mounted = true;
+  }
+
+  componentWillUnmount() {
+    this.mounted = false;
+  }
+
+  handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
+    event.preventDefault();
+    this.setState({ submitting: true });
+    this.props.generateSecretKey().then(this.stopSubmitting, this.stopSubmitting);
+  };
+
+  stopSubmitting = () => {
+    if (this.mounted) {
+      this.setState({ submitting: false });
+    }
+  };
+
+  render() {
+    const { secretKey } = this.props;
+    const { submitting } = this.state;
+    return (
+      <div id="generate-secret-key-form-container">
+        {secretKey ? (
+          <>
+            <div className="big-spacer-bottom">
+              <h3 className="spacer-bottom">{translate('encryption.secret_key')}</h3>
+              <input
+                className="input-clear input-code input-large"
+                id="secret-key"
+                readOnly={true}
+                type="text"
+                value={secretKey}
+              />
+              <ClipboardButton className="little-spacer-left" copyValue={secretKey} />
+            </div>
+            <h3 className="spacer-bottom">{translate('encryption.how_to_use')}</h3>
+            <div
+              className="markdown"
+              dangerouslySetInnerHTML={{ __html: translate('encryption.how_to_use.content') }}
+            />
+          </>
+        ) : (
+          <form id="generate-secret-key-form" onSubmit={this.handleSubmit}>
+            <p className="spacer-bottom">
+              <FormattedMessage
+                defaultMessage={translate('encryptionFormattedMessage.secret_key_description')}
+                id="encryption.secret_key_description"
+                values={{
+                  moreInformationLink: (
+                    <a
+                      href="https://redirect.sonarsource.com/doc/settings-encryption.html"
+                      rel="noopener noreferrer"
+                      target="_blank">
+                      {translate('more_information')}
+                    </a>
+                  )
+                }}
+              />
+            </p>
+            <SubmitButton disabled={submitting}>
+              {translate('encryption.generate_secret_key')}
+            </SubmitButton>
+            <DeferredSpinner className="spacer-left" loading={submitting} />
+          </form>
+        )}
+      </div>
+    );
+  }
+}
index 7c54dfe0d720b5174875b1bf9e77c8056acd3bd9..f16aad757b445ac7685046a5e5e61aabdd0e5f1e 100644 (file)
@@ -25,7 +25,7 @@ const routes = [
   },
   {
     path: 'encryption',
-    component: lazyLoad(() => import('./encryption/EncryptionAppContainer'))
+    component: lazyLoad(() => import('./encryption/EncryptionApp'))
   }
 ];
 
diff --git a/server/sonar-web/src/main/js/apps/settings/store/encryptionPage/actions.js b/server/sonar-web/src/main/js/apps/settings/store/encryptionPage/actions.js
deleted file mode 100644 (file)
index a8123a6..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import * as api from '../../../../api/settings';
-import { parseError } from '../../../../helpers/request';
-import { addGlobalErrorMessage, closeAllGlobalMessages } from '../../../../store/globalMessages';
-
-export const UPDATE_ENCRYPTION = 'UPDATE_ENCRYPTION';
-
-const updateEncryption = changes => ({
-  type: UPDATE_ENCRYPTION,
-  changes
-});
-
-const startLoading = dispatch => {
-  dispatch(updateEncryption({ loading: true }));
-  dispatch(closeAllGlobalMessages());
-};
-
-const handleError = dispatch => error => {
-  parseError(error).then(message => {
-    dispatch(addGlobalErrorMessage(message));
-    dispatch(updateEncryption({ loading: false }));
-  });
-};
-
-export const checkSecretKey = () => dispatch => {
-  startLoading(dispatch);
-  api
-    .checkSecretKey()
-    .then(data => dispatch(updateEncryption({ ...data, loading: false })))
-    .catch(handleError(dispatch));
-};
-
-export const generateSecretKey = () => dispatch => {
-  startLoading(dispatch);
-  api
-    .generateSecretKey()
-    .then(data =>
-      dispatch(
-        updateEncryption({
-          ...data,
-          secretKeyAvailable: false,
-          loading: false
-        })
-      )
-    )
-    .catch(handleError(dispatch));
-};
-
-export const encryptValue = value => dispatch => {
-  startLoading(dispatch);
-  api
-    .encryptValue(value)
-    .then(data => dispatch(updateEncryption({ ...data, loading: false })))
-    .catch(handleError(dispatch));
-};
-
-export const startGeneration = () => dispatch => {
-  dispatch(updateEncryption({ secretKeyAvailable: false, secretKey: undefined }));
-};
diff --git a/server/sonar-web/src/main/js/apps/settings/store/encryptionPage/reducer.js b/server/sonar-web/src/main/js/apps/settings/store/encryptionPage/reducer.js
deleted file mode 100644 (file)
index 3472ede..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { UPDATE_ENCRYPTION } from './actions';
-
-const initialState = { loading: true };
-
-const reducer = (state = initialState, action = {}) => {
-  if (action.type === UPDATE_ENCRYPTION) {
-    return { ...state, ...action.changes };
-  }
-  return state;
-};
-
-export default reducer;
index 37f7f1ecd563cb547d697dd2392791228be3707e..24b8555900389072eb97a82128a466738a2147d9 100644 (file)
@@ -20,7 +20,6 @@
 // @flow
 import { combineReducers } from 'redux';
 import definitions, * as fromDefinitions from './definitions/reducer';
-import encryptionPage from './encryptionPage/reducer';
 import values, * as fromValues from './values/reducer';
 import settingsPage, * as fromSettingsPage from './settingsPage/reducer';
 import globalMessages, * as fromGlobalMessages from '../../../store/globalMessages';
@@ -30,7 +29,6 @@ import globalMessages, * as fromGlobalMessages from '../../../store/globalMessag
 /*::
 type State = {
   definitions: {},
-  encryptionPage: {},
   globalMessages: GlobalMessagesState,
   settingsPage: {},
   values: ValuesState
@@ -41,7 +39,6 @@ const rootReducer = combineReducers({
   definitions,
   values,
   settingsPage,
-  encryptionPage,
   globalMessages
 });
 
@@ -78,7 +75,5 @@ export const isLoading = (state /*: State */, key /*: string */) =>
 export const getValidationMessage = (state /*: State */, key /*: string */) =>
   fromSettingsPage.getValidationMessage(state.settingsPage, key);
 
-export const getEncryptionState = (state /*: State */) => state.encryptionPage;
-
 export const getGlobalMessages = (state /*: State */) =>
   fromGlobalMessages.getGlobalMessages(state.globalMessages);
index e46f994f25eb05b45ed2c2bb24619afe0c6b572a..3d3bcfacec753d68ea8b916e95b26e465d66448d 100644 (file)
@@ -126,10 +126,6 @@ export function getSettingsAppValidationMessage(state: Store, key: string) {
   return fromSettingsApp.getValidationMessage(state.settingsApp, key);
 }
 
-export function getSettingsAppEncryptionState(state: Store) {
-  return fromSettingsApp.getEncryptionState(state.settingsApp);
-}
-
 export function getProjectAdminProjectModules(state: Store, projectKey: string) {
   return fromProjectAdminApp.getProjectModules(state.projectAdminApp, projectKey);
 }
index 14dde9c8641f8cfcb87138d49ed94d42e388d6c3..1c621e846718349586e604c890ef08a33f499bfc 100644 (file)
@@ -226,6 +226,7 @@ last_analysis_before=Last analysis before
 logging_out=You're logging out, please wait...
 manage=Manage
 management=Management
+more_information=More information
 my_organizations=My Organizations
 new_violations=New violations
 new_window=New window
@@ -2898,12 +2899,12 @@ portfolio.app.no_lines_of_code=All projects in this application are empty
 #
 #------------------------------------------------------------------------------
 encryption.form_intro=Secret key is registered. You can encrypt any property value with the following form:
-encryption.form_note=Note that the secret key can be changed, but all the encrypted properties will have to be updated. <a href="https://redirect.sonarsource.com/doc/settings-encryption.html">More information</a>
-encryption.encrypted_value=Encrypted Value
+encryption.form_note=Note that the secret key can be changed, but all the encrypted properties will have to be updated. {moreInformationLink}
+encryption.encrypted_value=Encrypted Value:
 encryption.generate_secret_key=Generate Secret Key
 encryption.generate_new_secret_key=Generate New Secret Key
 encryption.encrypt=Encrypt
-ecryption.secret_key_description=Secret key is required to be able to encrypt properties. <a href="https://redirect.sonarsource.com/doc/settings-encryption.html">More information</a>
+encryption.secret_key_description=Secret key is required to be able to encrypt properties. {moreInformationLink}
 encryption.secret_key=Secret Key
 encryption.how_to_use=How To Use
 encryption.how_to_use.content=<ul><li>Store the secret key in the file <code>~/.sonar/sonar-secret.txt</code> of the server. This file can be relocated by defining the property <code>sonar.secretKeyPath</code> in <code>conf/sonar.properties</code></li><li>Restrict access to this file by making it readable and by owner only</li><li>Restart the server if the property <code>sonar.secretKeyPath</code> has been set or changed.</li><li>Copy this file on all the machines that execute code inspection. Define the property <code>sonar.secretKeyPath</code> on those machines if the path is not <code>~/.sonar/sonar-secret.txt</code>.</li><li>For each property that you want to encrypt, generate the encrypted value and replace the original value wherever it is stored (configuration files, command lines).</li></ul>