sidonath-authlogic_rpx 1.0.4b

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.
@@ -0,0 +1,126 @@
1
+ # This module is responsible for adding RPX functionality to Authlogic. Checkout the README for more info and please
2
+ # see the sub modules for detailed documentation.
3
+ module AuthlogicRpx
4
+ # This module is responsible for adding in the RPX functionality to your models. It hooks itself into the
5
+ # acts_as_authentic method provided by Authlogic.
6
+ module ActsAsAuthentic
7
+ # Adds in the neccesary modules for acts_as_authentic to include and also disabled password validation if
8
+ # RPX is being used.
9
+ def self.included(klass)
10
+ klass.class_eval do
11
+ extend Config
12
+ add_acts_as_authentic_module(Methods, :prepend)
13
+ end
14
+ end
15
+
16
+ module Config
17
+
18
+ # map_id is used to enable RPX identity mapping
19
+ # experimental - a feature of RPX paid accounts and not properly developed/tested yet
20
+ #
21
+ # * <tt>Default:</tt> false
22
+ # * <tt>Accepts:</tt> boolean
23
+ def map_id(value = false)
24
+ rw_config(:map_id, value, false)
25
+ end
26
+ alias_method :map_id=, :map_id
27
+
28
+ # Name of this method is defined in find_by_rpx_identifier_method
29
+ # method in session.rb
30
+ def find_by_rpx_identifier(id)
31
+ identifier = RPXIdentifier.find_by_identifier(id)
32
+ return nil if identifier.nil?
33
+ identifier.user
34
+ end
35
+
36
+ end
37
+
38
+ module Methods
39
+
40
+ # Set up some simple validations
41
+ def self.included(klass)
42
+ klass.class_eval do
43
+ has_many :rpx_identifiers, :class_name => 'RPXIdentifier'
44
+
45
+ validates_length_of_password_field_options validates_length_of_password_field_options.merge(:if => :validate_password_with_rpx?)
46
+ validates_confirmation_of_password_field_options validates_confirmation_of_password_field_options.merge(:if => :validate_password_with_rpx?)
47
+ validates_length_of_password_confirmation_field_options validates_length_of_password_confirmation_field_options.merge(:if => :validate_password_with_rpx?)
48
+ before_validation :adding_rpx_identifier
49
+ after_create :map_rpx_identifier
50
+ attr_writer :creating_new_record_from_rpx
51
+ end
52
+ end
53
+
54
+ # support a block given to the save
55
+ def save(perform_validation = true, &block)
56
+ result = super perform_validation
57
+ yield(result) if block_given?
58
+ result
59
+ end
60
+
61
+ # test if account it using RPX authentication
62
+ def using_rpx?
63
+ !rpx_identifiers.empty?
64
+ end
65
+
66
+ # test if account it using normal password authentication
67
+ def using_password?
68
+ !send(crypted_password_field).blank?
69
+ end
70
+
71
+ private
72
+
73
+ def validate_password_with_rpx?
74
+ if @creating_new_record_from_rpx
75
+ false
76
+ else
77
+ !using_rpx? && require_password?
78
+ end
79
+ end
80
+
81
+ # hook for adding RPX identifier to an existing account. This is invoked prior to model validation.
82
+ # RPX information is plucked from the controller session object (where it was placed by the session model as a result
83
+ # of the RPX callback)
84
+ # The minimal action taken is to add an RPXIdentifier object to the user.
85
+ #
86
+ # This procedure chains to the map_added_rpx_data, which may be over-ridden in your project to perform
87
+ # additional mapping of RPX information to the user model as may be desired.
88
+ #
89
+ def adding_rpx_identifier
90
+ return true unless session_class && session_class.controller
91
+ added_rpx_data = session_class.controller.session['added_rpx_data']
92
+ unless added_rpx_data.blank?
93
+ session_class.controller.session['added_rpx_data'] = nil
94
+ map_added_rpx_data( added_rpx_data )
95
+ end
96
+ return true
97
+ end
98
+
99
+ # map_added_rpx_data maps additional fields from the RPX response into the user object during the "add RPX to existing account" process.
100
+ # Override this in your user model to perform field mapping as may be desired
101
+ # See https://rpxnow.com/docs#profile_data for the definition of available attributes
102
+ #
103
+ # By default, it only creates a new RPXIdentifier for the user.
104
+ #
105
+ def map_added_rpx_data( rpx_data )
106
+ self.rpx_identifiers.create( :identifier => rpx_data['profile']['identifier'] )
107
+ end
108
+
109
+ # experimental - a feature of RPX paid accounts and not properly developed/tested yet
110
+ def map_id?
111
+ self.class.map_id
112
+ end
113
+
114
+ # experimental - a feature of RPX paid accounts and not properly developed/tested yet
115
+ def map_rpx_identifier
116
+ RPXNow.map(rpx_identifier, id) if using_rpx? && map_id?
117
+ end
118
+
119
+ # experimental - a feature of RPX paid accounts and not properly developed/tested yet
120
+ def unmap_rpx_identifer
121
+ RPXNow.unmap(rpx_identifier, id) if using_rpx? && map_id?
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,42 @@
1
+ module AuthlogicRpx
2
+ module Helper
3
+
4
+ # helper to insert an embedded iframe RPX login
5
+ # takes options hash:
6
+ # * <tt>app_name:</tt> name of the application (will be prepended to RPX domain and used in RPX dialogues)
7
+ # * <tt>return_url:</tt> url for the RPX callback (e.g. user_sessions_url)
8
+ # * <tt>add_rpx:</tt> if true, requests RPX callback to add to current session. Else runs normal authentication process (default)
9
+ #
10
+ def rpx_embed(options = {})
11
+ params = (
12
+ { :authenticity_token => form_authenticity_token, :add_rpx => options[:add_rpx] }.collect { |n| "#{n[0]}=#{ u(n[1]) }" if n[1] }
13
+ ).compact.join('&')
14
+ RPXNow.embed_code(options[:app_name], u( options[:return_url] + '?' + params ) )
15
+ end
16
+
17
+ # helper to insert a link to pop-up RPX login
18
+ # takes options hash:
19
+ # * <tt>link_text:</tt> text to use in the link
20
+ # * <tt>app_name:</tt> name of the application (will be prepended to RPX domain and used in RPX dialogues)
21
+ # * <tt>return_url:</tt> url for the RPX callback (e.g. user_sessions_url)
22
+ # * <tt>add_rpx:</tt> if true, requests RPX callback to add to current session. Else runs normal authentication process (default)
23
+ # * <tt>unobtrusive:</tt> true/false; sets javascript style for link. Default: true
24
+ #
25
+ # NB: i18n considerations? supports a :language parameter (not tested)
26
+ def rpx_popup(options = {})
27
+ params = (
28
+ { :authenticity_token => form_authenticity_token, :add_rpx => options[:add_rpx] }.collect { |n| "#{n[0]}=#{ u(n[1]) }" if n[1] }
29
+ ).compact.join('&')
30
+ unobtrusive = options[:unobtrusive].nil? ? true : options[:unobtrusive]
31
+ return_url = options[:return_url] + '?' + params
32
+ return_url = u( return_url ) if unobtrusive # double-encoding required only if unobtrusive mode used
33
+ RPXNow.popup_code(
34
+ options[:link_text],
35
+ options[:app_name],
36
+ return_url,
37
+ :unobtrusive=>unobtrusive
38
+ )
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,219 @@
1
+ module AuthlogicRpx
2
+ # This module is responsible for adding all of the RPX goodness to the Authlogic::Session::Base class.
3
+ module Session
4
+ # Add a simple rpx_identifier attribute and some validations for the field.
5
+ def self.included(klass)
6
+ klass.class_eval do
7
+ extend Config
8
+ include Methods
9
+ end
10
+ end
11
+
12
+ module Config
13
+
14
+ def find_by_rpx_identifier_method(value = nil)
15
+ rw_config(:find_by_rpx_identifier_method, value, :find_by_rpx_identifier)
16
+ end
17
+ alias_method :find_by_rpx_identifier_method=, :find_by_rpx_identifier_method
18
+
19
+ # Auto Register is enabled by default.
20
+ # Add this in your Session object if you need to disable auto-registration via rpx
21
+ #
22
+ def auto_register(value=true)
23
+ auto_register_value(value)
24
+ end
25
+ def auto_register_value(value=nil)
26
+ rw_config(:auto_register,value,true)
27
+ end
28
+ alias_method :auto_register=,:auto_register
29
+
30
+ # Add this in your Session object to set the RPX API key
31
+ # RPX won't work without the API key. Set it here if not already set in your app configuration.
32
+ #
33
+ def rpx_key(value=nil)
34
+ rpx_key_value(value)
35
+ end
36
+ def rpx_key_value(value=nil)
37
+ if !inheritable_attributes.include?(:rpx_key)
38
+ RPXNow.api_key = value
39
+ end
40
+ rw_config(:rpx_key,value,false)
41
+ end
42
+ alias_method :rpx_key=,:rpx_key
43
+
44
+ # Add this in your Session object to set whether RPX returns extended user info
45
+ # By default, it will not, which is enough to get username, name, email and the rpx identified
46
+ # if you want to map additional information into your user details, you can request extended
47
+ # attributes (though not all providers give them - see the RPX docs)
48
+ #
49
+ def rpx_extended_info(value=true)
50
+ rpx_extended_info_value(value)
51
+ end
52
+ def rpx_extended_info_value(value=nil)
53
+ rw_config(:rpx_extended_info,value,false)
54
+ end
55
+ alias_method :rpx_extended_info=,:rpx_extended_info
56
+
57
+ end
58
+
59
+ module Methods
60
+
61
+ def self.included(klass)
62
+ klass.class_eval do
63
+ attr_accessor :new_registration
64
+ after_persisting :add_rpx_identifier, :if => :adding_rpx_identifier?
65
+ validate :validate_by_rpx, :if => :authenticating_with_rpx?
66
+ end
67
+ end
68
+
69
+ # Determines if the authenticated user is also a new registration.
70
+ # For use in the session controller to help direct the most appropriate action to follow.
71
+ #
72
+ def new_registration?
73
+ new_registration
74
+ end
75
+
76
+ # Determines if the authenticated user has a complete registration (no validation errors)
77
+ # For use in the session controller to help direct the most appropriate action to follow.
78
+ #
79
+ def registration_complete?
80
+ attempted_record && attempted_record.valid?
81
+ end
82
+
83
+ private
84
+ # Tests if current request is for RPX authentication
85
+ #
86
+ def authenticating_with_rpx?
87
+ controller.params[:token] && !controller.params[:add_rpx]
88
+ end
89
+
90
+ # hook instance finder method to class
91
+ #
92
+ def find_by_rpx_identifier_method
93
+ self.class.find_by_rpx_identifier_method
94
+ end
95
+
96
+ # Tests if auto_registration is enabled (on by default)
97
+ #
98
+ def auto_register?
99
+ self.class.auto_register_value
100
+ end
101
+
102
+ # Tests if rpx_extended_info is enabled (off by default)
103
+ #
104
+ def rpx_extended_info?
105
+ self.class.rpx_extended_info_value
106
+ end
107
+
108
+ # Tests if current request is the special case of adding RPX to an existing account
109
+ #
110
+ def adding_rpx_identifier?
111
+ controller.params[:token] && controller.params[:add_rpx]
112
+ end
113
+
114
+ # Handles the special case of RPX being added to an existing account.
115
+ # At this point, a session has been established as a result of a "save" on the user model (which indirectly triggers user session validation).
116
+ # We do not directly add the RPX details to the user record here in order to avoid getting
117
+ # into a recursive dance between the session and user models.
118
+ # Rather, it uses the trick of adding the necessary RPX information to the session object,
119
+ # and the user model will pluck these values out before completing its validation step.
120
+ #
121
+ def add_rpx_identifier
122
+ data = RPXNow.user_data(controller.params[:token], :extended=> rpx_extended_info? ) {|raw| raw }
123
+ controller.session['added_rpx_data'] = data if data
124
+ end
125
+
126
+ # the main RPX magic. At this point, a session is being validated and we know RPX identifier
127
+ # has been provided. We'll callback to RPX to verify the token, and authenticate the matching
128
+ # user.
129
+ # If no user is found, and we have auto_register enabled (default) this method will also
130
+ # create the user registration stub.
131
+ #
132
+ # On return to the controller, you can test for new_registration? and registration_complete?
133
+ # to determine the most appropriate action
134
+ #
135
+ def validate_by_rpx
136
+ @rpx_data = RPXNow.user_data(
137
+ controller.params[:token],
138
+ :extended => rpx_extended_info?) { |raw| raw }
139
+
140
+ # If we don't have a valid sign-in, give-up at this point
141
+ if @rpx_data.nil?
142
+ errors.add_to_base("Authentication failed. Please try again.")
143
+ return false
144
+ end
145
+
146
+ rpx_id = @rpx_data['profile']['identifier']
147
+ if rpx_id.blank?
148
+ errors.add_to_base("Authentication failed. Please try again.")
149
+ return false
150
+ end
151
+
152
+ self.attempted_record = klass.send(find_by_rpx_identifier_method, rpx_id)
153
+
154
+ # so what do we do if we can't find an existing user matching the RPX authentication...
155
+ if !attempted_record
156
+ if auto_register?
157
+ self.attempted_record = klass.new()
158
+ map_rpx_data
159
+
160
+ # save the new user record - without session maintenance else we
161
+ # get caught in a self-referential hell, since both session and
162
+ # user objects invoke each other upon save
163
+ self.new_registration = true
164
+ self.attempted_record.creating_new_record_from_rpx = true
165
+ self.attempted_record.rpx_identifiers.build(:identifier => rpx_id)
166
+ self.attempted_record.save_without_session_maintenance
167
+ else
168
+ errors.add_to_base("We did not find any accounts with that login. Enter your details and create an account.")
169
+ return false
170
+ end
171
+ else
172
+ map_rpx_data_each_login
173
+ end
174
+
175
+ end
176
+
177
+ # map_rpx_data maps additional fields from the RPX response into the user object during auto-registration.
178
+ # Override this in your session model to change the field mapping
179
+ # See https://rpxnow.com/docs#profile_data for the definition of available attributes
180
+ #
181
+ # In this procedure, you will be writing to fields of the "self.attempted_record" object, pulling data from the @rpx_data object.
182
+ #
183
+ # WARNING: if you are using auto-registration, any fields you map should NOT have constraints enforced at the database level.
184
+ # authlogic_rpx will optimistically attempt to save the user record during registration, and
185
+ # violating a database constraint will cause the authentication/registration to fail.
186
+ #
187
+ # You can/should enforce any required validations at the model level e.g.
188
+ # validates_uniqueness_of :username, :case_sensitive => false
189
+ # This will allow the auto-registration to proceed, and the user can be given a chance to rectify the validation errors
190
+ # on your user profile page.
191
+ #
192
+ # If it is not acceptable in your application to have user records created with potential validation errors in auto-populated fields, you
193
+ # will need to override map_rpx_data and implement whatever special handling makes sense in your case. For example:
194
+ # - directly check for uniqueness and other validation requirements
195
+ # - automatically "uniquify" fields like username
196
+ # - save conflicting profile information to "pending user review" columns or a seperate table
197
+ #
198
+ def map_rpx_data
199
+ self.attempted_record.send("#{klass.login_field}=", @rpx_data['profile']['preferredUsername'] ) if attempted_record.send(klass.login_field).blank?
200
+ self.attempted_record.send("#{klass.email_field}=", @rpx_data['profile']['email'] ) if attempted_record.send(klass.email_field).blank?
201
+ end
202
+
203
+ # map_rpx_data_each_login provides a hook to allow you to map RPX profile information every time the user
204
+ # logs in.
205
+ # By default, nothing is mapped.
206
+ #
207
+ # This would mainly be used to update relatively volatile information that you are maintaining in the user model (such as profile image url)
208
+ #
209
+ # In this procedure, you will be writing to fields of the "self.attempted_record" object, pulling data from the @rpx_data object.
210
+ #
211
+ #
212
+ def map_rpx_data_each_login
213
+
214
+ end
215
+
216
+ end
217
+
218
+ end
219
+ end
@@ -0,0 +1,51 @@
1
+ module AuthlogicRpx
2
+ # A class for describing the current version of a library. The version
3
+ # consists of three parts: the +major+ number, the +minor+ number, and the
4
+ # +tiny+ (or +patch+) number.
5
+ class Version
6
+ include Comparable
7
+
8
+ # A convenience method for instantiating a new Version instance with the
9
+ # given +major+, +minor+, and +tiny+ components.
10
+ def self.[](major, minor, tiny)
11
+ new(major, minor, tiny)
12
+ end
13
+
14
+ attr_reader :major, :minor, :tiny
15
+
16
+ # Create a new Version object with the given components.
17
+ def initialize(major, minor, tiny)
18
+ @major, @minor, @tiny = major, minor, tiny
19
+ end
20
+
21
+ # Compare this version to the given +version+ object.
22
+ def <=>(version)
23
+ to_i <=> version.to_i
24
+ end
25
+
26
+ # Converts this version object to a string, where each of the three
27
+ # version components are joined by the '.' character. E.g., 2.0.0.
28
+ def to_s
29
+ @to_s ||= [@major, @minor, @tiny].join(".")
30
+ end
31
+
32
+ # Converts this version to a canonical integer that may be compared
33
+ # against other version objects.
34
+ def to_i
35
+ @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
36
+ end
37
+
38
+ def to_a
39
+ [@major, @minor, @tiny]
40
+ end
41
+
42
+ MAJOR = 1
43
+ MINOR = 0
44
+ TINY = 4
45
+
46
+ # The current version as a Version instance
47
+ CURRENT = new(MAJOR, MINOR, TINY)
48
+ # The current version as a String
49
+ STRING = CURRENT.to_s
50
+ end
51
+ end
@@ -0,0 +1,8 @@
1
+ require "authlogic_rpx/version"
2
+ require "authlogic_rpx/acts_as_authentic"
3
+ require "authlogic_rpx/session"
4
+ require "authlogic_rpx/helper"
5
+
6
+ ActiveRecord::Base.send(:include, AuthlogicRpx::ActsAsAuthentic)
7
+ Authlogic::Session::Base.send(:include, AuthlogicRpx::Session)
8
+ ActionController::Base.helper AuthlogicRpx::Helper
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require "authlogic_rpx"
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{sidonath-authlogic_rpx}
5
+ s.version = "1.0.4b"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Paul Gallagher / tardate", "John J. Bachir / jjb", "Damir Zekic / sidonath"]
9
+ s.date = %q{2009-12-24}
10
+ s.description = %q{Authlogic extension/plugin that provides RPX (rpxnow.com) authentication support}
11
+ s.email = %q{damirz@gmail.com}
12
+ s.extra_rdoc_files = ["CHANGELOG.rdoc", "README.rdoc", "lib/authlogic_rpx.rb", "lib/authlogic_rpx/acts_as_authentic.rb", "lib/authlogic_rpx/helper.rb", "lib/authlogic_rpx/session.rb", "lib/authlogic_rpx/version.rb"]
13
+ s.files = ["CHANGELOG.rdoc", "MIT-LICENSE", "Manifest", "README.rdoc", "Rakefile", "sidonath-authlogic_rpx.gemspec", "init.rb", "lib/authlogic_rpx.rb", "lib/authlogic_rpx/acts_as_authentic.rb", "lib/authlogic_rpx/helper.rb", "lib/authlogic_rpx/session.rb", "lib/authlogic_rpx/version.rb", "rails/init.rb", "test/acts_as_authentic_test.rb", "test/fixtures/users.yml", "test/libs/rails_trickery.rb", "test/libs/user.rb", "test/libs/user_session.rb", "test/session_test.rb", "test/test_helper.rb"]
14
+ s.homepage = %q{http://github.com/sidonath/authlogic_rpx}
15
+ s.post_install_message = %q{}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Authlogic_rpx", "--main", "README.rdoc"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{authlogic_rpx}
19
+ s.rubygems_version = %q{1.3.5}
20
+ s.summary = %q{Authlogic plug-in for RPX support}
21
+ s.test_files = ["test/acts_as_authentic_test.rb", "test/session_test.rb", "test/test_helper.rb"]
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 3
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ s.add_runtime_dependency(%q<authlogic>, [">= 2.1.1"])
29
+ s.add_runtime_dependency(%q<rpx_now>, [">= 0.6.6"])
30
+ else
31
+ s.add_dependency(%q<authlogic>, [">= 2.1.1"])
32
+ s.add_dependency(%q<rpx_now>, [">= 0.6.6"])
33
+ end
34
+ else
35
+ s.add_dependency(%q<authlogic>, [">= 2.1.1"])
36
+ s.add_dependency(%q<rpx_now>, [">= 0.6.6"])
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class ActsAsAuthenticTest < ActiveSupport::TestCase
4
+
5
+ end
File without changes
@@ -0,0 +1,41 @@
1
+ # The only reason I am doing all of this non sense is becuase the openid_authentication requires that
2
+ # these constants be present. The only other alternative is to use an entire rails application for testing
3
+ # which is a little too overboard for this, I think.
4
+
5
+ RAILS_ROOT = ''
6
+
7
+ class ActionController < Authlogic::TestCase::MockController
8
+ class Request < Authlogic::TestCase::MockRequest
9
+ def request_method
10
+ ""
11
+ end
12
+ end
13
+
14
+ def root_url
15
+ ''
16
+ end
17
+
18
+ def request
19
+ return @request if defined?(@request)
20
+ super
21
+ # Rails does some crazy s#!t with the "method" method. If I don't do this I get a "wrong arguments (0 for 1) error"
22
+ @request.class.class_eval do
23
+ def method
24
+ nil
25
+ end
26
+ end
27
+ @request
28
+ end
29
+
30
+ def url_for(*args)
31
+ ''
32
+ end
33
+
34
+ def redirecting_to
35
+ @redirect_to
36
+ end
37
+
38
+ def redirect_to(*args)
39
+ @redirect_to = args
40
+ end
41
+ end
data/test/libs/user.rb ADDED
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ acts_as_authentic
3
+ end
@@ -0,0 +1,2 @@
1
+ class UserSession < Authlogic::Session::Base
2
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class SessionTest < ActiveSupport::TestCase
4
+
5
+ end
@@ -0,0 +1,61 @@
1
+ require "test/unit"
2
+ require "rubygems"
3
+ require "ruby-debug"
4
+ require "active_record"
5
+
6
+ ActiveRecord::Schema.verbose = false
7
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
8
+ ActiveRecord::Base.configurations = true
9
+ ActiveRecord::Schema.define(:version => 1) do
10
+
11
+ create_table :users do |t|
12
+ t.datetime :created_at
13
+ t.datetime :updated_at
14
+ t.integer :lock_version, :default => 0
15
+ t.string :login
16
+ t.string :crypted_password
17
+ t.string :password_salt
18
+ t.string :persistence_token
19
+ t.string :single_access_token
20
+ t.string :perishable_token
21
+ t.string :rpx_identifier
22
+ t.string :email
23
+ t.string :first_name
24
+ t.string :last_name
25
+ t.integer :login_count, :default => 0, :null => false
26
+ t.integer :failed_login_count, :default => 0, :null => false
27
+ t.datetime :last_request_at
28
+ t.datetime :current_login_at
29
+ t.datetime :last_login_at
30
+ t.string :current_login_ip
31
+ t.string :last_login_ip
32
+ end
33
+ end
34
+
35
+ require "active_record/fixtures"
36
+ require "openid"
37
+ require "authlogic"
38
+ require "authlogic/test_case"
39
+ require File.dirname(__FILE__) + "/libs/rails_trickery"
40
+ require File.dirname(__FILE__) + '/libs/user'
41
+ require File.dirname(__FILE__) + '/libs/user_session'
42
+
43
+ class ActiveSupport::TestCase
44
+ include ActiveRecord::TestFixtures
45
+ self.fixture_path = File.dirname(__FILE__) + "/fixtures"
46
+ self.use_transactional_fixtures = false
47
+ self.use_instantiated_fixtures = false
48
+ self.pre_loaded_fixtures = false
49
+ fixtures :all
50
+ setup :activate_authlogic
51
+
52
+ private
53
+ def activate_authlogic
54
+ Authlogic::Session::Base.controller = controller
55
+ end
56
+
57
+ def controller
58
+ @controller ||= Authlogic::TestCase::ControllerAdapter.new(ActionController.new)
59
+ end
60
+
61
+ end