myobie-rails-auth 0.0.0

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.markdown ADDED
@@ -0,0 +1,41 @@
1
+ Note
2
+ ====
3
+
4
+ This is not anywhere near done. It's still using swaths of code just copied straight over from merb, and even some of that doesn't do anything yet.
5
+
6
+ About
7
+ =====
8
+
9
+ I am not satisfied with any of the current authentication strategies available for rails. I am sure Rails 3 will have something built in, but until then this is what I am going to use. I am spoiled from the way Merb does it, but even then I am not 100% happy with how it works.
10
+
11
+ Currently, this is untested and very much a copy of how merb does it.
12
+
13
+ All I really care about:
14
+
15
+ * Authenticate the session
16
+ * Authentication strategies
17
+ * Let me use my own model how I want
18
+ * Let me do my own controller how I want
19
+ * Be easy to setup (as an initializer)
20
+ * Don't do anything magical
21
+
22
+ I hate how all the authentication libraries hide model, controller, view methods from you down in the gem file. I also hate the generators that are impossible to use to update from one version to the next.
23
+
24
+ In my mind, the best way to solve this is to not have a ton of necessary methods on anything.
25
+
26
+ All you need
27
+ ============
28
+
29
+ 1. UserModel#authenticate
30
+ 2. Use `ensure_authenticated` in your controller to make sure they are logged in.
31
+ 3. rescue_from Rails::Authentication::Unauthenticated to catch when they are not logged in.
32
+ 4. Setup an initializer that sets the UserModel class, etc
33
+
34
+ Simple.
35
+
36
+ TODO
37
+ ====
38
+
39
+ * Tests
40
+ * Remove Mash
41
+ * Decide if the status, body, etc should be set by the authentication gem or not (right now it's kinda both)
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 0
3
+ :patch: 0
4
+ :major: 0
@@ -0,0 +1,23 @@
1
+ module Rails
2
+
3
+ class Authentication
4
+ class Unauthenticated < Exception; end
5
+ end
6
+
7
+ module AuthenticatedHelper
8
+
9
+ protected
10
+ def ensure_authenticated(*strategies)
11
+ session.authenticate!(request, params, *strategies) unless session.authenticated?
12
+ auth = session.authentication
13
+ if auth.halted?
14
+ response.headers.merge!(auth.headers)
15
+ response.status = auth.status
16
+ raise Rails::Authentication::Unauthenticated, auth.body
17
+ end
18
+ session.user
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,210 @@
1
+ module Rails
2
+ class Authentication
3
+ module Strategies; end
4
+
5
+ attr_accessor :session
6
+ attr_writer :error_message
7
+
8
+ class DuplicateStrategy < Exception; end
9
+ class MissingStrategy < Exception; end
10
+ class NotImplemented < Exception; end
11
+
12
+ # This method returns the default user class to use throughout the
13
+ # merb-auth authentication framework. Rails::Authentication.user_class can
14
+ # be used by other plugins, and by default by strategies.
15
+ #
16
+ # By Default it is set to User class. If you need a different class
17
+ # The intention is that you overwrite this method
18
+ #
19
+ # @return <User Class Object>
20
+ #
21
+ # @api overwritable
22
+ cattr_accessor :user_class
23
+
24
+
25
+ ### copied from restful authentication
26
+ cattr_accessor :login_regex, :bad_login_message, :name_regex, :bad_name_message, :email_name_regex, :domain_head_regex, :domain_tld_regex, :email_regex, :bad_email_message
27
+
28
+ self.login_regex = /\A\w[\w\.\-_@]+\z/ # ASCII, strict
29
+ # self.login_regex = /\A[[:alnum:]][[:alnum:]\.\-_@]+\z/ # Unicode, strict
30
+ # self.login_regex = /\A[^[:cntrl:]\\<>\/&]*\z/ # Unicode, permissive
31
+
32
+ self.bad_login_message = "use only letters, numbers, and .-_@ please.".freeze
33
+
34
+ self.name_regex = /\A[^[:cntrl:]\\<>\/&]*\z/ # Unicode, permissive
35
+ self.bad_name_message = "avoid non-printing characters and \\&gt;&lt;&amp;/ please.".freeze
36
+
37
+ self.email_name_regex = '[\w\.%\+\-]+'.freeze
38
+ self.domain_head_regex = '(?:[A-Z0-9\-]+\.)+'.freeze
39
+ self.domain_tld_regex = '(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)'.freeze
40
+ self.email_regex = /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
41
+ self.bad_email_message = "should look like an email address.".freeze
42
+
43
+ def self.load_helpers(file_name)
44
+ require 'rails-auth/helpers' / file_name.to_s
45
+ end
46
+
47
+ def initialize(session)
48
+ @session = session
49
+ end
50
+
51
+ # Returns true if there is an authenticated user attached to this session
52
+ #
53
+ # @return <TrueClass|FalseClass>
54
+ #
55
+ def authenticated?
56
+ !!session[:user]
57
+ end
58
+
59
+ # This method will retrieve the user object stored in the session or nil if there
60
+ # is no user logged in.
61
+ #
62
+ # @return <User class>|NilClass
63
+ def user
64
+ return nil if !session[:user]
65
+ @user ||= fetch_user(session[:user])
66
+ end
67
+
68
+ # This method will store the user provided into the session
69
+ # and set the user as the currently logged in user
70
+ # @return <User Class>|NilClass
71
+ def user=(user)
72
+ session[:user] = nil && return if user.nil?
73
+ session[:user] = store_user(user)
74
+ @user = session[:user] ? user : session[:user]
75
+ end
76
+
77
+ # The workhorse of the framework. The authentiate! method is where
78
+ # the work is done. authenticate! will try each strategy in order
79
+ # either passed in, or in the default_strategy_order.
80
+ #
81
+ # If a strategy returns some kind of user object, this will be stored
82
+ # in the session, otherwise a Rails::Controller::Unauthenticated exception is raised
83
+ #
84
+ # @params Rails::Request, [List,Of,Strategies, optional_options_hash]
85
+ #
86
+ # Pass in a list of strategy objects to have this list take precedence over the normal defaults
87
+ #
88
+ # Use an options hash to provide an error message to be passed into the exception.
89
+ #
90
+ # @return user object of the verified user. An exception is raised if no user is found
91
+ #
92
+ def authenticate!(request, params, *rest)
93
+ opts = rest.last.kind_of?(Hash) ? rest.pop : {}
94
+ rest = rest.flatten
95
+
96
+ strategies = if rest.empty?
97
+ if request.session[:authentication_strategies]
98
+ request.session[:authentication_strategies]
99
+ else
100
+ Rails::Authentication.default_strategy_order
101
+ end
102
+ else
103
+ request.session[:authentication_strategies] ||= []
104
+ request.session[:authentication_strategies] << rest
105
+ request.session[:authentication_strategies].flatten!.uniq!
106
+ request.session[:authentication_strategies]
107
+ end
108
+
109
+ msg = opts[:message] || error_message
110
+ user = nil
111
+ # This one should find the first one that matches. It should not run any other
112
+ strategies.detect do |s|
113
+ s = Rails::Authentication.lookup_strategy[s] # Get the strategy from string or class
114
+ unless s.abstract?
115
+ strategy = s.new(request, params)
116
+ user = strategy.run!
117
+ if strategy.halted?
118
+ self.headers, self.status, self.body = [strategy.headers, strategy.status, strategy.body]
119
+ halt!
120
+ return
121
+ end
122
+ user
123
+ end
124
+ end
125
+
126
+ # Finally, Raise an error if there is no user found, or set it in the session if there is.
127
+ raise Rails::Authentication::Unauthenticated, msg unless user
128
+ session[:authentication_strategies] = nil # clear the session of Failed Strategies if login is successful
129
+ self.user = user
130
+ end
131
+
132
+ # "Logs Out" a user from the session. Also clears out all session data
133
+ def abandon!
134
+ @user = nil
135
+ session.clear
136
+ end
137
+
138
+ # A simple error message mechanism to provide general information. For more specific information
139
+ #
140
+ # This message is the default message passed to the Rails::Controller::Unauthenticated exception
141
+ # during authentication.
142
+ #
143
+ # This is a very simple mechanism for error messages. For more detailed control see Authenticaiton#errors
144
+ #
145
+ # @api overwritable
146
+ def error_message
147
+ @error_message || "Could not log in"
148
+ end
149
+
150
+ # Tells the framework how to store your user object into the session so that it can be re-created
151
+ # on the next login.
152
+ # You must overwrite this method for use in your projects. Slices and plugins may set this.
153
+ #
154
+ # @api overwritable
155
+ def store_user(user)
156
+ raise NotImplemented
157
+ end
158
+
159
+ # Tells the framework how to reconstitute a user from the data stored by store_user.
160
+ #
161
+ # You must overwrite this method for user in your projects. Slices and plugins may set this.
162
+ #
163
+ # @api overwritable
164
+ def fetch_user(session_contents = session[:user])
165
+ raise NotImplemented
166
+ end
167
+
168
+ # Keeps track of strategies by class or string
169
+ # When loading from string, strategies are loaded withing the Rails::Authentication::Strategies namespace
170
+ # When loaded by class, the class is stored directly
171
+ # @private
172
+ def self.lookup_strategy
173
+ @strategy_lookup || reset_strategy_lookup!
174
+ end
175
+
176
+ # Restets the strategy lookup. Useful in specs
177
+ def self.reset_strategy_lookup!
178
+ @strategy_lookup = Mash.new do |h,k|
179
+ case k
180
+ when Class
181
+ h[k] = k
182
+ when String, Symbol
183
+ h[k] = Rails::Authentication::Strategies.full_const_get(k.to_s)
184
+ end
185
+ end
186
+ end
187
+
188
+ # Maintains a list of keys to maintain when needing to keep some state
189
+ # in the face of session.abandon! You need to maintain this state yourself
190
+ # @public
191
+ def self.maintain_session_keys
192
+ @maintain_session_keys ||= [:authentication_strategies, :return_to]
193
+ end
194
+
195
+ private
196
+ def run_after_authentication_callbacks(user, request, params)
197
+ Rails::Authentication.after_callbacks.each do |cb|
198
+ user = case cb
199
+ when Proc
200
+ cb.call(user, request, params)
201
+ when Symbol, String
202
+ user.send(cb)
203
+ end
204
+ break unless user
205
+ end
206
+ user
207
+ end
208
+ end
209
+
210
+ end
@@ -0,0 +1,13 @@
1
+ module Rails
2
+ class Authentication
3
+
4
+ cattr_accessor :after_callbacks
5
+ @@after_callbacks = []
6
+
7
+ def self.after_authentication(*callbacks, &block)
8
+ self.after_callbacks = after_callbacks + callbacks.flatten unless callbacks.blank?
9
+ after_callbacks << block if block_given?
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,66 @@
1
+ module Rails
2
+ class Authentication
3
+
4
+ def errors
5
+ @errors ||= Errors.new
6
+ end
7
+
8
+ # Lifted from DataMapper's dm-validations plugin :)
9
+ # @author Guy van den Berg
10
+ # @since DM 0.9
11
+ class Errors
12
+
13
+ include Enumerable
14
+
15
+ # Clear existing authentication errors.
16
+ def clear!
17
+ errors.clear
18
+ end
19
+
20
+ # Add a authentication error. Use the field_name :general if the errors does
21
+ # not apply to a specific field of the Resource.
22
+ #
23
+ # @param <Symbol> field_name the name of the field that caused the error
24
+ # @param <String> message the message to add
25
+ def add(field_name, message)
26
+ (errors[field_name] ||= []) << message
27
+ end
28
+
29
+ # Collect all errors into a single list.
30
+ def full_messages
31
+ errors.inject([]) do |list,pair|
32
+ list += pair.last
33
+ end
34
+ end
35
+
36
+ # Return authentication errors for a particular field_name.
37
+ #
38
+ # @param <Symbol> field_name the name of the field you want an error for
39
+ def on(field_name)
40
+ errors_for_field = errors[field_name]
41
+ errors_for_field.blank? ? nil : errors_for_field
42
+ end
43
+
44
+ def each
45
+ errors.map.each do |k,v|
46
+ next if v.blank?
47
+ yield(v)
48
+ end
49
+ end
50
+
51
+ def empty?
52
+ entries.empty?
53
+ end
54
+
55
+ def method_missing(meth, *args, &block)
56
+ errors.send(meth, *args, &block)
57
+ end
58
+
59
+ private
60
+ def errors
61
+ @errors ||= {}
62
+ end
63
+
64
+ end # class Errors
65
+ end # Authentication
66
+ end # Rails
@@ -0,0 +1,3 @@
1
+ %w(current_user logged_in redirect_back require_login_or).each do |file|
2
+ require 'rails-auth/helpers' / file
3
+ end
@@ -0,0 +1,20 @@
1
+ module Rails
2
+
3
+ module AuthenticatedControllerExtensions
4
+
5
+ def included(base)
6
+ base.send :helper_method, :current_user
7
+ base.send :helper_method, :current_user?
8
+ end
9
+
10
+ def current_user
11
+ session.user
12
+ end
13
+
14
+ def current_user?
15
+ !!current_user
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,15 @@
1
+ module Rails
2
+
3
+ module AuthenticatedControllerExtensions
4
+
5
+ def included(base)
6
+ base.send :helper_method, :logged_in?
7
+ end
8
+
9
+ def logged_in?
10
+ session.authenticated?
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,18 @@
1
+ module Rails
2
+ module AuthenticatedControllerExtensions
3
+
4
+ def redirect_back_or(default_url, opts = {})
5
+ if !session[:return_to].blank?
6
+ redirect_to session[:return_to], opts
7
+ session[:return_to] = nil
8
+ else
9
+ redirect_to default_url, opts
10
+ end
11
+ end
12
+
13
+ def set_return_to
14
+ session[:return_to] = request.path
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Rails
2
+
3
+ module AuthenticatedControllerExtensions
4
+
5
+ def require_login_or(flash_type = nil, flash_message = nil)
6
+ flash[flash_type] = flash_message unless flash_message.blank? || flash_type.blank? || session.authenticated?
7
+ ensure_authenticated
8
+ end
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,148 @@
1
+ # This class has dubious semantics and we only have it so that people can write
2
+ # params[:key] instead of params['key'].
3
+ class Mash < Hash
4
+
5
+ # @param constructor<Object>
6
+ # The default value for the mash. Defaults to an empty hash.
7
+ #
8
+ # @details [Alternatives]
9
+ # If constructor is a Hash, a new mash will be created based on the keys of
10
+ # the hash and no default value will be set.
11
+ def initialize(constructor = {})
12
+ if constructor.is_a?(Hash)
13
+ super()
14
+ update(constructor)
15
+ else
16
+ super(constructor)
17
+ end
18
+ end
19
+
20
+ # @param key<Object> The default value for the mash. Defaults to nil.
21
+ #
22
+ # @details [Alternatives]
23
+ # If key is a Symbol and it is a key in the mash, then the default value will
24
+ # be set to the value matching the key.
25
+ def default(key = nil)
26
+ if key.is_a?(Symbol) && include?(key = key.to_s)
27
+ self[key]
28
+ else
29
+ super
30
+ end
31
+ end
32
+
33
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
34
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
35
+
36
+ # @param key<Object> The key to set.
37
+ # @param value<Object>
38
+ # The value to set the key to.
39
+ #
40
+ # @see Mash#convert_key
41
+ # @see Mash#convert_value
42
+ def []=(key, value)
43
+ regular_writer(convert_key(key), convert_value(value))
44
+ end
45
+
46
+ # @param other_hash<Hash>
47
+ # A hash to update values in the mash with. The keys and the values will be
48
+ # converted to Mash format.
49
+ #
50
+ # @return <Mash> The updated mash.
51
+ def update(other_hash)
52
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
53
+ self
54
+ end
55
+
56
+ alias_method :merge!, :update
57
+
58
+ # @param key<Object> The key to check for. This will be run through convert_key.
59
+ #
60
+ # @return <TrueClass, FalseClass> True if the key exists in the mash.
61
+ def key?(key)
62
+ super(convert_key(key))
63
+ end
64
+
65
+ # def include? def has_key? def member?
66
+ alias_method :include?, :key?
67
+ alias_method :has_key?, :key?
68
+ alias_method :member?, :key?
69
+
70
+ # @param key<Object> The key to fetch. This will be run through convert_key.
71
+ # @param *extras<Array> Default value.
72
+ #
73
+ # @return <Object> The value at key or the default value.
74
+ def fetch(key, *extras)
75
+ super(convert_key(key), *extras)
76
+ end
77
+
78
+ # @param *indices<Array>
79
+ # The keys to retrieve values for. These will be run through +convert_key+.
80
+ #
81
+ # @return <Array> The values at each of the provided keys
82
+ def values_at(*indices)
83
+ indices.collect {|key| self[convert_key(key)]}
84
+ end
85
+
86
+ # @param hash<Hash> The hash to merge with the mash.
87
+ #
88
+ # @return <Mash> A new mash with the hash values merged in.
89
+ def merge(hash)
90
+ self.dup.update(hash)
91
+ end
92
+
93
+ # @param key<Object>
94
+ # The key to delete from the mash.\
95
+ def delete(key)
96
+ super(convert_key(key))
97
+ end
98
+
99
+ # @param *rejected<Array[(String, Symbol)] The mash keys to exclude.
100
+ #
101
+ # @return <Mash> A new mash without the selected keys.
102
+ #
103
+ # @example
104
+ # { :one => 1, :two => 2, :three => 3 }.except(:one)
105
+ # #=> { "two" => 2, "three" => 3 }
106
+ def except(*keys)
107
+ super(*keys.map {|k| convert_key(k)})
108
+ end
109
+
110
+ # Used to provide the same interface as Hash.
111
+ #
112
+ # @return <Mash> This mash unchanged.
113
+ def stringify_keys!; self end
114
+
115
+ # @return <Hash> The mash as a Hash with string keys.
116
+ def to_hash
117
+ Hash.new(default).merge(self)
118
+ end
119
+
120
+ protected
121
+ # @param key<Object> The key to convert.
122
+ #
123
+ # @param <Object>
124
+ # The converted key. If the key was a symbol, it will be converted to a
125
+ # string.
126
+ #
127
+ # @api private
128
+ def convert_key(key)
129
+ key.kind_of?(Symbol) ? key.to_s : key
130
+ end
131
+
132
+ # @param value<Object> The value to convert.
133
+ #
134
+ # @return <Object>
135
+ # The converted value. A Hash or an Array of hashes, will be converted to
136
+ # their Mash equivalents.
137
+ #
138
+ # @api private
139
+ def convert_value(value)
140
+ if value.class == Hash
141
+ value.to_mash
142
+ elsif value.is_a?(Array)
143
+ value.collect { |e| convert_value(e) }
144
+ else
145
+ value
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,36 @@
1
+ module Rails
2
+ # These are not intended to be used directly
3
+ class Authentication
4
+ attr_accessor :body
5
+
6
+ def redirected?
7
+ !!headers["Location"]
8
+ end
9
+
10
+ def headers
11
+ @headers ||= {}
12
+ end
13
+
14
+ def status
15
+ @status ||= 200
16
+ end
17
+
18
+ def status=(sts)
19
+ @status = sts
20
+ end
21
+
22
+ def halted?
23
+ !!@halt
24
+ end
25
+
26
+ def headers=(headers)
27
+ raise ArgumentError, "Need to supply a hash to headers. Got #{headers.class}" unless headers.kind_of?(Hash)
28
+ @headers = headers
29
+ end
30
+
31
+ def halt!
32
+ @halt = true
33
+ end
34
+
35
+ end # Rails::Authentication
36
+ end # Rails
@@ -0,0 +1,43 @@
1
+ class ActionController::Session::AbstractStore::SessionHash
2
+
3
+ # Access to the authentication object directly. Particularly useful
4
+ # for accessing the errors.
5
+ #
6
+ # === Example
7
+ #
8
+ # <%= error_messages_for session.authentication %>
9
+ #
10
+ def authentication
11
+ @authentication ||= Rails::Authentication.new(self)
12
+ end
13
+
14
+ # Check to see if the current session is authenticated
15
+ # @return true if authenticated. false otherwise
16
+ def authenticated?
17
+ authentication.authenticated?
18
+ end
19
+
20
+ # Authenticates the session via the authentication object.
21
+ #
22
+ # See Rails::Authentication#authenticate for usage
23
+ def authenticate!(request, params, *rest)
24
+ authentication.authenticate!(request, params, *rest)
25
+ end
26
+
27
+ # Provides access to the currently authenticated user.
28
+ def user
29
+ authentication.user
30
+ end
31
+
32
+ # set the currently authenticated user manually
33
+ # Rails::Authentication#store_user should know how to store the object into the session
34
+ def user=(the_user)
35
+ authentication.user = the_user
36
+ end
37
+
38
+ # Remove the user from the session and clear all data.
39
+ def abandon!
40
+ authentication.abandon!
41
+ end
42
+
43
+ end
@@ -0,0 +1,31 @@
1
+ class Rails::Authentication
2
+ module Strategies
3
+ # To use the password strategies, it is expected that you will provide
4
+ # an @authenticate@ method on your user class. This should take two parameters
5
+ # login, and password. It should return nil or the user object.
6
+ module Basic
7
+
8
+ class Base < Rails::Authentication::Strategy
9
+ abstract!
10
+
11
+ # Overwrite this method to customize the field
12
+ def self.password_param
13
+ :password
14
+ end
15
+
16
+ # Overwrite this method to customize the field
17
+ def self.login_param
18
+ :email
19
+ end
20
+
21
+ def password_param
22
+ @password_param ||= Base.password_param
23
+ end
24
+
25
+ def login_param
26
+ @login_param ||= Base.login_param
27
+ end
28
+ end # Base
29
+ end # Password
30
+ end # Strategies
31
+ end # Rails::Authentication
@@ -0,0 +1,36 @@
1
+ require 'rails-auth/strategies/abstract_password'
2
+ # This strategy uses a login and password parameter.
3
+ #
4
+ # Overwrite the :password_param, and :login_param
5
+ # to return the name of the field (on the form) that you're using the
6
+ # login with. These can be strings or symbols
7
+ #
8
+ # == Required
9
+ #
10
+ # === Methods
11
+ # <User>.authenticate(login_param, password_param)
12
+ #
13
+ class Rails::Authentication
14
+ module Strategies
15
+ module Basic
16
+ class Form < Base
17
+
18
+ def run!
19
+ if request.params[login_param] && request.params[password_param]
20
+ user = user_class.authenticate(request.params[login_param], request.params[password_param])
21
+ if !user
22
+ request.session.authentication.errors.clear!
23
+ request.session.authentication.errors.add(login_param, strategy_error_message)
24
+ end
25
+ user
26
+ end
27
+ end # run!
28
+
29
+ def strategy_error_message
30
+ "#{login_param.to_s.capitalize} or #{password_param.to_s.capitalize} were incorrect"
31
+ end
32
+
33
+ end # Form
34
+ end # Password
35
+ end # Strategies
36
+ end # Authentication
@@ -0,0 +1,206 @@
1
+ module Rails
2
+ class Authentication
3
+ cattr_reader :strategies, :default_strategy_order, :registered_strategies
4
+ @@strategies, @@default_strategy_order, @@registered_strategies = [], [], {}
5
+
6
+ # Use this to set the default order of strategies
7
+ # if you need to in your application. You don't need to use all avaiable strategies
8
+ # in this array, but you may not include a strategy that has not yet been defined.
9
+ #
10
+ # @params [Rails::Authentiation::Strategy,Rails::Authentication::Strategy]
11
+ #
12
+ # @public
13
+ def self.default_strategy_order=(*order)
14
+ order = order.flatten
15
+ bad = order.select{|s| !s.ancestors.include?(Strategy)}
16
+ raise ArgumentError, "#{bad.join(",")} do not inherit from Rails::Authentication::Strategy" unless bad.empty?
17
+ @@default_strategy_order = order
18
+ end
19
+
20
+ # Allows for the registration of strategies.
21
+ # @params <Symbol, String>
22
+ # +label+ The label is the label to identify this strategy
23
+ # +path+ The path to the file containing the strategy. This must be an absolute path!
24
+ #
25
+ # Registering a strategy does not add it to the list of strategies to use
26
+ # it simply makes it available through the Rails::Authentication.activate method
27
+ #
28
+ # This is for plugin writers to make a strategy availalbe but this should not
29
+ # stop you from declaring your own strategies
30
+ #
31
+ # @plugin
32
+ def self.register(label, path)
33
+ self.registered_strategies[label] = path
34
+ end
35
+
36
+ # Activates a registered strategy by it's label.
37
+ # Intended for use with plugin authors. There is little
38
+ # need to register your own strategies. Just declare them
39
+ # and they will be active.
40
+ def self.activate!(label)
41
+ path = self.registered_strategies[label]
42
+ raise "The #{label} Strategy is not registered" unless path
43
+ require path
44
+ end
45
+
46
+ # The Rails::Authentication::Strategy is where all the action happens in the merb-auth framework.
47
+ # Inherit from this class to setup your own strategy. The strategy will automatically
48
+ # be placed in the default_strategy_order array, and will be included in the strategy runs.
49
+ #
50
+ # The strategy you implment should have a YourStrategy#run! method defined that returns
51
+ # 1. A user object if authenticated
52
+ # 2. nil if no authenticated user was found.
53
+ #
54
+ # === Example
55
+ #
56
+ # class MyStrategy < Rails::Authentication::Strategy
57
+ # def run!
58
+ # u = User.get(params[:login])
59
+ # u if u.authentic?(params[:password])
60
+ # end
61
+ # end
62
+ #
63
+ #
64
+ class Strategy
65
+ attr_accessor :request
66
+ attr_writer :body
67
+
68
+ class << self
69
+ def inherited(klass)
70
+ Rails::Authentication.strategies << klass
71
+ Rails::Authentication.default_strategy_order << klass
72
+ end
73
+
74
+ # Use this to declare the strategy should run before another strategy
75
+ def before(strategy)
76
+ order = Rails::Authentication.default_strategy_order
77
+ order.delete(self)
78
+ index = order.index(strategy)
79
+ order.insert(index,self)
80
+ end
81
+
82
+ # Use this to declare the strategy should run after another strategy
83
+ def after(strategy)
84
+ order = Rails::Authentication.default_strategy_order
85
+ order.delete(self)
86
+ index = order.index(strategy)
87
+ index == order.size ? order << self : order.insert(index + 1, self)
88
+ end
89
+
90
+ # Mark a strategy as abstract. This means that a strategy will not
91
+ # ever be run as part of the authentication. Instead this
92
+ # will be available to inherit from as a way to share code.
93
+ #
94
+ # You could for example setup a strategy to check for a particular kind of login
95
+ # and then have a subclass for each class type of user in your system.
96
+ # i.e. Customer / Staff, Student / Staff etc
97
+ def abstract!
98
+ @abstract = true
99
+ end
100
+
101
+ # Asks is this strategy abstract. i.e. can it be run as part of the authentication
102
+ def abstract?
103
+ !!@abstract
104
+ end
105
+
106
+ end # End class << self
107
+
108
+ def initialize(request, params)
109
+ @request = request
110
+ @params = params
111
+ end
112
+
113
+ # An alias to the request.params hash
114
+ # Only rely on this hash to find any router params you are looking for.
115
+ # If looking for paramteres use request.params
116
+ def params
117
+ @params
118
+ end
119
+
120
+ # An alials to the request.cookies hash
121
+ def cookies
122
+ request.cookies
123
+ end
124
+
125
+ # An alias to the request.session hash
126
+ def session
127
+ request.session
128
+ end
129
+
130
+ # Redirects causes the strategy to signal a redirect
131
+ # to the provided url.
132
+ #
133
+ # ====Parameters
134
+ # url<String>:: The url to redirect to
135
+ # options<Hash>:: An options hash with the following keys:
136
+ # +:permanent+ Set this to true to make the redirect permanent
137
+ # +:status+ Set this to an integer for the status to return
138
+ def redirect!(url, opts = {})
139
+ self.headers["Location"] = url
140
+ self.status = opts[:permanent] ? 301 : 302
141
+ self.status = opts[:status] if opts[:status]
142
+ self.body = opts[:message] || "<div>You are being redirected to <a href='#{url}'>#{url}</a></div>"
143
+ halt!
144
+ return true
145
+ end
146
+
147
+ # Returns ture if the strategy redirected
148
+ def redirected?
149
+ !!headers["Location"]
150
+ end
151
+
152
+ # Provides a place to put the status of the response
153
+ attr_accessor :status
154
+
155
+ # Provides a place to put headers
156
+ def headers
157
+ @headers ||={}
158
+ end
159
+
160
+ # Mark this strategy as complete for this request. Will cause that no other
161
+ # strategies will be executed.
162
+ def halt!
163
+ @halt = true
164
+ end
165
+
166
+ # Checks to see if this strategy has been halted
167
+ def halted?
168
+ !!@halt
169
+ end
170
+
171
+
172
+ # Allows you to provide a body of content to return when halting
173
+ def body
174
+ @body || ""
175
+ end
176
+
177
+ # This is the method that is called as the test for authentication and is where
178
+ # you put your code.
179
+ #
180
+ # You must overwrite this method in your strategy
181
+ #
182
+ # @api overwritable
183
+ def run!
184
+ raise NotImplemented
185
+ end
186
+
187
+ # Overwrite this method to scope a strategy to a particular user type
188
+ # you can use this with inheritance for example to try the same strategy
189
+ # on different user types
190
+ #
191
+ # By default, Rails::Authentication.user_class is used. This method allows for
192
+ # particular strategies to deal with a different type of user class.
193
+ #
194
+ # For example. If Rails::Authentication.user_class is Customer
195
+ # and you have a PasswordStrategy, you can subclass the PasswordStrategy
196
+ # and change this method to return Staff. Giving you a PasswordStrategy strategy
197
+ # for first Customer(s) and then Staff.
198
+ #
199
+ # @api overwritable
200
+ def user_class
201
+ Rails::Authentication.user_class.constantize
202
+ end
203
+
204
+ end # Strategy
205
+ end # Rails::Authentication
206
+ end # Rails
data/lib/rails-auth.rb ADDED
@@ -0,0 +1,21 @@
1
+ class String
2
+ def /(other)
3
+ "#{self}/#{other}"
4
+ end
5
+ end
6
+
7
+ require 'rails-auth/mash'
8
+
9
+ require 'rails-auth/authenticated_helper'
10
+ require 'rails-auth/authentication'
11
+ require 'rails-auth/callbacks'
12
+ require 'rails-auth/errors'
13
+ require 'rails-auth/responses'
14
+ require 'rails-auth/session_mixin'
15
+ require 'rails-auth/strategy'
16
+
17
+ basic_path = "rails-auth/strategies"
18
+
19
+ # Rails::Authentication.register(:default_basic_auth, basic_path / "basic_auth.rb")
20
+ # Rails::Authentication.register(:default_openid, basic_path / "openid.rb")
21
+ Rails::Authentication.register(:default_password_form, basic_path / "password_form.rb")
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RailsAuthTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bacon'
3
+ require 'mocha'
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ require 'rails-auth'
7
+
8
+ class Test::Unit::TestCase
9
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: myobie-rails-auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Herald
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-10 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Authentication like merb, but for rails
17
+ email: myobie@mac.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.markdown
26
+ - VERSION.yml
27
+ - lib/rails-auth
28
+ - lib/rails-auth/authenticated_helper.rb
29
+ - lib/rails-auth/authentication.rb
30
+ - lib/rails-auth/callbacks.rb
31
+ - lib/rails-auth/errors.rb
32
+ - lib/rails-auth/helpers
33
+ - lib/rails-auth/helpers/all.rb
34
+ - lib/rails-auth/helpers/current_user.rb
35
+ - lib/rails-auth/helpers/logged_in.rb
36
+ - lib/rails-auth/helpers/redirect_back.rb
37
+ - lib/rails-auth/helpers/require_login_or.rb
38
+ - lib/rails-auth/mash.rb
39
+ - lib/rails-auth/responses.rb
40
+ - lib/rails-auth/session_mixin.rb
41
+ - lib/rails-auth/strategies
42
+ - lib/rails-auth/strategies/abstract_password.rb
43
+ - lib/rails-auth/strategies/password_form.rb
44
+ - lib/rails-auth/strategy.rb
45
+ - lib/rails-auth.rb
46
+ - test/rails-auth_test.rb
47
+ - test/test_helper.rb
48
+ has_rdoc: true
49
+ homepage: http://github.com/myobie/rails-auth
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --inline-source
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.2.0
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Authentication like merb, but for rails
75
+ test_files: []
76
+