warden 0.5.3 → 0.6.0

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.
Files changed (35) hide show
  1. data/History.rdoc +8 -5
  2. data/README.textile +1 -1
  3. data/lib/warden.rb +7 -4
  4. data/lib/warden/declarable.rb +43 -0
  5. data/lib/warden/hooks.rb +121 -0
  6. data/lib/warden/manager.rb +52 -21
  7. data/lib/warden/mixins/common.rb +11 -2
  8. data/lib/warden/proxy.rb +88 -32
  9. data/lib/warden/serializers.rb +20 -0
  10. data/lib/warden/serializers/base.rb +38 -0
  11. data/lib/warden/serializers/cookie.rb +34 -0
  12. data/lib/warden/serializers/session.rb +30 -0
  13. data/lib/warden/strategies.rb +18 -0
  14. data/lib/warden/{authentication/strategy_base.rb → strategies/base.rb} +27 -2
  15. data/lib/warden/version.rb +1 -1
  16. data/spec/helpers/request_helper.rb +14 -12
  17. data/spec/{warden → helpers}/strategies/failz.rb +0 -0
  18. data/spec/{warden → helpers}/strategies/invalid.rb +0 -0
  19. data/spec/{warden → helpers}/strategies/pass.rb +0 -0
  20. data/spec/{warden → helpers}/strategies/pass_without_user.rb +0 -0
  21. data/spec/{warden → helpers}/strategies/password.rb +0 -0
  22. data/spec/spec_helper.rb +1 -1
  23. data/spec/warden/authenticated_data_store_spec.rb +4 -4
  24. data/spec/warden/manager_spec.rb +0 -8
  25. data/spec/warden/proxy_spec.rb +61 -10
  26. data/spec/warden/serializers/cookie_spec.rb +60 -0
  27. data/spec/warden/serializers/session_spec.rb +47 -0
  28. data/spec/warden/serializers_spec.rb +96 -0
  29. data/spec/warden/{strategy_base_spec.rb → strategies/base_spec.rb} +1 -1
  30. data/spec/warden/strategies_spec.rb +19 -15
  31. data/warden.gemspec +28 -18
  32. metadata +28 -18
  33. data/VERSION +0 -1
  34. data/lib/warden/authentication/hooks.rb +0 -124
  35. data/lib/warden/authentication/strategies.rb +0 -59
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require 'warden/declarable'
3
+
4
+ module Warden
5
+ module Serializers
6
+ extend Warden::Declarable
7
+
8
+ class << self
9
+ def check_validity!(label, serializer)
10
+ [:fetch, :store, :stored?, :delete].each do |method|
11
+ next if serializer.method_defined?(method)
12
+ raise NoMethodError, "#{method} is not declared in the #{label.inspect} serializer"
13
+ end
14
+ end
15
+
16
+ alias :_serializers :_declarations
17
+ end # << self
18
+
19
+ end # Serializers
20
+ end # Warden
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ module Warden
3
+ module Serializers
4
+ # A serializer is a place where you put the logic to serializing and deserializing an user. All serializers
5
+ # inherits from Warden::Serializers::Base.
6
+ #
7
+ # The Warden::Serializers.add method is a simple way to provide custom serializers. In order to do so,
8
+ # you _must_ declare @store@, @fetch@, @delete@ and @stored?@ methods.
9
+ #
10
+ # The parameters for Warden::Serializers.add method is:
11
+ # <label: Symbol> The label is the name given to a serializer. Use the label to refer to the serializer when authenticating
12
+ # <serializer: Class|nil> The optional serializer argument if set _must_ be a class that inherits from Warden::Serializers::Base
13
+ # <block> The block acts as a convinient way to declare your serializer. Inside is the class definition of a serializer.
14
+ #
15
+ # Check Session and Cookie serializers for more information.
16
+ #
17
+ class Base
18
+ attr_accessor :env
19
+ include ::Warden::Mixins::Common
20
+
21
+ def initialize(env)
22
+ @env = env
23
+ end
24
+
25
+ def key_for(scope)
26
+ "warden.user.#{scope}.key"
27
+ end
28
+
29
+ def serialize(user)
30
+ user
31
+ end
32
+
33
+ def deserialize(key)
34
+ key
35
+ end
36
+ end # Base
37
+ end # Serializers
38
+ end # Warden
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ module Warden
3
+ module Serializers
4
+ # A cookie serializer provided by Warden. You need to implement the serialize and deserialize
5
+ # methods in order to use it.
6
+ class Cookie < Base
7
+ def store(user, scope)
8
+ response.set_cookie key_for(scope), default_options(user)
9
+ end
10
+
11
+ def fetch(scope)
12
+ key = request.cookies[key_for(scope)]
13
+ return nil unless key
14
+ user = deserialize(key)
15
+ delete(scope) unless user
16
+ user
17
+ end
18
+
19
+ def stored?(scope)
20
+ !!request.cookies[key_for(scope)]
21
+ end
22
+
23
+ def delete(scope, user=nil)
24
+ response.delete_cookie(key_for(scope))
25
+ end
26
+
27
+ def default_options(user)
28
+ { :value => serialize(user), :expires => (Time.now + 7 * 24 * 3600), :path => "/" }
29
+ end
30
+ end # Cookie
31
+
32
+ Serializers.add(:cookie, Cookie)
33
+ end # Serializers
34
+ end # Warden
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ module Warden
3
+ module Serializers
4
+ # A session serializer provided by Warden. You need to implement the serialize and deserialize
5
+ # methods in order to use it.
6
+ class Session < Base
7
+ def store(user, scope)
8
+ session[key_for(scope)] = serialize(user)
9
+ end
10
+
11
+ def fetch(scope)
12
+ key = session[key_for(scope)]
13
+ return nil unless key
14
+ user = deserialize(key)
15
+ delete(scope) unless user
16
+ user
17
+ end
18
+
19
+ def stored?(scope)
20
+ !!session[key_for(scope)]
21
+ end
22
+
23
+ def delete(scope, user=nil)
24
+ session.delete(key_for(scope))
25
+ end
26
+ end # Session
27
+
28
+ Serializers.add(:session, Session)
29
+ end # Serializers
30
+ end # Warden
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ require 'warden/declarable'
3
+
4
+ module Warden
5
+ module Strategies
6
+ extend Warden::Declarable
7
+
8
+ class << self
9
+ def check_validity!(label, strategy)
10
+ return if strategy.method_defined?(:authenticate!)
11
+ raise NoMethodError, "authenticate! is not declared in the #{label.inspect} strategy"
12
+ end
13
+
14
+ alias :_strategies :_declarations
15
+ end # << self
16
+
17
+ end # Strategies
18
+ end # Warden
@@ -1,6 +1,32 @@
1
1
  # encoding: utf-8
