aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/settings
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2016-09-09 12:17:13 +0200
committerGitHub <noreply@github.com>2016-09-09 12:17:13 +0200
commit6ee2c4f68d6c1667dc829abc4b1604f20f85c15d (patch)
tree59eb0cbc48b22f4ddd338953af079e449f0a4b98 /server/sonar-web/src/main/js/apps/settings
parent96fb42e56d1eceaae36808f62b773ce941e3bc68 (diff)
downloadsonarqube-6ee2c4f68d6c1667dc829abc4b1604f20f85c15d.tar.gz
sonarqube-6ee2c4f68d6c1667dc829abc4b1604f20f85c15d.zip
SONAR-7979 Rewrite the "Encryption" page (#1214)
Diffstat (limited to 'server/sonar-web/src/main/js/apps/settings')
-rw-r--r--server/sonar-web/src/main/js/apps/settings/app.js2
-rw-r--r--server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js68
-rw-r--r--server/sonar-web/src/main/js/apps/settings/encryption/EncryptionAppContainer.js28
-rw-r--r--server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js86
-rw-r--r--server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js89
-rw-r--r--server/sonar-web/src/main/js/apps/settings/store/encryptionPage/actions.js70
-rw-r--r--server/sonar-web/src/main/js/apps/settings/store/encryptionPage/reducer.js31
-rw-r--r--server/sonar-web/src/main/js/apps/settings/store/rootReducer.js4
8 files changed, 378 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/apps/settings/app.js b/server/sonar-web/src/main/js/apps/settings/app.js
index 02e7181d253..4cf6c73457e 100644
--- a/server/sonar-web/src/main/js/apps/settings/app.js
+++ b/server/sonar-web/src/main/js/apps/settings/app.js
@@ -24,6 +24,7 @@ import { Router, Route, Redirect, useRouterHistory } from 'react-router';
import { createHistory } from 'history';
import App from './components/App';
import LicensesApp from './licenses/LicensesApp';
+import EncryptionAppContainer from './encryption/EncryptionAppContainer';
import rootReducer from './store/rootReducer';
import configureStore from '../../components/store/configureStore';
@@ -46,6 +47,7 @@ window.sonarqube.appStarted.then(options => {
<Redirect from="/index" to="/"/>
<Route path="/" component={withComponent(App)}/>
<Route path="/licenses" component={LicensesApp}/>
+ <Route path="/encryption" component={EncryptionAppContainer}/>
</Router>
</Provider>
), el);
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
new file mode 100644
index 00000000000..fd356a3dd7f
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js
@@ -0,0 +1,68 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 GenerateSecretKeyForm from './GenerateSecretKeyForm';
+import EncryptionForm from './EncryptionForm';
+import GlobalMessagesContainer from '../components/GlobalMessagesContainer';
+import { translate } from '../../../helpers/l10n';
+
+export default class EncryptionApp extends React.Component {
+ static propTypes = {
+ loading: React.PropTypes.bool.isRequired,
+ secretKeyAvailable: React.PropTypes.bool,
+ secretKey: React.PropTypes.string,
+ encryptedValue: React.PropTypes.string,
+
+ checkSecretKey: React.PropTypes.func.isRequired,
+ generateSecretKey: React.PropTypes.func.isRequired,
+ encryptValue: React.PropTypes.func.isRequired,
+ startGeneration: React.PropTypes.func.isRequired
+ };
+
+ componentDidMount () {
+ this.props.checkSecretKey();
+ }
+
+ render () {
+ return (
+ <div id="encryption-page" className="page page-limited">
+ <header className="page-header">
+ <h1 className="page-title">{translate('property.category.security.encryption')}</h1>
+ {this.props.loading && <i className="spinner"/>}
+ </header>
+
+ <GlobalMessagesContainer/>
+
+ {!this.props.loading && !this.props.secretKeyAvailable && (
+ <GenerateSecretKeyForm
+ secretKey={this.props.secretKey}
+ generateSecretKey={this.props.generateSecretKey}/>
+ )}
+
+ {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/EncryptionAppContainer.js b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionAppContainer.js
new file mode 100644
index 00000000000..42bd05c788d
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionAppContainer.js
@@ -0,0 +1,28 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 { getEncryptionState } from '../store/rootReducer';
+
+export default connect(
+ state => getEncryptionState(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
new file mode 100644
index 00000000000..f07e5cd601e
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js
@@ -0,0 +1,86 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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';
+
+export default class EncryptionForm extends React.Component {
+ static propTypes = {
+ encryptedValue: React.PropTypes.string,
+ encryptValue: React.PropTypes.func.isRequired,
+ generateSecretKey: React.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">
+ Secret key is registered. You can encrypt any property value with the following form:
+ </div>
+
+ <form id="encryption-form" className="big-spacer-bottom" onSubmit={e => this.handleEncrypt(e)}>
+ <input
+ id="encryption-form-value"
+ className="input-large"
+ type="text"
+ autoFocus={true}
+ required={true}
+ value={this.state.value}
+ onChange={e => this.setState({ value: e.target.value })}/>
+ <button className="spacer-left">Encrypt</button>
+ </form>
+
+ {this.props.encryptedValue != null && (
+ <div>
+ Encrypted Value:{' '}
+ <input
+ id="encrypted-value"
+ className="input-super-large"
+ type="text"
+ readOnly={true}
+ value={this.props.encryptedValue}/>
+ </div>
+ )}
+
+ <div className="huge-spacer-top bordered-top">
+ <div className="big-spacer-top spacer-bottom">
+ Note that the secret key can be changed, but all the encrypted properties will have to be updated.
+ {' '}
+ <a href="http://redirect.sonarsource.com/doc/settings-encryption.html">More information</a>
+ </div>
+
+ <form id="encryption-new-key-form" onSubmit={e => this.handleGenerateNewKey(e)}>
+ <button>Generate New Secret Key</button>
+ </form>
+ </div>
+ </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
new file mode 100644
index 00000000000..65b70985d88
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js
@@ -0,0 +1,89 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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';
+
+export default class GenerateSecretKeyForm extends React.Component {
+ static propTypes = {
+ secretKey: React.PropTypes.string,
+ generateSecretKey: React.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">Secret Key</h3>
+ <input
+ id="secret-key"
+ className="input-large"
+ type="text"
+ readOnly={true}
+ value={this.props.secretKey}/>
+ </div>
+
+ <h3 className="spacer-bottom">How To Use</h3>
+
+ <ul className="list-styled markdown">
+ <li className="spacer-bottom">
+ 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 className="spacer-bottom">
+ Restrict access to this file by making it readable and by owner only
+ </li>
+ <li className="spacer-bottom">
+ Restart the server if the property <code>sonar.secretKeyPath</code> has been set or changed.
+ </li>
+ <li className="spacer-bottom">
+ 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>
+ </div>
+ ) : (
+ <div>
+ <p className="spacer-bottom">
+ Secret key is required to be able to encrypt properties.
+ {' '}
+ <a href="http://redirect.sonarsource.com/doc/settings-encryption.html">More information</a>
+ </p>
+
+ <form id="generate-secret-key-form" onSubmit={e => this.handleSubmit(e)}>
+ <button>Generate Secret Key</button>
+ </form>
+ </div>
+ )}
+ </div>
+ );
+ }
+}
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
new file mode 100644
index 00000000000..54bc6de0cec
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/store/encryptionPage/actions.js
@@ -0,0 +1,70 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 '../../../code/utils';
+import { addGlobalErrorMessage, closeAllGlobalMessages } from '../../../../components/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
new file mode 100644
index 00000000000..8ae88c7c127
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/store/encryptionPage/reducer.js
@@ -0,0 +1,31 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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;
diff --git a/server/sonar-web/src/main/js/apps/settings/store/rootReducer.js b/server/sonar-web/src/main/js/apps/settings/store/rootReducer.js
index e886b4616c0..0c3b7dfe214 100644
--- a/server/sonar-web/src/main/js/apps/settings/store/rootReducer.js
+++ b/server/sonar-web/src/main/js/apps/settings/store/rootReducer.js
@@ -23,12 +23,14 @@ import values, * as fromValues from './values/reducer';
import settingsPage, * as fromSettingsPage from './settingsPage/reducer';
import licenses, * as fromLicenses from './licenses/reducer';
import globalMessages, * as fromGlobalMessages from '../../../components/store/globalMessages';
+import encryptionPage from './encryptionPage/reducer';
const rootReducer = combineReducers({
definitions,
values,
settingsPage,
licenses,
+ encryptionPage,
globalMessages
});
@@ -58,4 +60,6 @@ export const getAllLicenseKeys = state => fromLicenses.getAllLicenseKeys(state.l
export const getValidationMessage = (state, key) => fromSettingsPage.getValidationMessage(state.settingsPage, key);
+export const getEncryptionState = state => state.encryptionPage;
+
export const getGlobalMessages = state => fromGlobalMessages.getGlobalMessages(state.globalMessages);