Add MFA functionality
Этот коммит содержится в:
@@ -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>
|
||||
|
||||
Ссылка в новой задаче
Block a user