Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to have different serialize/deserialize methods for different scopes #48

Merged
merged 1 commit into from May 8, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 13 additions & 4 deletions lib/warden/manager.rb
Expand Up @@ -58,24 +58,33 @@ class << self
# Any object that can be serialized into the session in some way can be used as a "user" object
# Generally however complex object should not be stored in the session.
# If possible store only a "key" of the user object that will allow you to reconstitute it.
#
# You can supply different methods of serialization for different scopes by passing a scope symbol
#
# Example:
# Warden::Manager.serialize_into_session{ |user| user.id }
# # With Scope:
# Warden::Manager.serialize_into_session(:admin) { |user| user.id }
#
# :api: public
def serialize_into_session(&block)
Warden::SessionSerializer.send :define_method, :serialize, &block
def serialize_into_session(scope = nil, &block)
method_name = scope.nil? ? :serialize : "#{scope}_serialize"
Warden::SessionSerializer.send :define_method, method_name, &block
end

# Reconstitues the user from the session.
# Use the results of user_session_key to reconstitue the user from the session on requests after the initial login
# You can supply different methods of de-serialization for different scopes by passing a scope symbol
#
# Example:
# Warden::Manager.serialize_from_session{ |id| User.get(id) }
# # With Scope:
# Warden::Manager.serialize_from_session(:admin) { |id| AdminUser.get(id) }
#
# :api: public
def serialize_from_session(&block)
Warden::SessionSerializer.send :define_method, :deserialize, &block
def serialize_from_session(scope = nil, &block)
method_name = scope.nil? ? :deserialize : "#{scope}_deserialize"
Warden::SessionSerializer.send :define_method, method_name, &block
end
end

Expand Down
10 changes: 7 additions & 3 deletions lib/warden/session_serializer.rb
Expand Up @@ -22,13 +22,17 @@ def deserialize(key)

def store(user, scope)
return unless user
session[key_for(scope)] = serialize(user)
method_name = "#{scope}_serialize"
specialized = respond_to?(method_name)
session[key_for(scope)] = specialized ? send(method_name, user) : serialize(user)
end

def fetch(scope)
key = session[key_for(scope)]
return nil unless key
user = deserialize(key)

method_name = "#{scope}_deserialize"
user = respond_to?(method_name) ? send(method_name, key) : deserialize(key)
delete(scope) unless user
user
end
Expand All @@ -41,4 +45,4 @@ def delete(scope, user=nil)
session.delete(key_for(scope))
end
end # SessionSerializer
end # Warden
end # Warden
123 changes: 123 additions & 0 deletions spec/warden/scoped_session_serializer.rb
@@ -0,0 +1,123 @@
# encoding: utf-8
require 'spec_helper'

describe Warden::Manager do
before(:each) do
@env = env_with_params
@env['rack.session'] ||= {}
Warden::Manager.serialize_from_session { |k| k }
Warden::Manager.serialize_into_session { |u| u }
begin
Warden::SessionSerializer.send :remove_method, :admin_serialize
rescue
end
begin
Warden::SessionSerializer.send :remove_method, :admin_deserialize
rescue
end
end
after(:each) do
Warden::Manager.serialize_from_session { |k| k }
Warden::Manager.serialize_into_session { |u| u }
begin
Warden::SessionSerializer.send :remove_method, :admin_deserialize
Warden::SessionSerializer.send :remove_method, :admin_serialize
rescue
end
end

def serializer_respond_to?(name)
Warden::SessionSerializer.new(@env).respond_to? name
end

it "should respond to :serialize" do
serializer_respond_to?(:serialize).should == true
end

it "should respond to :deserialize" do
serializer_respond_to?(:deserialize).should == true
end

it "should respond to {scope}_deserialize if Manager.serialize_from_session is called with scope" do
Rack::Builder.new do
Warden::Manager.serialize_from_session ( :admin ) { |n| n }
end
serializer_respond_to?(:admin_deserialize).should == true
end

it "should respond to {scope}_serialize if Manager.serialize_into_session is called with scope" do
Rack::Builder.new do
Warden::Manager.serialize_into_session(:admin) { |n| n }
end
serializer_respond_to?(:admin_serialize).should == true
end

def initialize_with_scope(scope, &block)
Rack::Builder.new do
Warden::Manager.serialize_into_session(scope, &block)
end
end

it "should execute serialize if no {scope}_serialize is present" do
serialized_object = nil
initialize_with_scope(nil) do |user|
serialized_object = user
user
end
serializer = Warden::SessionSerializer.new(@env)
serializer.store("user", :admin)
serialized_object.should == "user"
end

it "should not have a {scope}_serialize by default" do
serializer_respond_to?(:admin_serialize).should == false
end

it "should execute {scope}_serialize when calling store with a scope" do
serialized_object = nil
initialize_with_scope(:admin) do |user|
serialized_object = user
user
end

serializer = Warden::SessionSerializer.new(@env)
serializer.store("user", :admin)
serialized_object.should == "user"
end


it "should execute {scope}_deserialize when calling store with a scope" do
serialized_object = nil

Rack::Builder.new do
Warden::Manager.serialize_from_session(:admin) do |key|
serialized_object = key
key
end
end

serializer = Warden::SessionSerializer.new(@env)
@env['rack.session'][serializer.key_for(:admin)] = "test"
serializer.fetch(:admin)

serialized_object.should == "test"
end

it "should execute deserialize if {scope}_deserialize is not present" do
serialized_object = nil

Rack::Builder.new do
Warden::Manager.serialize_from_session do |key|
serialized_object = key
key
end
end

serializer = Warden::SessionSerializer.new(@env)
@env['rack.session'][serializer.key_for(:admin)] = "test"
serializer.fetch(:admin)

serialized_object.should == "test"
end

end