password_strength 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +5 -0
- data/README.rdoc +97 -0
- data/lib/password_strength.js +194 -0
- data/lib/password_strength.rb +17 -0
- data/lib/password_strength/active_record.rb +8 -0
- data/lib/password_strength/active_record/ar2.rb +34 -0
- data/lib/password_strength/active_record/ar3.rb +40 -0
- data/lib/password_strength/base.rb +153 -0
- data/lib/password_strength/version.rb +8 -0
- data/test/active_record_test.rb +48 -0
- data/test/jsunittest/jsunittest.js +1017 -0
- data/test/jsunittest/unittest.css +54 -0
- data/test/password_strength_test.html +50 -0
- data/test/password_strength_test.js +239 -0
- data/test/password_strength_test.rb +192 -0
- data/test/schema.rb +8 -0
- data/test/test_helper.rb +12 -0
- data/test/user.rb +1 -0
- metadata +86 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
body, div, p, h1, h2, h3, ul, ol, span, a, table, td, form, img, li {
|
2
|
+
font-family: sans-serif;
|
3
|
+
}
|
4
|
+
|
5
|
+
body {
|
6
|
+
font-size:0.8em;
|
7
|
+
}
|
8
|
+
|
9
|
+
#log {
|
10
|
+
padding-bottom: 1em;
|
11
|
+
border-bottom: 2px solid #000;
|
12
|
+
margin-bottom: 2em;
|
13
|
+
}
|
14
|
+
|
15
|
+
.logsummary {
|
16
|
+
margin-top: 1em;
|
17
|
+
margin-bottom: 1em;
|
18
|
+
padding: 1ex;
|
19
|
+
border: 1px solid #000;
|
20
|
+
font-weight: bold;
|
21
|
+
}
|
22
|
+
|
23
|
+
.logtable {
|
24
|
+
width:100%;
|
25
|
+
border-collapse: collapse;
|
26
|
+
border: 1px dotted #666;
|
27
|
+
}
|
28
|
+
|
29
|
+
.logtable td, .logtable th {
|
30
|
+
text-align: left;
|
31
|
+
padding: 3px 8px;
|
32
|
+
border: 1px dotted #666;
|
33
|
+
}
|
34
|
+
|
35
|
+
.logtable .passed {
|
36
|
+
background-color: #cfc;
|
37
|
+
}
|
38
|
+
|
39
|
+
.logtable .failed, .logtable .error {
|
40
|
+
background-color: #fcc;
|
41
|
+
}
|
42
|
+
|
43
|
+
.logtable .warning {
|
44
|
+
background-color: #FC6;
|
45
|
+
}
|
46
|
+
|
47
|
+
.logtable td div.action_buttons {
|
48
|
+
display: inline;
|
49
|
+
}
|
50
|
+
|
51
|
+
.logtable td div.action_buttons input {
|
52
|
+
margin: 0 5px;
|
53
|
+
font-size: 10px;
|
54
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<title>JavaScript unit test file</title>
|
6
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
7
|
+
<script src="jsunittest/jsunittest.js" type="text/javascript"></script>
|
8
|
+
<link rel="stylesheet" href="jsunittest/unittest.css" type="text/css" />
|
9
|
+
|
10
|
+
<style type="text/css" media="screen">
|
11
|
+
#logger p {
|
12
|
+
background: #ffc;
|
13
|
+
padding: 5px;
|
14
|
+
}
|
15
|
+
</style>
|
16
|
+
<script type="text/javascript" charset="utf-8">
|
17
|
+
function log(name, message) {
|
18
|
+
var tag = document.getElementById("logger");
|
19
|
+
message = message.toString();
|
20
|
+
message = message.replace(/&/gm, "&");
|
21
|
+
message = message.replace(/</gm, "<");
|
22
|
+
message = message.replace(/>/gm, ">");
|
23
|
+
tag.innerHTML += "<p><strong>" + name + ":</strong> " + message + "</p>";
|
24
|
+
}
|
25
|
+
</script>
|
26
|
+
<script src="../lib/password_strength.js" type="text/javascript"></script>
|
27
|
+
</head>
|
28
|
+
<body>
|
29
|
+
|
30
|
+
<div id="content">
|
31
|
+
<div id="header">
|
32
|
+
<h1>JavaScript unit test file</h1>
|
33
|
+
<p>
|
34
|
+
This file tests <strong>password_strength.js</strong>.
|
35
|
+
</p>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<!-- Log output (one per Runner, via {testLog: "testlog"} option)-->
|
39
|
+
<div id="testlog"></div>
|
40
|
+
|
41
|
+
<!-- General debugger -->
|
42
|
+
<div id="logger"></div>
|
43
|
+
|
44
|
+
<!-- Put sample/test html here -->
|
45
|
+
<div id="sample">
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
<script src="password_strength_test.js" type="text/javascript" charset="utf-8"></script>
|
49
|
+
</body>
|
50
|
+
</html>
|
@@ -0,0 +1,239 @@
|
|
1
|
+
new Test.Unit.Runner({
|
2
|
+
setup: function() {
|
3
|
+
strength = new PasswordStrength();
|
4
|
+
strength.username = "johndoe";
|
5
|
+
strength.password = "mypass";
|
6
|
+
},
|
7
|
+
|
8
|
+
teardown: function() {
|
9
|
+
},
|
10
|
+
|
11
|
+
// Shortcut
|
12
|
+
testShortcut: function() { with(this) {
|
13
|
+
strength = PasswordStrength.test("johndoe", "mypass");
|
14
|
+
|
15
|
+
assertEqual("johndoe", strength.username);
|
16
|
+
assertEqual("mypass", strength.password);
|
17
|
+
assertNotNull(strength.status);
|
18
|
+
}},
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
// Good strength
|
23
|
+
testGoodStrength: function() { with(this) {
|
24
|
+
strength.status = "good";
|
25
|
+
assert(strength.isGood());
|
26
|
+
assert(strength.isValid("good"));
|
27
|
+
assertEqual(false, strength.isWeak());
|
28
|
+
assertEqual(false, strength.isStrong());
|
29
|
+
}},
|
30
|
+
|
31
|
+
// Weak strength
|
32
|
+
testWeakStrength: function() { with(this) {
|
33
|
+
strength.status = "weak";
|
34
|
+
assert(strength.isWeak());
|
35
|
+
assert(strength.isValid("weak"));
|
36
|
+
assertEqual(false, strength.isStrong());
|
37
|
+
assertEqual(false, strength.isGood());
|
38
|
+
}},
|
39
|
+
|
40
|
+
// Strong strength
|
41
|
+
testStrongStrength: function() { with(this) {
|
42
|
+
strength.status = "strong";
|
43
|
+
assert(strength.isStrong());
|
44
|
+
assert(strength.isValid("strong"));
|
45
|
+
assert(strength.isValid("good"));
|
46
|
+
assertEqual(false, strength.isWeak());
|
47
|
+
assertEqual(false, strength.isGood());
|
48
|
+
}},
|
49
|
+
|
50
|
+
// Short password
|
51
|
+
testShortPassword: function() { with(this) {
|
52
|
+
strength.password = "123";
|
53
|
+
strength.test();
|
54
|
+
|
55
|
+
assertEqual(0, strength.score);
|
56
|
+
assertEqual("weak", strength.status);
|
57
|
+
}},
|
58
|
+
|
59
|
+
// Password equals to username
|
60
|
+
testPasswordEqualsToUsername: function() { with(this) {
|
61
|
+
// @strength.password = "johndoe"
|
62
|
+
// @strength.test
|
63
|
+
//
|
64
|
+
// assert_equal 0, @strength.score
|
65
|
+
// assert_equal :weak, @strength.status
|
66
|
+
|
67
|
+
strength.username = "johndoe";
|
68
|
+
strength.password = "johndoe";
|
69
|
+
strength.test();
|
70
|
+
|
71
|
+
assertEqual(0, strength.score);
|
72
|
+
assertEqual("weak", strength.status);
|
73
|
+
}},
|
74
|
+
|
75
|
+
// Strong password
|
76
|
+
testStrongPassword: function() { with(this) {
|
77
|
+
// @strength.password = "^P4ssw0rd$"
|
78
|
+
// @strength.test
|
79
|
+
//
|
80
|
+
// assert_equal 100, @strength.score
|
81
|
+
// assert_equal :strong, @strength.status
|
82
|
+
|
83
|
+
strength.password = "^P4ssw0rd$";
|
84
|
+
strength.test();
|
85
|
+
|
86
|
+
assertEqual(100, strength.score);
|
87
|
+
assertEqual("strong", strength.status);
|
88
|
+
}},
|
89
|
+
|
90
|
+
// Weak password
|
91
|
+
testWeakPassword: function() { with(this) {
|
92
|
+
strength.password = "1234567890";
|
93
|
+
strength.test()
|
94
|
+
assertEqual("weak", strength.status);
|
95
|
+
|
96
|
+
strength.password = "asdfghjklm";
|
97
|
+
strength.test();
|
98
|
+
assertEqual("weak", strength.status);
|
99
|
+
}},
|
100
|
+
|
101
|
+
// Good password
|
102
|
+
testGoodPassword: function() { with(this) {
|
103
|
+
strength.password = "12345asdfg";
|
104
|
+
strength.test();
|
105
|
+
assertEqual("good", strength.status);
|
106
|
+
|
107
|
+
strength.password = "12345ASDFG";
|
108
|
+
strength.test();
|
109
|
+
assertEqual("good", strength.status);
|
110
|
+
|
111
|
+
strength.password = "12345Aa";
|
112
|
+
strength.test();
|
113
|
+
assertEqual("good", strength.status);
|
114
|
+
}},
|
115
|
+
|
116
|
+
// Penalize password with chars only
|
117
|
+
testPenalizePasswordWithCharsOnly: function() { with(this) {
|
118
|
+
strength.password = "abcdef";
|
119
|
+
assertEqual(-15, strength.scoreFor("only_chars"));
|
120
|
+
}},
|
121
|
+
|
122
|
+
// Penalize password with numbers only
|
123
|
+
testPenalizePasswordWithNumbersOnly: function() { with(this) {
|
124
|
+
strength.password = "12345";
|
125
|
+
assertEqual(-15, strength.scoreFor("only_numbers"));
|
126
|
+
}},
|
127
|
+
|
128
|
+
// Penalize password equals to username
|
129
|
+
testPenalizePasswordEqualsToUsername: function() { with(this) {
|
130
|
+
strength.username = "johndoe";
|
131
|
+
strength.password = "johndoe";
|
132
|
+
assertEqual(-100, strength.scoreFor("username"));
|
133
|
+
}},
|
134
|
+
|
135
|
+
// Penalize password with username
|
136
|
+
testPenalizePasswordWithUsername: function() { with(this) {
|
137
|
+
strength.username = "johndoe";
|
138
|
+
strength.password = "$1234johndoe^";
|
139
|
+
assertEqual(-15, strength.scoreFor("username"));
|
140
|
+
}},
|
141
|
+
|
142
|
+
// Penalize number sequence
|
143
|
+
testPenalizeNumberSequence: function() { with(this) {
|
144
|
+
strength.password = "123";
|
145
|
+
assertEqual(-15, strength.scoreFor("sequences"));
|
146
|
+
|
147
|
+
strength.password = "123123";
|
148
|
+
assertEqual(-30, strength.scoreFor("sequences"));
|
149
|
+
}},
|
150
|
+
|
151
|
+
// Penalize letter sequence
|
152
|
+
testPenalizeLetterSequence: function() { with(this) {
|
153
|
+
strength.password = "abc";
|
154
|
+
assertEqual(-15, strength.scoreFor("sequences"));
|
155
|
+
|
156
|
+
strength.password = "abcabc";
|
157
|
+
assertEqual(-30, strength.scoreFor("sequences"));
|
158
|
+
}},
|
159
|
+
|
160
|
+
// Penalize number and letter sequence
|
161
|
+
testPenalizeNumberAndLetterSequence: function() { with(this) {
|
162
|
+
strength.password = "123abc";
|
163
|
+
assertEqual(-30, strength.scoreFor("sequences"));
|
164
|
+
|
165
|
+
strength.password = "123abc123abc";
|
166
|
+
assertEqual(-60, strength.scoreFor("sequences"));
|
167
|
+
}},
|
168
|
+
|
169
|
+
// Penalize same letter sequence
|
170
|
+
testPenalizeSameLetterSequence: function() { with(this) {
|
171
|
+
strength.password = "aaa";
|
172
|
+
assertEqual(-30, strength.scoreFor("sequences"));
|
173
|
+
}},
|
174
|
+
|
175
|
+
// Penalize same number sequence
|
176
|
+
testPenalizeSameNumberSequence: function() { with(this) {
|
177
|
+
strength.password = "111";
|
178
|
+
assertEqual(-30, strength.scoreFor("sequences"));
|
179
|
+
}},
|
180
|
+
|
181
|
+
// Penalize reversed sequence
|
182
|
+
testPenalizeReversedSequence: function() { with(this) {
|
183
|
+
strength.password = "cba321";
|
184
|
+
assertEqual(-30, strength.scoreFor("sequences"));
|
185
|
+
|
186
|
+
strength.password = "cba321cba321";
|
187
|
+
assertEqual(-60, strength.scoreFor("sequences"));
|
188
|
+
}},
|
189
|
+
|
190
|
+
// Penalize short password
|
191
|
+
testPenalizeShortPassword: function() { with(this) {
|
192
|
+
strength.password = "123";
|
193
|
+
assertEqual(-100, strength.scoreFor("password_size"));
|
194
|
+
}},
|
195
|
+
|
196
|
+
// Password length
|
197
|
+
testPasswordLength: function() { with(this) {
|
198
|
+
strength.password = "12345";
|
199
|
+
assertEqual(20, strength.scoreFor("password_size"));
|
200
|
+
}},
|
201
|
+
|
202
|
+
// Password with numbers
|
203
|
+
testPasswordWithNumbers: function() { with(this) {
|
204
|
+
strength.password = "123";
|
205
|
+
assertEqual(5, strength.scoreFor("numbers"));
|
206
|
+
}},
|
207
|
+
|
208
|
+
// Password with symbols
|
209
|
+
testPasswordWithSymbols: function() { with(this) {
|
210
|
+
strength.password = "$!";
|
211
|
+
assertEqual(5, strength.scoreFor("symbols"));
|
212
|
+
}},
|
213
|
+
|
214
|
+
// Password with uppercase and lowercase
|
215
|
+
testPasswordWithUppercaseAndLowercase: function() { with(this) {
|
216
|
+
strength.password = "aA";
|
217
|
+
assertEqual(10, strength.scoreFor("uppercase_lowercase"));
|
218
|
+
}},
|
219
|
+
|
220
|
+
// numbers and chars
|
221
|
+
testNumbersAndChars: function() { with(this) {
|
222
|
+
strength.password = "a1";
|
223
|
+
assertEqual(15, strength.scoreFor("numbers_chars"));
|
224
|
+
}},
|
225
|
+
|
226
|
+
// Numbers and symbols
|
227
|
+
testNumbersAndSymbols: function() { with(this) {
|
228
|
+
strength.password = "1$";
|
229
|
+
assertEqual(15, strength.scoreFor("numbers_symbols"));
|
230
|
+
}},
|
231
|
+
|
232
|
+
// Symbols and chars
|
233
|
+
testSymbolsAndChars: function() { with(this) {
|
234
|
+
strength.password = "a$";
|
235
|
+
assertEqual(15, strength.scoreFor("symbols_chars"));
|
236
|
+
}},
|
237
|
+
|
238
|
+
|
239
|
+
});
|
@@ -0,0 +1,192 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestPasswordStrength < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@strength = PasswordStrength::Base.new("johndoe", "mypass")
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_shortcut
|
9
|
+
@strength = PasswordStrength.test("johndoe", "mypass")
|
10
|
+
|
11
|
+
assert_kind_of PasswordStrength::Base, @strength
|
12
|
+
assert_equal "johndoe", @strength.username
|
13
|
+
assert_equal "mypass", @strength.password
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_good_strength
|
17
|
+
@strength.instance_variable_set("@status", :good)
|
18
|
+
assert @strength.good?
|
19
|
+
assert @strength.valid?(:good)
|
20
|
+
assert_equal false, @strength.weak?
|
21
|
+
assert_equal false, @strength.strong?
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_weak_strength
|
25
|
+
@strength.instance_variable_set("@status", :weak)
|
26
|
+
assert @strength.weak?
|
27
|
+
assert @strength.valid?(:weak)
|
28
|
+
assert_equal false, @strength.good?
|
29
|
+
assert_equal false, @strength.strong?
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_strong_strength
|
33
|
+
@strength.instance_variable_set("@status", :strong)
|
34
|
+
assert @strength.strong?
|
35
|
+
assert @strength.valid?(:strong)
|
36
|
+
assert @strength.valid?(:good)
|
37
|
+
assert_equal false, @strength.good?
|
38
|
+
assert_equal false, @strength.weak?
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_short_password
|
42
|
+
@strength.password = "123"
|
43
|
+
@strength.test
|
44
|
+
|
45
|
+
assert_equal 0, @strength.score
|
46
|
+
assert_equal :weak, @strength.status
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_password_equals_to_username
|
50
|
+
@strength.password = "johndoe"
|
51
|
+
@strength.test
|
52
|
+
|
53
|
+
assert_equal 0, @strength.score
|
54
|
+
assert_equal :weak, @strength.status
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_strong_password
|
58
|
+
@strength.password = "^P4ssw0rd$"
|
59
|
+
@strength.test
|
60
|
+
|
61
|
+
assert_equal 100, @strength.score
|
62
|
+
assert_equal :strong, @strength.status
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_weak_password
|
66
|
+
@strength.password = "1234567890"
|
67
|
+
@strength.test
|
68
|
+
assert_equal :weak, @strength.status
|
69
|
+
|
70
|
+
@strength.password = "asdfghjklm"
|
71
|
+
@strength.test
|
72
|
+
assert_equal :weak, @strength.status
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_good_password
|
76
|
+
@strength.password = "12345asdfg"
|
77
|
+
@strength.test
|
78
|
+
assert_equal :good, @strength.status
|
79
|
+
|
80
|
+
@strength.password = "12345ASDFG"
|
81
|
+
@strength.test
|
82
|
+
assert_equal :good, @strength.status
|
83
|
+
|
84
|
+
@strength.password = "12345Aa"
|
85
|
+
@strength.test
|
86
|
+
assert_equal :good, @strength.status
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_penalize_password_with_chars_only
|
90
|
+
@strength.password = "abcdef"
|
91
|
+
assert_equal -15, @strength.score_for(:only_chars)
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_penalize_password_with_numbers_only
|
95
|
+
@strength.password = "12345"
|
96
|
+
assert_equal -15, @strength.score_for(:only_numbers)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_penalize_password_equals_to_username
|
100
|
+
@strength.username = "johndoe"
|
101
|
+
@strength.password = "johndoe"
|
102
|
+
assert_equal -100, @strength.score_for(:username)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_penalize_password_with_username
|
106
|
+
@strength.username = "johndoe"
|
107
|
+
@strength.password = "$1234johndoe^"
|
108
|
+
assert_equal -15, @strength.score_for(:username)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_penalize_number_sequence
|
112
|
+
@strength.password = "123"
|
113
|
+
assert_equal -15, @strength.score_for(:sequences)
|
114
|
+
|
115
|
+
@strength.password = "123123"
|
116
|
+
assert_equal -30, @strength.score_for(:sequences)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_penalize_letter_sequence
|
120
|
+
@strength.password = "abc"
|
121
|
+
assert_equal -15, @strength.score_for(:sequences)
|
122
|
+
|
123
|
+
@strength.password = "abcabc"
|
124
|
+
assert_equal -30, @strength.score_for(:sequences)
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_penalize_number_and_letter_sequence
|
128
|
+
@strength.password = "123abc"
|
129
|
+
assert_equal -30, @strength.score_for(:sequences)
|
130
|
+
|
131
|
+
@strength.password = "123abc123abc"
|
132
|
+
assert_equal -60, @strength.score_for(:sequences)
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_penalize_same_letter_sequence
|
136
|
+
@strength.password = "aaa"
|
137
|
+
assert_equal -30, @strength.score_for(:sequences)
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_penalize_same_number_sequence
|
141
|
+
@strength.password = "111"
|
142
|
+
assert_equal -30, @strength.score_for(:sequences)
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_penalize_reversed_sequence
|
146
|
+
@strength.password = "cba321"
|
147
|
+
assert_equal -30, @strength.score_for(:sequences)
|
148
|
+
|
149
|
+
@strength.password = "cba321cba321"
|
150
|
+
assert_equal -60, @strength.score_for(:sequences)
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_penalize_short_password
|
154
|
+
@strength.password = "123"
|
155
|
+
assert_equal -100, @strength.score_for(:password_size)
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_password_length
|
159
|
+
@strength.password = "12345"
|
160
|
+
assert_equal 20, @strength.score_for(:password_size)
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_password_with_numbers
|
164
|
+
@strength.password = "123"
|
165
|
+
assert_equal 5, @strength.score_for(:numbers)
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_password_with_symbols
|
169
|
+
@strength.password = "$!"
|
170
|
+
assert_equal 5, @strength.score_for(:symbols)
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_password_with_upper_and_lower_chars
|
174
|
+
@strength.password = "aA"
|
175
|
+
assert_equal 10, @strength.score_for(:uppercase_lowercase)
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_password_with_numbers_and_chars
|
179
|
+
@strength.password = "a1"
|
180
|
+
assert_equal 15, @strength.score_for(:numbers_chars)
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_password_with_numbers_and_symbols
|
184
|
+
@strength.password = "1$"
|
185
|
+
assert_equal 15, @strength.score_for(:numbers_symbols)
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_password_with_symbols_and_chars
|
189
|
+
@strength.password = "a$"
|
190
|
+
assert_equal 15, @strength.score_for(:symbols_chars)
|
191
|
+
end
|
192
|
+
end
|