warden 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,3 +1,8 @@
1
+ == Version 1.2.1 / 2012-06-16
2
+ * Minor caching and speed improvements
3
+ * Add support to #lock in the proxy
4
+ * Add support to after_failed_fetch callback
5
+
1
6
  == Version 1.2.0 / 2012-05-08
2
7
  * Deprecate warden_cookies since it was never functional
3
8
  * Add support to serialize_from_session and serialize_into_session per scope
data/lib/warden/hooks.rb CHANGED
@@ -117,6 +117,34 @@ module Warden
117
117
  @_before_failure ||= []
118
118
  end
119
119
 
120
+ # A callback that runs if no user could be fetched, meaning there is now no user logged in.
121
+ #
122
+ # Parameters:
123
+ # <options> Some options which specify when the callback should be executed
124
+ # scope - Executes the callback only if it maches the scope(s) given
125
+ # <block> A block to contain logic for the callback
126
+ # Block Parameters: |user, auth, scope|
127
+ # user - The authenticated user for the current scope
128
+ # auth - The warden proxy object
129
+ # opts - any options passed into the authenticate call including :scope
130
+ #
131
+ # Example:
132
+ # Warden::Manager.after_failed_fetch do |user, auth, opts|
133
+ # I18n.locale = :en
134
+ # end
135
+ #
136
+ # :api: public
137
+ def after_failed_fetch(options = {}, method = :push, &block)
138
+ raise BlockNotGiven unless block_given?
139
+ _after_failed_fetch.send(method, [block, options])
140
+ end
141
+
142
+ # Provides access to the callback array for after_failed_fetch
143
+ # :api: private
144
+ def _after_failed_fetch
145
+ @_after_failed_fetch ||= []
146
+ end
147
+
120
148
  # A callback that runs just prior to the logout of each scope.
121
149
  #
122
150
  # Parameters:
data/lib/warden/proxy.rb CHANGED
@@ -25,7 +25,7 @@ module Warden
25
25
  def_delegators :config, :default_strategies
26
26
 
27
27
  def initialize(env, manager) #:nodoc:
28
- @env, @users, @winning_strategies = env, {}, {}
28
+ @env, @users, @winning_strategies, @locked = env, {}, {}, false
29
29
  @manager, @config = manager, manager.config.dup
30
30
  @strategies = Hash.new { |h,k| h[k] = {} }
31
31
  manager._run_callbacks(:on_request, self)
@@ -45,9 +45,13 @@ module Warden
45
45
  @session_serializer ||= Warden::SessionSerializer.new(@env)
46
46
  end
47
47
 
48
- # Clear the cache of performed strategies so far. It has the same API
49
- # as authenticate, allowing you to clear an specific strategies for
50
- # given scope:
48
+ # Clear the cache of performed strategies so far. Warden runs each
49
+ # strategy just once during the request lifecycle. You can clear the
50
+ # strategies cache if you want to allow a strategy to be run more than
51
+ # once.
52
+ #
53
+ # This method has the same API as authenticate, allowing you to clear
54
+ # specific strategies for given scope:
51
55
  #
52
56
  # Parameters:
53
57
  # args - a list of symbols (labels) that name the strategies to attempt
@@ -73,6 +77,16 @@ module Warden
73
77
  end
74
78
  end
75
79
 
80
+ # Locks the proxy so new users cannot authenticate during the
81
+ # request lifecycle. This is useful when the request cannot
82
+ # be verified (for example, using a CSRF verification token).
83
+ # Notice that already authenticated users are kept as so.
84
+ #
85
+ # :api: public
86
+ def lock!
87
+ @locked = true
88
+ end
89
+
76
90
  # Run the authentiation strategies for the given strategies.
77
91
  # If there is already a user logged in for a given scope, the strategies are not run
78
92
  # This does not halt the flow of control and is a passive attempt to authenticate only
@@ -93,8 +107,8 @@ module Warden
93
107
 
94
108
  # Same API as authenticated, but returns a boolean instead of a user.
95
109
  # The difference between this method (authenticate?) and authenticated?
96
- # is that the former will run strategies if the user has not yet been authenticated,
97
- # and the second relies on already performed ones.
110
+ # is that the former will run strategies if the user has not yet been
111
+ # authenticated, and the second relies on already performed ones.
98
112
  # :api: public
99
113
  def authenticate?(*args)
100
114
  result = !!authenticate(*args)
@@ -192,10 +206,15 @@ module Warden
192
206
  opts = argument.is_a?(Hash) ? argument : { :scope => argument }
193
207
  scope = (opts[:scope] ||= @config.default_scope)
194
208
 
195
- @users[scope] ||= begin
196
- user = session_serializer.fetch(scope)
197
- opts[:event] = :fetch
198
- set_user(user, opts) if user
209
+ if @users.has_key?(scope)
210
+ @users[scope]
211
+ else
212
+ unless user = session_serializer.fetch(scope)
213
+ run_callbacks = opts.fetch(:run_callbacks, true)
214
+ manager._run_callbacks(:after_failed_fetch, user, self, :scope => scope) if run_callbacks
215
+ end
216
+
217
+ @users[scope] = user ? set_user(user, opts.merge(:event => :fetch)) : nil
199
218
  end
