hassox-warden 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +87 -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
|