UNPKG

ldx-widgets

Version:

widgets

208 lines (169 loc) 5.49 kB
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' {div, li, h4, ul, span} = React.DOM MIN_PASSWORD_LENGTH = 6 MAX_PASSWORD_LENGTH = 15 REMOVED_REQUIREMENTS = [2, 6] PasswordInput = React.createClass displayName: 'PasswordInput' propTypes: onChange: React.PropTypes.func getInitialState: -> owasp.config minLength: MIN_PASSWORD_LENGTH maxLength: MAX_PASSWORD_LENGTH isPassphrase: false test = owasp.test('') return { passwordTest: test passwordRequirements: @buildTestRequirements(test) currentPassword: null confirmPassword: null } getDefaultProps: -> onChange: -> inputColumnClass: 'col-3-12' requirementsColumnClass: 'col-3-12' confirmColumnClass: 'col-3-12' className: 'grid grid-pad' compact: no focusOnMount: no isValid: -> current = @refs.input.getValue() confirm = @refs.inputConfirm.getValue() if @refs.inputConfirm? return confirm?.length and confirm is current and @state.passwordTest.failedTests.length is 0 render: -> {isNewUser, resetPass, focusOnMount, inputColumnClass, requirementsColumnClass, confirmColumnClass, className, compact} = @props {passwordTest, currentPassword, confirmPassword, passwordRequirements} = @state passwordsMatch = currentPassword is confirmPassword passwordFailures = passwordTest.failedTests passwordErrors = passwordTest.errors passingTest = passwordFailures?.length is 0 # remove certain tests for our purposes if passwordFailures and passwordFailures.length is 0 then passingTest = yes confirmField = TextInput { key: 'inputConfirm' ref: 'inputConfirm' type: 'password' autoComplete: @props.autoComplete tabIndex: @props.tabIndex placeholder: t 'Confirm Password' onChange: @testConfirmPassword wrapperClass: if compact then 'password-confirm' else null value: confirmPassword onKeyUp: @handleKeyUp disabled: not passingTest } requirementsEls = passwordRequirements.concat([ li { key: 'passMatch' className: 'req-item' }, [ span { key: 'match-icon' className: "icon-status #{if passwordsMatch then 'success' else 'error'}" } span { key: 'match-text' className: 'req-text' }, t('Passwords match') ] if passingTest ]) div { className: className }, [ div { key: 'inputs' className: inputColumnClass }, [ TextInput { placeholder: t 'Password' ref: 'input' key: 'input' type: 'password' onChange: @testCurrentPassword tabIndex: @props.tabIndex } confirmField if compact ] div { key: 'confirm' className: confirmColumnClass }, confirmField if not compact 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: -> if @props.focusOnMount then @refs.input.focus() getValue: -> {passwordTest, currentPassword, confirmPassword} = @state passwordsMatch = currentPassword is confirmPassword passwordFailures = passwordTest.failedTests passingTest = passwordFailures?.length is 0 if not passwordsMatch or not passingTest then '' else confirmPassword handleKeyUp: (e) -> return unless e.keyCode is ENTER @props.handleKeyUp?() if @isValid() buildTestRequirements: (test) -> 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, errors} = test # Remove specified requirements for req in REMOVED_REQUIREMENTS index = failedTests?.indexOf(req) if index > -1 then failedTests.splice(index, 1) if index > -1 then errors.splice(index, 1) # Display the remaining tests for key, val of failedTestErrors status = if failedTests.indexOf(+key) > -1 then 'error' else '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: (e) -> value = @refs.input.getValue() test = owasp.test(value) @setState { passwordTest: test currentPassword: value passwordRequirements: @buildTestRequirements(test) } testConfirmPassword: (e) -> value = @refs.inputConfirm.getValue() @setState confirmPassword: value , -> @props.onChange() module.exports = PasswordInput