merb-auth-core 0.9.9 → 0.9.10
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.
- 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
|