devise_zxcvbn 1.1.2 → 2.1.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
2
  SHA1:
3
- metadata.gz: 1dae3acba04710e99c8a022e397283d0cd650ec0
4
- data.tar.gz: 3be3d11c83669c805e1cb89bc454d1e61c370732
3
+ metadata.gz: 27e05473f188650ce1ca066798ea1e9e36de7c02
4
+ data.tar.gz: f818364bd7315028a02e6918ce155a716389534e
5
5
  SHA512:
6
- metadata.gz: 3b16f5142230f80015bf5299ed620931fffff881eadae6e4891e3e80f1658e55b7d07ea3c5014a67b27f242f000cd4bb67d58921a4addeff581e4a8b52f4505b
7
- data.tar.gz: d012890d4a2325e46ddacf65a69c7c210b7ff596a30fea98d9b5e8c0fbc117a2ff257527378dcf79595027b4a012f81f3e450f4c45b4d0a39f0bde79b867bddf
6
+ metadata.gz: 667fa1d6eb19a08e1af744f617750a0cc414c5101b731a7814d7f2c75a2c876fc5eb67a6ff6421177971f6033f9e171e9fa8816ce00cdcb1ee9d699ffec3c459
7
+ data.tar.gz: 73df73acc005b46d4d83c877a3125ceb18169ec03d64143f47755d5343dab08a1cff4ba24ac498f118586c20e1fa22e3e29a7c924d720fd5cb85faf4454f6e9e
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/README.md CHANGED
@@ -1,9 +1,12 @@
1
1
  # devise_zxcvbn
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/devise_zxcvbn.png)](http://badge.fury.io/rb/devise_zxcvbn)
4
+ [![Circle CI](https://circleci.com/gh/bitzesty/devise_zxcvbn.svg?style=svg)](https://circleci.com/gh/bitzesty/devise_zxcvbn)
5
+ [![Code Climate](https://codeclimate.com/github/bitzesty/devise_zxcvbn/badges/gpa.svg)](https://codeclimate.com/github/bitzesty/devise_zxcvbn)
4
6
 
5
- Plugin for [devise](https://github.com/plataformatec/devise) to reject weak passwords, using [zxcvbn-ruby](https://github.com/envato/zxcvbn-ruby) which is a ruby port of [zxcvbn: realistic password strength estimation](https://tech.dropbox.com/2012/04/zxcvbn-realistic-password-strength-estimation/).
6
- The user's password will be rejected if the score is below 4 by default. It also uses the email as user input to zxcvbn, to downscore passwords containing the email.
7
+ Plugin for [devise](https://github.com/plataformatec/devise) to reject weak passwords, using [zxcvbn-js](https://github.com/bitzesty/zxcvbn-js) which is a ruby port of [zxcvbn: realistic password strength estimation](https://tech.dropbox.com/2012/04/zxcvbn-realistic-password-strength-estimation/).
8
+
9
+ The user's password will be rejected if the score is below 4 by default. It also uses the email as user input to zxcvbn, to reject passwords containing parts of the email (if using zxcvbn.js on the frontend you should also do this to get the same score).
7
10
 
8
11
  The scores 0, 1, 2, 3 or 4 are given when the estimated crack time (seconds) is less than `10**2`, `10**4`, `10**6`, `10**8`, Infinity.
9
12
 
@@ -14,15 +17,20 @@ Add this line to your application's Gemfile:
14
17
  gem 'devise_zxcvbn'
15
18
 
16
19
 
17
- ## Devise Configuration
20
+ ## Configuration
18
21
 
19
22
  class User < ActiveRecord::Base
20
- devise :database_authenticatable, :validatable, :zxcvbnable
23
+ devise :zxcvbnable
24
+
25
+ # Optionally add more weak words to check against:
26
+ def weak_words
27
+ ['mysitename', self.name, self.username]
28
+ end
21
29
  end
22
30
 
23
31
  ### Default parameters
24
32
 
25
- A score of less than 3 is not recommended.
33
+ _A score of less than 3 is not recommended._
26
34
 
27
35
  # config/initializers/devise.rb
28
36
  Devise.setup do |config|
@@ -31,7 +39,13 @@ A score of less than 3 is not recommended.
31
39
 
32
40
  ### Error Message
33
41
 
34
- Example error message, the `score` and `min_password_score` variables are also passed through if you need them.
42
+ The default error message:
43
+
44
+ "not strong enough. It scored %{score}. It must score at least %{min_password_score}."
45
+
46
+ You can customize this error message modifying the `devise` YAML file.
47
+
48
+ The `feedback`, `crack_time_display`, `score` and `min_password_score` variables are passed through if you need them.
35
49
 
36
50
  # config/locales/devise.en.yml
37
51
  en:
@@ -0,0 +1,9 @@
1
+ ## Customize machine
2
+ machine:
3
+ ruby:
4
+ version:
5
+ 2.2.3
6
+ ## Customize test commands
7
+ test:
8
+ override:
9
+ - RAILS_ENV=test bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml
@@ -6,9 +6,9 @@ require 'devise_zxcvbn/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "devise_zxcvbn"
8
8
  spec.version = DeviseZxcvbn::VERSION
9
- spec.authors = ["Matthew Ford"]
10
- spec.email = ["matt@bitzesty.com"]
11
- spec.description = %q{It adds password strength checking via ruby-zxcvbn to reject weak passwords }
9
+ spec.authors = ["Bit Zesty"]
10
+ spec.email = ["info@bitzesty.com"]
11
+ spec.description = %q{This gems works with devise to provide backend password strength checking via zxcvbn-js to reject weak passwords }
12
12
  spec.summary = %q{Devise plugin to reject weak passwords}
13
13
  spec.homepage = "https://github.com/bitzesty/devise_zxcvbn"
14
14
  spec.license = "MIT"
@@ -18,10 +18,12 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_development_dependency "activemodel"
21
22
  spec.add_development_dependency "bundler", "~> 1.3"
22
23
  spec.add_development_dependency "rake"
23
- spec.add_development_dependency "rspec", "~> 2.14"
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "rspec_junit_formatter"
24
26
 
25
27
  spec.add_runtime_dependency "devise"
26
- spec.add_runtime_dependency("zxcvbn-ruby", ">= 0.0.2")
28
+ spec.add_runtime_dependency("zxcvbn-js", "~> 4.2.0")
27
29
  end
@@ -4,22 +4,22 @@ require "zxcvbn"
4
4
 
5
5
  module Devise
6
6
 
7
+ # The minimun score for a password.
8
+ mattr_reader :min_password_score
7
9
  @@min_password_score = 4
8
10
 
9
- def self.min_password_score
10
- @@min_password_score
11
- end
12
-
13
11
  def self.min_password_score=(score)
14
- if (0..4).include?(score)
15
- if score < 3
16
- ::Rails.logger.warn "[devise_zxcvbn] A score of less than 3 is not recommended."
17
- end
18
- @@min_password_score = score
19
- else
20
- raise "The min_password_score must be an integer and between 0..4"
21
- end
12
+ raise "The min_password_score must be an integer and between 0..4" unless (0..4).include?(score)
13
+ @@min_password_score = score
14
+ end
15
+
16
+ def self.zxcvbn_tester
17
+ @@zxcvbn_tester ||= ::Zxcvbn::Tester.new
22
18
  end
23
19
  end
24
20
 
25
- Devise.add_module :zxcvbnable, :model => "devise_zxcvbn/model"
21
+ # Load default I18n
22
+ #
23
+ I18n.load_path.unshift File.join(File.dirname(__FILE__), *%w[devise_zxcvbn locales en.yml])
24
+
25
+ Devise.add_module :zxcvbnable, model: "devise_zxcvbn/model"
@@ -0,0 +1,4 @@
1
+ en:
2
+ errors:
3
+ messages:
4
+ weak_password: "not strong enough. It scored %{score}. It must score at least %{min_password_score}."
@@ -6,41 +6,70 @@ module Devise
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  delegate :min_password_score, to: "self.class"
9
+ delegate :zxcvbn_tester, to: "self.class"
9
10
 
10
11
  included do
11
12
  validate :not_weak_password, if: :password_required?
12
13
  end
13
14
 
14
15
  def password_score
15
- self.class.password_score(self)
16
+ @pass_score = self.class.password_score(self)
16
17
  end
17
18
 
18
19
  private
19
20
 
20
21
  def not_weak_password
21
- if password_score < min_password_score
22
- self.errors.add :password, :weak_password, score: password_score, min_password_score: min_password_score
23
- return false
22
+ if password_score.score < min_password_score
23
+ errors.add :password, :weak_password, i18n_variables
24
24
  end
25
25
  end
26
26
 
27
+ def i18n_variables
28
+ {
29
+ feedback: zxcvbn_feedback,
30
+ crack_time_display: time_to_crack,
31
+ score: @pass_score.score,
32
+ min_password_score: min_password_score
33
+ }
34
+ end
35
+
36
+ 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?
39
+
40
+ feedback.join('. ').gsub(/\.\s*\./, '.')
41
+ end
42
+
43
+ def time_to_crack
44
+ @pass_score.crack_times_display['offline_fast_hashing_1e10_per_second']
45
+ end
46
+
27
47
  module ClassMethods
28
48
  Devise::Models.config(self, :min_password_score)
49
+ Devise::Models.config(self, :zxcvbn_tester)
50
+
51
+ def password_score(user, arg_email=nil)
52
+ password = user.respond_to?(:password) ? user.password : user
29
53
 
30
- def password_score(user, email=nil)
31
- password = nil
32
- weak_words = []
54
+ zxcvbn_weak_words = []
33
55
 
34
- if user.is_a? String
35
- password = user
36
- else
37
- password = user.password
38
- email = user.email unless email
56
+ if arg_email
57
+ zxcvbn_weak_words += [arg_email, *DeviseZxcvbn::EmailTokeniser.split(arg_email)]
39
58
  end
40
59
 
41
- weak_words = [email, *DeviseZxcvbn::EmailTokeniser.split(email)] if email
60
+ # User method results are saved locally to prevent repeat calls that might be expensive
61
+ if user.respond_to? :email
62
+ local_email = user.email
63
+ zxcvbn_weak_words += [local_email, *DeviseZxcvbn::EmailTokeniser.split(local_email)]
64
+ end
65
+
66
+ if user.respond_to? :weak_words
67
+ local_weak_words = user.weak_words
68
+ raise "weak_words must return an Array" unless (local_weak_words.is_a? Array)
69
+ zxcvbn_weak_words += local_weak_words
70
+ end
42
71
 
43
- ::Zxcvbn.test(password, weak_words).score
72
+ zxcvbn_tester.test(password, zxcvbn_weak_words)
44
73
  end
45
74
  end
46
75
  end
@@ -1,3 +1,3 @@
1
1
  module DeviseZxcvbn
2
- VERSION = "1.1.2"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -0,0 +1,23 @@
1
+ require "devise_zxcvbn"
2
+
3
+ describe 'Devise zxcvbn' do
4
+
5
+ it "Returns the default value for min_password_score of 4" do
6
+ expect(Devise.min_password_score).to eq(4)
7
+ end
8
+
9
+ it "Raises an error if min_password_score value is out of range" do
10
+ expect { Devise.min_password_score = 8 }.to raise_error("The min_password_score must be an integer and between 0..4")
11
+ end
12
+
13
+ it "Sets the min_password_score value" do
14
+ Devise.min_password_score = 2
15
+ expect(Devise.min_password_score).to eq(2)
16
+ Devise.min_password_score = 4 # Restore default
17
+ end
18
+
19
+ it "returns a memoized instance of Zxcvbn::Tester" do
20
+ expect(::Zxcvbn::Tester).to receive(:new).once.and_call_original
21
+ 2.times { Devise.zxcvbn_tester }
22
+ end
23
+ end
@@ -0,0 +1,43 @@
1
+ require "devise"
2
+ require "devise_zxcvbn"
3
+ require "active_model"
4
+ require "devise_zxcvbn/model"
5
+
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")
12
+ end
13
+ end
14
+
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."])
20
+ end
21
+
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
26
+ end
27
+ end
28
+
29
+ class DummyClass
30
+ include ActiveModel::Validations
31
+ include Devise::Models::Zxcvbnable
32
+
33
+ attr_accessor :password
34
+
35
+ def initialize(password)
36
+ @password = password
37
+ end
38
+
39
+ def password_required?
40
+ true
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,96 @@
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
19
+ 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
+ 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
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
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
+ 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
+ mocks.verify_partial_doubles = true
41
+ 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
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_zxcvbn
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
- - Matthew Ford
7
+ - Bit Zesty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-27 00:00:00.000000000 Z
11
+ date: 2016-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemodel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -42,24 +56,24 @@ dependencies:
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - "~>"
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
- version: '2.14'
61
+ version: '0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - "~>"
66
+ - - ">="
53
67
  - !ruby/object:Gem::Version
54
- version: '2.14'
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: devise
70
+ name: rspec_junit_formatter
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
60
74
  - !ruby/object:Gem::Version
61
75
  version: '0'
62
- type: :runtime
76
+ type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
@@ -67,37 +81,58 @@ dependencies:
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
- name: zxcvbn-ruby
84
+ name: devise
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
74
88
  - !ruby/object:Gem::Version
75
- version: 0.0.2
89
+ version: '0'
76
90
  type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - ">="
81
95
  - !ruby/object:Gem::Version
82
- version: 0.0.2
83
- description: 'It adds password strength checking via ruby-zxcvbn to reject weak passwords '
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: zxcvbn-js
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 4.2.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 4.2.0
111
+ description: 'This gems works with devise to provide backend password strength checking
112
+ via zxcvbn-js to reject weak passwords '
84
113
  email:
85
- - matt@bitzesty.com
114
+ - info@bitzesty.com
86
115
  executables: []
87
116
  extensions: []
88
117
  extra_rdoc_files: []
89
118
  files:
90
119
  - ".gitignore"
120
+ - ".rspec"
91
121
  - Gemfile
92
122
  - LICENSE.txt
93
123
  - README.md
94
124
  - Rakefile
125
+ - circle.yml
95
126
  - devise_zxcvbn.gemspec
96
127
  - lib/devise_zxcvbn.rb
97
128
  - lib/devise_zxcvbn/email_tokeniser.rb
129
+ - lib/devise_zxcvbn/locales/en.yml
98
130
  - lib/devise_zxcvbn/model.rb
99
131
  - lib/devise_zxcvbn/version.rb
132
+ - spec/devise_zxcvbn/devise_zxcbn_spec.rb
100
133
  - spec/devise_zxcvbn/email_tokeniser_spec.rb
134
+ - spec/devise_zxcvbn/model_spec.rb
135
+ - spec/spec_helper.rb
101
136
  homepage: https://github.com/bitzesty/devise_zxcvbn
102
137
  licenses:
103
138
  - MIT
@@ -123,4 +158,7 @@ signing_key:
123
158
  specification_version: 4
124
159
  summary: Devise plugin to reject weak passwords
125
160
  test_files:
161
+ - spec/devise_zxcvbn/devise_zxcbn_spec.rb
126
162
  - spec/devise_zxcvbn/email_tokeniser_spec.rb
163
+ - spec/devise_zxcvbn/model_spec.rb
164
+ - spec/spec_helper.rb