200
219
  end
201
220
 
@@ -296,7 +315,7 @@ module Warden
296
315
 
297
316
  # Look for an existing user in the session for this scope.
298
317
  # If there was no user in the session. See if we can get one from the request.
299
- return user, opts if user = user(scope)
318
+ return user, opts if user = user(opts.merge(:scope => scope))
300
319
  _run_strategies_for(scope, args)
301
320
 
302
321
  if winning_strategy && winning_strategy.user
@@ -319,6 +338,9 @@ module Warden
319
338
  self.winning_strategy = @winning_strategies[scope]
320
339
  return if winning_strategy && winning_strategy.halted?
321
340
 
341
+ # Do not run any strategy if locked
342
+ return if @locked
343
+
322
344
  if args.empty?
323
345
  defaults = @config[:default_strategies]
324
346
  strategies = defaults[scope] || defaults[:_all]
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Warden
3
- VERSION = "1.2.0".freeze
3
+ VERSION = "1.2.1".freeze
4
4
  end
data/spec/spec_helper.rb CHANGED
@@ -14,6 +14,7 @@ end
14
14
 
15
15
  RSpec.configure do |config|
16
16
  config.include(Warden::Spec::Helpers)
17
+ config.include(Warden::Test::Helpers)
17
18
 
18
19
  def load_strategies
19
20
  Dir[File.join(File.dirname(__FILE__), "helpers", "strategies", "**/*.rb")].each do |f|
@@ -177,7 +177,35 @@ describe "standard authentication hooks" do
177
177
  env['warden.spec.order'].should == [1,2,3]
178
178
  end
179
179
  end
180
+ end
181
+
182
+
183
+ describe "after_failed_fetch" do
184
+ before(:each) do
185
+ RAM = Warden::Manager unless defined?(RAM)
186
+ RAM._after_failed_fetch.clear
187
+ end
180
188
 
189
+ after(:each) do
190
+ RAM._after_failed_fetch.clear
191
+ end
192
+
193
+ it "should not be called when user is fetched" do
194
+ RAM.after_failed_fetch{|u,a,o| fail }
195
+ env = env_with_params
196
+ setup_rack(lambda { |e| valid_response }).call(env)
197
+ env['rack.session']['warden.user.default.key'] = "Foo"
198
+ env['warden'].user.should == "Foo"
199
+ end
200
+
201
+ it "should be called if fetched user is nil" do
202
+ calls = 0
203
+ RAM.after_failed_fetch{|u,a,o| calls += 1 }
204
+ env = env_with_params
205
+ setup_rack(lambda { |e| valid_response }).call(env)
206
+ env['warden'].user.should be_nil
207
+ calls.should == 1
208
+ end
181
209
  end
182
210
 
183
211
  describe "before_failure" do
@@ -377,7 +377,7 @@ describe Warden::Proxy do
377
377
 
378
378
  it "should run the callbacks when :run_callbacks is true" do
379
379
  app = lambda do |env|
380
- env['warden'].manager.should_receive(:_run_callbacks)
380
+ env['warden'].manager.should_receive(:_run_callbacks).at_least(:once)
381
381
  env['warden'].authenticate(:pass)
382
382
  valid_response
383
383
  end
@@ -386,7 +386,7 @@ describe Warden::Proxy do
386
386
 
387
387
  it "should run the callbacks by default" do
388
388
  app = lambda do |env|
389
- env['warden'].manager.should_receive(:_run_callbacks)
389
+ env['warden'].manager.should_receive(:_run_callbacks).at_least(:once)
390
390
  env['warden'].authenticate(:pass)
391
391
  valid_response
392
392
  end
@@ -394,6 +394,26 @@ describe Warden::Proxy do
394
394
  end
395
395
  end
396
396
 
397
+ describe "lock" do
398
+ it "should not run any strategy" do
399
+ app = lambda do |env|
400
+ env['warden'].lock!
401
+ env['warden'].authenticate(:pass)
402
+ env['warden'].user.should be_nil
403
+ valid_response
404
+ end
405
+ end
406
+
407
+ it "should keep already authenticated users" do
408
+ app = lambda do |env|
409
+ env['warden'].authenticate(:pass)
410
+ env['warden'].lock!
411
+ env['warden'].user.should be
412
+ valid_response
413
+ end
414
+ end
415
+ end
416
+
397
417
  describe "get user" do
398
418
  before(:each) do
399
419
  @env['rack.session'] ||= {}
@@ -417,6 +437,16 @@ describe Warden::Proxy do
417
437
  setup_rack(app).call(@env)
418
438
  end
419
439
 