2
2
  module Warden
3
3
  module Strategies
4
+ # A strategy is a place where you can put logic related to authentication. Any strategy inherits
5
+ # from Warden::Strategies::Base.
6
+ #
7
+ # The Warden::Strategies.add method is a simple way to provide custom strategies.
8
+ # You _must_ declare an @authenticate!@ method.
9
+ # You _may_ provide a @valid?@ method.
10
+ # The valid method should return true or false depending on if the strategy is a valid one for the request.
11
+ #
12
+ # The parameters for Warden::Strategies.add method is:
13
+ # <label: Symbol> The label is the name given to a strategy. Use the label to refer to the strategy when authenticating
14
+ # <strategy: Class|nil> The optional stragtegy argument if set _must_ be a class that inherits from Warden::Strategies::Base and _must_
15
+ # implement an @authenticate!@ method
16
+ # <block> The block acts as a convinient way to declare your strategy. Inside is the class definition of a strategy.
17
+ #
18
+ # Examples:
19
+ #
20
+ # Block Declared Strategy:
21
+ # Warden::Strategies.add(:foo) do
22
+ # def authenticate!
23
+ # # authentication logic
24
+ # end
25
+ # end
26
+ #
27
+ # Class Declared Strategy:
28
+ # Warden::Strategies.add(:foo, MyStrategy)
29
+ #
4
30
  class Base
5
31
  # :api: public
6
32
  attr_accessor :user, :message
@@ -24,7 +50,7 @@ module Warden
24
50
  @halted = false
25
51
  end
26
52
 
27
- # The method that is called from above. This method calls the underlying authenticate! method
53
+ # The method that is called from above. This method calls the underlying authenticate! method
28
54
  # :api: private
29
55
  def _run! # :nodoc:
30
56
  result = authenticate!
@@ -107,7 +133,6 @@ module Warden
107
133
  headers["Content-Type"] = opts[:content_type] || 'text/plain'
108
134
 
109
135
  @message = opts[:message].nil? ? "You are being redirected to #{headers["Location"]}" : opts[:message]
110
-
111
136
  @result = :redirect
112
137
 
113
138
  headers["Location"]
@@ -1,3 +1,3 @@
1
1
  module Warden
2
- VERSION = "0.5.3"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -1,49 +1,51 @@
1
1
  module Warden::Spec
2
2
  module Helpers
3
-
3
+
4
4
  FAILURE_APP = lambda{|e|[401, {"Content-Type" => "text/plain"}, ["You Fail!"]] }
5
-
5
+
6
6
  def env_with_params(path = "/", params = {})
7
7
  method = params.fetch(:method, "GET")
8
8
  Rack::MockRequest.env_for(path, :input => Rack::Utils.build_query(params),
9
9
  'HTTP_VERSION' => '1.1',
10
10
  'REQUEST_METHOD' => "#{method}")
11
11
  end
12
-
12
+
13
13
  def setup_rack(app = nil, opts = {}, &block)
14
14
  app ||= block if block_given?
15
- opts[:default_strategies] ||= [:password]
15
+ opts[:default_strategies] ||= [:password]
16
+ opts[:default_serializers] ||= [:session]
16
17
  opts[:failure_app] ||= Warden::Spec::Helpers::FAILURE_APP
17
- Rack::Builder.new do
18
+ Rack::Builder.new do
18
19
  use Warden::Spec::Helpers::Session
19
20
  use Warden::Manager, opts do |manager|
20
21
  manager.failure_app = Warden::Spec::Helpers::FAILURE_APP
21
22
  manager.default_strategies *opts[:default_strategies]
23
+ manager.default_serializers *opts[:default_serializers]
22
24
  end
23
25
  run app
24
26
  end
25
27
  end
26
-
28
+
27
29
  def valid_response
28
- [200,{'Content-Type' => 'text/plain'},'OK']
30
+ Rack::Response.new("OK").finish
29
31
  end
30
-
32
+
31
33
  def failure_app
32
34
  Warden::Spec::Helpers::FAILURE_APP
33
35
  end
34
-
36
+
35
37
  def success_app
36
38
  lambda{|e| [200, {"Content-Type" => "text/plain"}, ["You Win"]]}
37
39
  end
38
-
40
+
39
41
  class Session
40
42
  attr_accessor :app
41
43
  def initialize(app,configs = {})
42
44
  @app = app
43
45
  end
44
-
46
+
45
47
  def call(e)
46
- e['rack.session'] ||= {}
48
+ e['rack.session'] ||= {}
47
49
  @app.call(e)
48
50
  end
49
51
  end # session
@@ -12,7 +12,7 @@ Spec::Runner.configure do |config|
12
12
  config.include(Warden::Spec::Helpers)
13
13
 
14
14
  def load_strategies
15
- Dir[File.join(File.dirname(__FILE__), "warden", "strategies", "**/*.rb")].each do |f|
15
+ Dir[File.join(File.dirname(__FILE__), "helpers", "strategies", "**/*.rb")].each do |f|
16
16
  load f
17
17
  end
18
18
  end
@@ -5,9 +5,9 @@ describe "authenticated data store" do
5
5
  before(:each) do
6
6
  @env = env_with_params
