1
0
Fork 0
mirror of https://github.com/heartcombo/devise.git synced 2022-11-09 12:18:31 -05:00

Decouple serializers from Devise modules. You can use any serializer 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.

This commit is contained in:
José Valim 2009-12-20 12:31:02 +01:00
parent a3e7ea59ae
commit f26e6a269f
10 changed files with 95 additions and 71 deletions

View file

@ -35,7 +35,7 @@ module Devise
} }
STRATEGIES = [:authenticatable] STRATEGIES = [:authenticatable]
SERIALIZERS = [:authenticatable, :rememberable] SERIALIZERS = [:session, :cookie]
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'] TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
# Maps the messages types that are used in flash message. This array is not # Maps the messages types that are used in flash message. This array is not
@ -166,6 +166,9 @@ rescue
require 'warden' require 'warden'
end 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 Warden::Manager.default_scope = nil
require 'devise/rails' require 'devise/rails'

View file

@ -4,7 +4,7 @@ module Devise
autoload :Confirmable, 'devise/models/confirmable' autoload :Confirmable, 'devise/models/confirmable'
autoload :Recoverable, 'devise/models/recoverable' autoload :Recoverable, 'devise/models/recoverable'
autoload :Rememberable, 'devise/models/rememberable' autoload :Rememberable, 'devise/models/rememberable'
autoload :SessionSerializer, 'devise/models/authenticatable' autoload :SessionSerializer, 'devise/models/session_serializer'
autoload :Timeoutable, 'devise/models/timeoutable' autoload :Timeoutable, 'devise/models/timeoutable'
autoload :Trackable, 'devise/models/trackable' autoload :Trackable, 'devise/models/trackable'
autoload :Validatable, 'devise/models/validatable' autoload :Validatable, 'devise/models/validatable'

View file

@ -1,22 +1,8 @@
require 'devise/strategies/authenticatable' require 'devise/strategies/authenticatable'
require 'devise/serializers/authenticatable' require 'devise/models/session_serializer'
module Devise module Devise
module Models 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 # Authenticable Module, responsible for encrypting password and validating
# authenticity of a user while signing in. # authenticity of a user while signing in.
# #

View file

@ -1,5 +1,4 @@
require 'digest/sha1' require 'devise/serializers/cookie'
require 'devise/serializers/rememberable'
module Devise module Devise
module Models module Models

View file

@ -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

View file

@ -1,11 +0,0 @@
require 'devise/serializers/base'
module Devise
module Serializers
class Authenticatable < Warden::Serializers::Session
include Devise::Serializers::Base
end
end
end
Warden::Serializers.add(:authenticatable, Devise::Serializers::Authenticatable)

View file

@ -7,24 +7,17 @@ module Devise
attr_reader :scope attr_reader :scope
def serialize(record) def serialize(record)
record.class.send(:"serialize_into_#{serialization_type}", record) record.class.send(:"serialize_into_#{klass_type}", record)
end end
def deserialize(keys) def deserialize(keys)
mapping.to.send(:"serialize_from_#{serialization_type}", keys) mapping.to.send(:"serialize_from_#{klass_type}", keys)
end end
def fetch(scope) def fetch(scope)
@scope = scope @scope = scope
super super
end 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 end
end end

View file

@ -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)

View file

@ -1,30 +0,0 @@
require 'devise/serializers/base'
module Devise
module Serializers
class Rememberable < 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(:rememberable, Devise::Serializers::Rememberable)

View file

@ -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)