myobie-rails-auth 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+