warden 0.5.3 → 0.6.0

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