zxcvbn-ruby 0.1.2 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ea3de385d539c52b8859c6f5a7b68b3c995ca14a
4
- data.tar.gz: 3da0c77713babf4ce1bda35e5744ea113c612c0b
2
+ SHA256:
3
+ metadata.gz: 3766aaa59eeb07a17e377051ad39091f2c96d52a76a5851476b7b163f81fdb10
4
+ data.tar.gz: d4b054399683992fca7845b4e175d372dd98a2e8bba7338841938529a7b80853
5
5
  SHA512:
6
- metadata.gz: 0e9622d9865fb93b686d26daecd864d49af288b003d54487f0b31d39ed29970f1c1f55de1b3d06c51a6b20ac90c0abbf08f300e19dac44116bc3562f469bc946
7
- data.tar.gz: e30863ef440be684e0d847cd8c108dad311522518098b52afcbb857071a8230369cd992a51e15c39a9adbb00d496f79347a0fb8697e9d8dc3d7dcdf2bdaacc9a
6
+ metadata.gz: 1860d4d74a4bc1f578c888fb9bd7f825ea05b36bcf5770a238be2630b1b928176908477650228522a30a5dc423ee25b45012bb091f72d1eafb951a7c0fef4657
7
+ data.tar.gz: 6453adfe0fc5c05a2a84ea319df97bd46a41ff0aed7ac875d19637e7aace42f8cc81df992fe3f454ed30e5c00d84113e9ceeecea2972336f562a18c39a81cb38
@@ -2,14 +2,12 @@ before_install:
2
2
  - gem install bundler
3
3
  language: ruby
4
4
  rvm:
5
- - '1.9'
6
- - '2.0'
7
- - '2.1'
8
- - '2.2'
9
- - '2.3.0'
5
+ - '2.3'
6
+ - '2.4'
7
+ - '2.5'
8
+ - '2.6'
10
9
  - ruby-head
11
10
  matrix:
12
11
  allow_failures:
13
12
  - rvm: ruby-head
14
13
  fast_finish: true
