Module: Devise::Models::SecureValidatable

Includes:
Compatibility
Defined in:
lib/devise-security/models/secure_validatable.rb

Overview

SecureValidatable creates better validations with more validation for security

Options

SecureValidatable adds the following options to devise_for:

* +email_regexp+: the regular expression used to validate e-mails;
* +password_length+: a range expressing password length. Defaults from devise
* +password_regex+: need strong password. Defaults to /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.assert_secure_validations_api!(base) ⇒ Object



64
65
66
# File 'lib/devise-security/models/secure_validatable.rb', line 64

def self.assert_secure_validations_api!(base)
  raise "Could not use SecureValidatable on #{base}" unless base.respond_to?(:validates)
end

.included(base) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/devise-security/models/secure_validatable.rb', line 21

def self.included(base)
  base.extend ClassMethods
  assert_secure_validations_api!(base)

  base.class_eval do
    already_validated_email = false

    # validate login in a strict way if not yet validated
    unless has_uniqueness_validation_of_login?
      validation_condition = "#{}_changed?".to_sym

      validates , uniqueness: {
                                    scope:          authentication_keys[1..-1],
                                    case_sensitive: !!case_insensitive_keys
                                  },
                                  if: validation_condition

      already_validated_email = .to_s == 'email'
    end

    unless devise_validation_enabled?
      validates :email, presence: true, if: :email_required?
      unless already_validated_email
        validates :email, uniqueness: true, allow_blank: true, if: :email_changed? # check uniq for email ever
      end

      validates :password, presence: true, length: password_length, confirmation: true, if: :password_required?
    end

    # extra validations
    validates :email, email: email_validation if email_validation # see https://github.com/devise-security/devise-security/blob/master/README.md#e-mail-validation
    validates :password,
              'devise_security/password_complexity': password_complexity,
              if: :password_required?

    # don't allow use same password
    validate :current_equal_password_validation

    # don't allow email to equal password
    validate :email_not_equal_password_validation unless allow_passwords_equal_to_email
  end
end

Instance Method Details

#current_equal_password_validationObject



68
69
70
71
72
73
74
# File 'lib/devise-security/models/secure_validatable.rb', line 68

def current_equal_password_validation
  return if new_record? || !will_save_change_to_encrypted_password? || password.blank?
  dummy = self.class.new(encrypted_password: encrypted_password_was).tap do |user|
    user.password_salt = password_salt_was if respond_to?(:password_salt)
  end
  self.errors.add(:password, :equal_to_current_password) if dummy.valid_password?(password)
end

#email_not_equal_password_validationObject



76
77
78
79
80
81
82
83
84
85
# File 'lib/devise-security/models/secure_validatable.rb', line 76

def email_not_equal_password_validation
  return if password.blank? || (!new_record? && !will_save_change_to_encrypted_password?)
  dummy = self.class.new.tap do |user|
    user.password_salt = password_salt if respond_to?(:password_salt)
    # whether case_insensitive_keys or strip_whitespace_keys include email or not, any
    # variation of the email should not be a supported password
    user.password = email.downcase.strip
  end
  self.errors.add(:password, :equal_to_email) if dummy.valid_password?(password.downcase.strip)
end