summaryrefslogtreecommitdiffstats
path: root/webapp/components/user_settings/user_settings_security.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/components/user_settings/user_settings_security.jsx')
-rw-r--r--webapp/components/user_settings/user_settings_security.jsx223
1 files changed, 219 insertions, 4 deletions
diff --git a/webapp/components/user_settings/user_settings_security.jsx b/webapp/components/user_settings/user_settings_security.jsx
index f24beb6b3..e4044e6d0 100644
--- a/webapp/components/user_settings/user_settings_security.jsx
+++ b/webapp/components/user_settings/user_settings_security.jsx
@@ -47,12 +47,16 @@ class SecurityTab extends React.Component {
super(props);
this.submitPassword = this.submitPassword.bind(this);
+ this.activateMfa = this.activateMfa.bind(this);
+ this.deactivateMfa = this.deactivateMfa.bind(this);
this.updateCurrentPassword = this.updateCurrentPassword.bind(this);
this.updateNewPassword = this.updateNewPassword.bind(this);
this.updateConfirmPassword = this.updateConfirmPassword.bind(this);
+ this.updateMfaToken = this.updateMfaToken.bind(this);
this.getDefaultState = this.getDefaultState.bind(this);
this.createPasswordSection = this.createPasswordSection.bind(this);
this.createSignInSection = this.createSignInSection.bind(this);
+ this.showQrCode = this.showQrCode.bind(this);
this.state = this.getDefaultState();
}
@@ -61,7 +65,9 @@ class SecurityTab extends React.Component {
currentPassword: '',
newPassword: '',
confirmPassword: '',
- authService: this.props.user.auth_service
+ authService: this.props.user.auth_service,
+ mfaShowQr: false,
+ mfaToken: ''
};
}
submitPassword(e) {
@@ -112,6 +118,51 @@ class SecurityTab extends React.Component {
}
);
}
+ activateMfa() {
+ const data = {};
+ data.activate = true;
+ data.token = this.state.mfaToken;
+
+ Client.updateMfa(data,
+ () => {
+ this.props.updateSection('');
+ AsyncClient.getMe();
+ this.setState(this.getDefaultState());
+ },
+ (err) => {
+ const state = this.getDefaultState();
+ if (err.message) {
+ state.serverError = err.message;
+ } else {
+ state.serverError = err;
+ }
+ state.mfaError = '';
+ this.setState(state);
+ }
+ );
+ }
+ deactivateMfa() {
+ const data = {};
+ data.activate = false;
+
+ Client.updateMfa(data,
+ () => {
+ this.props.updateSection('');
+ AsyncClient.getMe();
+ this.setState(this.getDefaultState());
+ },
+ (err) => {
+ const state = this.getDefaultState();
+ if (err.message) {
+ state.serverError = err.message;
+ } else {
+ state.serverError = err;
+ }
+ state.mfaError = '';
+ this.setState(state);
+ }
+ );
+ }
updateCurrentPassword(e) {
this.setState({currentPassword: e.target.value});
}
@@ -121,6 +172,163 @@ class SecurityTab extends React.Component {
updateConfirmPassword(e) {
this.setState({confirmPassword: e.target.value});
}
+ updateMfaToken(e) {
+ this.setState({mfaToken: e.target.value});
+ }
+ showQrCode(e) {
+ e.preventDefault();
+ this.setState({mfaShowQr: true});
+ }
+ createMfaSection() {
+ let updateSectionStatus;
+ let submit;
+
+ if (this.props.activeSection === 'mfa') {
+ let content;
+ let extraInfo;
+ if (this.props.user.mfa_active) {
+ content = (
+ <div key='mfaQrCode'>
+ <a
+ className='btn btn-primary'
+ href='#'
+ onClick={this.deactivateMfa}
+ >
+ <FormattedMessage
+ id='user.settings.mfa.remove'
+ defaultMessage='Remove MFA from your account'
+ />
+ </a>
+ <br/>
+ </div>
+ );
+
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.mfa.removeHelp'
+ defaultMessage='Removing multi-factor authentication will make your account more vulnerable to attacks.'
+ />
+ </span>
+ );
+ } else if (this.state.mfaShowQr) {
+ content = (
+ <div key='mfaButton'>
+ <label className='col-sm-5 control-label'>
+ <FormattedMessage
+ id='user.settings.mfa.qrCode'
+ defaultMessage='QR Code'
+ />
+ </label>
+ <div className='col-sm-7'>
+ <img
+ className='qr-code-img'
+ src={'/api/v1/users/generate_mfa_qr?time=' + this.props.user.update_at}
+ />
+ </div>
+ <br/>
+ <label className='col-sm-5 control-label'>
+ <FormattedMessage
+ id='user.settings.mfa.enterToken'
+ defaultMessage='Token'
+ />
+ </label>
+ <div className='col-sm-7'>
+ <input
+ className='form-control'
+ type='text'
+ onChange={this.updateMfaToken}
+ value={this.state.mfaToken}
+ />
+ </div>
+ </div>
+ );
+
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.mfa.addHelp'
+ defaultMessage='Please scan the QR code with the Google Authenticator app on your smartphone and fill in the token with one provided by the app.'
+ />
+ </span>
+ );
+
+ submit = this.activateMfa;
+ } else {
+ content = (
+ <div key='mfaQrCode'>
+ <a
+ className='btn btn-primary'
+ href='#'
+ onClick={this.showQrCode}
+ >
+ <FormattedMessage
+ id='user.settings.mfa.add'
+ defaultMessage='Add MFA to your account'
+ />
+ </a>
+ <br/>
+ </div>
+ );
+
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.mfa.addHelp'
+ defaultMessage='To add multi-factor authentication to your account you must have a smartphone with Google Authenticator installed.'
+ />
+ </span>
+ );
+ }
+
+ const inputs = [];
+ inputs.push(
+ <div
+ key='mfaSetting'
+ className='form-group'
+ >
+ {content}
+ </div>
+ );
+
+ updateSectionStatus = function resetSection(e) {
+ this.props.updateSection('');
+ this.setState({mfaToken: '', mfaShowQr: false, mfaError: null});
+ e.preventDefault();
+ }.bind(this);
+
+ return (
+ <SettingItemMax
+ title={Utils.localizeMessage('user.settings.mfa.title', 'Multi-factor Authentication')}
+ inputs={inputs}
+ extraInfo={extraInfo}
+ submit={submit}
+ server_error={this.state.serverError}
+ client_error={this.state.mfaError}
+ updateSection={updateSectionStatus}
+ />
+ );
+ }
+
+ let describe;
+ if (this.props.user.mfa_active) {
+ describe = Utils.localizeMessage('user.settings.security.active', 'Active');
+ } else {
+ describe = Utils.localizeMessage('user.settings.security.inactive', 'Inactive');
+ }
+
+ updateSectionStatus = function updateSection() {
+ this.props.updateSection('mfa');
+ }.bind(this);
+
+ return (
+ <SettingItemMin
+ title={Utils.localizeMessage('user.settings.mfa.title', 'Multi-factor Authentication')}
+ describe={describe}
+ updateSection={updateSectionStatus}
+ />
+ );
+ }
createPasswordSection() {
let updateSectionStatus;
@@ -316,7 +524,6 @@ class SecurityTab extends React.Component {
const user = this.props.user;
if (this.props.activeSection === 'signin') {
- const inputs = [];
const teamName = TeamStore.getCurrent().name;
let emailOption;
@@ -398,6 +605,7 @@ class SecurityTab extends React.Component {
);
}
+ const inputs = [];
inputs.push(
<div key='userSignInOption'>
{emailOption}
@@ -463,17 +671,22 @@ class SecurityTab extends React.Component {
}
render() {
const passwordSection = this.createPasswordSection();
- let signInSection;
let numMethods = 0;
numMethods = global.window.mm_config.EnableSignUpWithGitLab === 'true' ? numMethods + 1 : numMethods;
numMethods = global.window.mm_config.EnableSignUpWithGoogle === 'true' ? numMethods + 1 : numMethods;
numMethods = global.window.mm_config.EnableLdap === 'true' ? numMethods + 1 : numMethods;
- if (global.window.mm_config.EnableSignUpWithEmail && numMethods > 0) {
+ let signInSection;
+ if (global.window.mm_config.EnableSignUpWithEmail === 'true' && numMethods > 0) {
signInSection = this.createSignInSection();
}
+ let mfaSection;
+ if (global.window.mm_config.EnableMultifactorAuthentication === 'true' && global.window.mm_license.IsLicensed === 'true') {
+ mfaSection = this.createMfaSection();
+ }
+
return (
<div>
<div className='modal-header'>
@@ -512,6 +725,8 @@ class SecurityTab extends React.Component {
<div className='divider-dark first'/>
{passwordSection}
<div className='divider-light'/>
+ {mfaSection}
+ <div className='divider-light'/>
{signInSection}
<div className='divider-dark'/>
<br></br>