15
-
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [1.0.0] - 2019-05-14
10
+ ### Added
11
+ Adds more ported password checking features to bring this gem more up to date.
12
+ spatial - Keyboard patterns
13
+ repeat - Repeated characters
14
+ sequence - easily guessable sequences
15
+ date - date associations
16
+ [PR for further details](https://github.com/envato/zxcvbn-ruby/pull/22)
17
+
18
+ ### Removed
19
+ - This gem will no longer run on Ruby versions < 2.3
data/README.md CHANGED
@@ -18,10 +18,41 @@ Example usage:
18
18
  $ irb
19
19
  >> require 'zxcvbn'
20
20
  => true
21
- >> Zxcvbn.test('@lfred2004', ['alfred'])
22
- => #<Zxcvbn::Score:0x007fd467803098 @entropy=7.895, @crack_time=0.012, @crack_time_display="instant", @score=0, @match_sequence=[#<Zxcvbn::Match matched_word="alfred", token="@lfred", i=0, j=5, rank=1, pattern="dictionary", dictionary_name="user_inputs", l33t=true, sub={"@"=>"a"}, sub_display"@ -> a", base_entropy0.0, uppercase_entropy0.0, l33t_entropy1, entropy1.0, #<Zxcvbn::Match i=6, j=9, token="2004", pattern="year", entropy=6.894817763307944], @password="@lfred2004", @calc_time=0.003436>
23
- >> Zxcvbn.test('asdfghju7654rewq', ['alfred'])
24
- => #<Zxcvbn::Score:0x007fd4689c1168 @entropy=29.782, @crack_time=46159.451, @crack_time_display="14 hours", @score=2, @match_sequence=[#<Zxcvbn::Match pattern="spatial", i=0, j=15, token="asdfghju7654rewq", graph="qwerty", turns=5, shifted_count=0, entropy=29.7820508329166>], password"asdfghju7654rewq", calc_time0.00526
21
+ >> pp Zxcvbn.test('@lfred2004', ['alfred'])
22
+ #<Zxcvbn::Score:0x00007f7f590610c8
23
+ @calc_time=0.0055760000250302255,
24
+ @crack_time=0.012,
25
+ @crack_time_display="instant",
26
+ @entropy=7.895,
27
+ @feedback=
28
+ #<Zxcvbn::Feedback:0x00007f7f59060150
29
+ @suggestions=
30
+ ["Add another word or two. Uncommon words are better.",
31
+ "Predictable substitutions like '@' instead of 'a' don't help very much"],
32
+ @warning=nil>,
33
+ @match_sequence=
34
+ [#<Zxcvbn::Match matched_word="alfred", token="@lfred", i=0, j=5, rank=1, pattern="dictionary", dictionary_name="user_inputs", l33t=true, sub={"@"=>"a"}, sub_display="@ -> a", base_entropy=0.0, uppercase_entropy=0.0, l33t_entropy=1, entropy=1.0>,
35
+ #<Zxcvbn::Match i=6, j=9, token="2004", pattern="year", entropy=6.894817763307944>],
36
+ @password="@lfred2004",
37
+ @score=0>
38
+ => #<Zxcvbn::Score:0x00007f7f59060150>
39
+ >> pp Zxcvbn.test('asdfghju7654rewq', ['alfred'])
40
+ #<Zxcvbn::Score:0x00007f7f5a9e9248
41
+ @calc_time=0.007504999986849725,
42
+ @crack_time=46159.451,
43
+ @crack_time_display="14 hours",
44
+ @entropy=29.782,
45
+ @feedback=
46
+ #<Zxcvbn::Feedback:0x00007f7f5a9e9130
47
+ @suggestions=
48
+ ["Add another word or two. Uncommon words are better.",
49
+ "Use a longer keyboard pattern with more turns"],
50
+ @warning="Short keyboard patterns are easy to guess">,
51
+ @match_sequence=
52
+ [#<Zxcvbn::Match pattern="spatial", i=0, j=15, token="asdfghju7654rewq", graph="qwerty", turns=5, shifted_count=0, entropy=29.7820508329166>],
53
+ @password="asdfghju7654rewq",
54
+ @score=2>
55
+ => #<Zxcvbn::Score:0x00007f7f5a9e9248>
25
56
  ```
26
57
 
27
58
  ## Testing Multiple Passwords
@@ -34,10 +65,42 @@ $ irb
34
65
  => true
35
66
  >> tester = Zxcvbn::Tester.new
36
67
  => #<Zxcvbn::Tester:0x3fe99d869aa4>
37
- >> tester.test('@lfred2004', ['alfred'])
38
- => #<Zxcvbn::Score:0x007fd4689c1168 @entropy=29.782, @crack_time=46159.451, @crack_time_display="14 hours", @score=2, @match_sequence=[#<Zxcvbn::Match pattern="spatial", i=0, j=15, token="asdfghju7654rewq", graph="qwerty", turns=5, shifted_count=0, entropy=29.7820508329166>], password"asdfghju7654rewq", calc_time0.00526
39
- >> tester.test('@lfred2004', ['alfred'])
40
- => #<Zxcvbn::Score:0x007fd4689c1168 @entropy=29.782, @crack_time=46159.451, @crack_time_display="14 hours", @score=2, @match_sequence=[#<Zxcvbn::Match pattern="spatial", i=0, j=15, token="asdfghju7654rewq", graph="qwerty", turns=5, shifted_count=0, entropy=29.7820508329166>], password"asdfghju7654rewq", calc_time0.00526
68
+ >> pp tester.test('@lfred2004', ['alfred'])
69
+ #<Zxcvbn::Score:0x00007f7f586fcf50
70
+ @calc_time=0.00631899997824803,
71
+ @crack_time=0.012,
72
+ @crack_time_display="instant",
73
+ @entropy=7.895,
74
+ @feedback=
75
+ #<Zxcvbn::Feedback:0x00007f7f586fcac8
76
+ @suggestions=
77
+ ["Add another word or two. Uncommon words are better.",
78
+ "Predictable substitutions like '@' instead of 'a' don't help very much"],
79
+ @warning=nil>,
80
+ @match_sequence=
81
+ [#<Zxcvbn::Match matched_word="alfred", token="@lfred", i=0, j=5, rank=1, pattern="dictionary", dictionary_name="user_inputs", l33t=true, sub={"@"=>"a"}, sub_display="@ -> a", base_entropy=0.0, uppercase_entropy=0.0, l33t_entropy=1, entropy=1.0>,
82
+ #<Zxcvbn::Match i=6, j=9, token="2004", pattern="year", entropy=6.894817763307944>],
83
+ @password="@lfred2004",
84
+ @score=0>
85
+ => #<Zxcvbn::Score:0x00007f7f586fcf50>
86
+ >> pp tester.test('@lfred2004', ['alfred'])
87
+ #<Zxcvbn::Score:0x00007f7f56d57438
88
+ @calc_time=0.001986999996006489,
89
+ @crack_time=0.012,
90
+ @crack_time_display="instant",
91
+ @entropy=7.895,
92
+ @feedback=
93
+ #<Zxcvbn::Feedback:0x00007f7f56d56bf0
94
+ @suggestions=
95
+ ["Add another word or two. Uncommon words are better.",
96
+ "Predictable substitutions like '@' instead of 'a' don't help very much"],
97
+ @warning=nil>,
98
+ @match_sequence=
99
+ [#<Zxcvbn::Match matched_word="alfred", token="@lfred", i=0, j=5, rank=1, pattern="dictionary", dictionary_name="user_inputs", l33t=true, sub={"@"=>"a"}, sub_display="@ -> a", base_entropy=0.0, uppercase_entropy=0.0, l33t_entropy=1, entropy=1.0>,
100
+ #<Zxcvbn::Match i=6, j=9, token="2004", pattern="year", entropy=6.894817763307944>],
101
+ @password="@lfred2004",
102
+ @score=0>
103
+ => #<Zxcvbn::Score:0x00007f7f56d57438>
41
104
  ```
42
105
 
43
106
  **Note**: Storing the entropy of an encrypted or hashed value provides
@@ -0,0 +1,10 @@
1
+ module Zxcvbn
2
+ class Feedback
3
+ attr_accessor :warning, :suggestions
4
+
5
+ def initialize(options = {})
6
+ @warning = options[:warning]
7
+ @suggestions = options[:suggestions] || []
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,133 @@
1
+ require 'zxcvbn/entropy'
2
+ require 'zxcvbn/feedback'
3
+
4
+ module Zxcvbn
5
+ class FeedbackGiver
6
+ NAME_DICTIONARIES = %w[surnames male_names female_names].freeze
7
+
8
+ DEFAULT_FEEDBACK = Feedback.new(
9
+ suggestions: [
10
+ 'Use a few words, avoid common phrases',
11
+ 'No need for symbols, digits, or uppercase letters'
12
+ ]
13
+ ).freeze
14
+
15
+ EMPTY_FEEDBACK = Feedback.new.freeze
16
+
17
+ def self.get_feedback(score, sequence)
18
+ # starting feedback
19
+ return DEFAULT_FEEDBACK if sequence.length.zero?
20
+
21
+ # no feedback if score is good or great.
22
+ return EMPTY_FEEDBACK if score > 2
23
+
24
+ # tie feedback to the longest match for longer sequences
25
+ longest_match = sequence[0]
26
+ for match in sequence[1..-1]
27
+ longest_match = match if match.token.length > longest_match.token.length
28
+ end
29
+
30
+ feedback = get_match_feedback(longest_match, sequence.length == 1)
31
+ extra_feedback = 'Add another word or two. Uncommon words are better.'
32
+
33
+ if feedback.nil?
34
+ feedback = Feedback.new(suggestions: [extra_feedback])
35
+ else
36
+ feedback.suggestions.unshift extra_feedback
37
+ end
38
+
39
+ feedback
40
+ end
41
+
42
+ def self.get_match_feedback(match, is_sole_match)
43
+ case match.pattern
44
+ when 'dictionary'
45
+ get_dictionary_match_feedback match, is_sole_match
46
+
47
+ when 'spatial'
48
+ layout = match.graph.upcase
49
+ warning = if match.turns == 1
50
+ 'Straight rows of keys are easy to guess'
51
+ else
52
+ 'Short keyboard patterns are easy to guess'
53
+ end
54
+
55
+ Feedback.new(
56
+ warning: warning,
57
+ suggestions: [
58
+ 'Use a longer keyboard pattern with more turns'
59
+ ]
60
+ )
61
+
62
+ when 'repeat'
63
+ Feedback.new(
64
+ warning: 'Repeats like "aaa" are easy to guess',
65
+ suggestions: [
66
+ 'Avoid repeated words and characters'
67
+ ]
68
+ )
69
+
70
+ when 'sequence'
71
+ Feedback.new(
72
+ warning: 'Sequences like abc or 6543 are easy to guess',
73
+ suggestions: [
74
+ 'Avoid sequences'
75
+ ]
76
+ )
77
+
78
+ when 'date'
79
+ Feedback.new(
80
+ warning: 'Dates are often easy to guess',
81
+ suggestions: [
82
+ 'Avoid dates and years that are associated with you'
83
+ ]
84
+ )
85
+ end
86
+ end
87
+
88
+ def self.get_dictionary_match_feedback(match, is_sole_match)
89
+ warning = if match.dictionary_name == 'passwords'
90
+ if is_sole_match && !match.l33t && !match.reversed
91
+ if match.rank <= 10
92
+ 'This is a top-10 common password'
93
+ elsif match.rank <= 100
94
+ 'This is a top-100 common password'
95
+ else
96
+ 'This is a very common password'
97
+ end
98
+ else
99
+ 'This is similar to a commonly used password'
100
+ end
101
+ elsif NAME_DICTIONARIES.include? match.dictionary_name
102
+ if is_sole_match
103
+ 'Names and surnames by themselves are easy to guess'
104
+ else
105
+ 'Common names and surnames are easy to guess'
106
+ end
107
+ end
108
+
109
+ suggestions = []
110
+ word = match.token
111
+
112
+ if word =~ Zxcvbn::Entropy::START_UPPER
113
+ suggestions.push "Capitalization doesn't help very much"
114
+ elsif word =~ Zxcvbn::Entropy::ALL_UPPER && word.downcase != word
115
+ suggestions.push(
116
+ 'All-uppercase is almost as easy to guess as all-lowercase'
117
+ )
118
+ end
119
+
120
+ if match.l33t
121
+ suggestions.push(
122
+ "Predictable substitutions like '@' instead of 'a' \
123
+ don't help very much"
124
+ )
125
+ end
126
+
127
+ Feedback.new(
128
+ warning: warning,
129
+ suggestions: suggestions
130
+ )
131
+ end
132
+ end
133
+ end
@@ -1,4 +1,5 @@
1
1
  require 'benchmark'
2
+ require 'zxcvbn/feedback_giver'
2
3
  require 'zxcvbn/omnimatch'
3
4
  require 'zxcvbn/scorer'
4
5
 
@@ -17,6 +18,7 @@ module Zxcvbn
17
18
  result = @scorer.minimum_entropy_match_sequence(password, matches)
18
19
  end
19
20
  result.calc_time = calc_time
21
+ result.feedback = FeedbackGiver.get_feedback(result.score, result.match_sequence)
20
22
  result
21
23
  end
22
24
  end
@@ -1,7 +1,7 @@
1
1
  module Zxcvbn
2
2
  class Score
3
3
  attr_accessor :entropy, :crack_time, :crack_time_display, :score, :pattern,
4
- :match_sequence, :password, :calc_time
4
+ :match_sequence, :password, :calc_time, :feedback
5
5
 
6
6
  def initialize(options = {})
7
7
  @entropy = options[:entropy]
@@ -1,3 +1,3 @@
1
1
  module Zxcvbn
2
- VERSION = '0.1.2'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -0,0 +1,212 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zxcvbn::FeedbackGiver do
4
+ # NOTE: We go in via the tester because the `FeedbackGiver` relies on both
5
+ # Omnimatch and the Scorer, which are troublesome to wire up for tests
6
+ let(:tester) { Zxcvbn::Tester.new }
7
+
8
+ describe '.get_feedback' do
9
+ it "gives empty feedback when a password's score is good" do
10
+ feedback = tester.test('5815A30BE798').feedback
11
+
12
+ expect(feedback).to be_a Zxcvbn::Feedback
13
+ expect(feedback.warning).to be_nil
14
+ expect(feedback.suggestions).to be_empty
15
+ end
16
+
17
+ it 'gives general feedback when a password is empty' do
18
+ feedback = tester.test('').feedback
19
+
20
+ expect(feedback).to be_a Zxcvbn::Feedback
21
+ expect(feedback.warning).to be_nil
22
+ expect(feedback.suggestions).to contain_exactly(
23
+ 'Use a few words, avoid common phrases',
24
+ 'No need for symbols, digits, or uppercase letters'
25
+ )
26
+ end
27
+
28
+ it "gives general feedback when a password is poor but doesn't match any heuristics" do
29
+ feedback = tester.test(':005:0').feedback
30
+
31
+ expect(feedback).to be_a Zxcvbn::Feedback
32
+ expect(feedback.warning).to be_nil
33
+ expect(feedback.suggestions).to contain_exactly(
34
+ 'Add another word or two. Uncommon words are better.'
35
+ )
36
+ end
37
+
38
+ describe 'gives specific feedback' do
39
+ describe 'for dictionary passwords' do
40
+ it 'that are extremely common' do
41
+ feedback = tester.test('password').feedback
42
+
43
+ expect(feedback).to be_a Zxcvbn::Feedback
44
+ expect(feedback.warning).to eql('This is a top-10 common password')
45
+ expect(feedback.suggestions).to contain_exactly(
46
+ 'Add another word or two. Uncommon words are better.'
47
+ )
48
+ end
49
+
50
+ it 'that are very, very common' do
51
+ feedback = tester.test('letmein').feedback
52
+
53
+ expect(feedback).to be_a Zxcvbn::Feedback
54
+ expect(feedback.warning).to eql('This is a top-100 common password')
55
+ expect(feedback.suggestions).to contain_exactly(
56
+ 'Add another word or two. Uncommon words are better.'
57
+ )
58
+ end
59
+
60
+ it 'that are very common' do
61
+ feedback = tester.test('playstation').feedback
62
+
63
+ expect(feedback).to be_a Zxcvbn::Feedback
64
+ expect(feedback.warning).to eql('This is a very common password')
65
+ expect(feedback.suggestions).to contain_exactly(
66
+ 'Add another word or two. Uncommon words are better.'
67
+ )
68
+ end
69
+
70
+ it 'that are common and you tried to use l33tsp33k' do
71
+ feedback = tester.test('pl4yst4ti0n').feedback
72
+
73
+ expect(feedback).to be_a Zxcvbn::Feedback
74
+ expect(feedback.warning).to eql(
75
+ 'This is similar to a commonly used password'
76
+ )
77
+ expect(feedback.suggestions).to contain_exactly(
78
+ 'Add another word or two. Uncommon words are better.',
79
+ "Predictable substitutions like '@' instead of 'a' don't help very much"
80
+ )
81
+ end
82
+
83
+ it 'that are common and you capitalised the start' do
84
+ feedback = tester.test('Password').feedback
85
+
86
+ expect(feedback).to be_a Zxcvbn::Feedback
87
+ expect(feedback.warning).to eql(
88
+ 'This is a top-10 common password'
89
+ )
90
+ expect(feedback.suggestions).to contain_exactly(
91
+ 'Add another word or two. Uncommon words are better.',
92
+ "Capitalization doesn't help very much"
93
+ )
94
+ end
95
+
96
+ it 'that are common and you capitalised the whole thing' do
97
+ feedback = tester.test('PASSWORD').feedback
98
+
99
+ expect(feedback).to be_a Zxcvbn::Feedback
100
+ expect(feedback.warning).to eql(
101
+ 'This is a top-10 common password'
102
+ )
103
+ expect(feedback.suggestions).to contain_exactly(
104
+ 'Add another word or two. Uncommon words are better.',
105
+ 'All-uppercase is almost as easy to guess as all-lowercase'
106
+ )
107
+ end
108
+
109
+ it 'that contain a common first name or last name' do
110
+ feedback = tester.test('jessica').feedback
111
+
112
+ expect(feedback).to be_a Zxcvbn::Feedback
113
+ expect(feedback.warning).to eql(
114
+ 'Names and surnames by themselves are easy to guess'
115
+ )
116
+ expect(feedback.suggestions).to contain_exactly(
117
+ 'Add another word or two. Uncommon words are better.'
118
+ )
119
+
120
+ feedback = tester.test('smith').feedback
121
+
122
+ expect(feedback).to be_a Zxcvbn::Feedback
123
+ expect(feedback.warning).to eql(
124
+ 'Names and surnames by themselves are easy to guess'
125
+ )
126
+ expect(feedback.suggestions).to contain_exactly(
127
+ 'Add another word or two. Uncommon words are better.'
128
+ )
129
+ end
130
+
131
+ it 'that contain a common name and surname' do
132
+ feedback = tester.test('jessica smith').feedback
133
+
134
+ expect(feedback).to be_a Zxcvbn::Feedback
135
+ expect(feedback.warning).to eql(
136
+ 'Common names and surnames are easy to guess'
137
+ )
138
+ expect(feedback.suggestions).to contain_exactly(
139
+ 'Add another word or two. Uncommon words are better.'
140
+ )
141
+ end
142
+ end
143
+
144
+ describe 'for spatial passwords' do
145
+ it 'that contain a straight keyboard row' do
146
+ feedback = tester.test('1qaz').feedback
147
+
148
+ expect(feedback).to be_a Zxcvbn::Feedback
149
+ expect(feedback.warning).to eql(
150
+ 'Straight rows of keys are easy to guess'
151
+ )
152
+ expect(feedback.suggestions).to contain_exactly(
153
+ 'Add another word or two. Uncommon words are better.',
154
+ 'Use a longer keyboard pattern with more turns'
155
+ )
156
+ end
157
+
158
+ it 'that contain a keyboard pattern with one turn' do
159
+ feedback = tester.test('zaqwer').feedback
160
+
161
+ expect(feedback).to be_a Zxcvbn::Feedback
162
+ expect(feedback.warning).to eql(
163
+ 'Short keyboard patterns are easy to guess'
164
+ )
165
+ expect(feedback.suggestions).to contain_exactly(
166
+ 'Add another word or two. Uncommon words are better.',
167
+ 'Use a longer keyboard pattern with more turns'
168
+ )
169
+ end
170
+ end
171
+
172
+ it 'for passwords with repeated characters' do
173
+ feedback = tester.test('zzz').feedback
174
+
175
+ expect(feedback).to be_a Zxcvbn::Feedback
176
+ expect(feedback.warning).to eql(
177
+ 'Repeats like "aaa" are easy to guess'
178
+ )
179
+ expect(feedback.suggestions).to contain_exactly(
180
+ 'Add another word or two. Uncommon words are better.',
181
+ 'Avoid repeated words and characters'
182
+ )
183
+ end
184
+
185
+ it 'for passwords with sequential characters' do
186
+ feedback = tester.test('pqrpqrpqr').feedback
187
+
188
+ expect(feedback).to be_a Zxcvbn::Feedback
189
+ expect(feedback.warning).to eql(
190
+ 'Sequences like abc or 6543 are easy to guess'
191
+ )
192
+ expect(feedback.suggestions).to contain_exactly(
193
+ 'Add another word or two. Uncommon words are better.',
194
+ 'Avoid sequences'
195
+ )
196
+ end
197
+
198
+ it 'for passwords containing dates' do
199
+ feedback = tester.test('testing02\12\1997').feedback
200
+
201
+ expect(feedback).to be_a Zxcvbn::Feedback
202
+ expect(feedback.warning).to eql(
203
+ 'Dates are often easy to guess'
204
+ )
205
+ expect(feedback.suggestions).to contain_exactly(
206
+ 'Add another word or two. Uncommon words are better.',
207
+ 'Avoid dates and years that are associated with you'
208
+ )
209
+ end
210
+ end
211
+ end
212
+ end
@@ -16,6 +16,11 @@ describe Zxcvbn::Tester do
16
16
  expect(ruby_result.score).to eq js_result['score']
17
17
  expect(ruby_result.pattern).to eq js_result['pattern']
18
18
  expect(ruby_result.match_sequence.count).to eq js_result['match_sequence'].count
19
+
20
+ # NOTE: feedback didn't exist in the version of the JS library this gem
21
+ # is based on, so instead we just check that it put `Feedback` in
22
+ # there. Real tests for its values go in `feedback_giver_spec.rb`.
23
+ expect(ruby_result.feedback).to be_a Zxcvbn::Feedback
19
24
  end
20
25
  end
21
26
 
@@ -14,6 +14,9 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "zxcvbn-ruby"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Zxcvbn::VERSION
17
+ gem.license = 'MIT'
18
+
19
+ gem.required_ruby_version = '~> 2.3'
17
20
 
18
21
  gem.add_development_dependency 'therubyracer'
19
22
  gem.add_development_dependency 'rspec'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zxcvbn-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Hodgkiss
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-04-18 00:00:00.000000000 Z
12
+ date: 2019-05-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: therubyracer
@@ -50,6 +50,7 @@ files:
50
50
  - ".gitignore"
51
51
  - ".rspec"
52
52
  - ".travis.yml"
53
+ - CHANGELOG.md
53
54
  - Gemfile
54
55
  - LICENSE
55
56
  - README.md
@@ -65,6 +66,8 @@ files:
65
66
  - lib/zxcvbn/data.rb
66
67
  - lib/zxcvbn/dictionary_ranker.rb
67
68
  - lib/zxcvbn/entropy.rb
69
+ - lib/zxcvbn/feedback.rb
70
+ - lib/zxcvbn/feedback_giver.rb
68
71
  - lib/zxcvbn/match.rb
69
72
  - lib/zxcvbn/matchers/date.rb
70
73
  - lib/zxcvbn/matchers/dictionary.rb
@@ -84,6 +87,7 @@ files:
84
87
  - lib/zxcvbn/tester.rb
85
88
  - lib/zxcvbn/version.rb
86
89
  - spec/dictionary_ranker_spec.rb
90
+ - spec/feedback_giver_spec.rb
87
91
  - spec/matchers/date_spec.rb
88
92
  - spec/matchers/dictionary_spec.rb
89
93
  - spec/matchers/digits_spec.rb
@@ -113,7 +117,8 @@ files:
113
117
  - spec/zxcvbn_spec.rb
114
118
  - zxcvbn-ruby.gemspec
115
119
  homepage: http://github.com/envato/zxcvbn-ruby
116
- licenses: []
120
+ licenses:
121
+ - MIT
117
122
  metadata: {}
118
123
  post_install_message:
119
124
  rdoc_options: []
@@ -121,22 +126,22 @@ require_paths:
121
126
  - lib
122
127
  required_ruby_version: !ruby/object:Gem::Requirement
123
128
  requirements:
124
- - - ">="
129
+ - - "~>"
125
130
  - !ruby/object:Gem::Version
126
- version: '0'
131
+ version: '2.3'
127
132
  required_rubygems_version: !ruby/object:Gem::Requirement
128
133
  requirements:
129
134
  - - ">="
130
135
  - !ruby/object:Gem::Version
131
136
  version: '0'
132
137
  requirements: []
133
- rubyforge_project:
134
- rubygems_version: 2.6.11
138
+ rubygems_version: 3.0.3
135
139
  signing_key:
136
140
  specification_version: 4
137
141
  summary: ''
138
142
  test_files:
139
143
  - spec/dictionary_ranker_spec.rb
144
+ - spec/feedback_giver_spec.rb
140
145
  - spec/matchers/date_spec.rb
141
146
  - spec/matchers/dictionary_spec.rb
142
147
  - spec/matchers/digits_spec.rb