merb-auth-core 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/merb-auth-core.rb +1 -1
- data/lib/merb-auth-core/authenticated_helper.rb +12 -12
- data/lib/merb-auth-core/authentication.rb +35 -35
- data/lib/merb-auth-core/bootloader.rb +2 -2
- data/lib/merb-auth-core/callbacks.rb +6 -6
- data/lib/merb-auth-core/customizations.rb +5 -5
- data/lib/merb-auth-core/errors.rb +1 -1
- data/lib/merb-auth-core/responses.rb +8 -8
- data/lib/merb-auth-core/router_helper.rb +6 -6
- data/lib/merb-auth-core/session_mixin.rb +10 -10
- data/lib/merb-auth-core/strategy.rb +37 -37
- data/lib/merb-auth-core/version.rb +1 -1
- data/spec/helpers/authentication_helper_spec.rb +22 -22
- data/spec/merb-auth-core/authentication_spec.rb +66 -66
- data/spec/merb-auth-core/callbacks_spec.rb +16 -16
- data/spec/merb-auth-core/customizations_spec.rb +5 -5
- data/spec/merb-auth-core/errors_spec.rb +9 -9
- data/spec/merb-auth-core/failed_login_spec.rb +16 -16
- data/spec/merb-auth-core/merb-auth-core_spec.rb +1 -1
- data/spec/merb-auth-core/router_helper_spec.rb +23 -23
- data/spec/merb-auth-core/strategy_spec.rb +54 -54
- data/spec/spec_helper.rb +7 -7
- metadata +14 -6
data/Rakefile
CHANGED
@@ -27,7 +27,7 @@ begin
|
|
27
27
|
gemspec.files = %w(LICENSE Rakefile README.textile TODO) + Dir['{lib,spec}/**/*']
|
28
28
|
|
29
29
|
# Runtime dependencies
|
30
|
-
gemspec.add_dependency 'merb-core',
|
30
|
+
gemspec.add_dependency 'merb-core', '~> 1.1'
|
31
31
|
|
32
32
|
# Development dependencies
|
33
33
|
gemspec.add_development_dependency 'rspec', ">= 1.2.9"
|
data/lib/merb-auth-core.rb
CHANGED
@@ -12,7 +12,7 @@ require "merb-auth-core/router_helper"
|
|
12
12
|
require "merb-auth-core/callbacks"
|
13
13
|
|
14
14
|
Merb::BootLoader.before_app_loads do
|
15
|
-
# require code that must be loaded before the application
|
15
|
+
# require code that must be loaded before the application
|
16
16
|
Merb::Controller.send(:include, Merb::AuthenticatedHelper)
|
17
17
|
end
|
18
18
|
|
@@ -1,33 +1,33 @@
|
|
1
1
|
module Merb
|
2
2
|
class Controller::Unauthenticated < ControllerExceptions::Unauthorized; end
|
3
|
-
|
4
|
-
module AuthenticatedHelper
|
3
|
+
|
4
|
+
module AuthenticatedHelper
|
5
5
|
protected
|
6
6
|
# This is the main method to use as a before filter. You can call it with options
|
7
7
|
# and strategies to use. It will check if a user is logged in, and failing that
|
8
|
-
# will run through either specified.
|
9
|
-
#
|
10
|
-
# @params all are optional. A list of strategies, optionally followed by a
|
11
|
-
# options hash.
|
8
|
+
# will run through either specified.
|
9
|
+
#
|
10
|
+
# @params all are optional. A list of strategies, optionally followed by a
|
11
|
+
# options hash.
|
12
12
|
#
|
13
13
|
# If used with no options, or only the hash, the default strategies will be used
|
14
|
-
# see Authentictaion.default_strategy_order.
|
14
|
+
# see Authentictaion.default_strategy_order.
|
15
15
|
#
|
16
16
|
# If a list of strategies is passed in, the default strategies are ignored, and
|
17
|
-
# the passed in strategies are used in order until either one is found, or all fail.
|
17
|
+
# the passed in strategies are used in order until either one is found, or all fail.
|
18
18
|
#
|
19
|
-
# A failed login will result in an Unauthenticated exception being raised.
|
19
|
+
# A failed login will result in an Unauthenticated exception being raised.
|
20
20
|
#
|
21
21
|
# Use the :message key in the options hash to pass in a failure message to the
|
22
22
|
# exception.
|
23
|
-
#
|
23
|
+
#
|
24
24
|
# === Example
|
25
25
|
#
|
26
26
|
# class MyController < Application
|
27
27
|
# before :ensure_authenticated, :with => [OpenID,FormPassword, :message => "Failz!"]
|
28
28
|
# #... <snip>
|
29
29
|
# end
|
30
|
-
#
|
30
|
+
#
|
31
31
|
def ensure_authenticated(*strategies)
|
32
32
|
session.authenticate!(request, params, *strategies) unless session.authenticated?
|
33
33
|
auth = session.authentication
|
@@ -37,6 +37,6 @@ module Merb
|
|
37
37
|
throw :halt, auth.body
|
38
38
|
end
|
39
39
|
session.user
|
40
|
-
end
|
40
|
+
end
|
41
41
|
end
|
42
42
|
end
|
@@ -4,11 +4,11 @@ module Merb
|
|
4
4
|
include Extlib::Hook
|
5
5
|
attr_accessor :session
|
6
6
|
attr_writer :error_message
|
7
|
-
|
7
|
+
|
8
8
|
class DuplicateStrategy < Exception; end
|
9
9
|
class MissingStrategy < Exception; end
|
10
10
|
class NotImplemented < Exception; end
|
11
|
-
|
11
|
+
|
12
12
|
# This method returns the default user class to use throughout the
|
13
13
|
# merb-auth authentication framework. Merb::Authentication.user_class can
|
14
14
|
# be used by other plugins, and by default by strategies.
|
@@ -20,40 +20,40 @@ module Merb
|
|
20
20
|
#
|
21
21
|
# @api overwritable
|
22
22
|
cattr_accessor :user_class
|
23
|
-
|
23
|
+
|
24
24
|
def initialize(session)
|
25
25
|
@session = session
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
# Returns true if there is an authenticated user attached to this session
|
29
29
|
#
|
30
30
|
# @return <TrueClass|FalseClass>
|
31
|
-
#
|
31
|
+
#
|
32
32
|
def authenticated?
|
33
33
|
!!session[:user]
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# This method will retrieve the user object stored in the session or nil if there
|
37
37
|
# is no user logged in.
|
38
|
-
#
|
38
|
+
#
|
39
39
|
# @return <User class>|NilClass
|
40
40
|
def user
|
41
41
|
return nil if !session[:user]
|
42
42
|
@user ||= fetch_user(session[:user])
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# This method will store the user provided into the session
|
46
46
|
# and set the user as the currently logged in user
|
47
47
|
# @return <User Class>|NilClass
|
48
48
|
def user=(user)
|
49
49
|
session[:user] = nil && return if user.nil?
|
50
50
|
session[:user] = store_user(user)
|
51
|
-
@user = session[:user] ? user : session[:user]
|
51
|
+
@user = session[:user] ? user : session[:user]
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# The workhorse of the framework. The authentiate! method is where
|
55
55
|
# the work is done. authenticate! will try each strategy in order
|
56
|
-
# either passed in, or in the default_strategy_order.
|
56
|
+
# either passed in, or in the default_strategy_order.
|
57
57
|
#
|
58
58
|
# If a strategy returns some kind of user object, this will be stored
|
59
59
|
# in the session, otherwise a Merb::Controller::Unauthenticated exception is raised
|
@@ -61,7 +61,7 @@ module Merb
|
|
61
61
|
# @params Merb::Request, [List,Of,Strategies, optional_options_hash]
|
62
62
|
#
|
63
63
|
# Pass in a list of strategy objects to have this list take precedence over the normal defaults
|
64
|
-
#
|
64
|
+
#
|
65
65
|
# Use an options hash to provide an error message to be passed into the exception.
|
66
66
|
#
|
67
67
|
# @return user object of the verified user. An exception is raised if no user is found
|
@@ -69,9 +69,9 @@ module Merb
|
|
69
69
|
def authenticate!(request, params, *rest)
|
70
70
|
opts = rest.last.kind_of?(Hash) ? rest.pop : {}
|
71
71
|
rest = rest.flatten
|
72
|
-
|
72
|
+
|
73
73
|
strategies = if rest.empty?
|
74
|
-
if request.session[:authentication_strategies]
|
74
|
+
if request.session[:authentication_strategies]
|
75
75
|
request.session[:authentication_strategies]
|
76
76
|
else
|
77
77
|
Merb::Authentication.default_strategy_order
|
@@ -82,15 +82,15 @@ module Merb
|
|
82
82
|
request.session[:authentication_strategies].flatten!.uniq!
|
83
83
|
request.session[:authentication_strategies]
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
msg = opts[:message] || error_message
|
87
|
-
user = nil
|
87
|
+
user = nil
|
88
88
|
# This one should find the first one that matches. It should not run antother
|
89
89
|
strategies.detect do |s|
|
90
90
|
s = Merb::Authentication.lookup_strategy[s] # Get the strategy from string or class
|
91
91
|
unless s.abstract?
|
92
92
|
strategy = s.new(request, params)
|
93
|
-
user = strategy.run!
|
93
|
+
user = strategy.run!
|
94
94
|
if strategy.halted?
|
95
95
|
self.headers, self.status, self.body = [strategy.headers, strategy.status, strategy.body]
|
96
96
|
halt!
|
@@ -99,26 +99,26 @@ module Merb
|
|
99
99
|
user
|
100
100
|
end
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
# Check after callbacks to make sure the user is still cool
|
104
104
|
user = run_after_authentication_callbacks(user, request, params) if user
|
105
|
-
|
105
|
+
|
106
106
|
# Finally, Raise an error if there is no user found, or set it in the session if there is.
|
107
107
|
raise Merb::Controller::Unauthenticated, msg unless user
|
108
|
-
session[:authentication_strategies] = nil # clear the session of Failed Strategies if login is successful
|
108
|
+
session[:authentication_strategies] = nil # clear the session of Failed Strategies if login is successful
|
109
109
|
self.user = user
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
112
|
# "Logs Out" a user from the session. Also clears out all session data
|
113
113
|
def abandon!
|
114
114
|
@user = nil
|
115
115
|
session.clear
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
# A simple error message mechanism to provide general information. For more specific information
|
119
119
|
#
|
120
120
|
# This message is the default message passed to the Merb::Controller::Unauthenticated exception
|
121
|
-
# during authentication.
|
121
|
+
# during authentication.
|
122
122
|
#
|
123
123
|
# This is a very simple mechanism for error messages. For more detailed control see Authenticaiton#errors
|
124
124
|
#
|
@@ -126,16 +126,16 @@ module Merb
|
|
126
126
|
def error_message
|
127
127
|
@error_message || "Could not log in"
|
128
128
|
end
|
129
|
-
|
130
|
-
# Tells the framework how to store your user object into the session so that it can be re-created
|
131
|
-
# on the next login.
|
129
|
+
|
130
|
+
# Tells the framework how to store your user object into the session so that it can be re-created
|
131
|
+
# on the next login.
|
132
132
|
# You must overwrite this method for use in your projects. Slices and plugins may set this.
|
133
133
|
#
|
134
134
|
# @api overwritable
|
135
135
|
def store_user(user)
|
136
136
|
raise NotImplemented
|
137
137
|
end
|
138
|
-
|
138
|
+
|
139
139
|
# Tells the framework how to reconstitute a user from the data stored by store_user.
|
140
140
|
#
|
141
141
|
# You must overwrite this method for user in your projects. Slices and plugins may set this.
|
@@ -144,7 +144,7 @@ module Merb
|
|
144
144
|
def fetch_user(session_contents = session[:user])
|
145
145
|
raise NotImplemented
|
146
146
|
end
|
147
|
-
|
147
|
+
|
148
148
|
# Keeps track of strategies by class or string
|
149
149
|
# When loading from string, strategies are loaded withing the Merb::Authentication::Strategies namespace
|
150
150
|
# When loaded by class, the class is stored directly
|
@@ -152,26 +152,26 @@ module Merb
|
|
152
152
|
def self.lookup_strategy
|
153
153
|
@strategy_lookup || reset_strategy_lookup!
|
154
154
|
end
|
155
|
-
|
155
|
+
|
156
156
|
# Restets the strategy lookup. Useful in specs
|
157
157
|
def self.reset_strategy_lookup!
|
158
|
-
@strategy_lookup = Mash.new do |h,k|
|
158
|
+
@strategy_lookup = Mash.new do |h,k|
|
159
159
|
case k
|
160
160
|
when Class
|
161
161
|
h[k] = k
|
162
162
|
when String, Symbol
|
163
|
-
h[k] = Merb::Authentication::Strategies.full_const_get(k.to_s)
|
163
|
+
h[k] = Merb::Authentication::Strategies.full_const_get(k.to_s)
|
164
164
|
end
|
165
165
|
end
|
166
166
|
end
|
167
|
-
|
168
|
-
# Maintains a list of keys to maintain when needing to keep some state
|
167
|
+
|
168
|
+
# Maintains a list of keys to maintain when needing to keep some state
|
169
169
|
# in the face of session.abandon! You need to maintain this state yourself
|
170
170
|
# @public
|
171
171
|
def self.maintain_session_keys
|
172
172
|
@maintain_session_keys ||= [:authentication_strategies]
|
173
173
|
end
|
174
|
-
|
174
|
+
|
175
175
|
private
|
176
176
|
def run_after_authentication_callbacks(user, request, params)
|
177
177
|
Merb::Authentication.after_callbacks.each do |cb|
|
@@ -185,6 +185,6 @@ module Merb
|
|
185
185
|
end
|
186
186
|
user
|
187
187
|
end
|
188
|
-
|
188
|
+
|
189
189
|
end # Merb::Authentication
|
190
190
|
end # Merb
|
@@ -2,14 +2,14 @@ module Merb
|
|
2
2
|
class Authentication
|
3
3
|
cattr_accessor :after_callbacks
|
4
4
|
@@after_callbacks = []
|
5
|
-
|
5
|
+
|
6
6
|
# Use the after_authentication callbacks to setup things that should occur after the
|
7
|
-
# user is authenticated.
|
7
|
+
# user is authenticated.
|
8
8
|
#
|
9
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.
|
10
|
+
# Callbacks are executed in the order they are added.
|
11
11
|
#
|
12
|
-
# @params
|
12
|
+
# @params
|
13
13
|
# <*callbacks:[Symbol|Proc]> The callback.. Symbol == method on the user object
|
14
14
|
# Proc will be passed the user, request and param objects
|
15
15
|
# <&block> A block to check. The user, request and params will be passed into the block
|
@@ -24,11 +24,11 @@ module Merb
|
|
24
24
|
# end
|
25
25
|
#
|
26
26
|
# @api public
|
27
|
-
|
27
|
+
|
28
28
|
def self.after_authentication(*callbacks, &block)
|
29
29
|
self.after_callbacks = after_callbacks + callbacks.flatten unless callbacks.blank?
|
30
30
|
after_callbacks << block if block_given?
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
end
|
34
34
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Merb
|
2
2
|
class Authentication
|
3
|
-
|
3
|
+
|
4
4
|
class << self
|
5
|
-
|
5
|
+
|
6
6
|
# Adds any customizations just before the after_app_loads boot loader
|
7
7
|
# so that plugins can offer default customization. This will still allow
|
8
8
|
# for a user to overwrite any customizations if required in the after_app_loads
|
@@ -12,13 +12,13 @@ module Merb
|
|
12
12
|
default_customizations << block
|
13
13
|
default_customizations
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
# Gets the list of declared customizations
|
17
17
|
def default_customizations
|
18
18
|
@custom_default_blocks ||= []
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
end # Merb::Authentication
|
24
24
|
end # Merb
|
@@ -2,35 +2,35 @@ module Merb
|
|
2
2
|
# These are not intended to be used directly
|
3
3
|
class Authentication
|
4
4
|
attr_accessor :body
|
5
|
-
|
5
|
+
|
6
6
|
def redirected?
|
7
7
|
!!headers["Location"]
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def headers
|
11
11
|
@headers ||= {}
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def status
|
15
15
|
@status ||= 200
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def status=(sts)
|
19
19
|
@status = sts
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def halted?
|
23
23
|
!!@halt
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def headers=(headers)
|
27
27
|
raise ArgumentError, "Need to supply a hash to headers. Got #{headers.class}" unless headers.kind_of?(Hash)
|
28
28
|
@headers = headers
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def halt!
|
32
32
|
@halt = true
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
end # Merb::Authentication
|
36
36
|
end # Merb
|
@@ -5,17 +5,17 @@ Merb::Router.extensions do
|
|
5
5
|
# as an argument to the authenticate method.
|
6
6
|
#
|
7
7
|
# ===Example
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# authenticate(OpenID) do
|
10
10
|
# resource :posts
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# authenticate do
|
13
13
|
# match("/").to(:controller => "home")
|
14
14
|
# end
|
15
15
|
# end
|
16
|
-
#
|
16
|
+
#
|
17
17
|
# This is a simple example that shows protecting the entire set of routes for
|
18
|
-
# the posts resource with the OpenID strategy.
|
18
|
+
# the posts resource with the OpenID strategy.
|
19
19
|
#
|
20
20
|
# The match on "/" is protected, _first_ by the OpenID strategy,
|
21
21
|
# then by the dfeeault set of stratgies. Strategies are applied from the
|
@@ -30,7 +30,7 @@ Merb::Router.extensions do
|
|
30
30
|
else
|
31
31
|
result = request.session.authenticate!(request, params, *strategies)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
if request.session.authentication.halted?
|
35
35
|
auth = request.session.authentication
|
36
36
|
[auth.status, auth.headers, auth.body]
|
@@ -41,5 +41,5 @@ Merb::Router.extensions do
|
|
41
41
|
end
|
42
42
|
defer(p, &block)
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
end
|
@@ -1,45 +1,45 @@
|
|
1
1
|
module Merb
|
2
2
|
module Session
|
3
|
-
|
3
|
+
|
4
4
|
# Access to the authentication object directly. Particularly useful
|
5
5
|
# for accessing the errors.
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# === Example
|
8
8
|
#
|
9
9
|
# <%= error_messages_for session.authentication %>
|
10
|
-
#
|
10
|
+
#
|
11
11
|
def authentication
|
12
12
|
@authentication ||= Merb::Authentication.new(self)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
# Check to see if the current session is authenticated
|
16
16
|
# @return true if authenticated. false otherwise
|
17
17
|
def authenticated?
|
18
18
|
authentication.authenticated?
|
19
19
|
end
|
20
|
-
|
21
|
-
# Authenticates the session via the authentication object.
|
20
|
+
|
21
|
+
# Authenticates the session via the authentication object.
|
22
22
|
#
|
23
23
|
# See Merb::Authentication#authenticate for usage
|
24
24
|
def authenticate!(request, params, *rest)
|
25
25
|
authentication.authenticate!(request, params, *rest)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
# Provides access to the currently authenticated user.
|
29
29
|
def user
|
30
30
|
authentication.user
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# set the currently authenticated user manually
|
34
34
|
# Merb::Authentication#store_user should know how to store the object into the session
|
35
35
|
def user=(the_user)
|
36
36
|
authentication.user = the_user
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Remove the user from the session and clear all data.
|
40
40
|
def abandon!
|
41
41
|
authentication.abandon!
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
end # Session
|
45
45
|
end # Merb
|