// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
import SettingItemMin from '../setting_item_min.jsx';
import SettingItemMax from '../setting_item_max.jsx';
import AccessHistoryModal from '../access_history_modal.jsx';
import ActivityLogModal from '../activity_log_modal.jsx';
import ToggleModalButton from '../toggle_modal_button.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import Client from 'utils/web_client.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage, FormattedTime, FormattedDate} from 'react-intl';
import {Link} from 'react-router/es6';
const holders = defineMessages({
currentPasswordError: {
id: 'user.settings.security.currentPasswordError',
defaultMessage: 'Please enter your current password'
},
passwordLengthError: {
id: 'user.settings.security.passwordLengthError',
defaultMessage: 'New passwords must be at least {min} characters and at most {max} characters.'
},
passwordMatchError: {
id: 'user.settings.security.passwordMatchError',
defaultMessage: 'The new passwords you entered do not match'
},
method: {
id: 'user.settings.security.method',
defaultMessage: 'Sign-in Method'
},
close: {
id: 'user.settings.security.close',
defaultMessage: 'Close'
}
});
import React from 'react';
class SecurityTab extends React.Component {
constructor(props) {
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();
}
getDefaultState() {
return {
currentPassword: '',
newPassword: '',
confirmPassword: '',
passwordError: '',
serverError: '',
authService: this.props.user.auth_service,
mfaShowQr: false,
mfaToken: ''
};
}
submitPassword(e) {
e.preventDefault();
var user = this.props.user;
var currentPassword = this.state.currentPassword;
var newPassword = this.state.newPassword;
var confirmPassword = this.state.confirmPassword;
const {formatMessage} = this.props.intl;
if (currentPassword === '') {
this.setState({passwordError: formatMessage(holders.currentPasswordError), serverError: ''});
return;
}
const passwordErr = Utils.isValidPassword(newPassword);
if (passwordErr !== '') {
this.setState({
passwordError: passwordErr,
serverError: ''
});
return;
}
if (newPassword !== confirmPassword) {
var defaultState = Object.assign(this.getDefaultState(), {passwordError: formatMessage(holders.passwordMatchError), serverError: ''});
this.setState(defaultState);
return;
}
Client.updatePassword(
user.id,
currentPassword,
newPassword,
() => {
this.props.updateSection('');
AsyncClient.getMe();
this.setState(this.getDefaultState());
},
(err) => {
var state = this.getDefaultState();
if (err.message) {
state.serverError = err.message;
} else {
state.serverError = err;
}
state.passwordError = '';
this.setState(state);
}
);
}
activateMfa() {
Client.updateMfa(
this.state.mfaToken,
true,
() => {
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() {
Client.updateMfa(
'',
false,
() => {
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});
}
updateNewPassword(e) {
this.setState({newPassword: e.target.value});
}
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 = (
);
extraInfo = (
);
} else if (this.state.mfaShowQr) {
content = (
);
extraInfo = (
);
submit = this.activateMfa;
} else {
content = (
);
extraInfo = (
);
}
const inputs = [];
inputs.push(
{content}
);
updateSectionStatus = function resetSection(e) {
this.props.updateSection('');
this.setState({mfaToken: '', mfaShowQr: false, mfaError: null, serverError: null});
e.preventDefault();
}.bind(this);
return (
);
}
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 (
);
}
createPasswordSection() {
let updateSectionStatus;
if (this.props.activeSection === 'password') {
const inputs = [];
let submit;
if (this.props.user.auth_service === '') {
submit = this.submitPassword;
inputs.push(
);
inputs.push(
);
inputs.push(
);
} else if (this.props.user.auth_service === Constants.GITLAB_SERVICE) {
inputs.push(
);
} else if (this.props.user.auth_service === Constants.LDAP_SERVICE) {
inputs.push(
);
}
updateSectionStatus = function resetSection(e) {
this.props.updateSection('');
this.setState({currentPassword: '', newPassword: '', confirmPassword: '', serverError: null, passwordError: null});
e.preventDefault();
$('.settings-modal .modal-body').scrollTop(0).perfectScrollbar('update');
}.bind(this);
return (
}
inputs={inputs}
submit={submit}
server_error={this.state.serverError}
client_error={this.state.passwordError}
updateSection={updateSectionStatus}
/>
);
}
let describe;
if (this.props.user.auth_service === '') {
const d = new Date(this.props.user.last_password_update);
const hours12 = !PreferenceStore.getBool(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, Constants.Preferences.USE_MILITARY_TIME, false);
describe = (
),
time: (
)
}}
/>
);
} else if (this.props.user.auth_service === Constants.GITLAB_SERVICE) {
describe = (
);
} else if (this.props.user.auth_service === Constants.LDAP_SERVICE) {
describe = (
);
}
updateSectionStatus = function updateSection() {
this.props.updateSection('password');
}.bind(this);
return (
}
describe={describe}
updateSection={updateSectionStatus}
/>
);
}
createSignInSection() {
let updateSectionStatus;
const user = this.props.user;
if (this.props.activeSection === 'signin') {
const teamName = TeamStore.getCurrent().name;
let emailOption;
if (global.window.mm_config.EnableSignUpWithEmail === 'true' && user.auth_service !== '') {
let link;
if (user.auth_service === Constants.LDAP_SERVICE) {
link = '/claim/ldap_to_email?email=' + encodeURIComponent(user.email);
} else {
link = '/claim/oauth_to_email?email=' + encodeURIComponent(user.email) + '&old_type=' + user.auth_service;
}
emailOption = (
);
}
let gitlabOption;
if (global.window.mm_config.EnableSignUpWithGitLab === 'true' && user.auth_service === '') {
gitlabOption = (
);
}
let googleOption;
if (global.window.mm_config.EnableSignUpWithGoogle === 'true' && user.auth_service === '') {
googleOption = (
);
}
let ldapOption;
if (global.window.mm_config.EnableLdap === 'true' && user.auth_service === '') {
ldapOption = (
);
}
let samlOption;
if (global.window.mm_config.EnableSaml === 'true' && user.auth_service === '') {
samlOption = (
);
}
const inputs = [];
inputs.push(
{emailOption}
{gitlabOption}
{ldapOption}
{samlOption}
{googleOption}
);
updateSectionStatus = function updateSection(e) {
this.props.updateSection('');
this.setState({serverError: null});
e.preventDefault();
}.bind(this);
const extraInfo = (
);
return (
);
}
updateSectionStatus = function updateSection() {
this.props.updateSection('signin');
}.bind(this);
let describe = (
);
if (this.props.user.auth_service === Constants.GITLAB_SERVICE) {
describe = (
);
} else if (this.props.user.auth_service === Constants.LDAP_SERVICE) {
describe = (
);
} else if (this.props.user.auth_service === Constants.SAML_SERVICE) {
describe = (
);
}
return (
);
}
render() {
const user = this.props.user;
const passwordSection = this.createPasswordSection();
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;
numMethods = global.window.mm_config.EnableSaml === 'true' ? numMethods + 1 : numMethods;
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' &&
(user.auth_service === '' || user.auth_service === Constants.LDAP_SERVICE)) {
mfaSection = this.createMfaSection();
}
return (
{passwordSection}
{mfaSection}
{signInSection}
);
}
}
SecurityTab.defaultProps = {
user: {},
activeSection: ''
};
SecurityTab.propTypes = {
intl: intlShape.isRequired,
user: React.PropTypes.object,
activeSection: React.PropTypes.string,
updateSection: React.PropTypes.func,
updateTab: React.PropTypes.func,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired,
setEnforceFocus: React.PropTypes.func.isRequired
};
export default injectIntl(SecurityTab);