Assuming you already have a Devise model named User
and you want to add following Devise Security Extension to it
- Password Expirable
- Password Archivable
- Session Limitable
then your User
model should look like following:
User model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable,
:password_expirable, :password_archivable, :session_limitable # Devise Security Extensions
...
...
...
end
Let's assume that you have USERS
table in your DB schema (there are instructions at the bottom, if it's not the case).
As it is known that the migrations are to be created manually and there are no helpers available to create the schema run the following commands to generate the Devise Security Extension modules migrations:
Generate migration for Password Expirable module:
web_app$ rails g migration AddDeviseSecurityExtensionPasswordExpirableColumnsToUsers
invoke active_record
create db/migrate/20150213121619_add_devise_security_extension_password_expirable_columns_to_users.rb
Open db/migrate/20150213121619_add_devise_security_extension_password_expirable_columns_to_users.rb
and add following code to it:
class AddDeviseSecurityExtensionPasswordExpirableColumnsToUsers < ActiveRecord::Migration
def change
add_column :users, :password_changed_at, :datetime
add_index :users, :password_changed_at
end
end
Now generate migration for Session Limitable module:
web_app$ rails g migration AddDeviseSecurityExtensionSessionLimitableColumnsToUsers
invoke active_record
create db/migrate/20150213121824_add_devise_security_extension_session_limitable_columns_to_users.rb
Open db/migrate/20150213121824_add_devise_security_extension_session_limitable_columns_to_users.rb
add following code to it:
class AddDeviseSecurityExtensionSessionLimitableColumnsToUsers < ActiveRecord::Migration
def change
add_column :users, :unique_session_id, :string, limit: 20
end
end
Now generate migration for Password Archivable module:
web_app$ rails g migration CreateDeviseSecurityExtensionPasswordArchivableOldPasswordsTable
invoke active_record
create db/migrate/20150213121755_create_devise_security_extension_password_archivable_old_passwords_table.rb
Open db/migrate/20150213121755_create_devise_security_extension_password_archivable_old_passwords_table.rb
and add following code to it:
class CreateDeviseSecurityExtensionPasswordArchivableOldPasswordsTable < ActiveRecord::Migration
def change
create_table :old_passwords do |t|
t.string :encrypted_password, :null => false
t.string :password_salt
t.string :password_archivable_type, :null => false
t.integer :password_archivable_id, :null => false
t.datetime :created_at
end
add_index :old_passwords, [:password_archivable_type, :password_archivable_id], :name => :index_password_archivable
end
end
Note
If you are yet to generate Devise model migration file, then first do it using the generator provided by Devise. The generated migration file say /db/migrate/20150115114522_devise_create_users.rb
then should have following code:
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
To add Password Expirable and Session Limitable Devise Security Extensions columns to your USERS
table you have two options:
- Directly edit the migration file
/db/migrate/20150115114522_devise_create_users.rb
and append the extensions columns to it.After appending, the schema file should look like
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
# Security Extension => Password expirable
t.datetime :password_changed_at
# Security Extension => Session limitable
t.string :unique_session_id, :limit => 20
t.timestamps
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
add_index :users, :password_changed_at
end
end
- Or, generate additional individual migrations as shown at the top.
In any case you will need to create a new migration for Password archivable module because it requires creating a new table.
Then as usual run rake db:migrate
command to apply the migrations created above:
$ rake db:migrate
== 20150213121619 AddDeviseSecurityExtensionPasswordExpirableColumnsToUsers: migrating
-- add_column(:users, :password_changed_at, :datetime)
-> 0.8296s
-- add_index(:users, :password_changed_at)
-> 0.3028s
== 20150213121619 AddDeviseSecurityExtensionPasswordExpirableColumnsToUsers: migrated (1.1326s)
== 20150213121755 CreateDeviseSecurityExtensionPasswordArchivableOldPasswordsTable: migrating
-- create_table(:old_passwords)
-> 0.3546s
-- add_index(:old_passwords, [:password_archivable_type, :password_archivable_id], {:name=>:index_password_archivable})
-> 0.3123s
== 20150213121755 CreateDeviseSecurityExtensionPasswordArchivableOldPasswordsTable: migrated (0.6672s)
== 20150213121824 AddDeviseSecurityExtensionSessionLimitableColumnsToUsers: migrating
-- add_column(:users, :unique_session_id, :string, {:limit=>20})
-> 0.8799s
== 20150213121824 AddDeviseSecurityExtensionSessionLimitableColumnsToUsers: migrated (0.8801s)
Thanks.