lib/devise_zxcvbn/model.rb in devise_zxcvbn-4.4.1 vs lib/devise_zxcvbn/model.rb in devise_zxcvbn-5.0.0

- old
+ new

@@ -1,72 +1,81 @@ -require 'devise_zxcvbn/email_tokeniser' +require "devise_zxcvbn/email_tokeniser" +require "devise_zxcvbn/errors/devise_zxcvbn_error" +require "ostruct" module Devise module Models module Zxcvbnable extend ActiveSupport::Concern delegate :min_password_score, to: "self.class" delegate :zxcvbn_tester, to: "self.class" included do - validate :not_weak_password, if: :password_required? + validate :strong_password, unless: :skip_password_complexity? end def password_score - @pass_score = self.class.password_score(self) + @password_score = self.class.password_score(self) end + def password_weak? + password_score.score < min_password_score + end + private - def not_weak_password - if errors.messages.blank? && password_score.score < min_password_score + def strong_password + if errors.messages.blank? && password_weak? errors.add :password, :weak_password, i18n_variables end end def i18n_variables { feedback: zxcvbn_feedback, crack_time_display: time_to_crack, - score: @pass_score.score, + score: password_score.score, min_password_score: min_password_score } end def zxcvbn_feedback - feedback = @pass_score.feedback.values.flatten.reject(&:empty?) - return 'Add another word or two. Uncommon words are better.' if feedback.empty? + feedback = password_score.feedback.values.flatten.reject(&:empty?) + return "Add another word or two. Uncommon words are better." if feedback.empty? - feedback.join('. ').gsub(/\.\s*\./, '.') + feedback.join(". ").gsub(/\.\s*\./, ".") end def time_to_crack - @pass_score.crack_times_display['offline_fast_hashing_1e10_per_second'] + password_score.crack_times_display["offline_fast_hashing_1e10_per_second"] end - module ClassMethods + class_methods do Devise::Models.config(self, :min_password_score) Devise::Models.config(self, :zxcvbn_tester) - def password_score(user, arg_email=nil) - password = user.respond_to?(:password) ? user.password.to_s : user + def password_score(user, arg_email = nil) + return raise DeviseZxcvbnError, "the object must respond to password" unless user.respond_to?(:password) + password = user.password.to_s + zxcvbn_weak_words = [] if arg_email zxcvbn_weak_words += [arg_email, *DeviseZxcvbn::EmailTokeniser.split(arg_email)] end # User method results are saved locally to prevent repeat calls that might be expensive - if user.respond_to? :email + if user.respond_to?(:email) local_email = user.email zxcvbn_weak_words += [local_email, *DeviseZxcvbn::EmailTokeniser.split(local_email)] end - if user.respond_to? :weak_words + if user.respond_to?(:weak_words) + return raise DeviseZxcvbnError, "weak_words must return an Array" unless user.weak_words.is_a?(Array) + local_weak_words = user.weak_words - raise "weak_words must return an Array" unless (local_weak_words.is_a? Array) zxcvbn_weak_words += local_weak_words end zxcvbn_tester.test(password, zxcvbn_weak_words) end