devise_zxcvbn 4.4.1 → 5.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: 9cdd3611652924ce1a2ff81a832d5bc6a8f0ea61
4
- data.tar.gz: c8fef0f8d2ba13d3eabce3fa5088531b715dd39b
2
+ SHA256:
3
+ metadata.gz: ff8317142cd17809de1fe6825970d106063f6c1413ef86d24be86b1c5b4dcc51
4
+ data.tar.gz: 569c6ab6a45ffca59600a36a18c079d4924361680a22663872a2618fac99031e
5
5
  SHA512:
6
- metadata.gz: 896fa3543e049ea4d8bd2230ae6a5ce2bbe3bdec4b53482b21c62d912e37ce3ec05f30ac839169a197f0ba195b787e38ee2129413c1ba8424cbe848001676dfd
7
- data.tar.gz: c33446dd6366fbc6f9f857ffd8a14f284e0a58aba6c0e05ab3a780d718752bc3f61d2425a0d14ecc4a4635576756f146be27c63c3c48eca8d5f5b3be5ceac6e2
6
+ metadata.gz: 696f4916cc7e45b7f88fd7af2e972ce53185e294b07fd4a766106a6e5a9ae5ad545f71165d05d9341381eed31d9e4d9e35db8e16554500b464327979055b33f7
7
+ data.tar.gz: 58c4048efc829042e0bfb27c28614891e81bc853d65e5742592f19f99039723d786cffd5f29282674e29a04035642d4abdae5911500fc93b7b802ee58592f637
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .byebug_history
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # devise_zxcvbn
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/devise_zxcvbn.png)](http://badge.fury.io/rb/devise_zxcvbn)
3
+ [![Gem Version](https://badge.fury.io/rb/devise_zxcvbn.svg)](http://badge.fury.io/rb/devise_zxcvbn)
4
4
  [![Circle CI](https://circleci.com/gh/bitzesty/devise_zxcvbn.svg?style=svg)](https://circleci.com/gh/bitzesty/devise_zxcvbn)
5
5
  [![Code Climate](https://codeclimate.com/github/bitzesty/devise_zxcvbn/badges/gpa.svg)](https://codeclimate.com/github/bitzesty/devise_zxcvbn)
6
6
 
@@ -14,50 +14,87 @@ The scores 0, 1, 2, 3 or 4 are given when the estimated crack time (seconds) is
14
14
 
15
15
  Add this line to your application's Gemfile:
16
16
 
17
- gem 'devise_zxcvbn'
18
-
17
+ ```ruby
18
+ gem 'devise_zxcvbn'
19
+ ```
19
20
 
20
21
  ## Configuration
21
22
 
22
- class User < ActiveRecord::Base
23
- devise :zxcvbnable
23
+ ```ruby
24
+ class User < ActiveRecord::Base
25
+ devise :zxcvbnable
26
+
27
+ # Optionally add more weak words to check against:
28
+ def weak_words
29
+ ['mysitename', self.name, self.username]
30
+ end
31
+ end
32
+ ```
33
+
34
+ ## Available methods for devise resources
35
+
36
+ ```ruby
37
+ class User < ApplicationRecord
38
+ devise :zxcvbnable
39
+ end
24
40
 
25
- # Optionally add more weak words to check against:
26
- def weak_words
27
- ['mysitename', self.name, self.username]
28
- end
29
- end
41
+ user = User.new.tap do |user|
42
+ user.email = "example@example.com"
43
+ user.password = "123456789"
44
+ end
45
+
46
+ user.password_score => #<OpenStruct password="123456789", guesses=6, guesses_log10=0.7781512503836435, sequence=[{"pattern"=>"dictionary", "i"=>0, "j"=>8, "token"=>"123456789", "matched_word"=>"123456789", "rank"=>5, "dictionary_name"=>"passwords", "reversed"=>false, "l33t"=>false, "base_guesses"=>5, "uppercase_variations"=>1, "l33t_variations"=>1, "guesses"=>5, "guesses_log10"=>0.6989700043360187}], calc_time=15, crack_times_seconds={"online_throttling_100_per_hour"=>216, "online_no_throttling_10_per_second"=>0.6, "offline_slow_hashing_1e4_per_second"=>0.0006, "offline_fast_hashing_1e10_per_second"=>6.0e-10}, crack_times_display={"online_throttling_100_per_hour"=>"4 minutes", "online_no_throttling_10_per_second"=>"less than a second", "offline_slow_hashing_1e4_per_second"=>"less than a second", "offline_fast_hashing_1e10_per_second"=>"less than a second"}, score=0, feedback={"warning"=>"This is a top-10 common password", "suggestions"=>["Add another word or two. Uncommon words are better."]}>
47
+ # returns a simple OpenStruct object so than you could send another messages to get more info
48
+
49
+ user.password_weak? => true/false # returns a boolean result of checking of weakness of your set password
50
+ ```
30
51
 
31
52
  ### Default parameters
32
53
 
33
54
  _A score of less than 3 is not recommended._
34
55
 
35
- # config/initializers/devise.rb
36
- Devise.setup do |config|
37
- config.min_password_score = 4
38
- end
56
+ ```ruby
57
+ # config/initializers/devise.rb
58
+ Devise.setup do |config|
59
+ config.min_password_score = 4
60
+ end
61
+ ```
39
62
 
40
63
  ### Error Message
41
64
 
42
65
  The default error message:
43
66
 
44
- "not strong enough. It scored %{score}. It must score at least %{min_password_score}."
67
+ ```yml
68
+ "not strong enough. It scored %{score}. It must score at least %{min_password_score}."
69
+ ```
45
70
 
46
71
  You can customize this error message modifying the `devise` YAML file.
47
72
 
48
- The `feedback`, `crack_time_display`, `score` and `min_password_score` variables are passed through if you need them.
73
+ The `crack_time_display`, `password_sample`, `score` and `min_password_score` variables are passed through if you need them.
74
+
75
+ ```yml
76
+ # config/locales/devise.en.yml
77
+ en:
78
+ errors:
79
+ messages:
80
+ weak_password: "not strong enough. Consider adding a number, symbols or more letters to make it stronger."
81
+ ```
82
+
83
+ ### Skipping password complexity validation
49
84
 
50
- # config/locales/devise.en.yml
51
- en:
52
- errors:
53
- messages:
54
- weak_password: "not strong enough. Consider adding a number, symbols or more letters to make it stronger."
85
+ To turn off password complexity validation for certain conditions, you could implement a concern (or similar) that overloads `skip_password_complexity?`:
55
86
 
87
+ ```ruby
88
+ def skip_password_complexity?
89
+ true
90
+ end
91
+ ```
56
92
 
57
93
  ## Contributing
58
94
 
59
95
  1. Fork it
60
96
  2. Create your feature branch (`git checkout -b my-new-feature`)
61
- 3. Commit your changes (`git commit -am 'Add some feature'`)
62
- 4. Push to the branch (`git push origin my-new-feature`)
63
- 5. Create new Pull Request
97
+ 3. Add test coverage for the feature, We use rspec for this purpose
98
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
99
+ 5. Push to the branch (`git push origin my-new-feature`)
100
+ 6. Create new Pull Request
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "rake"
24
24
  spec.add_development_dependency "rspec"
25
25
  spec.add_development_dependency "rspec_junit_formatter"
26
+ spec.add_development_dependency "byebug"
26
27
 
27
28
  spec.add_runtime_dependency "devise"
28
29
  spec.add_runtime_dependency("zxcvbn-js", "~> 4.4.1")
@@ -0,0 +1,2 @@
1
+ class DeviseZxcvbnError < StandardError # TODO: we need own hierarchy
2
+ end
@@ -1,4 +1,6 @@
1
- require 'devise_zxcvbn/email_tokeniser'
1
+ require "devise_zxcvbn/email_tokeniser"
2
+ require "devise_zxcvbn/errors/devise_zxcvbn_error"
3
+ require "ostruct"
2
4
 
3
5
  module Devise
4
6
  module Models
@@ -9,17 +11,21 @@ module Devise
9
11
  delegate :zxcvbn_tester, to: "self.class"
10
12
 
11
13
  included do
12
- validate :not_weak_password, if: :password_required?
14
+ validate :strong_password, unless: :skip_password_complexity?
13
15
  end
14
16
 
15
17
  def password_score
16
- @pass_score = self.class.password_score(self)
18
+ @password_score = self.class.password_score(self)
19
+ end
20
+
21
+ def password_weak?
22
+ password_score.score < min_password_score
17
23
  end
18
24
 
19
25
  private
20
26
 
21
- def not_weak_password
22
- if errors.messages.blank? && password_score.score < min_password_score
27
+ def strong_password
28
+ if errors.messages.blank? && password_weak?
23
29
  errors.add :password, :weak_password, i18n_variables
24
30
  end
25
31
  end
@@ -28,28 +34,30 @@ module Devise
28
34
  {
29
35
  feedback: zxcvbn_feedback,
30
36
  crack_time_display: time_to_crack,
31
- score: @pass_score.score,
37
+ score: password_score.score,
32
38
  min_password_score: min_password_score
33
39
  }
34
40
  end
35
41
 
36
42
  def zxcvbn_feedback
37
- feedback = @pass_score.feedback.values.flatten.reject(&:empty?)
38
- return 'Add another word or two. Uncommon words are better.' if feedback.empty?
43
+ feedback = password_score.feedback.values.flatten.reject(&:empty?)
44
+ return "Add another word or two. Uncommon words are better." if feedback.empty?
39
45
 
40
- feedback.join('. ').gsub(/\.\s*\./, '.')
46
+ feedback.join(". ").gsub(/\.\s*\./, ".")
41
47
  end
42
48
 
43
49
  def time_to_crack
44
- @pass_score.crack_times_display['offline_fast_hashing_1e10_per_second']
50
+ password_score.crack_times_display["offline_fast_hashing_1e10_per_second"]
45
51
  end
46
52
 
47
- module ClassMethods
53
+ class_methods do
48
54
  Devise::Models.config(self, :min_password_score)
49
55
  Devise::Models.config(self, :zxcvbn_tester)
50
56
 
51
- def password_score(user, arg_email=nil)
52
- password = user.respond_to?(:password) ? user.password.to_s : user
57
+ def password_score(user, arg_email = nil)
58
+ return raise DeviseZxcvbnError, "the object must respond to password" unless user.respond_to?(:password)
59
+
60
+ password = user.password.to_s
53
61
 
54
62
  zxcvbn_weak_words = []
55
63
 
@@ -58,14 +66,15 @@ module Devise
58
66
  end
59
67
 
60
68
  # User method results are saved locally to prevent repeat calls that might be expensive
61
- if user.respond_to? :email
69
+ if user.respond_to?(:email)
62
70
  local_email = user.email
63
71
  zxcvbn_weak_words += [local_email, *DeviseZxcvbn::EmailTokeniser.split(local_email)]
64
72
  end
65
73
 
66
- if user.respond_to? :weak_words
74
+ if user.respond_to?(:weak_words)
75
+ return raise DeviseZxcvbnError, "weak_words must return an Array" unless user.weak_words.is_a?(Array)
76
+
67
77
  local_weak_words = user.weak_words
68
- raise "weak_words must return an Array" unless (local_weak_words.is_a? Array)
69
78
  zxcvbn_weak_words += local_weak_words
70
79
  end
71
80
 
@@ -1,3 +1,3 @@
1
1
  module DeviseZxcvbn
2
- VERSION = "4.4.1"
2
+ VERSION = "5.0.0"
3
3
  end
@@ -1,7 +1,6 @@
1
1
  require "devise_zxcvbn"
2
2
 
3
3
  describe 'Devise zxcvbn' do
4
-
5
4
  it "Returns the default value for min_password_score of 4" do
6
5
  expect(Devise.min_password_score).to eq(4)
7
6
  end
@@ -0,0 +1,2 @@
1
+ class DeviseZxcvbnError < StandardError # TODO: we need own hierarchy
2
+ end
@@ -1,43 +1,130 @@
1
- require "devise"
2
- require "devise_zxcvbn"
3
- require "active_model"
4
- require "devise_zxcvbn/model"
1
+ require 'active_model'
2
+ require 'devise'
3
+ require 'devise_zxcvbn'
4
+ require 'devise_zxcvbn/model'
5
5
 
6
6
  describe Devise::Models::Zxcvbnable do
7
- describe "#password_score" do
8
- it "returns the score from zxcvbn_tester" do
9
- password_score = DummyClass.new("12345678").password_score
10
- expect(password_score.score).to eq(0)
11
- expect(password_score.crack_times_display['offline_fast_hashing_1e10_per_second']).to eq("less than a second")
7
+ ValidDummyClass = Struct.new(:password, :skip_password_complexity, keyword_init: true) do
8
+ include ActiveModel::Validations
9
+ include Devise::Models::Zxcvbnable
10
+
11
+ def skip_password_complexity?
12
+ skip_password_complexity
12
13
  end
13
14
  end
14
15
 
15
- describe "Password validation" do
16
- it "Invalid if password score is less than the min_password_score" do
17
- user = DummyClass.new("12345678")
18
- expect(user).to_not be_valid
19
- expect(user.errors[:password]).to eq(["not strong enough. It scored 0. It must score at least 4."])
16
+ let(:skip_password_complexity) { false }
17
+
18
+ describe '#password_score' do
19
+ context 'when password is strong' do
20
+ let(:user) { ValidDummyClass.new(password: 'Jm1C4C3aaDzC1aRW', skip_password_complexity: skip_password_complexity) }
21
+
22
+ it 'returns the score equal 4' do
23
+ password_score = user.password_score
24
+
25
+ expect(password_score.score).to eq(4)
26
+ expect(password_score.crack_times_display['offline_fast_hashing_1e10_per_second']).to eq('12 days')
27
+ end
28
+ end
29
+
30
+ context 'when password is weak' do
31
+ let(:user) { ValidDummyClass.new(password: '12345678', skip_password_complexity: skip_password_complexity) }
32
+
33
+ it 'returns the weak score' do
34
+ password_score = user.password_score
35
+
36
+ expect(password_score.score).to eq(0)
37
+ expect(password_score.crack_times_display['offline_fast_hashing_1e10_per_second']).to eq('less than a second')
38
+ end
20
39
  end
40
+ end
41
+
42
+ describe '#password_weak?' do
43
+ let(:user) { ValidDummyClass.new(password: 'Jm1C4C3aaDzC1aRW', skip_password_complexity: skip_password_complexity) }
21
44
 
22
- it "Valid if password score is greater than the min_password_score" do
23
- user = DummyClass.new("Jm1C4C3aaDzC")
24
- expect(user).to be_valid
25
- expect(user.errors[:password]).to be_empty
45
+ it 'returns false for the call of the method' do
46
+ expect(user.password_weak?).to be_falsey
26
47
  end
27
48
  end
28
49
 
29
- class DummyClass
30
- include ActiveModel::Validations
31
- include Devise::Models::Zxcvbnable
50
+ describe 'validations' do
51
+ subject { resource.validate; resource }
52
+
53
+ let(:resource) { ValidDummyClass.new(password: password, skip_password_complexity: skip_password_complexity) }
54
+
55
+ context 'when password complexity check is required' do
56
+ context 'when password is strong' do
57
+ let(:password) { 'Jm1C4C3aaDzC1aRW' }
32
58
 
33
- attr_accessor :password
59
+ it 'expects the model to be valid' do
60
+ expect(subject).to be_valid
61
+ end
34
62
 
35
- def initialize(password)
36
- @password = password
63
+ it 'returns empty validation messages' do
64
+ expect(subject.errors[:password]).to be_empty
65
+ end
66
+ end
67
+
68
+ context 'when password is weak' do
69
+ let(:password) { '12345678' }
70
+
71
+ it 'expects the model to be invalid' do
72
+ expect(subject).to be_invalid
73
+ end
74
+
75
+ it 'returns validation message' do
76
+ expect(subject.errors[:password])
77
+ .to eq(['not strong enough. It scored 0. It must score at least 4.'])
78
+ end
79
+ end
80
+ end
81
+
82
+ context 'when password complexity check is not required' do
83
+ let(:skip_password_complexity) { true }
84
+
85
+ context 'when password score is strong' do
86
+ let(:password) { 'Jm1C4C3aaDzC1aRW' }
87
+
88
+ it 'expects the model to be valid' do
89
+ expect(subject).to be_valid
90
+ end
91
+ end
92
+
93
+ context 'when password score is weak' do
94
+ let(:password) { '12345678' }
95
+
96
+ it 'expects the model to be valid' do
97
+ expect(subject).to be_valid
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ describe 'exceptions raises' do
104
+ context 'when password method is not given for instance' do
105
+ class InvalidPasswordDummyClass < ValidDummyClass
106
+ undef_method :password
107
+ end
108
+
109
+ let(:user) { InvalidPasswordDummyClass.new }
110
+
111
+ it 'raises exception regarding absence password method' do
112
+ expect { user.password_score }.to raise_error(DeviseZxcvbnError, 'the object must respond to password')
113
+ end
37
114
  end
38
115
 
39
- def password_required?
40
- true
116
+ context 'when weak_words method returns not Array' do
117
+ class InvalidWeakWordsDummyClass < ValidDummyClass
118
+ def weak_words
119
+ String.new()
120
+ end
121
+ end
122
+
123
+ let(:user) { InvalidWeakWordsDummyClass.new }
124
+
125
+ it 'raises exception regarding type of weak_words method' do
126
+ expect { user.password_score }.to raise_error(DeviseZxcvbnError, 'weak_words must return an Array')
127
+ end
41
128
  end
42
129
  end
43
130
  end
data/spec/spec_helper.rb CHANGED
@@ -1,96 +1,11 @@
1
- # This file was generated by the `rspec --init` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # The generated `.rspec` file contains `--require spec_helper` which will cause
4
- # this file to always be loaded, without a need to explicitly require it in any
5
- # files.
6
- #
7
- # Given that it is always loaded, you are encouraged to keep this file as
8
- # light-weight as possible. Requiring heavyweight dependencies from this file
9
- # will add to the boot time of your test suite on EVERY test run, even for an
10
- # individual file that may not need all of that loaded. Instead, consider making
11
- # a separate helper file that requires the additional dependencies and performs
12
- # the additional setup, and require it from the spec files that actually need
13
- # it.
14
- #
15
- # The `.rspec` file also contains a few flags that are not defaults but that
16
- # users commonly want.
17
- #
18
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
1
+ require 'byebug'
2
+
19
3
  RSpec.configure do |config|
20
- # rspec-expectations config goes here. You can use an alternate
21
- # assertion/expectation library such as wrong or the stdlib/minitest
22
- # assertions if you prefer.
23
4
  config.expect_with :rspec do |expectations|
24
- # This option will default to `true` in RSpec 4. It makes the `description`
25
- # and `failure_message` of custom matchers include text for helper methods
26
- # defined using `chain`, e.g.:
27
- # be_bigger_than(2).and_smaller_than(4).description
28
- # # => "be bigger than 2 and smaller than 4"
29
- # ...rather than:
30
- # # => "be bigger than 2"
31
5
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
6
  end
33
7
 
34
- # rspec-mocks config goes here. You can use an alternate test double
35
- # library (such as bogus or mocha) by changing the `mock_with` option here.
36
8
  config.mock_with :rspec do |mocks|
37
- # Prevents you from mocking or stubbing a method that does not exist on
38
- # a real object. This is generally recommended, and will default to
39
- # `true` in RSpec 4.
40
9
  mocks.verify_partial_doubles = true
41
10
  end
42
-
43
- # The settings below are suggested to provide a good initial experience
44
- # with RSpec, but feel free to customize to your heart's content.
45
- =begin
46
- # These two settings work together to allow you to limit a spec run
47
- # to individual examples or groups you care about by tagging them with
48
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
49
- # get run.
50
- config.filter_run :focus
51
- config.run_all_when_everything_filtered = true
52
-
53
- # Allows RSpec to persist some state between runs in order to support
54
- # the `--only-failures` and `--next-failure` CLI options. We recommend
55
- # you configure your source control system to ignore this file.
56
- config.example_status_persistence_file_path = "spec/examples.txt"
57
-
58
- # Limits the available syntax to the non-monkey patched syntax that is
59
- # recommended. For more details, see:
60
- # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
61
- # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
62
- # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
63
- config.disable_monkey_patching!
64
-
65
- # This setting enables warnings. It's recommended, but in some cases may
66
- # be too noisy due to issues in dependencies.
67
- config.warnings = true
68
-
69
- # Many RSpec users commonly either run the entire suite or an individual
70
- # file, and it's useful to allow more verbose output when running an
71
- # individual spec file.
72
- if config.files_to_run.one?
73
- # Use the documentation formatter for detailed output,
74
- # unless a formatter has already been configured
75
- # (e.g. via a command-line flag).
76
- config.default_formatter = 'doc'
77
- end
78
-
79
- # Print the 10 slowest examples and example groups at the
80
- # end of the spec run, to help surface which specs are running
81
- # particularly slow.
82
- config.profile_examples = 10
83
-
84
- # Run specs in random order to surface order dependencies. If you find an
85
- # order dependency and want to debug it, you can fix the order by providing
86
- # the seed, which is printed after each run.
87
- # --seed 1234
88
- config.order = :random
89
-
90
- # Seed global randomization in this process using the `--seed` CLI option.
91
- # Setting this allows you to use `--seed` to deterministically reproduce
92
- # test failures related to randomization by passing the same `--seed` value
93
- # as the one that triggered the failure.
94
- Kernel.srand config.seed
95
- =end
96
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_zxcvbn
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.1
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bit Zesty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-27 00:00:00.000000000 Z
11
+ date: 2019-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: devise
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -126,11 +140,13 @@ files:
126
140
  - devise_zxcvbn.gemspec
127
141
  - lib/devise_zxcvbn.rb
128
142
  - lib/devise_zxcvbn/email_tokeniser.rb
143
+ - lib/devise_zxcvbn/errors/devise_zxcvbn_error.rb
129
144
  - lib/devise_zxcvbn/locales/en.yml
130
145
  - lib/devise_zxcvbn/model.rb
131
146
  - lib/devise_zxcvbn/version.rb
132
147
  - spec/devise_zxcvbn/devise_zxcbn_spec.rb
133
148
  - spec/devise_zxcvbn/email_tokeniser_spec.rb
149
+ - spec/devise_zxcvbn/errors/devise_zxcvbn_error.rb
134
150
  - spec/devise_zxcvbn/model_spec.rb
135
151
  - spec/spec_helper.rb
136
152
  homepage: https://github.com/bitzesty/devise_zxcvbn
@@ -152,13 +168,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
168
  - !ruby/object:Gem::Version
153
169
  version: '0'
154
170
  requirements: []
155
- rubyforge_project:
156
- rubygems_version: 2.4.5.1
171
+ rubygems_version: 3.0.1
157
172
  signing_key:
158
173
  specification_version: 4
159
174
  summary: Devise plugin to reject weak passwords
160
175
  test_files:
161
176
  - spec/devise_zxcvbn/devise_zxcbn_spec.rb
162
177
  - spec/devise_zxcvbn/email_tokeniser_spec.rb
178
+ - spec/devise_zxcvbn/errors/devise_zxcvbn_error.rb
163
179
  - spec/devise_zxcvbn/model_spec.rb
164
180
  - spec/spec_helper.rb