Skip to content

Instantly share code, notes, and snippets.

@bhuga
Forked from spullen/devise_create_user.rb
Created November 9, 2012 22:23
Show Gist options
  • Save bhuga/4048705 to your computer and use it in GitHub Desktop.
Save bhuga/4048705 to your computer and use it in GitHub Desktop.
HybridAuthenticatable 2
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :username, :null => false, :default => ""
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
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 # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
t.string :override_ldap, :default => false
t.timestamps
end
add_index :users, :username, :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, :authentication_token, :unique => true
end
end
# lib/hybrid_authenticatable/models/hybrid_authenticatable.rb
require 'devise'
require 'strategy'
require 'models/hybrid_authenticatable'
require 'models/password_encryptable'
module HybridAuthenticatable
end
Devise.add_module(:hybrid_authenticatable,
:route => :session,
:strategy => true,
:controller => :sessions,
:model => 'models/hybrid_authenticatable')
Devise.add_module(:password_encryptable,
:route => :session,
:strategy => false,
:controller => :sessions,
:model => 'models/password_encryptable')
# lib/hybrid_authenticatable/models/hybrid_authenticatable.rb
require 'strategy'
module Devise
module Models
module HybridAuthenticatable
extend ActiveSupport::Concern
end
end
end
# lib/hybrid_authenticatable/models/password_encryptable.rb
require 'bcrypt'
module Devise
module Models
module PasswordEncryptable
extend ActiveSupport::Concern
included do
attr_reader :password, :current_password
attr_accessor :password_confirmation
end
def self.required_fields(klass)
[:encrypted_password] + klass.authentication_keys
end
# Generates password encryption based on the given value.
def password=(new_password)
@password = new_password
self.encrypted_password = password_digest(@password) if @password.present?
end
# A reliable way to expose the salt regardless of the implementation.
def authenticatable_salt
encrypted_password[0,29] if encrypted_password
end
protected
# Digests the password using bcrypt.
def password_digest(password)
::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s
end
module ClassMethods
Devise::Models.config(self, :pepper, :stretches)
end
end
end
end
# lib/hybrid_authenticatable/strategy.rb
require 'devise/strategies/authenticatable'
module Devise
module Strategies
class HybridAuthenticatable < Authenticatable
def authenticate!
resource = mapping.to.find_for_authentication(authentication_hash)
return fail(:invalid) if resource.nil? || !valid_password?
if resource.override_ldap == true
mapping.to.send(:extend, Devise::Models::DatabaseAuthenticatable::ClassMethods)
mapping.to.send(:include, Devise::Models::DatabaseAuthenticatable)
return fail(:invalid) unless resource.valid_password?(password)
else
mapping.to.send(:include, Devise::Models::LdapAuthenticatable)
return fail(:invalid) unless resource.valid_ldap_authentication?(password)
end
if validate(resource)
success!(resource)
else
return fail(:invalid)
end
end
end
end
end
Warden::Strategies.add(:hybrid_authenticatable, Devise::Strategies::HybridAuthenticatable)
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :username, :null => false, :default => ""
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
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 # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
t.string :override_ldap, :default => false
t.timestamps
end
add_index :users, :username, :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, :authentication_token, :unique => true
end
end
# app/models/user.rb
class User < ActiveRecord::Base
devise :hybrid_authenticatable, :password_encryptable, :rememberable, :trackable
attr_accessible :username, :email, :password, :password_confirmation, :remember_me, :override_ldap
validates :username, :presence => true, :uniqueness => true
validates :email, :presence => true, :uniqueness => true
validates :password, :presence => true, :if => lambda { |user| user.override_ldap == true }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment