mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Extract encryptors into their own module for better bcrypt support.
This commit is contained in:
parent
31d821c2e0
commit
09088706bb
20 changed files with 204 additions and 158 deletions
|
@ -7,7 +7,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
|||
* Allows you to have multiple roles (or models/scopes) signed in at the same time;
|
||||
* Is based on a modularity concept: use just what you really need.
|
||||
|
||||
It's composed of 11 modules:
|
||||
It's composed of 12 modules:
|
||||
|
||||
* Database Authenticatable: encrypts and stores a password in the database to validate the authenticity of an user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
|
||||
* Token Authenticatable: signs in a user based on an authentication token (also known as "single access token"). The token can be given both through query string or HTTP Basic Authentication.
|
||||
|
@ -20,6 +20,7 @@ It's composed of 11 modules:
|
|||
* Timeoutable: expires sessions that have no activity in a specified period of time.
|
||||
* Validatable: provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
||||
* Lockable: locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
||||
* Encryptable: allows support of other authentication mechanisms besides Bcrypt (the default).
|
||||
|
||||
== Information
|
||||
|
||||
|
@ -152,9 +153,9 @@ Finally, you need to set up default url options for the mailer in each environme
|
|||
|
||||
The devise method in your models also accepts some options to configure its modules. For example, you can choose which encryptor to use in database_authenticatable:
|
||||
|
||||
devise :database_authenticatable, :confirmable, :recoverable, :encryptor => :bcrypt
|
||||
devise :database_authenticatable, :confirmable, :recoverable, :stretches => 20
|
||||
|
||||
Besides :encryptor, you can define :pepper, :stretches, :confirm_within, :remember_for, :timeout_in, :unlock_in and other values. For details, see the initializer file that was created when you invoked the "devise:install" generator described above.
|
||||
Besides :stretches, you can define :pepper, :encryptor, :confirm_within, :remember_for, :timeout_in, :unlock_in and other values. For details, see the initializer file that was created when you invoked the "devise:install" generator described above.
|
||||
|
||||
=== Configuring multiple models
|
||||
|
||||
|
@ -308,7 +309,7 @@ Devise supports ActiveRecord (default) and Mongoid. To choose other ORM, you jus
|
|||
|
||||
=== Migrating from other solutions
|
||||
|
||||
Devise implements encryption strategies for Clearance, Authlogic and Restful-Authentication. To make use of these strategies, set the desired encryptor in the encryptor initializer config option. You might also need to rename your encrypted password and salt columns to match Devise's fields (encrypted_password and password_salt).
|
||||
Devise implements encryption strategies for Clearance, Authlogic and Restful-Authentication. To make use of these strategies, you need set the desired encryptor in the encryptor initializer config option and add :encryptable to your model. You might also need to rename your encrypted password and salt columns to match Devise's fields (encrypted_password and password_salt).
|
||||
|
||||
== Additional information
|
||||
|
||||
|
|
|
@ -48,18 +48,13 @@ module Devise
|
|||
:sha512 => 128,
|
||||
:clearance_sha1 => 40,
|
||||
:restful_authentication_sha1 => 40,
|
||||
:authlogic_sha512 => 128,
|
||||
:bcrypt => 60
|
||||
:authlogic_sha512 => 128
|
||||
}
|
||||
|
||||
# Custom domain for cookies. Not set by default
|
||||
mattr_accessor :cookie_domain
|
||||
@@cookie_domain = false
|
||||
|
||||
# Used to encrypt password. Please generate one with rake secret.
|
||||
mattr_accessor :pepper
|
||||
@@pepper = nil
|
||||
|
||||
# The number of times to encrypt password.
|
||||
mattr_accessor :stretches
|
||||
@@stretches = 10
|
||||
|
@ -121,9 +116,13 @@ module Devise
|
|||
mattr_accessor :timeout_in
|
||||
@@timeout_in = 30.minutes
|
||||
|
||||
# Used to encrypt password. Please generate one with rake secret.
|
||||
mattr_accessor :pepper
|
||||
@@pepper = nil
|
||||
|
||||
# Used to define the password encryption algorithm.
|
||||
mattr_accessor :encryptor
|
||||
@@encryptor = :bcrypt
|
||||
@@encryptor = nil
|
||||
|
||||
# Tells if devise should apply the schema in ORMs where devise declaration
|
||||
# and schema belongs to the same class (as Datamapper and Mongoid).
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
require "bcrypt"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = BCrypt
|
||||
# Uses the BCrypt hash algorithm to encrypt passwords.
|
||||
class Bcrypt < Base
|
||||
# Gererates a default password digest based on stretches, salt, pepper and the
|
||||
# incoming password. We don't strech it ourselves since BCrypt does so internally.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
::BCrypt::Engine.hash_secret([password, pepper].join, salt, stretches)
|
||||
end
|
||||
|
||||
def self.salt(stretches)
|
||||
::BCrypt::Engine.generate_salt(stretches)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
require 'devise/strategies/database_authenticatable'
|
||||
require 'bcrypt'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
|
@ -9,14 +10,7 @@ module Devise
|
|||
#
|
||||
# DatabaseAuthenticable adds the following options to devise_for:
|
||||
#
|
||||
# * +pepper+: encryption key used for creating encrypted password. Each time
|
||||
# password changes, it's gonna be encrypted again, and this key is added
|
||||
# to the password and salt to create a secure hash. Always use `rake secret'
|
||||
# to generate a new key.
|
||||
#
|
||||
# * +stretches+: defines how many times the password will be encrypted.
|
||||
#
|
||||
# * +encryptor+: the encryptor going to be used. By default :sha1.
|
||||
# * +stretches+: the cost given to bcrypt.
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
|
@ -30,20 +24,15 @@ module Devise
|
|||
attr_accessor :password_confirmation
|
||||
end
|
||||
|
||||
# Regenerates password salt and encrypted password each time password is set,
|
||||
# and then trigger any "after_changed_password"-callbacks.
|
||||
# Generators password encryption based on the value given.
|
||||
def password=(new_password)
|
||||
@password = new_password
|
||||
|
||||
if @password.present?
|
||||
self.password_salt = self.class.password_salt
|
||||
self.encrypted_password = password_digest(@password)
|
||||
end
|
||||
self.encrypted_password = password_digest(@password) if @password.present?
|
||||
end
|
||||
|
||||
# Verifies whether an incoming_password (ie from sign in) is the user password.
|
||||
def valid_password?(incoming_password)
|
||||
password_digest(incoming_password) == self.encrypted_password
|
||||
::BCrypt::Password.new(self.encrypted_password) == incoming_password
|
||||
end
|
||||
|
||||
# Set password and password confirmation to nil
|
||||
|
@ -77,26 +66,20 @@ module Devise
|
|||
def after_database_authentication
|
||||
end
|
||||
|
||||
# A reliable way to expose the salt regardless of the implementation.
|
||||
def authenticatable_salt
|
||||
self.encrypted_password[0,29]
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Digests the password using the configured encryptor.
|
||||
# Digests the password using bcrypt.
|
||||
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
|
||||
::BCrypt::Password.create(password, :cost => self.class.stretches).to_s
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
Devise::Models.config(self, :pepper, :stretches, :encryptor)
|
||||
|
||||
# Returns the class for the configured encryptor.
|
||||
def encryptor_class
|
||||
@encryptor_class ||= ::Devise::Encryptors.const_get(encryptor.to_s.classify)
|
||||
end
|
||||
|
||||
def password_salt
|
||||
self.encryptor_class.salt(self.stretches)
|
||||
end
|
||||
Devise::Models.config(self, :stretches)
|
||||
|
||||
# We assume this method already gets the sanitized values from the
|
||||
# DatabaseAuthenticatable strategy. If you are using this method on
|
||||
|
|
65
lib/devise/models/encryptable.rb
Normal file
65
lib/devise/models/encryptable.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
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)
|
||||
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, :pepper, :encryptor)
|
||||
|
||||
# Returns the class for the configured encryptor.
|
||||
def encryptor_class
|
||||
@encryptor_class ||= ::Devise::Encryptors.const_get(encryptor.to_s.classify)
|
||||
end
|
||||
|
||||
def password_salt
|
||||
self.encryptor_class.salt(self.stretches)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -82,7 +82,7 @@ module Devise
|
|||
end
|
||||
|
||||
def rememberable_value
|
||||
respond_to?(:remember_token) ? self.remember_token : self.password_salt
|
||||
respond_to?(:remember_token) ? self.remember_token : self.authenticatable_salt
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -10,6 +10,7 @@ Devise.with_options :model => true do |d|
|
|||
end
|
||||
|
||||
# Other authentications
|
||||
d.add_module :encryptable
|
||||
d.add_module :oauthable, :controller => :oauth_callbacks, :route => :oauth_callback
|
||||
|
||||
# Misc after
|
||||
|
|
|
@ -33,6 +33,23 @@ module Devise
|
|||
end
|
||||
end
|
||||
|
||||
initializer "devise.encryptor_check" do
|
||||
case Devise.encryptor
|
||||
when :bcrypt
|
||||
puts "[DEVISE] From version 1.2, there is no need to set your encryptor to bcrypt " <<
|
||||
"since encryptors are only enabled if you include :encryptable in your models. " <<
|
||||
"With this change, we can integrate better with bcrypt and get rid of the " <<
|
||||
"password_salt column (since bcrypt stores the salt with password). " <<
|
||||
"Please comment config.encryptor in your initializer to get rid of this warning."
|
||||
when nil
|
||||
# Nothing to say
|
||||
else
|
||||
puts "[DEVISE] You are using #{Devise.encryptor} as encryptor. From version 1.2, " <<
|
||||
"you need to explicitly add :encryptable to your models in order for this " <<
|
||||
"configuration value to work."
|
||||
end
|
||||
end
|
||||
|
||||
# Check all available mappings and only load related controllers.
|
||||
def eager_load!
|
||||
mappings = Devise.mappings.values.map(&:modules).flatten.uniq
|
||||
|
|
|
@ -18,7 +18,11 @@ module Devise
|
|||
|
||||
apply_devise_schema :email, String, :null => null, :default => default
|
||||
apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
|
||||
apply_devise_schema :password_salt, String, :null => null, :default => default
|
||||
end
|
||||
|
||||
# Creates password salt for encryption support.
|
||||
def encryptable
|
||||
apply_devise_schema :password_salt, String
|
||||
end
|
||||
|
||||
# Creates authentication_token.
|
||||
|
|
|
@ -6,6 +6,7 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
|
|||
t.rememberable
|
||||
t.trackable
|
||||
|
||||
# t.encryptable
|
||||
# t.confirmable
|
||||
# t.lockable :lock_strategy => :<%= Devise.lock_strategy %>, :unlock_strategy => :<%= Devise.unlock_strategy %>
|
||||
# t.token_authenticatable
|
||||
|
|
|
@ -4,7 +4,7 @@ module Devise
|
|||
def model_contents
|
||||
<<-CONTENT
|
||||
# Include default devise modules. Others available are:
|
||||
# :token_authenticatable, :confirmable, :lockable, :timeoutable and :oauthable
|
||||
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :oauthable
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :trackable, :validatable
|
||||
|
||||
|
|
|
@ -44,19 +44,10 @@ Devise.setup do |config|
|
|||
# config.http_authentication_realm = "Application"
|
||||
|
||||
# ==> Configuration for :database_authenticatable
|
||||
# Define which will be the encryption algorithm. Devise also supports encryptors
|
||||
# from others authentication tools as :clearance_sha1, :authlogic_sha512 (then
|
||||
# you should set stretches above to 20 for default behavior) and :restful_authentication_sha1
|
||||
# (then you should set stretches to 10, and copy REST_AUTH_SITE_KEY to pepper)
|
||||
config.encryptor = :bcrypt
|
||||
|
||||
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
|
||||
# using other encryptors, it sets how many times you want the password re-encrypted.
|
||||
config.stretches = 10
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %>
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# The time you want to give your user to confirm his account. During this time
|
||||
# he will be able to access your application without confirming. Default is nil.
|
||||
|
@ -112,6 +103,17 @@ Devise.setup do |config|
|
|||
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||
# config.unlock_in = 1.hour
|
||||
|
||||
# ==> Configuration for :encryptable
|
||||
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
|
||||
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
|
||||
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
|
||||
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
|
||||
# REST_AUTH_SITE_KEY to pepper)
|
||||
# config.encryptor = :sha512
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
# config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %>
|
||||
|
||||
# ==> Configuration for :token_authenticatable
|
||||
# Defines name of the authentication token params key
|
||||
# config.token_authentication_key = :auth_token
|
||||
|
|
|
@ -2,55 +2,17 @@ require 'test_helper'
|
|||
require 'digest/sha1'
|
||||
|
||||
class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
|
||||
def encrypt_password(user, pepper=User.pepper, stretches=User.stretches, encryptor=User.encryptor_class)
|
||||
encryptor.digest('123456', stretches, user.password_salt, pepper)
|
||||
end
|
||||
|
||||
def swap_with_encryptor(klass, encryptor, options={})
|
||||
klass.instance_variable_set(:@encryptor_class, nil)
|
||||
|
||||
swap klass, options.merge(:encryptor => encryptor) do
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
klass.instance_variable_set(:@encryptor_class, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'should respond to password and password confirmation' do
|
||||
user = new_user
|
||||
assert user.respond_to?(:password)
|
||||
assert user.respond_to?(:password_confirmation)
|
||||
end
|
||||
|
||||
test 'should generate encrypted password and salt while setting password' do
|
||||
test 'should generate encrypted password while setting password' do
|
||||
user = new_user
|
||||
assert_present user.password_salt
|
||||
assert_present user.encrypted_password
|
||||
end
|
||||
|
||||
test 'should not change password salt when updating' do
|
||||
user = create_user
|
||||
salt = user.password_salt
|
||||
user.expects(:password_salt=).never
|
||||
user.save!
|
||||
assert_equal salt, user.password_salt
|
||||
end
|
||||
|
||||
test 'should generate a base64 hash using SecureRandom for password salt' do
|
||||
swap_with_encryptor User, :sha1 do
|
||||
ActiveSupport::SecureRandom.expects(:base64).with(44).returns('friendly_token')
|
||||
assert_equal 'friendly_token', new_user.password_salt
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not generate salt if password is blank' do
|
||||
assert_blank new_user(:password => nil).password_salt
|
||||
assert_blank new_user(:password => '').password_salt
|
||||
end
|
||||
|
||||
test 'should not generate encrypted password if password is blank' do
|
||||
assert_blank new_user(:password => nil).encrypted_password
|
||||
assert_blank new_user(:password => '').encrypted_password
|
||||
|
@ -64,47 +26,12 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
|||
assert_not_equal encrypted_password, user.encrypted_password
|
||||
end
|
||||
|
||||
test 'should fallback to sha1 as default encryption' do
|
||||
user = new_user
|
||||
assert_equal encrypt_password(user), user.encrypted_password
|
||||
end
|
||||
|
||||
test 'should fallback to devise pepper default configuration' do
|
||||
begin
|
||||
Devise.pepper = ''
|
||||
user = new_user
|
||||
assert_equal encrypt_password(user), user.encrypted_password
|
||||
assert_not_equal encrypt_password(user, 'another_pepper'), user.encrypted_password
|
||||
|
||||
Devise.pepper = 'new_pepper'
|
||||
user = new_user
|
||||
assert_equal encrypt_password(user, 'new_pepper'), user.encrypted_password
|
||||
assert_not_equal encrypt_password(user, 'another_pepper'), user.encrypted_password
|
||||
ensure
|
||||
Devise.pepper = nil
|
||||
end
|
||||
end
|
||||
|
||||
test 'should respect encryptor configuration' do
|
||||
swap_with_encryptor User, :sha512 do
|
||||
user = create_user
|
||||
assert_equal user.encrypted_password, encrypt_password(user, User.pepper, User.stretches, ::Devise::Encryptors::Sha512)
|
||||
end
|
||||
end
|
||||
|
||||
test 'should test for a valid password' do
|
||||
user = create_user
|
||||
assert user.valid_password?('123456')
|
||||
assert_not user.valid_password?('654321')
|
||||
end
|
||||
|
||||
test 'should not validate password when salt is nil' do
|
||||
admin = create_admin
|
||||
admin.password_salt = nil
|
||||
admin.save
|
||||
assert_not admin.valid_password?('123456')
|
||||
end
|
||||
|
||||
test 'should respond to current password' do
|
||||
assert new_user.respond_to?(:current_password)
|
||||
end
|
||||
|
|
65
test/models/encryptable_test.rb
Normal file
65
test/models/encryptable_test.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
require 'test_helper'
|
||||
|
||||
class EncryptableTest < ActiveSupport::TestCase
|
||||
def encrypt_password(admin, pepper=Admin.pepper, stretches=Admin.stretches, encryptor=Admin.encryptor_class)
|
||||
encryptor.digest('123456', stretches, admin.password_salt, pepper)
|
||||
end
|
||||
|
||||
def swap_with_encryptor(klass, encryptor, options={})
|
||||
klass.instance_variable_set(:@encryptor_class, nil)
|
||||
|
||||
swap klass, options.merge(:encryptor => encryptor) do
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
klass.instance_variable_set(:@encryptor_class, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'should generate salt while setting password' do
|
||||
assert_present create_admin.password_salt
|
||||
end
|
||||
|
||||
test 'should not change password salt when updating' do
|
||||
admin = create_admin
|
||||
salt = admin.password_salt
|
||||
admin.expects(:password_salt=).never
|
||||
admin.save!
|
||||
assert_equal salt, admin.password_salt
|
||||
end
|
||||
|
||||
test 'should generate a base64 hash using SecureRandom for password salt' do
|
||||
swap_with_encryptor Admin, :sha1 do
|
||||
ActiveSupport::SecureRandom.expects(:base64).with(44).returns('friendly_token')
|
||||
assert_equal 'friendly_token', create_admin.password_salt
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not generate salt if password is blank' do
|
||||
assert_blank create_admin(:password => nil).password_salt
|
||||
assert_blank create_admin(:password => '').password_salt
|
||||
end
|
||||
|
||||
test 'should encrypt password again if password has changed' do
|
||||
admin = create_admin
|
||||
encrypted_password = admin.encrypted_password
|
||||
admin.password = admin.password_confirmation = 'new_password'
|
||||
admin.save!
|
||||
assert_not_equal encrypted_password, admin.encrypted_password
|
||||
end
|
||||
|
||||
test 'should respect encryptor configuration' do
|
||||
swap_with_encryptor Admin, :sha512 do
|
||||
admin = create_admin
|
||||
assert_equal admin.encrypted_password, encrypt_password(admin, Admin.pepper, Admin.stretches, ::Devise::Encryptors::Sha512)
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not validate password when salt is nil' do
|
||||
admin = create_admin
|
||||
admin.password_salt = nil
|
||||
admin.save
|
||||
assert_not admin.valid_password?('123456')
|
||||
end
|
||||
end
|
|
@ -260,12 +260,12 @@ class WithSaltRememberableTest < ActiveSupport::TestCase
|
|||
test 'serialize into cookie' do
|
||||
user = create_user
|
||||
user.remember_me!
|
||||
assert_equal [user.id, user.password_salt], User.serialize_into_cookie(user)
|
||||
assert_equal [user.id, user.authenticatable_salt], User.serialize_into_cookie(user)
|
||||
end
|
||||
|
||||
test 'serialize from cookie' do
|
||||
user = create_user
|
||||
user.remember_me!
|
||||
assert_equal user, User.serialize_from_cookie(user.id, user.password_salt)
|
||||
assert_equal user, User.serialize_from_cookie(user.id, user.authenticatable_salt)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
require 'test_helper'
|
||||
|
||||
class Configurable < User
|
||||
devise :database_authenticatable, :confirmable, :rememberable, :timeoutable, :lockable,
|
||||
devise :database_authenticatable, :encryptable, :confirmable, :rememberable, :timeoutable, :lockable,
|
||||
:stretches => 15, :pepper => 'abcdef', :confirm_within => 5.days,
|
||||
:remember_for => 7.days, :timeout_in => 15.minutes, :unlock_in => 10.days
|
||||
end
|
||||
|
@ -26,16 +26,16 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
test 'can cherry pick modules' do
|
||||
assert_include_modules Admin, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :rememberable
|
||||
assert_include_modules Admin, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :rememberable, :encryptable
|
||||
end
|
||||
|
||||
test 'chosen modules are inheritable' do
|
||||
assert_include_modules Inheritable, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :rememberable
|
||||
assert_include_modules Inheritable, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :rememberable, :encryptable
|
||||
end
|
||||
|
||||
test 'order of module inclusion' do
|
||||
correct_module_order = [:database_authenticatable, :rememberable, :recoverable, :registerable, :lockable, :timeoutable]
|
||||
incorrect_module_order = [:database_authenticatable, :timeoutable, :registerable, :recoverable, :lockable, :rememberable]
|
||||
correct_module_order = [:database_authenticatable, :rememberable, :encryptable, :recoverable, :registerable, :lockable, :timeoutable]
|
||||
incorrect_module_order = [:database_authenticatable, :timeoutable, :registerable, :recoverable, :lockable, :encryptable, :rememberable]
|
||||
|
||||
assert_include_modules Admin, *incorrect_module_order
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ Devise.setup do |config|
|
|||
# from others authentication tools as :clearance_sha1, :authlogic_sha512 (then
|
||||
# you should set stretches above to 20 for default behavior) and :restful_authentication_sha1
|
||||
# (then you should set stretches to 10, and copy REST_AUTH_SITE_KEY to pepper)
|
||||
config.encryptor = :bcrypt
|
||||
config.encryptor = :sha512
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
config.pepper = "d142367154e5beacca404b1a6a4f8bc52c6fdcfa3ccc3cf8eb49f3458a688ee6ac3b9fae488432a3bfca863b8a90008368a9f3a3dfbe5a962e64b6ab8f3a3a1a"
|
||||
|
|
|
@ -15,7 +15,8 @@ class CreateTables < ActiveRecord::Migration
|
|||
end
|
||||
|
||||
create_table :admins do |t|
|
||||
t.database_authenticatable :null => true, :encryptor => :bcrypt
|
||||
t.database_authenticatable :null => true
|
||||
t.encryptable
|
||||
t.rememberable
|
||||
t.recoverable
|
||||
t.lockable
|
||||
|
|
|
@ -15,7 +15,7 @@ ActiveRecord::Schema.define(:version => 20100401102949) do
|
|||
create_table "admins", :force => true do |t|
|
||||
t.string "email", :default => ""
|
||||
t.string "encrypted_password", :limit => 128, :default => ""
|
||||
t.string "password_salt", :default => ""
|
||||
t.string "password_salt"
|
||||
t.string "reset_password_token"
|
||||
t.integer "failed_attempts", :default => 0
|
||||
t.string "unlock_token"
|
||||
|
@ -29,7 +29,6 @@ ActiveRecord::Schema.define(:version => 20100401102949) do
|
|||
t.string "facebook_token"
|
||||
t.string "email", :default => "", :null => false
|
||||
t.string "encrypted_password", :limit => 128, :default => "", :null => false
|
||||
t.string "password_salt", :default => "", :null => false
|
||||
t.string "confirmation_token"
|
||||
t.datetime "confirmed_at"
|
||||
t.datetime "confirmation_sent_at"
|
||||
|
|
|
@ -2,6 +2,6 @@ module SharedAdmin
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
devise :database_authenticatable, :registerable, :timeoutable, :recoverable, :rememberable, :lockable, :unlock_strategy => :time
|
||||
devise :database_authenticatable, :encryptable, :registerable, :timeoutable, :recoverable, :rememberable, :lockable, :unlock_strategy => :time
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue