loyal_warden 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/Gemfile +11 -0
  2. data/History.rdoc +150 -0
  3. data/LICENSE +20 -0
  4. data/README.textile +9 -0
  5. data/Rakefile +12 -0
  6. data/lib/loyal_warden.rb +2 -0
  7. data/lib/warden.rb +45 -0
  8. data/lib/warden/config.rb +112 -0
  9. data/lib/warden/errors.rb +66 -0
  10. data/lib/warden/hooks.rb +211 -0
  11. data/lib/warden/manager.rb +136 -0
  12. data/lib/warden/mixins/common.rb +44 -0
  13. data/lib/warden/proxy.rb +371 -0
  14. data/lib/warden/session_serializer.rb +52 -0
  15. data/lib/warden/strategies.rb +47 -0
  16. data/lib/warden/strategies/base.rb +175 -0
  17. data/lib/warden/test/helpers.rb +36 -0
  18. data/lib/warden/test/warden_helpers.rb +43 -0
  19. data/lib/warden/version.rb +4 -0
  20. data/loyal_warden.gemspec +26 -0
  21. data/spec/helpers/request_helper.rb +51 -0
  22. data/spec/helpers/strategies/failz.rb +8 -0
  23. data/spec/helpers/strategies/invalid.rb +8 -0
  24. data/spec/helpers/strategies/pass.rb +8 -0
  25. data/spec/helpers/strategies/pass_with_message.rb +8 -0
  26. data/spec/helpers/strategies/password.rb +13 -0
  27. data/spec/helpers/strategies/single.rb +12 -0
  28. data/spec/spec_helper.rb +24 -0
  29. data/spec/warden/authenticated_data_store_spec.rb +114 -0
  30. data/spec/warden/config_spec.rb +48 -0
  31. data/spec/warden/errors_spec.rb +47 -0
  32. data/spec/warden/hooks_spec.rb +373 -0
  33. data/spec/warden/manager_spec.rb +316 -0
  34. data/spec/warden/proxy_spec.rb +1041 -0
  35. data/spec/warden/scoped_session_serializer.rb +123 -0
  36. data/spec/warden/session_serializer_spec.rb +53 -0
  37. data/spec/warden/strategies/base_spec.rb +313 -0
  38. data/spec/warden/strategies_spec.rb +93 -0
  39. data/spec/warden/test/helpers_spec.rb +93 -0
  40. data/spec/warden/test/test_mode_spec.rb +76 -0
  41. data/warden.gemspec +24 -0
  42. metadata +105 -0
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ module Warden
3
+ class SessionSerializer
4
+ attr_reader :env
5
+
6
+ def initialize(env)
7
+ @env = env
8
+ end
9
+
10
+ def key_for(scope)
11
+ "warden.user.#{scope}.key"
12
+ end
13
+
14
+ def serialize(user)
15
+ user
16
+ end
17
+
18
+ def deserialize(key)
19
+ key
20
+ end
21
+
22
+ def store(user, scope)
23
+ return unless user
24
+ method_name = "#{scope}_serialize"
25
+ specialized = respond_to?(method_name)
26
+ session[key_for(scope)] = specialized ? send(method_name, user) : serialize(user)
27
+ end
28
+
29
+ def fetch(scope)
30
+ key = session[key_for(scope)]
31
+ return nil unless key
32
+
33
+ method_name = "#{scope}_deserialize"
34
+ user = respond_to?(method_name) ? send(method_name, key) : deserialize(key)
35
+ delete(scope) unless user
36
+ user
37
+ end
38
+
39
+ def stored?(scope)
40
+ !!session[key_for(scope)]
41
+ end
42
+
43
+ def delete(scope, user=nil)
44
+ session.delete(key_for(scope))
45
+ end
46
+
47
+ # We can't cache this result because the session can be lazy loaded
48
+ def session
49
+ env["rack.session"] || {}
50
+ end
51
+ end # SessionSerializer
52
+ end # Warden
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+ module Warden
3
+ module Strategies
4
+ class << self
5
+ # Add a strategy and store it in a hash.
6
+ def add(label, strategy = nil, &block)
7
+ strategy ||= Class.new(Warden::Strategies::Base)
8
+ strategy.class_eval(&block) if block_given?
9
+
10
+ unless strategy.method_defined?(:authenticate!)
11
+ raise NoMethodError, "authenticate! is not declared in the #{label.inspect} strategy"
12
+ end
13
+
14
+ base = Warden::Strategies::Base
15
+ unless strategy.ancestors.include?(base)
16
+ raise "#{label.inspect} is not a #{base}"
17
+ end
18
+
19
+ _strategies[label] = strategy
20
+ end
21
+
22
+ # Update a previously given strategy.
23
+ def update(label, &block)
24
+ strategy = _strategies[label]
25
+ raise "Unknown strategy #{label.inspect}" unless strategy
26
+ add(label, strategy, &block)
27
+ end
28
+
29
+ # Provides access to strategies by label
30
+ # :api: public
31
+ def [](label)
32
+ _strategies[label]
33
+ end
34
+
35
+ # Clears all declared.
36
+ # :api: public
37
+ def clear!
38
+ _strategies.clear
39
+ end
40
+
41
+ # :api: private
42
+ def _strategies
43
+ @strategies ||= {}
44
+ end
45
+ end # << self
46
+ end # Strategies
47
+ end # Warden
@@ -0,0 +1,175 @@
1
+ # encoding: utf-8
2
+ module Warden
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
+ #
30
+ class Base
31
+ # :api: public
32
+ attr_accessor :user, :message
33
+
34
+ # :api: private
35
+ attr_accessor :result, :custom_response
36
+
37
+ # :api: public
38
+ attr_reader :env, :scope, :status
39
+
40
+ include ::Warden::Mixins::Common
41
+
42
+ # :api: private
43
+ def initialize(env, scope=nil) # :nodoc:
44
+ @env, @scope = env, scope
45
+ @status, @headers = nil, {}
46
+ @halted, @performed = false, false
47
+ end
48
+
49
+ # The method that is called from above. This method calls the underlying authenticate! method
50
+ # :api: private
51
+ def _run! # :nodoc:
52
+ @performed = true
53
+ authenticate!
54
+ self
55
+ end
56
+
57
+ # Returns if this strategy was already performed.
58
+ # :api: private
59
+ def performed? #:nodoc:
60
+ @performed
61
+ end
62
+
63
+ # Marks this strategy as not performed.
64
+ # :api: private
65
+ def clear!
66
+ @performed = false
67
+ end
68
+
69
+ # Acts as a guarding method for the strategy.
70
+ # If #valid? responds false, the strategy will not be executed
71
+ # Overwrite with your own logic
72
+ # :api: overwritable
73
+ def valid?; true; end
74
+
75
+ # Provides access to the headers hash for setting custom headers
76
+ # :api: public
77
+ def headers(header = {})
78
+ @headers ||= {}
79
+ @headers.merge! header
80
+ @headers
81
+ end
82
+
83
+ # Access to the errors object.
84
+ # :api: public
85
+ def errors
86
+ @env['warden'].errors
87
+ end
88
+
89
+ # Cause the processing of the strategies to stop and cascade no further
90
+ # :api: public
91
+ def halt!
92
+ @halted = true
93
+ end
94
+
95
+ # Checks to see if a strategy was halted
96
+ # :api: public
97
+ def halted?
98
+ !!@halted
99
+ end
100
+
101
+ # Checks to see if a strategy should result in a permanent login
102
+ # :api: public
103
+ def store?
104
+ true
105
+ end
106
+
107
+ # A simple method to return from authenticate! if you want to ignore this strategy
108
+ # :api: public
109
+ def pass; end
110
+
111
+ # Whenever you want to provide a user object as "authenticated" use the +success!+ method.
112
+ # This will halt the strategy, and set the user in the approprieate scope.
113
+ # It is the "login" method
114
+ #
115
+ # Parameters:
116
+ # user - The user object to login. This object can be anything you have setup to serialize in and out of the session
117
+ #
118
+ # :api: public
119
+ def success!(user, message = nil)
120
+ halt!
121
+ @user = user
122
+ @message = message
123
+ @result = :success
124
+ end
125
+
126
+ # This causes the strategy to fail. It does not throw an :warden symbol to drop the request out to the failure application
127
+ # You must throw an :warden symbol somewhere in the application to enforce this
128
+ # Halts the strategies so that this is the last strategy checked
129
+ # :api: public
130
+ def fail!(message = "Failed to Login")
131
+ halt!
132
+ @message = message
133
+ @result = :failure
134
+ end
135
+
136
+ # Casuses the strategy to fail, but not halt. The strategies will cascade after this failure and warden will check the next strategy. The last strategy to fail will have it's message displayed.
137
+ # :api: public
138
+ def fail(message = "Failed to Login")
139
+ @message = message
140
+ @result = :failure
141
+ end
142
+
143
+ # Causes the authentication to redirect. An :warden symbol must be thrown to actually execute this redirect
144
+ #
145
+ # Parameters:
146
+ # url <String> - The string representing the URL to be redirected to
147
+ # pararms <Hash> - Any parameters to encode into the URL
148
+ # opts <Hash> - Any options to recirect with.
149
+ # available options: permanent => (true || false)
150
+ #
151
+ # :api: public
152
+ def redirect!(url, params = {}, opts = {})
153
+ halt!
154
+ @status = opts[:permanent] ? 301 : 302
155
+ headers["Location"] = url
156
+ headers["Location"] << "?" << Rack::Utils.build_query(params) unless params.empty?
157
+ headers["Content-Type"] = opts[:content_type] || 'text/plain'
158
+
159
+ @message = opts[:message] || "You are being redirected to #{headers["Location"]}"
160
+ @result = :redirect
161
+
162
+ headers["Location"]
163
+ end
164
+
165
+ # Return a custom rack array. You must throw an :warden symbol to activate this
166
+ # :api: public
167
+ def custom!(response)
168
+ halt!
169
+ @custom_response = response
170
+ @result = :custom
171
+ end
172
+
173
+ end # Base
174
+ end # Strategies
175
+ end # Warden
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ module Warden
4
+ module Test
5
+ # A collection of test helpers for testing full stack rack applications using Warden
6
+ # These provide the ability to login and logout on any given request
7
+ # Note: During the teardown phase of your specs you should include: Warden.test_reset!
8
+ module Helpers
9
+ def self.included(base)
10
+ ::Warden.test_mode!
11
+ end
12
+
13
+ # A helper method that will peform a login of a user in warden for the next request
14
+ # Provide it the same options as you would to Warden::Proxy#set_user
15
+ # @see Warden::Proxy#set_user
16
+ # @api public
17
+ def login_as(user, opts = {})
18
+ Warden.on_next_request do |proxy|
19
+ opts[:event] ||= :authentication
20
+ proxy.set_user(user, opts)
21
+ end
22
+ end
23
+
24
+ # Logs out a user from the session.
25
+ # Without arguments, all users will be logged out
26
+ # Provide a list of scopes to only log out users with that scope.
27
+ # @see Warden::Proxy#logout
28
+ # @api public
29
+ def logout(*scopes)
30
+ Warden.on_next_request do |proxy|
31
+ proxy.logout(*scopes)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+
3
+ module Warden
4
+
5
+ module Test
6
+ module WardenHelpers
7
+ # Returns list of regex objects that match paths expected to be an asset
8
+ # @see Warden::Proxy#asset_request?
9
+ # @api public
10
+ def asset_paths
11
+ @asset_paths ||= [/^\/assets\//]
12
+ end
13
+
14
+ # Sets list of regex objects that match paths expected to be an asset
15
+ # @see Warden::Proxy#asset_request?
16
+ # @api public
17
+ def asset_paths=(*vals)
18
+ @asset_paths = vals
19
+ end
20
+
21
+ # Adds a block to be executed on the next request when the stack reaches warden.
22
+ # The warden proxy is yielded to the block
23
+ # @api public
24
+ def on_next_request(&blk)
25
+ _on_next_request << blk
26
+ end
27
+
28
+ # resets wardens tests
29
+ # any blocks queued to execute will be removed
30
+ # @api public
31
+ def test_reset!
32
+ _on_next_request.clear
33
+ end
34
+
35
+ # A containter for the on_next_request items.
36
+ # @api private
37
+ def _on_next_request
38
+ @_on_next_request ||= []
39
+ @_on_next_request
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+ module Warden
3
+ VERSION = "1.2.3".freeze
4
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require './lib/warden/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{loyal_warden}
7
+ # s.version = Warden::VERSION.dup
8
+ s.version = '0.0.5'
9
+ s.authors = ["Daniel Neighman"]
10
+ s.email = %q{has.sox@gmail.com}
11
+ s.license = "MIT"
12
+ s.extra_rdoc_files = [
13
+ "LICENSE",
14
+ "README.textile"
15
+ ]
16
+ s.files = Dir["**/*"] - Dir["*.gem"] - ["Gemfile.lock"]
17
+ s.homepage = %q{http://github.com/hassox/warden}
18
+ s.rdoc_options = ["--charset=UTF-8"]
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{warden}
21
+ s.rubygems_version = %q{1.3.7}
22
+ s.summary = %q{Rack middleware that provides authentication for rack applications}
23
+
24
+ s.add_dependency "rack", ">= 1.0"
25
+ end
26
+
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+ module Warden::Spec
3
+ module Helpers
4
+ FAILURE_APP = lambda{|e|[401, {"Content-Type" => "text/plain"}, ["You Fail!"]] }
5
+
6
+ def env_with_params(path = "/", params = {}, env = {})
7
+ method = params.delete(:method) || "GET"
8
+ env = { 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => "#{method}" }.merge(env)
9
+ Rack::MockRequest.env_for("#{path}?#{Rack::Utils.build_query(params)}", env)
10
+ end
11
+
12
+ def setup_rack(app = nil, opts = {}, &block)
13
+ app ||= block if block_given?
14
+
15
+ opts[:failure_app] ||= failure_app
16
+ opts[:default_strategies] ||= [:password]
17
+ opts[:default_serializers] ||= [:session]
18
+ blk = opts[:configurator] || proc{}
19
+
20
+ Rack::Builder.new do
21
+ use opts[:session] || Warden::Spec::Helpers::Session unless opts[:nil_session]
22
+ use Warden::Manager, opts, &blk
23
+ run app
24
+ end
25
+ end
26
+
27
+ def valid_response
28
+ Rack::Response.new("OK").finish
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
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ Warden::Strategies.add(:failz) do
3
+ def authenticate!
4
+ request.env['warden.spec.strategies'] ||= []
5
+ request.env['warden.spec.strategies'] << :failz
6
+ fail!("The Fails Strategy Has Failed You")
7
+ end
8
+ end