Skip to content

Instantly share code, notes, and snippets.

@dapi
Created December 19, 2010 18:20
Show Gist options
  • Save dapi/747552 to your computer and use it in GitHub Desktop.
Save dapi/747552 to your computer and use it in GitHub Desktop.
Use Devise authentication for Typus 3.0
class AddTypusAttributesToUsers < ActiveRecord::Migration
def self.up
add_column :users, :role, :string
add_column :users, :status, :boolean, :null=>false, :default=>true
User.find(1).update_attribute(:role,'admin')
end
def self.down
remove_column :users, :role
remove_column :users, :status
end
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :nick, :email, :password, :password_confirmation, :remember_me
validates_uniqueness_of :nick
#
# Typus adaptation
#
enable_as_typus_user
ROLE = Typus::Configuration.roles.keys.sort
LANGUAGE = Typus.locales
def self.authenticate(email, password)
resource = find_for_database_authentication({ :email=>email })
resource && resource.valid_password?( password ) ? resource : nil
end
# Typus redefines it
def password_required?
true
end
def first_name
email
end
def last_name
end
def preferences
''
end
end
Copy link

ghost commented Feb 4, 2011

also need a typus/devise session handler:

module Typus

module Authentication

module TypusSession

  protected

  include Session

  def authenticate
    if admin_user_signed_in?
      current_admin_user
    else
      back_to = request.env['PATH_INFO'] unless [admin_dashboard_path, admin_path].include?(request.env['PATH_INFO'])
      redirect_to new_admin_session_path(:back_to => back_to)
    end
  end

  def admin_user
    current_admin_user
  end

end

end

end

Copy link

ghost commented Feb 4, 2011

class AdminUser < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

attr_accessible :email, :password, :password_confirmation, :remember_me, :customer_name

ROLE = Typus::Configuration.roles.keys.sort
LANGUAGE = Typus.locales

include Typus::EnableAsTypusUser::InstanceMethods

def self.authenticate(email, password)
resource = find_for_database_authentication({ :email=>email })
resource && resource.valid_password?( password ) ? resource : nil
end

# Typus redefines it
def password_required?
  true
end

def first_name
  email
end

def last_name
end

def salt
end

def salt=(value)
end

def crypted_password=(value)
end

def token=(value)
end

def preferences
  nil
end

def preference
  nil
end

end

@dapi
Copy link
Author

dapi commented Feb 4, 2011

ocharan, set .role to 'admin' for admins

@fesplugas
Copy link

@dapi
Copy link
Author

dapi commented Feb 7, 2011

Yes, of course

@bradphelan
Copy link

After some fiddling round this library worked for me.

module Typus
  module Orm
    module ActiveRecord
      module User

        def self.included(base)
          base.extend(ClassMethods)
        end

        module ClassMethods

          def enable_as_typus_devise_user

            extend ClassMethodsMixin

            validates :role, :presence => true

            serialize :preferences

            include InstanceMethods

          end

        end

        module ClassMethodsMixin

          def authenticate(email, password)
            resource = find_for_database_authentication({ :email=>email })
            r = resource && resource.valid_password?( password ) ? resource : nil
          end

        end

        module InstanceMethods

          def name
            full_name = []
            if respond_to?(:first_name) && respond_to?(:last_name)
              full_name = [first_name, last_name].delete_if { |s| s.blank? }
            end
            full_name.any? ? full_name.join(" ") : email
          end

          # This includes lots of stuff we don't need but
          # is easier than copy and pasting
          include Typus::EnableAsTypusUser::InstanceMethods


        end

      end
    end
  end
end

module Typus

  module Authentication

    module Session

      def authenticate
        if user_signed_in?
          u = current_user
          session[:typus_user_id] = u.id
        else
          back_to = request.env['PATH_INFO'] unless [
            admin_dashboard_path, 
            admin_path
          ].include?(request.env['PATH_INFO'])

          redirect_to new_user_session(:back_to => back_to)
        end

      end

      def admin_user
        current_user
      end

    end

  end

end

and use it within your app/user/model.rb as

require 'typus_devise'

class User < ActiveRecord::Base

  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable, :lockable and :timeoutable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me

  belongs_to :role

  public

  #
  # Typus adaptation
  #

  include Typus::Orm::ActiveRecord::User
  enable_as_typus_devise_user

  # Have to fix this as typus requires the role as a string
  alias :orole :role
  def role
    orole.name
  end

end

@fesplugas
Copy link

Interesting stuff ... I will add this to the wiki so people can use it.

@bradphelan
Copy link

This has got me 9/10 of the way there. However I think the authentication mechanism that typus uses could be factored out into some kind of adapter pattern which could be registered in the config file but I didn't get that far.

@fesplugas
Copy link

There's a kind of adapter ... in fact, you can enable which kind of authentication you want to use: none, http_basic and session. The problem is that is not clear enough as I'm not showing that configuration setting unless you have used the typus:migration generator.

You can see where it's called the authentication mechanism here.

@bradphelan
Copy link

I guess if Typus.authentication returned 'devise_session' and there was the appropriate
Typus::Authentication::DeviseSession
class around it might work.

However there are some spots in your views where you hard code routes instead of delegating to the adapter.

----------------------
app/views/admin/helpers/_login_info.html.erb
----------------------
  1 <ul>
  2   <li><%= Typus::I18n.t("Logged as") %> <%= link_to admin_user.name, { :controller => "/admin/#{Typus.user_class.to_resource}", :action => 'edit', :id => admin_user.id } %></li>
  3   <li><%= link_to Typus::I18n.t("Sign out"), admin_session_path, :confirm => Typus::I18n.t("Are you sure you want to sign out and end your session?"), :method => :delete %></li>
  4 </ul>

for instance

  "/admin/#{Typus.user_class.to_resource}"

is the trouble bit

@fesplugas
Copy link

I started to extract the authentication mechanisms to make easier to integrate with other systems, but I must say I have never integrated devise with typus because I'm using the session mechanism.

I accept pull requests fixing that stuff, so feel free to work on that if you want.

@fesplugas
Copy link

I've pushed a branch which adds devise support to Typus.

https://github.com/fesplugas/typus/commits/wip/devise

@bradphelan
Copy link

Works well. Thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment