warden 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.textile +1 -0
- data/Rakefile +57 -0
- data/TODO.textile +2 -0
- data/lib/warden.rb +14 -0
- data/lib/warden/authentication/hooks.rb +125 -0
- data/lib/warden/authentication/strategies.rb +58 -0
- data/lib/warden/authentication/strategy_base.rb +124 -0
- data/lib/warden/errors.rb +70 -0
- data/lib/warden/manager.rb +134 -0
- data/lib/warden/mixins/common.rb +25 -0
- data/lib/warden/proxy.rb +200 -0
- data/spec/helpers/request_helper.rb +51 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/warden/authenticated_data_store_spec.rb +111 -0
- data/spec/warden/errors_spec.rb +46 -0
- data/spec/warden/hooks_spec.rb +103 -0
- data/spec/warden/manager_spec.rb +158 -0
- data/spec/warden/proxy_spec.rb +218 -0
- data/spec/warden/strategies/failz.rb +9 -0
- data/spec/warden/strategies/invalid.rb +7 -0
- data/spec/warden/strategies/pass.rb +7 -0
- data/spec/warden/strategies/pass_without_user.rb +7 -0
- data/spec/warden/strategies/password.rb +12 -0
- data/spec/warden/strategies_spec.rb +78 -0
- data/spec/warden/strategy_base_spec.rb +259 -0
- data/spec/warden_spec.rb +4 -0
- metadata +83 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
module Warden
|
2
|
+
# The middleware for Rack Authentication
|
3
|
+
# The middlware requires that there is a session upstream
|
4
|
+
# The middleware injects an authentication object into
|
5
|
+
# the rack environment hash
|
6
|
+
class Manager
|
7
|
+
attr_accessor :config, :failure_app
|
8
|
+
|
9
|
+
# initialize the middleware.
|
10
|
+
# Provide a :failure_app in the options to setup an application to run when there is a failure
|
11
|
+
# The manager is yielded when initialized with a block. This is useful when declaring it in Rack::Builder
|
12
|
+
# :api: public
|
13
|
+
def initialize(app, config = {})
|
14
|
+
@app = app
|
15
|
+
@config = config
|
16
|
+
yield self if block_given?
|
17
|
+
|
18
|
+
# should ensure there is a failure application defined.
|
19
|
+
@failure_app = config[:failure_app] if config[:failure_app]
|
20
|
+
raise "No Failure App provided" unless @failure_app
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
# Set the default strategies to use.
|
25
|
+
# :api: public
|
26
|
+
def default_strategies(*strategies)
|
27
|
+
if strategies.empty?
|
28
|
+
@config[:default_strategies]
|
29
|
+
else
|
30
|
+
@config[:default_strategies] = strategies.flatten
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# :api: private
|
35
|
+
def call(env) # :nodoc:
|
36
|
+
# if this is downstream from another warden instance, don't do anything.
|
37
|
+
return @app.call(env) unless env['warden'].nil?
|
38
|
+
|
39
|
+
env['warden'] = Proxy.new(env, @config)
|
40
|
+
result = catch(:warden) do
|
41
|
+
@app.call(env)
|
42
|
+
end
|
43
|
+
|
44
|
+
result ||= {}
|
45
|
+
case result
|
46
|
+
when Array
|
47
|
+
if result.first != 401
|
48
|
+
return result
|
49
|
+
else
|
50
|
+
call_failure_app(env)
|
51
|
+
end
|
52
|
+
when Hash
|
53
|
+
if (result[:action] ||= :unauthenticated) == :unauthenticated
|
54
|
+
process_unauthenticated(result,env)
|
55
|
+
end # case result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class << self
|
60
|
+
|
61
|
+
|
62
|
+
# Does the work of storing the user in the session
|
63
|
+
# :api: private
|
64
|
+
def _store_user(user, session, scope = :default) # :nodoc:
|
65
|
+
return nil if user.nil?
|
66
|
+
session["warden.user.#{scope}.key"] = serialize_into_session.call(user)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Does the work of fetching the user from the session
|
70
|
+
# :api: private
|
71
|
+
def _fetch_user(session, scope = :default) # :nodoc:
|
72
|
+
key = session["warden.user.#{scope}.key"]
|
73
|
+
return nil if key.nil?
|
74
|
+
serialize_from_session.call(key)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Prepares the user to serialize into the session.
|
78
|
+
# Any object that can be serialized into the session in some way can be used as a "user" object
|
79
|
+
# Generally however complex object should not be stored in the session.
|
80
|
+
# If possible store only a "key" of the user object that will allow you to reconstitute it.
|
81
|
+
#
|
82
|
+
# Example:
|
83
|
+
# Warden::Manager.serialize_into_session{ |user| user.id }
|
84
|
+
#
|
85
|
+
# :api: public
|
86
|
+
def serialize_into_session(&block)
|
87
|
+
@serialize_into_session = block if block_given?
|
88
|
+
@serialize_into_session ||= lambda{|user| user}
|
89
|
+
end
|
90
|
+
|
91
|
+
# Reconstitues the user from the session.
|
92
|
+
# Use the results of user_session_key to reconstitue the user from the session on requests after the initial login
|
93
|
+
#
|
94
|
+
# Example:
|
95
|
+
# Warden::Manager.serialize_from_session{ |id| User.get(id) }
|
96
|
+
#
|
97
|
+
# :api: public
|
98
|
+
def serialize_from_session(&blk)
|
99
|
+
@serialize_from_session = blk if block_given?
|
100
|
+
@serialize_from_session ||= lambda{|key| key}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
# When a request is unauthentiated, here's where the processing occurs.
|
106
|
+
# It looks at the result of the proxy to see if it's been executed and what action to take.
|
107
|
+
# :api: private
|
108
|
+
def process_unauthenticated(result, env)
|
109
|
+
case env['warden'].result
|
110
|
+
when :failure
|
111
|
+
call_failure_app(env, result)
|
112
|
+
when :redirect
|
113
|
+
[env['warden']._status, env['warden'].headers, [env['warden'].message || "You are being redirected to #{env['warden'].headers['Location']}"]]
|
114
|
+
when :custom
|
115
|
+
env['warden'].custom_response
|
116
|
+
when nil
|
117
|
+
call_failure_app(env, result)
|
118
|
+
end # case env['warden'].result
|
119
|
+
end
|
120
|
+
|
121
|
+
# Calls the failure app.
|
122
|
+
# The before_failure hooks are run on each failure
|
123
|
+
# :api: private
|
124
|
+
def call_failure_app(env, opts = {})
|
125
|
+
env["PATH_INFO"] = "/#{opts[:action]}"
|
126
|
+
env["warden.options"] = opts
|
127
|
+
|
128
|
+
# Call the before failure callbacks
|
129
|
+
Warden::Manager._before_failure.each{|hook| hook.call(env,opts)}
|
130
|
+
|
131
|
+
@failure_app.call(env).to_a
|
132
|
+
end # call_failure_app
|
133
|
+
end
|
134
|
+
end # Warden
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Warden
|
2
|
+
module Mixins
|
3
|
+
module Common
|
4
|
+
|
5
|
+
# Convinience method to access the session
|
6
|
+
# :api: public
|
7
|
+
def session
|
8
|
+
@env['rack.session']
|
9
|
+
end # session
|
10
|
+
|
11
|
+
# Convenience method to access the rack request
|
12
|
+
# :api: public
|
13
|
+
def request
|
14
|
+
@request ||= Rack::Request.new(@env)
|
15
|
+
end # request
|
16
|
+
|
17
|
+
# Convenience method to access the rack request params
|
18
|
+
# :api: public
|
19
|
+
def params
|
20
|
+
request.params
|
21
|
+
end # params
|
22
|
+
|
23
|
+
end # Common
|
24
|
+
end # Mixins
|
25
|
+
end # Warden
|
data/lib/warden/proxy.rb
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
module Warden
|
2
|
+
class UserNotSet < RuntimeError; end
|
3
|
+
|
4
|
+
class Proxy
|
5
|
+
# :api: private
|
6
|
+
attr_accessor :winning_strategy
|
7
|
+
|
8
|
+
# An accessor to the rack env hash
|
9
|
+
# :api: public
|
10
|
+
attr_reader :env
|
11
|
+
|
12
|
+
extend ::Forwardable
|
13
|
+
include ::Warden::Mixins::Common
|
14
|
+
alias_method :_session, :session
|
15
|
+
|
16
|
+
# :api: private
|
17
|
+
def_delegators :winning_strategy, :headers, :message, :_status, :custom_response
|
18
|
+
|
19
|
+
def initialize(env, config = {}) # :nodoc:
|
20
|
+
@env = env
|
21
|
+
@config = config
|
22
|
+
@strategies = @config.fetch(:default_strategies, [])
|
23
|
+
@users = {}
|
24
|
+
errors # setup the error object in the session
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check to see if there is an authenticated user for the given scope.
|
28
|
+
# When scope is not specified, :default is assumed.
|
29
|
+
#
|
30
|
+
# Parameters:
|
31
|
+
# args - a list of symbols (labels) that name the strategies to attempt
|
32
|
+
# opts - an options hash that contains the :scope of the user to check
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
# env['warden'].authenticated?(:password, :scope => :admin)
|
36
|
+
# :api: public
|
37
|
+
def authenticated?(*args)
|
38
|
+
scope = scope_from_args(args)
|
39
|
+
_perform_authentication(*args)
|
40
|
+
!user(scope).nil?
|
41
|
+
end # authenticated?
|
42
|
+
|
43
|
+
# Run the authentiation strategies for the given strategies.
|
44
|
+
# If there is already a user logged in for a given scope, the strategies are not run
|
45
|
+
# This does not halt the flow of control and is a passive attempt to authenticate only
|
46
|
+
# When scope is not specified, :default is assumed.
|
47
|
+
#
|
48
|
+
# Parameters:
|
49
|
+
# args - a list of symbols (labels) that name the strategies to attempt
|
50
|
+
# opts - an options hash that contains the :scope of the user to check
|
51
|
+
#
|
52
|
+
# Example:
|
53
|
+
# env['auth'].authenticate(:password, :basic, :scope => :sudo)
|
54
|
+
# :api: public
|
55
|
+
def authenticate(*args)
|
56
|
+
scope = scope_from_args(args)
|
57
|
+
_perform_authentication(*args)
|
58
|
+
user(scope)
|
59
|
+
end
|
60
|
+
|
61
|
+
# The same as +authenticate+ except on failure it will throw an :warden symbol causing the request to be halted
|
62
|
+
# and rendered through the +failure_app+
|
63
|
+
#
|
64
|
+
# Example
|
65
|
+
# env['warden'].authenticate!(:password, :scope => :publisher) # throws if it cannot authenticate
|
66
|
+
#
|
67
|
+
# :api: public
|
68
|
+
def authenticate!(*args)
|
69
|
+
opts = opts_from_args(args)
|
70
|
+
scope = scope_from_args(args)
|
71
|
+
_perform_authentication(*args)
|
72
|
+
throw(:warden, opts.merge(:action => :unauthenticated)) if !user(scope)
|
73
|
+
user(scope)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Manually set the user into the session and auth proxy
|
77
|
+
#
|
78
|
+
# Parameters:
|
79
|
+
# user - An object that has been setup to serialize into and out of the session.
|
80
|
+
# opts - An options hash. Use the :scope option to set the scope of the user
|
81
|
+
# :api: public
|
82
|
+
def set_user(user, opts = {})
|
83
|
+
scope = (opts[:scope] ||= :default)
|
84
|
+
Warden::Manager._store_user(user, _session, scope) # Get the user into the session
|
85
|
+
|
86
|
+
# Run the after hooks for setting the user
|
87
|
+
Warden::Manager._after_set_user.each{|hook| hook.call(user, self, opts)}
|
88
|
+
|
89
|
+
@users[scope] = user # Store the user in the proxy user object
|
90
|
+
end
|
91
|
+
|
92
|
+
# Provides acccess to the user object in a given scope for a request.
|
93
|
+
# will be nil if not logged in
|
94
|
+
#
|
95
|
+
# Example:
|
96
|
+
# # without scope (default user)
|
97
|
+
# env['warden'].user
|
98
|
+
#
|
99
|
+
# # with scope
|
100
|
+
# env['warden'].user(:admin)
|
101
|
+
#
|
102
|
+
# :api: public
|
103
|
+
def user(scope = :default)
|
104
|
+
@users[scope]
|
105
|
+
end
|
106
|
+
|
107
|
+
# Provides a scoped session data for authenticated users.
|
108
|
+
# Warden manages clearing out this data when a user logs out
|
109
|
+
#
|
110
|
+
# Example
|
111
|
+
# # default scope
|
112
|
+
# env['warden'].data[:foo] = "bar"
|
113
|
+
#
|
114
|
+
# # :sudo scope
|
115
|
+
# env['warden'].data(:sudo)[:foo] = "bar"
|
116
|
+
#
|
117
|
+
# :api: public
|
118
|
+
def session(scope = :default)
|
119
|
+
raise NotAuthenticated, "#{scope.inspect} user is not logged in" unless authenticated?(:scope => scope)
|
120
|
+
_session["warden.user.#{scope}.session"] ||= {}
|
121
|
+
end
|
122
|
+
|
123
|
+
# Provides logout functionality.
|
124
|
+
# The logout also manages any authenticated data storage and clears it when a user logs out.
|
125
|
+
#
|
126
|
+
# Parameters:
|
127
|
+
# scopes - a list of scopes to logout
|
128
|
+
#
|
129
|
+
# Example:
|
130
|
+
# # Logout everyone and clear the session
|
131
|
+
# env['warden'].logout
|
132
|
+
#
|
133
|
+
# # Logout the default user but leave the rest of the session alone
|
134
|
+
# env['warden'].logout(:default)
|
135
|
+
#
|
136
|
+
# # Logout the :publisher and :admin user
|
137
|
+
# env['warden'].logout(:publisher, :admin)
|
138
|
+
#
|
139
|
+
# :api: public
|
140
|
+
def logout(*scopes)
|
141
|
+
if scopes.empty?
|
142
|
+
_session.clear
|
143
|
+
else
|
144
|
+
scopes.each do |s|
|
145
|
+
_session["warden.user.#{s}.key"] = nil
|
146
|
+
_session["warden.user.#{s}.session"] = nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# proxy methods through to the winning strategy
|
152
|
+
# :api: private
|
153
|
+
def result # :nodoc:
|
154
|
+
winning_strategy.nil? ? nil : winning_strategy.result
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
# :api: private
|
159
|
+
def _perform_authentication(*args)
|
160
|
+
scope = scope_from_args(args)
|
161
|
+
opts = opts_from_args(args)
|
162
|
+
# Look for an existing user in the session for this scope
|
163
|
+
if @users[scope] || set_user(Warden::Manager._fetch_user(_session, scope), :scope => scope)
|
164
|
+
return @users[scope]
|
165
|
+
end
|
166
|
+
|
167
|
+
# If there was no user in the session. See if we can get one from the request
|
168
|
+
strategies = args.empty? ? @strategies : args
|
169
|
+
raise "No Strategies Found" if strategies.empty? || !(strategies - Warden::Strategies._strategies.keys).empty?
|
170
|
+
strategies.each do |s|
|
171
|
+
strategy = Warden::Strategies[s].new(@env, @conf)
|
172
|
+
self.winning_strategy = strategy
|
173
|
+
next unless strategy.valid?
|
174
|
+
strategy._run!
|
175
|
+
break if strategy.halted?
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
if winning_strategy && winning_strategy.user
|
180
|
+
set_user(winning_strategy.user, opts)
|
181
|
+
|
182
|
+
# Run the after_authentication hooks
|
183
|
+
Warden::Manager._after_authentication.each{|hook| hook.call(winning_strategy.user, self, opts)}
|
184
|
+
end
|
185
|
+
|
186
|
+
winning_strategy
|
187
|
+
end
|
188
|
+
|
189
|
+
# :api: private
|
190
|
+
def scope_from_args(args)
|
191
|
+
Hash === args.last ? args.last.fetch(:scope, :default) : :default
|
192
|
+
end
|
193
|
+
|
194
|
+
# :api: private
|
195
|
+
def opts_from_args(args)
|
196
|
+
Hash === args.last ? args.pop : {}
|
197
|
+
end
|
198
|
+
|
199
|
+
end # Proxy
|
200
|
+
end # Warden
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Warden::Spec
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
FAILURE_APP = lambda{|e|[401, {"Content-Type" => "text/plain"}, ["You Fail!"]] }
|
5
|
+
|
6
|
+
def env_with_params(path = "/", params = {})
|
7
|
+
method = params.fetch(:method, "GET")
|
8
|
+
Rack::MockRequest.env_for(path, :input => Rack::Utils.build_query(params),
|
9
|
+
'HTTP_VERSION' => '1.1',
|
10
|
+
'REQUEST_METHOD' => "#{method}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup_rack(app = nil, opts = {}, &block)
|
14
|
+
app ||= block if block_given?
|
15
|
+
# opts[:default_strategies] ||= [:password]
|
16
|
+
# opts[:failure_app] ||= failure_app
|
17
|
+
Rack::Builder.new do
|
18
|
+
use Warden::Spec::Helpers::Session
|
19
|
+
use Warden::Manager, opts do |manager|
|
20
|
+
manager.failure_app = Warden::Spec::Helpers::FAILURE_APP
|
21
|
+
manager.default_strategies :password
|
22
|
+
end
|
23
|
+
run app
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid_response
|
28
|
+
[200,{'Content-Type' => 'text/plain'},'OK']
|
29
|
+
end
|
30
|
+
|
31
|
+
def failure_app
|
32
|
+
Warden::Spec::Helpers::FAILURE_APP
|
33
|
+
end
|
34
|
+
|
35
|
+
def success_app
|
36
|
+
lambda{|e| [200, {"Content-Type" => "text/plain"}, ["You Win"]]}
|
37
|
+
end
|
38
|
+
|
39
|
+
class Session
|
40
|
+
attr_accessor :app
|
41
|
+
def initialize(app,configs = {})
|
42
|
+
@app = app
|
43
|
+
end
|
44
|
+
|
45
|
+
def call(e)
|
46
|
+
e['rack.session'] ||= {}
|
47
|
+
@app.call(e)
|
48
|
+
end
|
49
|
+
end # session
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$TESTING=true
|
2
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rack'
|
5
|
+
require 'warden'
|
6
|
+
|
7
|
+
Dir[File.join(File.dirname(__FILE__), "warden", "strategies", "**/*.rb")].each do |f|
|
8
|
+
require f
|
9
|
+
end
|
10
|
+
Dir[File.join(File.dirname(__FILE__), "helpers", "**/*.rb")].each do |f|
|
11
|
+
require f
|
12
|
+
end
|
13
|
+
|
14
|
+
Spec::Runner.configure do |config|
|
15
|
+
config.include(Warden::Spec::Helpers)
|
16
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "authenticated data store" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@env = env_with_params
|
7
|
+
@env['rack.session'] = {
|
8
|
+
"warden.user.foo.key" => "foo user",
|
9
|
+
"warden.user.default.key" => "default user",
|
10
|
+
:foo => "bar"
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should store data for the default scope" do
|
15
|
+
app = lambda do |e|
|
16
|
+
e['warden'].should be_authenticated(:pass)
|
17
|
+
e['warden'].should be_authenticated(:pass, :scope => :foo)
|
18
|
+
|
19
|
+
# Store the data for :deafult
|
20
|
+
e['warden'].session[:key] = "value"
|
21
|
+
valid_response
|
22
|
+
end
|
23
|
+
setup_rack(app).call(@env)
|
24
|
+
@env['rack.session']['warden.user.default.session'].should == {:key => "value"}
|
25
|
+
@env['rack.session']['warden.user.foo.session'].should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should store data for the foo user" do
|
29
|
+
app = lambda do |e|
|
30
|
+
e['warden'].session(:foo)[:key] = "value"
|
31
|
+
valid_response
|
32
|
+
end
|
33
|
+
setup_rack(app).call(@env)
|
34
|
+
@env['rack.session']['warden.user.foo.session'].should == {:key => "value"}
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should store the data seperately" do
|
38
|
+
app = lambda do |e|
|
39
|
+
e['warden'].session[:key] = "value"
|
40
|
+
e['warden'].session(:foo)[:key] = "another value"
|
41
|
+
valid_response
|
42
|
+
end
|
43
|
+
setup_rack(app).call(@env)
|
44
|
+
@env['rack.session']['warden.user.default.session'].should == {:key => "value"}
|
45
|
+
@env['rack.session']['warden.user.foo.session' ].should == {:key => "another value"}
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should clear the foo scoped data when foo logs out" do
|
49
|
+
app = lambda do |e|
|
50
|
+
e['warden'].session[:key] = "value"
|
51
|
+
e['warden'].session(:foo)[:key] = "another value"
|
52
|
+
e['warden'].logout(:foo)
|
53
|
+
valid_response
|
54
|
+
end
|
55
|
+
setup_rack(app).call(@env)
|
56
|
+
@env['rack.session']['warden.user.default.session'].should == {:key => "value"}
|
57
|
+
@env['rack.session']['warden.user.foo.session' ].should be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should clear out the default data when :default logs out" do
|
61
|
+
app = lambda do |e|
|
62
|
+
e['warden'].session[:key] = "value"
|
63
|
+
e['warden'].session(:foo)[:key] = "another value"
|
64
|
+
e['warden'].logout(:default)
|
65
|
+
valid_response
|
66
|
+
end
|
67
|
+
setup_rack(app).call(@env)
|
68
|
+
@env['rack.session']['warden.user.default.session'].should be_nil
|
69
|
+
@env['rack.session']['warden.user.foo.session' ].should == {:key => "another value"}
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should clear out all data when a general logout is performed" do
|
73
|
+
app = lambda do |e|
|
74
|
+
e['warden'].session[:key] = "value"
|
75
|
+
e['warden'].session(:foo)[:key] = "another value"
|
76
|
+
e['warden'].logout
|
77
|
+
valid_response
|
78
|
+
end
|
79
|
+
setup_rack(app).call(@env)
|
80
|
+
@env['rack.session']['warden.user.default.session'].should be_nil
|
81
|
+
@env['rack.session']['warden.user.foo.session' ].should be_nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should logout multuiple personas at once" do
|
85
|
+
@env['rack.session']['warden.user.bar.key'] = "bar user"
|
86
|
+
|
87
|
+
app = lambda do |e|
|
88
|
+
e['warden'].session[:key] = "value"
|
89
|
+
e['warden'].session(:foo)[:key] = "another value"
|
90
|
+
e['warden'].session(:bar)[:key] = "yet another"
|
91
|
+
e['warden'].logout(:bar, :default)
|
92
|
+
valid_response
|
93
|
+
end
|
94
|
+
setup_rack(app).call(@env)
|
95
|
+
@env['rack.session']['warden.user.default.session'].should be_nil
|
96
|
+
@env['rack.session']['warden.user.foo.session' ].should == {:key => "another value"}
|
97
|
+
@env['rack.session']['warden.user.bar.session' ].should be_nil
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should not store data for a user who is not logged in" do
|
101
|
+
@env['rack.session']
|
102
|
+
app = lambda do |e|
|
103
|
+
e['warden'].session(:not_here)[:key] = "value"
|
104
|
+
valid_response
|
105
|
+
end
|
106
|
+
|
107
|
+
lambda do
|
108
|
+
setup_rack(app).call(@env)
|
109
|
+
end.should raise_error(Warden::NotAuthenticated)
|
110
|
+
end
|
111
|
+
end
|