7
7
  @env['rack.session'] = {
8
- "warden.user.foo.key" => "foo user",
9
- "warden.user.default.key" => "default user",
10
- :foo => "bar"
8
+ "warden.user.foo.key" => "foo user",
9
+ "warden.user.default.key" => "default user",
10
+ :foo => "bar"
11
11
  }
12
12
  end
13
13
 
@@ -18,7 +18,7 @@ describe "authenticated data store" do
18
18
  e['warden'].should be_authenticated
19
19
  e['warden'].should be_authenticated(:foo)
20
20
 
21
- # Store the data for :deafult
21
+ # Store the data for :default
22
22
  e['warden'].session[:key] = "value"
23
23
  valid_response
24
24
  end
@@ -12,14 +12,6 @@ describe Warden::Manager do
12
12
  env["warden"].should be_an_instance_of(Warden::Proxy)
13
13
  end
14
14
 
15
- describe "user storage" do
16
- it "should take a user and store it in the provided session" do
17
- session = {}
18
- Warden::Manager._store_user("The User", session, "some_scope")
19
- session["warden.user.some_scope.key"].should == "The User"
20
- end
21
- end
22
-
23
15
  describe "thrown auth" do
24
16
  before(:each) do
25
17
  @basic_app = lambda{|env| [200,{'Content-Type' => 'text/plain'},'OK']}
@@ -165,9 +165,9 @@ describe Warden::Proxy do
165
165
  env['warden'].authenticate(:pass, :scope => :foo)
166
166
  env['warden'].authenticate(:pass, :scope => :bar)
167
167
  env['warden'].authenticate(:password)
168
- env['warden'].authenticated?(:foo).should == true
169
- env['warden'].authenticated?(:bar).should == true
170
- env['warden'].authenticated?.should == false
168
+ env['warden'].authenticated?(:foo).should be_true
169
+ env['warden'].authenticated?(:bar).should be_true
170
+ env['warden'].authenticated?.should be_false
171
171
  valid_response
172
172
  end
173
173
  env = env_with_params
@@ -195,7 +195,7 @@ describe Warden::Proxy do
195
195
  end
196
196
  end # describe "authentication"
197
197
 
198
- describe "stored in session" do
198
+ describe "stored?" do
199
199
  before(:each) do
200
200
  @env['rack.session'] ||= {}
201
201
  @env['rack.session']['warden.user.default.key'] = "User"
@@ -203,7 +203,7 @@ describe Warden::Proxy do
203
203
 
204
204
  it "returns true if user key is stored in session" do
205
205
  app = lambda do |env|
206
- env['warden'].stored_in_session?.should be_true
206
+ env['warden'].stored?.should be_true
207
207
  valid_response
208
208
  end
209
209
  setup_rack(app).call(@env)
@@ -212,11 +212,31 @@ describe Warden::Proxy do
212
212
  it "returns false if user key is not stored in session" do
213
213
  @env['rack.session'].delete("warden.user.default.key")
214
214
  app = lambda do |env|
215
- env['warden'].stored_in_session?.should be_false
215
+ env['warden'].stored?.should be_false
216
216
  valid_response
217
217
  end
218
218
  setup_rack(app).call(@env)
219
219
  end
220
+
221
+ it "returns false if scope given is not stored in session" do
222
+ app = lambda do |env|
223
+ env['warden'].stored?.should be_true
224
+ env['warden'].stored?(:another).should be_false
225
+ valid_response
226
+ end
227
+ setup_rack(app).call(@env)
228
+ end
229
+
230
+ it "returns based on the given store" do
231
+ @env['rack.session'].delete("warden.user.default.key")
232
+ @env["HTTP_COOKIE"] = "warden.user.default.key=user;"
233
+ app = lambda do |env|
234
+ env['warden'].stored?(:default, :session).should be_false
235
+ env['warden'].stored?(:default, :cookie).should be_true
236
+ valid_response
237
+ end
238
+ setup_rack(app, :default_serializers => [:session, :cookie]).call(@env)
239
+ end
220
240
  end
221
241
 
222
242
  describe "set user" do
@@ -232,6 +252,19 @@ describe Warden::Proxy do
232
252
  setup_rack(app).call(env)
