ldx-widgets
Version:
widgets
229 lines (215 loc) • 7.89 kB
JavaScript
(function() {
var CheckboxInput, ENTER, MAX_PASSWORD_LENGTH, MIN_PASSWORD_LENGTH, PasswordInput, REMOVED_REQUIREMENTS, React, TextInput, _, div, h4, li, owasp, ref, span, ul;
React = require('react');
_ = require('lodash');
owasp = require('owasp-password-strength-test');
TextInput = React.createFactory(require('./text_input'));
CheckboxInput = React.createFactory(require('./checkbox_input'));
ENTER = require('../constants/keyboard').ENTER;
ref = React.DOM, div = ref.div, li = ref.li, h4 = ref.h4, ul = ref.ul, span = ref.span;
MIN_PASSWORD_LENGTH = 6;
MAX_PASSWORD_LENGTH = 15;
REMOVED_REQUIREMENTS = [2, 6];
PasswordInput = React.createClass({
displayName: 'PasswordInput',
propTypes: {
onChange: React.PropTypes.func
},
getInitialState: function() {
var test;
owasp.config({
minLength: MIN_PASSWORD_LENGTH,
maxLength: MAX_PASSWORD_LENGTH,
isPassphrase: false
});
test = owasp.test('');
return {
passwordTest: test,
passwordRequirements: this.buildTestRequirements(test),
currentPassword: null,
confirmPassword: null
};
},
getDefaultProps: function() {
return {
onChange: function() {},
inputColumnClass: 'col-3-12',
requirementsColumnClass: 'col-3-12',
confirmColumnClass: 'col-3-12',
className: 'grid grid-pad',
compact: false,
focusOnMount: false
};
},
isValid: function() {
var confirm, current;
current = this.refs.input.getValue();
if (this.refs.inputConfirm != null) {
confirm = this.refs.inputConfirm.getValue();
}
return (confirm != null ? confirm.length : void 0) && confirm === current && this.state.passwordTest.failedTests.length === 0;
},
render: function() {
var className, compact, confirmColumnClass, confirmField, confirmPassword, currentPassword, focusOnMount, inputColumnClass, isNewUser, passingTest, passwordErrors, passwordFailures, passwordRequirements, passwordTest, passwordsMatch, ref1, ref2, requirementsColumnClass, requirementsEls, resetPass;
ref1 = this.props, isNewUser = ref1.isNewUser, resetPass = ref1.resetPass, focusOnMount = ref1.focusOnMount, inputColumnClass = ref1.inputColumnClass, requirementsColumnClass = ref1.requirementsColumnClass, confirmColumnClass = ref1.confirmColumnClass, className = ref1.className, compact = ref1.compact;
ref2 = this.state, passwordTest = ref2.passwordTest, currentPassword = ref2.currentPassword, confirmPassword = ref2.confirmPassword, passwordRequirements = ref2.passwordRequirements;
passwordsMatch = currentPassword === confirmPassword;
passwordFailures = passwordTest.failedTests;
passwordErrors = passwordTest.errors;
passingTest = (passwordFailures != null ? passwordFailures.length : void 0) === 0;
if (passwordFailures && passwordFailures.length === 0) {
passingTest = true;
}
confirmField = TextInput({
key: 'inputConfirm',
ref: 'inputConfirm',
type: 'password',
autoComplete: this.props.autoComplete,
tabIndex: this.props.tabIndex,
placeholder: t('Confirm Password'),
onChange: this.testConfirmPassword,
wrapperClass: compact ? 'password-confirm' : null,
value: confirmPassword,
onKeyUp: this.handleKeyUp,
disabled: !passingTest
});
requirementsEls = passwordRequirements.concat([
passingTest ? li({
key: 'passMatch',
className: 'req-item'
}, [
span({
key: 'match-icon',
className: "icon-status " + (passwordsMatch ? 'success' : 'error')
}), span({
key: 'match-text',
className: 'req-text'
}, t('Passwords match'))
]) : void 0
]);
return div({
className: className
}, [
div({
key: 'inputs',
className: inputColumnClass
}, [
TextInput({
placeholder: t('Password'),
ref: 'input',
key: 'input',
type: 'password',
onChange: this.testCurrentPassword,
tabIndex: this.props.tabIndex
}), compact ? confirmField : void 0
]), !compact ? div({
key: 'confirm',
className: confirmColumnClass
}, confirmField) : void 0, div({
key: 'requirements',
className: requirementsColumnClass
}, [
h4({
key: 'pass-req-header',
className: 'password-reqs-header'
}, (t('Password requirements')) + ":"), ul({
key: 'pass-reqs',
className: 'password-reqs'
}, requirementsEls)
])
]);
},
componentDidMount: function() {
if (this.props.focusOnMount) {
return this.refs.input.focus();
}
},
getValue: function() {
var confirmPassword, currentPassword, passingTest, passwordFailures, passwordTest, passwordsMatch, ref1;
ref1 = this.state, passwordTest = ref1.passwordTest, currentPassword = ref1.currentPassword, confirmPassword = ref1.confirmPassword;
passwordsMatch = currentPassword === confirmPassword;
passwordFailures = passwordTest.failedTests;
passingTest = (passwordFailures != null ? passwordFailures.length : void 0) === 0;
if (!passwordsMatch || !passingTest) {
return '';
} else {
return confirmPassword;
}
},
handleKeyUp: function(e) {
var base;
if (e.keyCode !== ENTER) {
return;
}
if (this.isValid()) {
return typeof (base = this.props).handleKeyUp === "function" ? base.handleKeyUp() : void 0;
}
},
buildTestRequirements: function(test) {
var errors, failedTestErrors, failedTests, i, index, key, len, passwordRequirements, req, status, val;
failedTestErrors = {
0: t("At least __minLength__ characters", {
minLength: MIN_PASSWORD_LENGTH
}),
3: t("At least __count__ lowercase letter", {
count: 1
}),
4: t("At least __count__ uppercase letter", {
count: 1
}),
5: t("At least __count__ number", {
count: 1
})
};
passwordRequirements = [];
failedTests = test.failedTests, errors = test.errors;
for (i = 0, len = REMOVED_REQUIREMENTS.length; i < len; i++) {
req = REMOVED_REQUIREMENTS[i];
index = failedTests != null ? failedTests.indexOf(req) : void 0;
if (index > -1) {
failedTests.splice(index, 1);
}
if (index > -1) {
errors.splice(index, 1);
}
}
for (key in failedTestErrors) {
val = failedTestErrors[key];
status = failedTests.indexOf(+key) > -1 ? 'error' : 'success';
passwordRequirements.push(li({
key: key,
className: 'req-item'
}, [
span({
key: 'status',
className: "icon-status " + status
}, null), span({
key: 'val',
className: 'req-text'
}, val)
]));
}
return passwordRequirements;
},
testCurrentPassword: function(e) {
var test, value;
value = this.refs.input.getValue();
test = owasp.test(value);
return this.setState({
passwordTest: test,
currentPassword: value,
passwordRequirements: this.buildTestRequirements(test)
});
},
testConfirmPassword: function(e) {
var value;
value = this.refs.inputConfirm.getValue();
return this.setState({
confirmPassword: value
}, function() {
return this.props.onChange();
});
}
});
module.exports = PasswordInput;
}).call(this);