merb-auth-core 0.9.9 → 0.9.10
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +62 -33
- data/Rakefile +4 -2
- data/lib/merb-auth-core/authentication.rb +35 -3
- data/lib/merb-auth-core/callbacks.rb +34 -0
- data/lib/merb-auth-core/router_helper.rb +21 -1
- data/lib/merb-auth-core/session_mixin.rb +36 -48
- data/lib/merb-auth-core.rb +2 -1
- data/spec/merb-auth-core/authentication_spec.rb +36 -0
- data/spec/merb-auth-core/callbacks_spec.rb +103 -0
- data/spec/merb-auth-core/router_helper_spec.rb +0 -2
- data/spec/spec_helper.rb +7 -2
- metadata +6 -4
data/README.textile
CHANGED
@@ -5,9 +5,10 @@ Merb web framework.
|
|
5
5
|
|
6
6
|
MerbAuth does not try to dictate what you should use as a user model, or how
|
7
7
|
it should authenticate. Instead it focuses on the logic required to check
|
8
|
-
that an object passes authentication, and store
|
9
|
-
session. This is in fact the guiding principle of MerbAuth. The Session is
|
10
|
-
used as the place for authentication, with a sprinkling of controller helpers.
|
8
|
+
that an object passes authentication, and store the keys of authenticated
|
9
|
+
objects in the session. This is in fact the guiding principle of MerbAuth. The Session is
|
10
|
+
used as the place for authentication, with a sprinkling of controller helpers.
|
11
|
+
You can choose to protect a controller action, or a route / group of routes.
|
11
12
|
This makes sense to talk about an authenticated session. For example, inside
|
12
13
|
your controller:
|
13
14
|
|
@@ -25,6 +26,9 @@ your controller:
|
|
25
26
|
* session.abandon!
|
26
27
|
sets the session to unauthenticated, and clears all session data
|
27
28
|
|
29
|
+
* session.authenticate!
|
30
|
+
authenticates the session against the active strategies
|
31
|
+
|
28
32
|
MerbAuth makes use of Merb's exception handling facilities which return correct
|
29
33
|
HTTP status codes when a 200 OK would be inappropriate. To fail a login, or
|
30
34
|
to force a login at any point in your controller code, simply raise an
|
@@ -69,7 +73,7 @@ to the params hash, session etc.
|
|
69
73
|
|
70
74
|
To pass authentication, simply return a non-nil
|
71
75
|
non-false value from the @run!@ method. Any false or nil value will cause
|
72
|
-
that strategy to fail. Then the next strategy will be tried
|
76
|
+
that strategy to fail. Then the next strategy will be tried.
|
73
77
|
|
74
78
|
You can add as many strategies as you like and they will be tried one after
|
75
79
|
another until either one is found that works (login), or none of them have
|
@@ -93,26 +97,23 @@ h3. Customizing the user_class
|
|
93
97
|
|
94
98
|
Notice the @user_class@ method in the above strategy examples. This is a convenience method on a strategy
|
95
99
|
to provide you with the user_class to use for this strategy. You can overwrite
|
96
|
-
this method on a per strategy basis to use different user model types.
|
100
|
+
this method on a per strategy basis to use different user model types. You do not _have_ to use this method
|
101
|
+
and it's only there to keep track of the "default" user class. (if any)
|
97
102
|
|
98
103
|
By default the strategy#user_class method will defer to Merb::Authentication#user_class. You can
|
99
104
|
set which is the "default class" that Merb::Authentication will use in the provided strategies by
|
100
|
-
setting
|
105
|
+
setting it in Merb.root/merb/merb-auth/setup.rb
|
101
106
|
|
102
107
|
<pre><code>
|
103
|
-
class Person
|
104
|
-
include DataMapper::Resource
|
105
|
-
|
106
|
-
Merb::Authentication.user_class = self
|
107
108
|
|
108
|
-
|
109
|
-
|
109
|
+
Merb::Authentication.user_class = Person
|
110
|
+
|
110
111
|
</code></pre>
|
111
112
|
|
112
|
-
This will cascade throughout the default strategies, and your own strategies
|
113
|
-
|
113
|
+
This will cascade throughout the default strategies, and your own strategies using the user class
|
114
|
+
that you defined. In this case Person.
|
114
115
|
|
115
|
-
There is no default class set for
|
116
|
+
There is no default class set for Merb::Authentication.user_class by default
|
116
117
|
|
117
118
|
h3. Strategies and Inheritance
|
118
119
|
|
@@ -138,7 +139,7 @@ To activate a registered strategy:
|
|
138
139
|
Merb::Authentication.activate!(:defualt_password_form)
|
139
140
|
</code></pre>
|
140
141
|
|
141
|
-
You can easily mix this in with your own strategies. In you
|
142
|
+
You can easily mix this in with your own strategies. In you Merb.root/merb-auth/strategies.rb
|
142
143
|
<pre><code>
|
143
144
|
class MyStrategy < Merb::Authentication::Strategy
|
144
145
|
def run!
|
@@ -155,7 +156,7 @@ You can easily mix this in with your own strategies. In you lib/authentication/s
|
|
155
156
|
end
|
156
157
|
</code></pre>
|
157
158
|
|
158
|
-
This will collect them in order of
|
159
|
+
This will collect them in order of declaration. i.e.:
|
159
160
|
MyStrategy, Merb::Authentication::Strategies::Basic::OpenID, AnotherStrategy
|
160
161
|
|
161
162
|
h3. Customizing the order of the strategies
|
@@ -173,8 +174,35 @@ manually.
|
|
173
174
|
It's possible to leave some out, and re-order existing ones. It will error
|
174
175
|
out if you specify one that doesn't exist though.
|
175
176
|
|
177
|
+
h3. Authentication based on Routes
|
178
|
+
|
179
|
+
With MerbAuth you can protect routes rather than individual actions on a controller.
|
180
|
+
The benefit with doing this is that the request is stopped earlier in the request
|
181
|
+
process. This is a more efficient method of protection than controller based protection.
|
182
|
+
|
183
|
+
The downside is that a controllers action is not guaranteed to be protected. For example
|
184
|
+
|
185
|
+
<pre><code>
|
186
|
+
|
187
|
+
authenticate do
|
188
|
+
match("/one").to(:controller => "one", :action => "index")
|
189
|
+
end
|
190
|
+
|
191
|
+
match("/two").to(:controller => "one", :action => "index")
|
192
|
+
|
193
|
+
</code></pre>
|
194
|
+
|
195
|
+
The /one route is protected, but you can see that both of these routes point to the same
|
196
|
+
controller action. If the One#index method is accessed through the /two route, there is
|
197
|
+
no protection. You can specify which strategies to use as arguments to the authenticate method.
|
198
|
+
The default strategies are used if there is no argument given.
|
199
|
+
|
176
200
|
h3. Specifying selected strategies per action
|
177
201
|
|
202
|
+
If you need to protect an action regardless of which route leads to it, you can use
|
203
|
+
controller level protection. Use a @before :ensure_authenticated@ filter to protect actions
|
204
|
+
in your controller whenever the are accessed.
|
205
|
+
|
178
206
|
It's possible to configure each call to @ensure_authenticated@ with a custom list
|
179
207
|
of strategies to run. These will be run in order and should have an instance method
|
180
208
|
of #run!
|
@@ -185,7 +213,8 @@ of #run!
|
|
185
213
|
Merb::Authenticated::Strategies::Basic::Form,
|
186
214
|
Merb::Authenticated::Strategies::Basic::BasicAuth,
|
187
215
|
Merb::Authenticated::Strategies::Basic::OpenID,
|
188
|
-
]
|
216
|
+
],
|
217
|
+
:only => [:index]
|
189
218
|
before :machine_only, :only => [:create]
|
190
219
|
|
191
220
|
def index
|
@@ -212,13 +241,14 @@ h3. Where should Strategies be defined?
|
|
212
241
|
|
213
242
|
You should store your strategies in
|
214
243
|
<pre><code>
|
215
|
-
|
216
|
-
`--
|
244
|
+
merb
|
245
|
+
`-- merb-auth
|
217
246
|
|-- setup.rb
|
218
247
|
`-- strategies.rb
|
219
248
|
</code></pre>
|
220
249
|
|
221
250
|
This is a good place to put everything together so you can see what you're doing at a glance.
|
251
|
+
It is also auto included by merb-auth-core when you're using it.
|
222
252
|
|
223
253
|
h3. What Strategies are there?
|
224
254
|
|
@@ -228,7 +258,7 @@ h3. Storing you user object into the session
|
|
228
258
|
|
229
259
|
You need to tell MerbAuth how to serialize your object into
|
230
260
|
and out of the session. If possible try not to store large or complex
|
231
|
-
data items in the session.
|
261
|
+
data items in the session but just store the objects key.
|
232
262
|
|
233
263
|
To configure your user object to go in and out of the session, here's how you
|
234
264
|
could do it.
|
@@ -309,27 +339,26 @@ There's at least 4 ways to provide feedback to users for failed logins.
|
|
309
339
|
h3. Additional checks / actions to perform after the user is found
|
310
340
|
|
311
341
|
Sometimes you may need to perform additional operations on the user object
|
312
|
-
|
313
|
-
Merb::Authentication
|
314
|
-
deal with this.
|
342
|
+
after you have found a valid user in the strategy. There is a hook method
|
343
|
+
Merb::Authentication.after_authentication which is designed for this.
|
315
344
|
|
316
345
|
Here's an example of checking that a user object is active after it's been
|
317
346
|
found:
|
318
347
|
|
319
|
-
|
320
|
-
|
348
|
+
Merb::Authentication.after_authentication do |user, request, params|
|
349
|
+
user.active? ? user : nil
|
321
350
|
end
|
351
|
+
|
352
|
+
Pass the user model on if everything is still ok. Return nil if you decide in the
|
353
|
+
after_authentication hook that the user should in fact not be allowed to be authenticated.
|
322
354
|
|
323
|
-
|
324
|
-
session is available in that block as <code>session</code>
|
325
|
-
|
326
|
-
Really that's all there is to it. By default this plugin doesn't actually
|
355
|
+
By default this plugin doesn't actually
|
327
356
|
authenticate anything ;) It's up to you to get your model going, and add an
|
328
|
-
authentication strategy.
|
329
|
-
|
357
|
+
authentication strategy.
|
358
|
+
|
359
|
+
To logout use
|
330
360
|
@session.abandon!@ and to force a login at any time use
|
331
361
|
@raise Unauthenticated, "You Aren't Cool Enough"@
|
332
|
-
Be aware that strategies may throw :halt for use as a before filter...
|
333
362
|
|
334
363
|
h3. Contributors
|
335
364
|
|
data/Rakefile
CHANGED
@@ -9,7 +9,9 @@ require 'rake/testtask'
|
|
9
9
|
|
10
10
|
|
11
11
|
GEM_NAME = "merb-auth-core"
|
12
|
-
|
12
|
+
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
13
|
+
GEM_VERSION = Merb::VERSION + PKG_BUILD
|
14
|
+
|
13
15
|
AUTHOR = "Adam French, Daniel Neighman"
|
14
16
|
EMAIL = "has.sox@gmail.com"
|
15
17
|
HOMEPAGE = "http://merbivore.com/"
|
@@ -27,7 +29,7 @@ spec = Gem::Specification.new do |s|
|
|
27
29
|
s.author = AUTHOR
|
28
30
|
s.email = EMAIL
|
29
31
|
s.homepage = HOMEPAGE
|
30
|
-
s.add_dependency('merb-core',
|
32
|
+
s.add_dependency('merb-core', "~> #{Merb::VERSION}")
|
31
33
|
s.add_dependency('extlib')
|
32
34
|
s.require_path = 'lib'
|
33
35
|
s.files = %w(LICENSE README.textile Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Merb
|
2
2
|
class Authentication
|
3
|
+
module Strategies; end
|
3
4
|
include Extlib::Hook
|
4
5
|
attr_accessor :session
|
5
6
|
attr_writer :error_message
|
@@ -74,19 +75,30 @@ module Merb
|
|
74
75
|
user = nil
|
75
76
|
# This one should find the first one that matches. It should not run antother
|
76
77
|
strategies.detect do |s|
|
78
|
+
s = Merb::Authentication.lookup_strategy[s] # Get the strategy from string or class
|
77
79
|
unless s.abstract?
|
78
80
|
strategy = s.new(request, params)
|
79
81
|
user = strategy.run!
|
80
82
|
if strategy.halted?
|
81
|
-
self.headers
|
82
|
-
self.status = strategy.status
|
83
|
-
self.body = strategy.body
|
83
|
+
self.headers, self.status, self.body = [strategy.headers, strategy.status, strategy.body]
|
84
84
|
halt!
|
85
85
|
return
|
86
86
|
end
|
87
87
|
user
|
88
88
|
end
|
89
89
|
end
|
90
|
+
# Check after callbacks to make sure the user is still cool
|
91
|
+
Merb::Authentication.after_callbacks.each do |cb|
|
92
|
+
user = case cb
|
93
|
+
when Proc
|
94
|
+
cb.call(user, request, params)
|
95
|
+
when Symbol, String
|
96
|
+
user.send(cb)
|
97
|
+
end
|
98
|
+
break unless user
|
99
|
+
end if user
|
100
|
+
|
101
|
+
# Finally, Raise an error if there is no user found, or set it in the session if there is.
|
90
102
|
raise Merb::Controller::Unauthenticated, msg unless user
|
91
103
|
self.user = user
|
92
104
|
end
|
@@ -126,5 +138,25 @@ module Merb
|
|
126
138
|
def fetch_user(session_contents = session[:user])
|
127
139
|
raise NotImplemented
|
128
140
|
end
|
141
|
+
|
142
|
+
# Keeps track of strategies by class or string
|
143
|
+
# When loading from string, strategies are loaded withing the Merb::Authentication::Strategies namespace
|
144
|
+
# When loaded by class, the class is stored directly
|
145
|
+
def self.lookup_strategy
|
146
|
+
@strategy_lookup || reset_strategy_lookup!
|
147
|
+
end
|
148
|
+
|
149
|
+
# Restets the strategy lookup. Useful in specsd
|
150
|
+
def self.reset_strategy_lookup!
|
151
|
+
@strategy_lookup = Mash.new do |h,k|
|
152
|
+
case k
|
153
|
+
when Class
|
154
|
+
h[k] = k
|
155
|
+
when String, Symbol
|
156
|
+
h[k] = Merb::Authentication::Strategies.full_const_get(k.to_s)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
129
161
|
end # Merb::Authentication
|
130
162
|
end # Merb
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Merb
|
2
|
+
class Authentication
|
3
|
+
cattr_accessor :after_callbacks
|
4
|
+
@@after_callbacks = []
|
5
|
+
|
6
|
+
# Use the after_authentication callbacks to setup things that should occur after the
|
7
|
+
# user is authenticated.
|
8
|
+
#
|
9
|
+
# Pass in symbols, procs and or a block to the method to setup the callbacks.
|
10
|
+
# Callbacks are executed in the order they are added.
|
11
|
+
#
|
12
|
+
# @params
|
13
|
+
# <*callbacks:[Symbol|Proc]> The callback.. Symbol == method on the user object
|
14
|
+
# Proc will be passed the user, request and param objects
|
15
|
+
# <&block> A block to check. The user, request and params will be passed into the block
|
16
|
+
#
|
17
|
+
# To confirm that the user is still eligable to login, simply return the user from
|
18
|
+
# the method or block. To stop the user from being authenticated return false or nil
|
19
|
+
#
|
20
|
+
# ====Example
|
21
|
+
#
|
22
|
+
# Merb::Authentication.after_authentication do |user,request,params|
|
23
|
+
# user.active? ? user : nil
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
|
28
|
+
def self.after_authentication(*callbacks, &block)
|
29
|
+
self.after_callbacks = after_callbacks + callbacks.flatten unless callbacks.blank?
|
30
|
+
after_callbacks << block if block_given?
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -1,5 +1,25 @@
|
|
1
1
|
Merb::Router.extensions do
|
2
|
-
|
2
|
+
# Use this method in your router to ensure that the user is authenticated
|
3
|
+
#
|
4
|
+
# This will run through any strategies that you have setup, or that you declare
|
5
|
+
# as an argument to the authenticate method.
|
6
|
+
#
|
7
|
+
# ===Example
|
8
|
+
#
|
9
|
+
# authenticate(OpenID) do
|
10
|
+
# resource :posts
|
11
|
+
#
|
12
|
+
# authenticate do
|
13
|
+
# match("/").to(:controller => "home")
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# This is a simple example that shows protecting the entire set of routes for
|
18
|
+
# the posts resource with the OpenID strategy.
|
19
|
+
#
|
20
|
+
# The match on "/" is protected, _first_ by the OpenID strategy,
|
21
|
+
# then by the dfeeault set of stratgies. Strategies are applied from the
|
22
|
+
# outer block first, working to the inner blocks.
|
3
23
|
def authenticate(*strategies, &block)
|
4
24
|
p = Proc.new do |request, params|
|
5
25
|
if request.session.authenticated?
|
@@ -1,57 +1,45 @@
|
|
1
1
|
module Merb
|
2
2
|
module Session
|
3
|
+
|
4
|
+
# Access to the authentication object directly. Particularly useful
|
5
|
+
# for accessing the errors.
|
6
|
+
#
|
7
|
+
# === Example
|
8
|
+
#
|
9
|
+
# <%= error_messages_for session.authentication %>
|
10
|
+
#
|
11
|
+
def authentication
|
12
|
+
@authentication ||= Merb::Authentication.new(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Check to see if the current session is authenticated
|
16
|
+
# @return true if authenticated. false otherwise
|
17
|
+
def authenticated?
|
18
|
+
authentication.authenticated?
|
19
|
+
end
|
3
20
|
|
4
|
-
|
5
|
-
|
6
|
-
|
21
|
+
# Authenticates the session via the authentication object.
|
22
|
+
#
|
23
|
+
# See Merb::Authentication#authenticate for usage
|
24
|
+
def authenticate!(request, params, *rest)
|
25
|
+
authentication.authenticate!(request, params, *rest)
|
7
26
|
end
|
8
27
|
|
9
|
-
|
10
|
-
|
28
|
+
# Provides access to the currently authenticated user.
|
29
|
+
def user
|
30
|
+
authentication.user
|
31
|
+
end
|
11
32
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@authentication ||= Merb::Authentication.new(self)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Check to see if the current session is authenticated
|
26
|
-
# @return true if authenticated. false otherwise
|
27
|
-
def authenticated?
|
28
|
-
authentication.authenticated?
|
29
|
-
end
|
30
|
-
|
31
|
-
# Authenticates the session via the authentication object.
|
32
|
-
#
|
33
|
-
# See Merb::Authentication#authenticate for usage
|
34
|
-
def authenticate!(request, params, *rest)
|
35
|
-
authentication.authenticate!(request, params, *rest)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Provides access to the currently authenticated user.
|
39
|
-
def user
|
40
|
-
authentication.user
|
41
|
-
end
|
42
|
-
|
43
|
-
# set the currently authenticated user manually
|
44
|
-
# Merb::Authentication#store_user should know how to store the object into the session
|
45
|
-
def user=(the_user)
|
46
|
-
authentication.user = the_user
|
47
|
-
end
|
48
|
-
|
49
|
-
# Remove the user from the session and clear all data.
|
50
|
-
def abandon!
|
51
|
-
authentication.abandon!
|
52
|
-
end
|
53
|
-
|
54
|
-
end # InstanceMethods
|
33
|
+
# set the currently authenticated user manually
|
34
|
+
# Merb::Authentication#store_user should know how to store the object into the session
|
35
|
+
def user=(the_user)
|
36
|
+
authentication.user = the_user
|
37
|
+
end
|
38
|
+
|
39
|
+
# Remove the user from the session and clear all data.
|
40
|
+
def abandon!
|
41
|
+
authentication.abandon!
|
42
|
+
end
|
55
43
|
|
56
44
|
end # Session
|
57
45
|
end # Merb
|
data/lib/merb-auth-core.rb
CHANGED
@@ -11,6 +11,7 @@ require 'merb-auth-core/authenticated_helper'
|
|
11
11
|
require 'merb-auth-core/customizations'
|
12
12
|
require 'merb-auth-core/bootloader'
|
13
13
|
require 'merb-auth-core/router_helper'
|
14
|
+
require 'merb-auth-core/callbacks'
|
14
15
|
|
15
16
|
Merb::BootLoader.before_app_loads do
|
16
17
|
# require code that must be loaded before the application
|
@@ -23,4 +24,4 @@ end
|
|
23
24
|
|
24
25
|
Merb::Plugins.add_rakefiles "merb-auth-core/merbtasks"
|
25
26
|
|
26
|
-
Merb.push_path(:lib_authentication, Merb.
|
27
|
+
Merb.push_path(:lib_authentication, Merb.root_path("merb" / "merb-auth"), "*.rb" )
|
@@ -226,6 +226,41 @@ describe "Merb::Authentication Session" do
|
|
226
226
|
Viking.captures.should == ["Stwo", "Sone"]
|
227
227
|
end
|
228
228
|
|
229
|
+
|
230
|
+
describe "Strategy loading as strings" do
|
231
|
+
|
232
|
+
before :each do
|
233
|
+
Merb::Authentication.reset_strategy_lookup!
|
234
|
+
|
235
|
+
class Merb::Authentication::Strategies::Zone < Merb::Authentication::Strategy
|
236
|
+
def run!
|
237
|
+
Viking.capture(Merb::Authentication::Strategies::Zone)
|
238
|
+
params[:z_one]
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should allow for loading the strategies as strings" do
|
244
|
+
@request.params[:z_one] = "z_one"
|
245
|
+
@request.session.authenticate!(@request, @request.params, "Zone")
|
246
|
+
@request.session.user.should == "z_one"
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should raise a const misisng error when the error is not namespaced" do
|
250
|
+
@request.params[:pass_1] = "s_one"
|
251
|
+
lambda do
|
252
|
+
@request.session.authenticate!(@request, @request.params, "Sone")
|
253
|
+
end.should raise_error(NameError)
|
254
|
+
end
|
255
|
+
|
256
|
+
|
257
|
+
it "should allow a mix of strategies as strings or classes" do
|
258
|
+
@request.params[:pass_2] = "s_two"
|
259
|
+
@request.session.authenticate!(@request, @request.params, "Zone", Sone, Stwo)
|
260
|
+
Viking.captures.should == %w(Merb::Authentication::Strategies::Zone Sone Stwo)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
229
264
|
end
|
230
265
|
|
231
266
|
describe "user_class" do
|
@@ -315,4 +350,5 @@ describe "Merb::Authentication Session" do
|
|
315
350
|
|
316
351
|
|
317
352
|
|
353
|
+
|
318
354
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", 'spec_helper.rb')
|
2
|
+
|
3
|
+
describe "Authentication callbacks" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Merb::Authentication.after_callbacks.clear
|
7
|
+
clear_strategies!
|
8
|
+
Viking.captures.clear
|
9
|
+
|
10
|
+
# A basic user model that has some simple methods
|
11
|
+
# to set and aknowlege that it's been called
|
12
|
+
class AUser
|
13
|
+
attr_accessor :active, :name
|
14
|
+
|
15
|
+
def initialize(params)
|
16
|
+
params.each do |k,v|
|
17
|
+
instance_variable_set("@#{k}", v)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def acknowledge(value)
|
22
|
+
Viking.capture(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def acknowledge!(value = "default acknowledge")
|
26
|
+
throw(:acknowledged, value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def method_missing(name, *args)
|
30
|
+
if /(.*?)\?$/ =~ name.to_s
|
31
|
+
!!instance_variable_get("@#{$1}")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Create a strategy to test the after stuff
|
37
|
+
class MyStrategy < Merb::Authentication::Strategy
|
38
|
+
def run!
|
39
|
+
AUser.new(request.params[:user] || {}) unless request.params[:no_user]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
@request = fake_request
|
44
|
+
@params = @request.params
|
45
|
+
@auth = Merb::Authentication.new(@request.session)
|
46
|
+
puts Merb::Authentication.strategies.inspect
|
47
|
+
end
|
48
|
+
|
49
|
+
after(:all) do
|
50
|
+
clear_strategies!
|
51
|
+
Merb::Authentication.after_callbacks.clear
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should allow you to setup a callback as a block" do
|
55
|
+
Merb::Authentication.after_authentication{ |user, request, params| user.acknowledge!("w00t threw it") }
|
56
|
+
result = catch(:acknowledged) do
|
57
|
+
@request.session.authenticate!(@request, @params)
|
58
|
+
end
|
59
|
+
result.should == "w00t threw it"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should allow you to setup a callback as a method" do
|
63
|
+
Merb::Authentication.after_authentication(:acknowledge!)
|
64
|
+
result = catch(:acknowledged) do
|
65
|
+
result = @request.session.authenticate!(@request,@params)
|
66
|
+
end
|
67
|
+
result.should == "default acknowledge"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should allow many callbacks to be setup and executed" do
|
71
|
+
Merb::Authentication.after_authentication{|u,r,p| u.acknowledge("first"); u}
|
72
|
+
Merb::Authentication.after_authentication{|u,r,p| u.acknowledge("second"); u}
|
73
|
+
@request.session.authenticate!(@request, @params)
|
74
|
+
Viking.captures.should == %w(first second)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should stop processing if the user is not returned from the callback" do
|
78
|
+
Merb::Authentication.after_authentication{|u,r,p| u.acknowledge("first"); nil}
|
79
|
+
Merb::Authentication.after_authentication{|u,r,p| u.acknowledge("second"); u}
|
80
|
+
lambda do
|
81
|
+
@request.session.authenticate!(@request,@params)
|
82
|
+
end.should raise_error(Merb::Controller::Unauthenticated)
|
83
|
+
Viking.captures.should == ["first"]
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should raise an Unauthenticated if a callback returns nil" do
|
87
|
+
Merb::Authentication.after_authentication{|u,r,p| nil }
|
88
|
+
lambda do
|
89
|
+
@request.session.authenticate!(@request,@params)
|
90
|
+
end.should raise_error(Merb::Controller::Unauthenticated)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should not try to process the callbacks when no user is found" do
|
94
|
+
Merb::Authentication.after_authentication{|u,r,p| u.acknowledge("first"); u}
|
95
|
+
Merb::Authentication.after_authentication{|u,r,p| u.acknowledge("second"); u}
|
96
|
+
@request.params[:no_user] = true
|
97
|
+
lambda do
|
98
|
+
@request.session.authenticate!(@request,@params)
|
99
|
+
end.should raise_error(Merb::Controller::Unauthenticated)
|
100
|
+
Viking.captures.should be_empty
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -33,7 +33,7 @@ Spec::Runner.configure do |config|
|
|
33
33
|
config.include(StrategyHelper)
|
34
34
|
end
|
35
35
|
|
36
|
-
class Exceptions <
|
36
|
+
class Exceptions < Merb::Controller
|
37
37
|
def unauthenticated
|
38
38
|
session.abandon!
|
39
39
|
"Login please"
|
@@ -88,6 +88,11 @@ class Viking
|
|
88
88
|
|
89
89
|
def self.capture(klass)
|
90
90
|
@captures ||= []
|
91
|
-
|
91
|
+
case klass
|
92
|
+
when Class
|
93
|
+
@captures << klass.name
|
94
|
+
else
|
95
|
+
@captures << klass
|
96
|
+
end
|
92
97
|
end
|
93
98
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: merb-auth-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam French, Daniel Neighman
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-10-
|
12
|
+
date: 2008-10-21 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.9.
|
23
|
+
version: 0.9.10
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: extlib
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- lib/merb-auth-core/authenticated_helper.rb
|
52
52
|
- lib/merb-auth-core/authentication.rb
|
53
53
|
- lib/merb-auth-core/bootloader.rb
|
54
|
+
- lib/merb-auth-core/callbacks.rb
|
54
55
|
- lib/merb-auth-core/customizations.rb
|
55
56
|
- lib/merb-auth-core/errors.rb
|
56
57
|
- lib/merb-auth-core/merbtasks.rb
|
@@ -64,6 +65,7 @@ files:
|
|
64
65
|
- spec/merb-auth-core
|
65
66
|
- spec/merb-auth-core/activation_fixture.rb
|
66
67
|
- spec/merb-auth-core/authentication_spec.rb
|
68
|
+
- spec/merb-auth-core/callbacks_spec.rb
|
67
69
|
- spec/merb-auth-core/customizations_spec.rb
|
68
70
|
- spec/merb-auth-core/errors_spec.rb
|
69
71
|
- spec/merb-auth-core/merb-auth-core_spec.rb
|
@@ -92,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
94
|
requirements: []
|
93
95
|
|
94
96
|
rubyforge_project: merb
|
95
|
-
rubygems_version: 1.
|
97
|
+
rubygems_version: 1.3.0
|
96
98
|
signing_key:
|
97
99
|
specification_version: 2
|
98
100
|
summary: An Authentication framework for Merb
|