1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
//
// A validating password field, with a label and error messages.
//
import React from 'react'
import { FormGroup, ControlLabel, FormControl, HelpBlock} from 'react-bootstrap'
import Validate from 'lib/validate'
export default class PasswordField extends React.Component {
static get defaultProps() {
return {
id: null, // required. controlId of the element
label: "Password",
onChange: null, // callback passed current password
validationMode: "crack", // one of 'none', 'match', 'crack'
matchText: null, // used if validationMode == 'match'
inputRef: null, // a ref to the input. Used to set focus
}
}
constructor(props) {
super(props)
this.state = {
password: null, // password value
passwordState: null, // password validation state
passwordError: false, // password help message
}
this.keypress = this.keypress.bind(this)
}
componentDidMount() {
if (this.props.validationMode == 'crack') {
Validate.loadPasswdLib()
}
}
render() {
let passwordHelp = null
if (this.state.passwordError) {
passwordHelp = <HelpBlock>{this.state.passwordError}</HelpBlock>
}
return (
<FormGroup controlId={this.props.id} validationState={this.state.passwordState}>
<ControlLabel>{this.props.label}</ControlLabel>
<FormControl
type="password"
inputRef={this.props.inputRef}
value={this.state.password || ""}
onChange={this.keypress}
/>
{this.state.passwordState == 'success' ? null : <FormControl.Feedback/>}
{passwordHelp}
</FormGroup>
)
}
keypress(e) {
let password = e.target.value
if (this.props.onChange) {
this.props.onChange(password)
}
this.setState({password: password})
if (this.props.validationMode == 'crack') {
if (password.length > 0) {
this.validateCrack(password)
} else {
this.setState({
passwordState: null,
passwordError: null
})
}
} else if (this.props.validationMode == 'match') {
this.validateMatch(password)
}
}
validateCrack(password) {
let state = null
let message = null
let result = Validate.passwordStrength(password)
if (result) {
message = "Time to crack: " + result.crack_times_display.offline_slow_hashing_1e4_per_second
if (result.score == 0) {
state = 'error'
} else if (result.score == 1 || result.score == 2) {
state = 'warning'
} else {
state = 'success'
}
}
this.setState({
passwordState: state,
passwordError: message
})
}
validateMatch(password) {
if (this.props.matchText) {
if (password != this.props.matchText) {
this.setState({
passwordState: 'error',
passwordError: "Does not match"
})
} else {
this.setState({
passwordState: 'success',
passwordError: null
})
}
}
}
}
|