From 09088706bb36f61e8268150936b088de3a677716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 25 Sep 2010 16:08:46 +0200 Subject: [PATCH] Extract encryptors into their own module for better bcrypt support. --- README.rdoc | 9 ++- lib/devise.rb | 13 ++-- lib/devise/encryptors/bcrypt.rb | 19 ----- lib/devise/models/database_authenticatable.rb | 43 ++++------- lib/devise/models/encryptable.rb | 65 ++++++++++++++++ lib/devise/models/rememberable.rb | 2 +- lib/devise/modules.rb | 1 + lib/devise/rails.rb | 17 +++++ lib/devise/schema.rb | 6 +- .../active_record/templates/migration.rb | 1 + lib/generators/devise/orm_helpers.rb | 2 +- lib/generators/templates/devise.rb | 20 ++--- test/models/database_authenticatable_test.rb | 75 +------------------ test/models/encryptable_test.rb | 65 ++++++++++++++++ test/models/rememberable_test.rb | 4 +- test/models_test.rb | 10 +-- test/rails_app/config/initializers/devise.rb | 2 +- .../migrate/20100401102949_create_tables.rb | 3 +- test/rails_app/db/schema.rb | 3 +- test/rails_app/lib/shared_admin.rb | 2 +- 20 files changed, 204 insertions(+), 158 deletions(-) delete mode 100644 lib/devise/encryptors/bcrypt.rb create mode 100644 lib/devise/models/encryptable.rb create mode 100644 test/models/encryptable_test.rb diff --git a/README.rdoc b/README.rdoc index 433b1787..5c724ffe 100644 --- a/README.rdoc +++ b/README.rdoc @@ -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 diff --git a/lib/devise.rb b/lib/devise.rb index b52cd127..6402b7c2 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -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). diff --git a/lib/devise/encryptors/bcrypt.rb b/lib/devise/encryptors/bcrypt.rb deleted file mode 100644 index 45c59e9b..00000000 --- a/lib/devise/encryptors/bcrypt.rb +++ /dev/null @@ -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 diff --git a/lib/devise/models/database_authenticatable.rb b/lib/devise/models/database_authenticatable.rb index c5a10dd6..316ff512 100644 --- a/lib/devise/models/database_authenticatable.rb +++ b/lib/devise/models/database_authenticatable.rb @@ -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 diff --git a/lib/devise/models/encryptable.rb b/lib/devise/models/encryptable.rb new file mode 100644 index 00000000..febd73e7 --- /dev/null +++ b/lib/devise/models/encryptable.rb @@ -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 diff --git a/lib/devise/models/rememberable.rb b/lib/devise/models/rememberable.rb index e474bf53..995cbf5b 100644 --- a/lib/devise/models/rememberable.rb +++ b/lib/devise/models/rememberable.rb @@ -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 diff --git a/lib/devise/modules.rb b/lib/devise/modules.rb index 1f688c03..46816017 100644 --- a/lib/devise/modules.rb +++ b/lib/devise/modules.rb @@ -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 diff --git a/lib/devise/rails.rb b/lib/devise/rails.rb index 97944997..69f0fb8e 100644 --- a/lib/devise/rails.rb +++ b/lib/devise/rails.rb @@ -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 diff --git a/lib/devise/schema.rb b/lib/devise/schema.rb index 23bd5d33..8270568f 100644 --- a/lib/devise/schema.rb +++ b/lib/devise/schema.rb @@ -18,9 +18,13 @@ 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. def token_authenticatable(options={}) apply_devise_schema :authentication_token, String diff --git a/lib/generators/active_record/templates/migration.rb b/lib/generators/active_record/templates/migration.rb index 53a60e48..deb3d499 100644 --- a/lib/generators/active_record/templates/migration.rb +++ b/lib/generators/active_record/templates/migration.rb @@ -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 diff --git a/lib/generators/devise/orm_helpers.rb b/lib/generators/devise/orm_helpers.rb index a892e91f..535c0fb8 100644 --- a/lib/generators/devise/orm_helpers.rb +++ b/lib/generators/devise/orm_helpers.rb @@ -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 diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb index 52e52c07..fed313c0 100644 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -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 diff --git a/test/models/database_authenticatable_test.rb b/test/models/database_authenticatable_test.rb index 93b5d932..3f123b18 100644 --- a/test/models/database_authenticatable_test.rb +++ b/test/models/database_authenticatable_test.rb @@ -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 diff --git a/test/models/encryptable_test.rb b/test/models/encryptable_test.rb new file mode 100644 index 00000000..97a3910f --- /dev/null +++ b/test/models/encryptable_test.rb @@ -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 diff --git a/test/models/rememberable_test.rb b/test/models/rememberable_test.rb index 6cd9b24e..10706dee 100644 --- a/test/models/rememberable_test.rb +++ b/test/models/rememberable_test.rb @@ -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 diff --git a/test/models_test.rb b/test/models_test.rb index ed9c3682..386bfb4a 100644 --- a/test/models_test.rb +++ b/test/models_test.rb @@ -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 diff --git a/test/rails_app/config/initializers/devise.rb b/test/rails_app/config/initializers/devise.rb index 376cd080..87263452 100644 --- a/test/rails_app/config/initializers/devise.rb +++ b/test/rails_app/config/initializers/devise.rb @@ -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" diff --git a/test/rails_app/db/migrate/20100401102949_create_tables.rb b/test/rails_app/db/migrate/20100401102949_create_tables.rb index 7128a1aa..fb97cd09 100644 --- a/test/rails_app/db/migrate/20100401102949_create_tables.rb +++ b/test/rails_app/db/migrate/20100401102949_create_tables.rb @@ -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 diff --git a/test/rails_app/db/schema.rb b/test/rails_app/db/schema.rb index 0e4db5c6..db9f823a 100644 --- a/test/rails_app/db/schema.rb +++ b/test/rails_app/db/schema.rb @@ -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" diff --git a/test/rails_app/lib/shared_admin.rb b/test/rails_app/lib/shared_admin.rb index bb9d7728..0d864d2b 100644 --- a/test/rails_app/lib/shared_admin.rb +++ b/test/rails_app/lib/shared_admin.rb @@ -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 \ No newline at end of file