require 'devise/strategies/database_authenticatable' module Devise module Models # Encryptable Module adds support to several encryptors. # # == Options # # Encryptable adds the following options to devise_for: # # * +pepper+: a random string used to provide a more secure hash. # # * +encryptor+: the encryptor going to be used. By default is nil. # # == Examples # # User.find(1).valid_password?('password123') # returns true/false # module Encryptable extend ActiveSupport::Concern included do attr_reader :password, :current_password attr_accessor :password_confirmation end # Generates password salt. def password=(new_password) self.password_salt = self.class.password_salt if new_password.present? super end def authenticatable_salt self.password_salt end # Verifies whether an incoming_password (ie from sign in) is the user password. def valid_password?(incoming_password) Devise.secure_compare(password_digest(incoming_password), self.encrypted_password) end protected # Digests the password using the configured encryptor. def password_digest(password) if self.password_salt.present? self.class.encryptor_class.digest(password, self.class.stretches, self.password_salt, self.class.pepper) end end module ClassMethods Devise::Models.config(self, :encryptor) # Returns the class for the configured encryptor. def encryptor_class @encryptor_class ||= case encryptor when :bcrypt raise "In order to use bcrypt as encryptor, simply remove :encryptable from your devise model" when nil raise "You need to give an :encryptor as option in order to use :encryptable" else ::Devise::Encryptors.const_get(encryptor.to_s.classify) end end def password_salt self.encryptor_class.salt(self.stretches) end end end end end