zxcvbn-ruby 0.1.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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