Skip to content

Instantly share code, notes, and snippets.

@kdwinter
Created June 14, 2010 21:52
Show Gist options
  • Save kdwinter/438370 to your computer and use it in GitHub Desktop.
Save kdwinter/438370 to your computer and use it in GitHub Desktop.
Authlogic with Mongoid (in spirit of http://pastie.org/503478)
module Authenticable
def self.included(model)
model.class_eval do
extend ClassMethods
include InstanceMethods
field :username
field :email
field :crypted_password
field :password_salt
field :persistence_token
field :login_count, :type => Integer, :default => 0
field :last_request_at, :type => DateTime
field :last_login_at, :type => DateTime
field :current_login_at, :type => DateTime
field :last_login_ip
field :current_login_ip
index :username
index :email
index :persistence_token
index :last_login_at
include Authlogic::ActsAsAuthentic::Base
include Authlogic::ActsAsAuthentic::Email
include Authlogic::ActsAsAuthentic::LoggedInStatus
include Authlogic::ActsAsAuthentic::Login
include Authlogic::ActsAsAuthentic::MagicColumns
include Authlogic::ActsAsAuthentic::Password
include Authlogic::ActsAsAuthentic::PerishableToken
include Authlogic::ActsAsAuthentic::PersistenceToken
include Authlogic::ActsAsAuthentic::RestfulAuthentication
include Authlogic::ActsAsAuthentic::SessionMaintenance
include Authlogic::ActsAsAuthentic::SingleAccessToken
include Authlogic::ActsAsAuthentic::ValidationsScope
end
end
module ClassMethods
def <(klass)
return true if klass == ::ActiveRecord::Base
super(klass)
end
def column_names
fields.map &:first
end
def quoted_table_name
'users'
end
def primary_key
# FIXME: Is this check good enough?
if caller.first.to_s =~ /(persist|session)/
:_id
else
@@primary_key
end
end
def default_timezone
:utc
end
def find_by__id(*args)
find *args
end
# Change this to your preferred login field
def find_by_username(username)
where(:username => username).first
end
def with_scope(query)
query = where(query) if query.is_a?(Hash)
yield query
end
end
module InstanceMethods
def readonly?
false
end
end
end
class User
include Mongoid::Document
include Mongoid::Timestamps
include Authenticable
acts_as_authentic do |config|
# Change this to your preferred login field
config.login_field = 'username'
config.merge_validates_uniqueness_of_login_field_options :scope => '_id', :case_sensitive => true
end
end
class UserSession < Authlogic::Session::Base
def to_key
new_record? ? nil : [self.send(self.class.primary_key)]
end
end
@mimosz
Copy link

mimosz commented Jul 29, 2010

It's nice~

@jimsynz
Copy link

jimsynz commented Sep 6, 2010

Love it.

@danielb2
Copy link

no luck for me. Is this using rails3? Can someone set up a skeleton app?

primary_key returns nil for me ( overridden somewhere else ) ?

@kdwinter
Copy link
Author

I'm sorry, haven't used/changed this since I pasted it. I've switched to MongoMapper and use this snippet to make it work with that. :)

I'm not even sure if you need the ProtectedAttributes module, as Mongoid might support that by itself by now. You could try not including that.

@danielb2
Copy link

Thanks for the quick response. I've fiddled with it long enough and I think I will just switch to Devise sine I'm using that successfully for another mongoid project. What was the reason you switched to MM instead?

I did try commenting it out, and still got the same issue btw.

@huacnlee
Copy link

primary_key can't override, in Rails 3

@asceth
Copy link

asceth commented Mar 28, 2011

On the user model do:

def self.primary_key
  if caller.first.to_s =~ /(persist|session)/
    :_id
  else
    @@primary_key
  end
end

Fixes the errors I had with recent mongoid/authlogic.

@cmelbye
Copy link

cmelbye commented Jun 13, 2011

Is this still working for people? I'm getting this error:

/Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/mongoid-2.0.2/lib/mongoid/criterion/inclusion.rb:153:in `where': wrong number of arguments (2 for 1) (ArgumentError)
    from /Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/mongoid-2.0.2/lib/mongoid/finders.rb:14:in `block (2 levels) in '
    from /Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/authlogic-3.0.3/lib/authlogic/acts_as_authentic/logged_in_status.rb:34:in `block in included'
    from /Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/authlogic-3.0.3/lib/authlogic/acts_as_authentic/logged_in_status.rb:32:in `class_eval'
    from /Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/authlogic-3.0.3/lib/authlogic/acts_as_authentic/logged_in_status.rb:32:in `included'
    from /Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/authlogic-3.0.3/lib/authlogic/acts_as_authentic/base.rb:37:in `include'
    from /Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/authlogic-3.0.3/lib/authlogic/acts_as_authentic/base.rb:37:in `block in acts_as_authentic'
    from /Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/authlogic-3.0.3/lib/authlogic/acts_as_authentic/base.rb:37:in `each'
    from /Users/charlie/.rvm/gems/ruby-1.9.2-p180/gems/authlogic-3.0.3/lib/authlogic/acts_as_authentic/base.rb:37:in `acts_as_authentic'
    from /Users/charlie/Developer/Ruby/bitpal/app/models/user.rb:8:in `'
    from /Users/charlie/Developer/Ruby/bitpal/app/models/user.rb:2:in `'

Authlogic is calling the "where" method with two arguments, which I guess isn't how mongoid works:

where("last_request_at > ?", logged_in_timeout.seconds.ago)

@mcansky
Copy link

mcansky commented Aug 12, 2011

interesting, I'm trying to make the original pastie work with sinatra, but so far no luck, thinking it's almost 2 years old I believe some stuff have evolved
yet something stroke me : your code looks much more modular and doesn't have the part where some methods (callbacks) are generated) is it because of mongoid or just the way you wrote the thing ?

@jimsynz
Copy link

jimsynz commented Aug 13, 2011

I gave up and switched to Devise :)

@rfc2822
Copy link

rfc2822 commented Aug 14, 2011

Having the same problem like cmelbye, I found out that it is enough to comment out the line
include Authlogic::ActsAsAuthentic::LoggedInStatus
as this sub-module causes the where problem.

@jpascal
Copy link

jpascal commented Nov 7, 2011

Understand where a problem :(

Started POST "/sessions" for 127.0.0.1 at 2011-11-07 16:09:18 +0300
Processing by SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"bB2XWOa8vsAW0Zd2DK0GeTAaOgpU5cbUK7JPnFsaH2s=", "session"=>{"username"=>"jpascal", "password"=>"[FILTERED]"}, "commit"=>"Login"}
MONGODB grabs['system.namespaces'].find({})
MONGODB grabs['users'].find({:username=>"jpascal"}).limit(-1).sort([[:_id, :asc]])
Completed 500 Internal Server Error in 185ms

TypeError (nil is not a symbol):
app/controllers/sessions_controller.rb:10:in `create'

Rendered /usr/local/rvm/gems/ruby-1.9.2-p290@hotelgrab/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.5ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290@hotelgrab/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.1ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-p290@hotelgrab/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (8.5ms)

class SessionsController < ApplicationController
...
def create
@user_session = UserSession.new(params[:session])
if @user_session.save
redirect_to root_url
else
render :action => 'new'
end
end
...
end

@jurikern
Copy link

jurikern commented May 4, 2013

index({:username => 1}, {:unique => true})
index({:email => 1}, {:unique => true})
index({:persistence_token => 1}, {:unique => true})

It's new syntax for creating indexes

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