440
+ it "should cache unfound user" do
441
+ Warden::SessionSerializer.any_instance.should_receive(:fetch).once
442
+ app = lambda do |env|
443
+ env['warden'].user.should be_nil
444
+ env['warden'].user.should be_nil
445
+ valid_response
446
+ end
447
+ setup_rack(app).call(@env)
448
+ end
449
+
420
450
  describe "previously logged in" do
421
451
  before(:each) do
422
452
  @env['rack.session']['warden.user.default.key'] = "A Previous User"
@@ -431,6 +461,16 @@ describe Warden::Proxy do
431
461
  setup_rack(app).call(@env)
432
462
  end
433
463
 
464
+ it "should cache found user" do
465
+ Warden::SessionSerializer.any_instance.should_receive(:fetch).once.and_return "A Previous User"
466
+ app = lambda do |env|
467
+ env['warden'].user.should == "A Previous User"
468
+ env['warden'].user.should == "A Previous User"
469
+ valid_response
470
+ end
471
+ setup_rack(app).call(@env)
472
+ end
473
+
434
474
  it "should not run strategies when the user exists in the session" do
435
475
  app = lambda do |env|
436
476
  env['warden'].authenticate!(:pass)
@@ -452,7 +492,7 @@ describe Warden::Proxy do
452
492
 
453
493
  it "should call run_callbacks when we pass a :run_callback => true" do
454
494
  app = lambda do |env|
455
- env['warden'].manager.should_receive(:_run_callbacks)
495
+ env['warden'].manager.should_receive(:_run_callbacks).at_least(:once)
456
496
  env['warden'].user(:run_callbacks => true)
457
497
  valid_response
458
498
  end
@@ -461,7 +501,7 @@ describe Warden::Proxy do
461
501
 
462
502
  it "should call run_callbacks by default" do
463
503
  app = lambda do |env|
464
- env['warden'].manager.should_receive(:_run_callbacks)
504
+ env['warden'].manager.should_receive(:_run_callbacks).at_least(:once)
465
505
  env['warden'].user
466
506
  valid_response
467
507
  end
@@ -2,8 +2,6 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Warden::Test::Helpers do
5
- include Warden::Test::Helpers
6
-
7
5
  before{ $captures = [] }
8
6
  after{ Warden.test_reset! }
9
7
 
data/warden.gemspec CHANGED
@@ -6,7 +6,6 @@ Gem::Specification.new do |s|
6
6
  s.name = %q{warden}
7
7
  s.version = Warden::VERSION.dup
8
8
  s.authors = ["Daniel Neighman"]
9
- s.date = %q{2011-07-27}
10
9
  s.email = %q{has.sox@gmail.com}
11
10
  s.extra_rdoc_files = [
12
11
  "LICENSE",
metadata CHANGED
@@ -1,35 +1,48 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: warden
3
- version: !ruby/object:Gem::Version
4
- version: 1.2.0
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
5
  prerelease:
6
+ segments:
7
+ - 1
8
+ - 2
9
+ - 1
10
+ version: 1.2.1
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Daniel Neighman
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2011-07-27 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-06-16 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
15
22
  name: rack
16
- requirement: &2156244180 !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
17
25
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '1.0'
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 1
32
+ - 0
33
+ version: "1.0"
22
34
  type: :runtime
23
- prerelease: false
24
- version_requirements: *2156244180
35
+ version_requirements: *id001
25
36
  description:
26
37
  email: has.sox@gmail.com
27
38
  executables: []
39
+
28
40
  extensions: []
29
- extra_rdoc_files:
41
+
42
+ extra_rdoc_files:
30
43
  - LICENSE
31
44
  - README.textile
32
- files:
45
+ files:
33
46
  - Gemfile
34
47
  - History.rdoc
35
48
  - lib/warden/config.rb
@@ -69,30 +82,39 @@ files:
69
82
  - spec/warden/test/helpers_spec.rb
70
83
  - spec/warden/test/test_mode_spec.rb
71
84
  - warden.gemspec
85
+ has_rdoc: true
72
86
  homepage: http://github.com/hassox/warden
73
87
  licenses: []
88
+
74
89
  post_install_message:
75
- rdoc_options:
90
+ rdoc_options:
76
91
  - --charset=UTF-8
77
- require_paths:
92
+ require_paths:
78
93
  - lib
79
- required_ruby_version: !ruby/object:Gem::Requirement
94
+ required_ruby_version: !ruby/object:Gem::Requirement
80
95
  none: false
81
- requirements:
82
- - - ! '>='
83
- - !ruby/object:Gem::Version
84
- version: '0'
85
- required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
104
  none: false
87
- requirements:
88
- - - ! '>='
89
- - !ruby/object:Gem::Version
90
- version: '0'
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ hash: 3
109
+ segments:
110
+ - 0
111
+ version: "0"
91
112
  requirements: []
113
+
92
114
  rubyforge_project: warden
93
- rubygems_version: 1.8.15
115
+ rubygems_version: 1.5.3
94
116
  signing_key:
95
117
  specification_version: 3
96
118
  summary: Rack middleware that provides authentication for rack applications
97
119
  test_files: []
98
- has_rdoc:
120
+