Skip to content

Commit

Permalink
Decouple serializers from Devise modules. You can use any serializer …
Browse files Browse the repository at this point in the history
…at any time, as long the API required by the serializer is satisfied. Since session serializer is encrypted, it simply stores the id and the resource klass. Cookie is not encrypted, so it creates a random token and store it in the database, so in order to do the token cleanup, you need provide remember_me! and forget_me! methods, as in :rememberable.
  • Loading branch information
josevalim committed Dec 20, 2009
1 parent a3e7ea5 commit f26e6a2
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 71 deletions.
9 changes: 6 additions & 3 deletions lib/devise.rb
Expand Up @@ -35,7 +35,7 @@ module Orm
}

STRATEGIES = [:authenticatable]
SERIALIZERS = [:authenticatable, :rememberable]
SERIALIZERS = [:session, :cookie]
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']

# Maps the messages types that are used in flash message. This array is not
Expand Down Expand Up @@ -166,6 +166,9 @@ def friendly_token
require 'warden'
end

# Set the default_scope to nil, so it's overwritten when the first route is declared.
# Clear some Warden default configuration which will be overwritten
Warden::Strategies.clear!
Warden::Serializers.clear!
Warden::Manager.default_scope = nil
require 'devise/rails'

require 'devise/rails'
2 changes: 1 addition & 1 deletion lib/devise/models.rb
Expand Up @@ -4,7 +4,7 @@ module Models
autoload :Confirmable, 'devise/models/confirmable'
autoload :Recoverable, 'devise/models/recoverable'
autoload :Rememberable, 'devise/models/rememberable'
autoload :SessionSerializer, 'devise/models/authenticatable'
autoload :SessionSerializer, 'devise/models/session_serializer'
autoload :Timeoutable, 'devise/models/timeoutable'
autoload :Trackable, 'devise/models/trackable'
autoload :Validatable, 'devise/models/validatable'
Expand Down
16 changes: 1 addition & 15 deletions lib/devise/models/authenticatable.rb
@@ -1,22 +1,8 @@
require 'devise/strategies/authenticatable'
require 'devise/serializers/authenticatable'
require 'devise/models/session_serializer'

module Devise
module Models
module SessionSerializer
# Hook to serialize user into session. Overwrite if you want.
def serialize_into_session(record)
[record.class, record.id]
end

# Hook to serialize user from session. Overwrite if you want.
def serialize_from_session(keys)
klass, id = keys
raise "#{self} cannot serialize from #{klass} session since it's not its ancestors" unless klass <= self
klass.find(:first, :conditions => { :id => id })
end
end

# Authenticable Module, responsible for encrypting password and validating
# authenticity of a user while signing in.
#
Expand Down
3 changes: 1 addition & 2 deletions lib/devise/models/rememberable.rb
@@ -1,5 +1,4 @@
require 'digest/sha1'
require 'devise/serializers/rememberable'
require 'devise/serializers/cookie'

module Devise
module Models
Expand Down
19 changes: 19 additions & 0 deletions lib/devise/models/session_serializer.rb
@@ -0,0 +1,19 @@
require 'devise/serializers/session'

module Devise
module Models
module SessionSerializer
# Hook to serialize user into session. Overwrite if you want.
def serialize_into_session(record)
[record.class, record.id]
end

# Hook to serialize user from session. Overwrite if you want.
def serialize_from_session(keys)
klass, id = keys
raise "#{self} cannot serialize from #{klass} session since it's not one of its ancestors" unless klass <= self
klass.find(:first, :conditions => { :id => id })
end
end
end
end
11 changes: 0 additions & 11 deletions lib/devise/serializers/authenticatable.rb

This file was deleted.

11 changes: 2 additions & 9 deletions lib/devise/serializers/base.rb
Expand Up @@ -7,24 +7,17 @@ module Base
attr_reader :scope

def serialize(record)
record.class.send(:"serialize_into_#{serialization_type}", record)
record.class.send(:"serialize_into_#{klass_type}", record)
end

def deserialize(keys)
mapping.to.send(:"serialize_from_#{serialization_type}", keys)
mapping.to.send(:"serialize_from_#{klass_type}", keys)
end

def fetch(scope)
@scope = scope
super
end

def serialization_type
@serialization_type ||= begin
warden = self.class.ancestors.find{ |k| k < Warden::Serializers::Base && k != self.class }
warden.name.split("::").last.underscore
end
end
end
end
end
43 changes: 43 additions & 0 deletions lib/devise/serializers/cookie.rb
@@ -0,0 +1,43 @@
require 'devise/serializers/base'

module Devise
module Serializers
# This is a cookie serializer which stores the information if a :remember_me
# is sent in the params and if the model responds to remember_me! as well.
# As in Session serializer, the invoked methods are:
#
# User.serialize_into_cookie(@user)
# User.serialize_from_cookie(*args)
#
# An implementation for such methods can be found at Devise::Models::Rememberable.
#
# Differently from session, this approach is based in a token which is stored in
# the database. So if you want to sign out all clients at once, you just need to
# clean up the token column.
#
class Cookie < Warden::Serializers::Cookie
include Devise::Serializers::Base

def store(record, scope)
remember_me = params[scope].try(:fetch, :remember_me, nil)
if Devise::TRUE_VALUES.include?(remember_me) && record.respond_to?(:remember_me!)
record.remember_me!
super
end
end

def default_options(record)
super.merge!(:expires => record.remember_expires_at)
end

def delete(scope, record=nil)
if record && record.respond_to?(:forget_me!)
record.forget_me!
super
end
end
end
end
end

Warden::Serializers.add(:cookie, Devise::Serializers::Cookie)
30 changes: 0 additions & 30 deletions lib/devise/serializers/rememberable.rb

This file was deleted.

22 changes: 22 additions & 0 deletions lib/devise/serializers/session.rb
@@ -0,0 +1,22 @@
require 'devise/serializers/base'

module Devise
module Serializers
# This serializer stores sign in information in th client session. It just
# extends Warden own serializer to move all the serialization logic to a
# class. For example, if a @user resource is given, it will call the following
# two methods to serialize and deserialize a record:
#
# User.serialize_into_session(@user)
# User.serialize_from_session(*args)
#
# This can be used any strategy and the default implementation is available
# at Devise::Models::SessionSerializer.
#
class Session < Warden::Serializers::Session
include Devise::Serializers::Base
end
end
end

Warden::Serializers.add(:session, Devise::Serializers::Session)

0 comments on commit f26e6a2

Please sign in to comment.