233
253
  end
234
254
 
255
+ it "should store the user in all serializers" do
256
+ env = env_with_params("/")
257
+ app = lambda do |env|
258
+ env['warden'].authenticate(:pass)
259
+ env['warden'].should be_authenticated
260
+ env['warden'].user.should == "Valid User"
261
+ valid_response
262
+ end
263
+ setup_rack(app, :default_serializers => [:session, :cookie]).call(env)
264
+ headers = env['warden'].serializers.last.response.headers
265
+ headers['Set-Cookie'].split(";").first.should == "warden.user.default.key=Valid+User"
266
+ end
267
+
235
268
  it "should not store the user if the :store option is set to false" do
236
269
  env = env_with_params("/")
237
270
  app = lambda do |e|
@@ -268,6 +301,15 @@ describe Warden::Proxy do
268
301
  setup_rack(app).call(@env)
269
302
  end
270
303
 
304
+ it "should load user from others serializers" do
305
+ @env["HTTP_COOKIE"] = "warden.user.default.key=user;"
306
+ app = lambda do |env|
307
+ env['warden'].user.should == "user"
308
+ valid_response
309
+ end
310
+ setup_rack(app, :default_serializers => [:session, :cookie]).call(@env)
311
+ end
312
+
271
313
  describe "previously logged in" do
272
314
 
273
315
  before(:each) do
@@ -299,14 +341,14 @@ describe Warden::Proxy do
299
341
  before(:each) do
300
342
  @env = env = env_with_params
301
343
  @env['rack.session'] = {"warden.user.default.key" => "default key", "warden.user.foo.key" => "foo key", :foo => "bar"}
302
- app = lambda do |e|
344
+ @app = lambda do |e|
303
345
  e['warden'].logout(env['warden.spec.which_logout'])
304
346
  valid_response
305
347
  end
306
- @app = setup_rack(app)
307
348
  end
308
349
 
309
350
  it "should logout only the scoped foo user" do
351
+ @app = setup_rack(@app)
310
352
  @env['warden.spec.which_logout'] = :foo
311
353
  @app.call(@env)
312
354
  @env['rack.session']['warden.user.default.key'].should == "default key"
@@ -315,6 +357,7 @@ describe Warden::Proxy do
315
357
  end
316
358
 
317
359
  it "should logout only the scoped default user" do
360
+ @app = setup_rack(@app)
318
361
  @env['warden.spec.which_logout'] = :default
319
362
  @app.call(@env)
320
363
  @env['rack.session']['warden.user.default.key'].should be_nil
@@ -343,7 +386,6 @@ describe Warden::Proxy do
343
386
  end
344
387
  setup_rack(app).call(@env)
345
388
  @env['warden'].user.should be_nil
346
-
347
389
  end
348
390
 
349
391
  it "should clear the session data when logging out" do
@@ -357,6 +399,15 @@ describe Warden::Proxy do
357
399
  setup_rack(app).call(@env)
358
400
  end
359
401
 
402
+ it "should clear the session in all serializers" do
403
+ @app = setup_rack(@app, :default_serializers => [:session, :cookie])
404
+ @env['warden.spec.which_logout'] = :default
405
+ @app.call(@env)
406
+ @env['warden'].serializers.last.should_not be_nil
407
+ headers = @env['warden'].serializers.last.response.headers
408
+ headers['Set-Cookie'].first.split(";").first.should == "warden.user.default.key="
409
+ end
410
+
360
411
  it "should clear out the session by calling reset_session! so that plugins can setup their own session clearing" do
361
412
  @env['rack.session'].should_not be_nil
362
413
  app = lambda do |e|
@@ -395,7 +446,7 @@ describe Warden::Proxy do
395
446
  it "should return false for authenticated when there are no valid? strategies" do
396
447
  @env['rack.session'] = {}
397
448
  app = lambda do |e|
398
- e['warden'].authenticated?(:invalid).should == false
449
+ e['warden'].authenticated?(:invalid).should be_false
399
450
  end
400
451
  setup_rack(app).call(@env)
401
452
  end