sidonath-authlogic_rpx 1.0.4b → 1.0.4em

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest CHANGED
@@ -3,11 +3,14 @@ MIT-LICENSE
3
3
  Manifest
4
4
  README.rdoc
5
5
  Rakefile
6
- authlogic_rpx.gemspec
6
+ generators/add_authlogic_rpx_migration/USAGE
7
+ generators/add_authlogic_rpx_migration/add_authlogic_rpx_migration_generator.rb
8
+ generators/add_authlogic_rpx_migration/templates/migration.rb
7
9
  init.rb
8
10
  lib/authlogic_rpx.rb
9
11
  lib/authlogic_rpx/acts_as_authentic.rb
10
12
  lib/authlogic_rpx/helper.rb
13
+ lib/authlogic_rpx/rpx_identifier.rb
11
14
  lib/authlogic_rpx/session.rb
12
15
  lib/authlogic_rpx/version.rb
13
16
  rails/init.rb
data/README.rdoc CHANGED
@@ -34,9 +34,9 @@ The demonstration Rails application is where you can see Authlogic_RPX in action
34
34
  Three gems are required: authlogic, grosser-rpx_now, and authlogic_rpx. Install these as appropriate to your environment and preferences.
35
35
 
36
36
  Currently tested versions:
37
- * authlogic 2.1.2,2.1.1
38
- * rpx_now 0.6.6
39
- * authlogic_rpx 1.0.4
37
+ * authlogic 2.1.3,2.1.2,2.1.1
38
+ * rpx_now 0.6.11,0.6.6
39
+ * authlogic_rpx 1.1.0
40
40
 
41
41
 
42
42
  === 1. Direct gem installation
@@ -50,9 +50,9 @@ Currently tested versions:
50
50
 
51
51
  Include in config/environment.rb:
52
52
 
53
- config.gem 'authlogic', :version => '>= 2.1.1'
54
- config.gem 'rpx_now', :version => '>= 0.6.6', :source => 'http://gemcutter.org'
55
- config.gem 'authlogic_rpx', :version => '>= 1.0.4', :source => 'http://gemcutter.org'
53
+ config.gem 'authlogic', :version => '>= 2.1.3'
54
+ config.gem 'rpx_now', :version => '>= 0.6.11', :source => 'http://gemcutter.org'
55
+ config.gem 'authlogic_rpx', :version => '>= 1.1.0', :source => 'http://gemcutter.org'
56
56
 
57
57
  Then to install, run from the command line:
58
58
 
@@ -63,9 +63,9 @@ Then to install, run from the command line:
63
63
 
64
64
  Include in RAILS_ROOT/.gems:
65
65
 
66
- authlogic --version '>= 2.1.1'
67
- rpx_now --version '>= 0.6.6' --source gemcutter.org
68
- authlogic_rpx --version '>= 1.0.4' --source gemcutter.org
66
+ authlogic --version '>= 2.1.3'
67
+ rpx_now --version '>= 0.6.11' --source gemcutter.org
68
+ authlogic_rpx --version '>= 1.1.0' --source gemcutter.org
69
69
 
70
70
 
71
71
  == Using Authlogic RPX
@@ -89,47 +89,52 @@ The main steps for enabling Authlogic RPX:
89
89
 
90
90
  === 1. Enable RPX for your user model
91
91
 
92
- The user model will have a has_many relationship with a new model, called RPXIdentifier. Create a migration which creates a table for this model.
92
+ The user model will have a has_many relationship with a new model, called RPXIdentifier.
93
+ A generator is provider to create the necessary migration:
93
94
 
94
- You may need to remove database constraints on other fields if they will be unused in the RPX case (e.g. crypted_password and password_salt to make password authentication optional).
95
+ ruby script/generate add_authlogic_rpx_migration
96
+
97
+ You may need to customise the migration file to remove database constraints on other fields if they will be unused in the RPX case
98
+ (e.g. crypted_password and password_salt to make password authentication optional).
95
99
 
96
- If you are using auto-registration, you must also remove any database constraints for fields that will be automatically mapped (see notes in "3. Add custom user profile mapping during auto-registration")
100
+ If you are using auto-registration, you must also remove any database constraints for fields that will be automatically mapped
101
+ (see notes in "3. Add custom user profile mapping during auto-registration")
97
102
 
98
- class CreateRPXIdentifiers < ActiveRecord::Migration
103
+ class AddAuthlogicRpxMigration < ActiveRecord::Migration
99
104
  def self.up
100
105
  create_table :rpx_identifiers do |t|
101
- t.string :identifier
102
- t.integer :user_id
103
-
104
- t.index :identifier, :user_id
105
- t.index :user_id, :identifier
106
-
107
- t.timestamps
108
- end
109
-
110
- [:crypted_password, :password_salt].each do |field|
111
- change_column :users, field, :string, :default => nil, :null => true
106
+ t.string :identifier
107
+ t.integer :user_id
108
+ t.timestamps
112
109
  end
110
+ add_index :rpx_identifiers, :identifier, :unique => true, :null => false
111
+ add_index :rpx_identifiers, :user_id, :unique => false, :null => false
112
+
113
+ # == Customisation may be required here ==
114
+ # You may need to remove database constraints on other fields if they will be unused in the RPX case
115
+ # (e.g. crypted_password and password_salt to make password authentication optional).
116
+ # If you are using auto-registration, you must also remove any database constraints for fields that will be automatically mapped
117
+ # e.g.:
118
+ #change_column :users, :crypted_password, :string, :default => nil, :null => true
119
+ #change_column :users, :password_salt, :string, :default => nil, :null => true
120
+
113
121
  end
114
-
122
+
115
123
  def self.down
116
124
  drop_table :rpx_identifiers
117
-
118
- [:crypted_password, :password_salt].each do |field|
119
- User.all(:conditions => "#{field} is NULL").each { |user| user.update_attribute(field, "") if user.send(field).nil? }
120
- change_column :users, field, :string, :default => "", :null => false
121
- end
125
+
126
+ # == Customisation may be required here ==
127
+ # Restore user model database constraints as appropriate
128
+ # e.g.:
129
+ #[:crypted_password, :password_salt].each do |field|
130
+ # User.all(:conditions => "#{field} is NULL").each { |user| user.update_attribute(field, "") if user.send(field).nil? }
131
+ # change_column :users, field, :string, :default => "", :null => false
132
+ #end
133
+
122
134
  end
123
135
  end
124
136
 
125
- The RPXIdentifier model should look like this
126
-
127
- class RPXIdentifier < ActiveRecord::Base
128
- belongs_to :user
129
- validates_presence_of :identifier
130
- validates_presence_of :user_id
131
- end
132
-
137
+ NB: The RPXIdentifier model is included in the authlogic_rpx gem and does not need to be added to your project.
133
138
 
134
139
  The user model then needs to be tagged with "acts_as_authentic". authlogic_rpx automatically adds to the user model the relationship with RPXIdentifiers.
135
140
 
@@ -137,6 +142,9 @@ The user model then needs to be tagged with "acts_as_authentic". authlogic_rpx a
137
142
  acts_as_authentic do |c|
138
143
  c.my_config_option = my_value # for available options see documentation in: Authlogic::ActsAsAuthentic
139
144
  end # block optional
145
+
146
+ # enable Authlogic_RPX account merging (false by default, if this statement is not present)
147
+ account_merge_enabled true
140
148
 
141
149
  # not needed -- this relationship is automatically added by authlogic_rpx
142
150
  # has_many :rpx_identifiers, :class_name => 'RPXIdentifier'
@@ -177,6 +185,15 @@ For example, to disable auto-registration and enable extended info:
177
185
 
178
186
  {See the source for the sample user_session.rb}[http://github.com/tardate/rails-authlogic-rpx-sample/blob/master/app/models/user_session.rb].
179
187
 
188
+ ==== Upgrading from Authlogic_RPX v1.0.4 or earlier
189
+
190
+ In Authlogic_RPX v1.0.4 and earlier, the rpx_identifier was stored in the user model.
191
+ From 1.1.0, this has been extracted to a separate table (rpx_identifiers).
192
+
193
+ When upgrading an application using 1.0.4 or earlier to 1.1.0, it is NOT necessary to migrate the rpx_identifiers.
194
+ Also DO NOT remove the legacy rpx_identifier column from your existing user model.
195
+ The Authlogic_RPX code will migrate users to the new database structure as and when they login.
196
+
180
197
  === 3. Add custom user profile mapping (optional)
181
198
 
182
199
  Authlogic_rpx provides three hooks for mapping information from the RPX profile into your application's user model:
@@ -258,14 +275,12 @@ In the map_rpx_data_each_login procedure, you will be writing to fields of the "
258
275
 
259
276
  map_added_rpx_data maps additional fields from the RPX response into the user object during the "add RPX to existing account" process.
260
277
 
261
- By default, it only maps the rpx_identifier field. If you have other fields you want to map, you can provide your own implementation of the map_added_rpx_data method in the User model (NOT UserSession, unlike for map_rpx_data and map_rpx_data_each_login).
262
-
263
- NB: If you override this method, you will be responsible for also mapping the rpx_identifier.
278
+ Override this in your user model to perform field mapping as may be desired.
279
+ Provide your own implementation of the map_added_rpx_data method in the User model (NOT UserSession, unlike for map_rpx_data and map_rpx_data_each_login).
264
280
 
265
281
  In the map_added_rpx_data procedure, you will be writing to fields of the "self" object, pulling data from the rpx_data parameter. For example:
266
282
 
267
283
  def map_added_rpx_data( rpx_data )
268
- self.rpx_identifiers.create( :identifier => rpx_data['profile']['identifier'] )
269
284
 
270
285
  # map some additional fields, e.g. photo_url
271
286
  self.photo_url = rpx_data['profile']['photo'] if photo_url.blank?
data/lib/authlogic_rpx.rb CHANGED
@@ -2,6 +2,7 @@ require "authlogic_rpx/version"
2
2
  require "authlogic_rpx/acts_as_authentic"
3
3
  require "authlogic_rpx/session"
4
4
  require "authlogic_rpx/helper"
5
+ require "authlogic_rpx/rpx_identifier"
5
6
 
6
7
  ActiveRecord::Base.send(:include, AuthlogicRpx::ActsAsAuthentic)
7
8
  Authlogic::Session::Base.send(:include, AuthlogicRpx::Session)
@@ -24,13 +24,39 @@ module AuthlogicRpx
24
24
  rw_config(:map_id, value, false)
25
25
  end
26
26
  alias_method :map_id=, :map_id
27
+
28
+ # account_merge_enabled is used to enable merging of accounts.
29
+ #
30
+ # * <tt>Default:</tt> false
31
+ # * <tt>Accepts:</tt> boolean
32
+ def account_merge_enabled(value=false)
33
+ account_merge_enabled_value(value)
34
+ end
35
+ def account_merge_enabled_value(value=nil)
36
+ rw_config(:account_merge_enabled,value,false)
37
+ end
38
+ alias_method :account_merge_enabled=,:account_merge_enabled
39
+
27
40
 
41
+
28
42
  # Name of this method is defined in find_by_rpx_identifier_method
29
43
  # method in session.rb
30
44
  def find_by_rpx_identifier(id)
31
45
  identifier = RPXIdentifier.find_by_identifier(id)
32
- return nil if identifier.nil?
33
- identifier.user
46
+ if identifier.nil?
47
+ if self.column_names.include? 'rpx_identifier'
48
+ # check for authentication using <=1.0.4, migrate identifier to rpx_identifiers table
49
+ user = self.find( :first, :conditions => [ "rpx_identifier = ?", id ] )
50
+ unless user.nil?
51
+ user.rpx_identifiers.create( :identifier => id )
52
+ end
53
+ return user
54
+ else
55
+ return nil
56
+ end
57
+ else
58
+ identifier.user
59
+ end
34
60
  end
35
61
 
36
62
  end
@@ -40,7 +66,7 @@ module AuthlogicRpx
40
66
  # Set up some simple validations
41
67
  def self.included(klass)
42
68
  klass.class_eval do
43
- has_many :rpx_identifiers, :class_name => 'RPXIdentifier'
69
+ has_many :rpx_identifiers, :class_name => 'RPXIdentifier', :dependent => :destroy
44
70
 
45
71
  validates_length_of_password_field_options validates_length_of_password_field_options.merge(:if => :validate_password_with_rpx?)
46
72
  validates_confirmation_of_password_field_options validates_confirmation_of_password_field_options.merge(:if => :validate_password_with_rpx?)
@@ -49,6 +75,10 @@ module AuthlogicRpx
49
75
  after_create :map_rpx_identifier
50
76
  attr_writer :creating_new_record_from_rpx
51
77
  end
78
+
79
+ RPXIdentifier.class_eval do
80
+ belongs_to klass.name.downcase.to_sym
81
+ end
52
82
  end
53
83
 
54
84
  # support a block given to the save
@@ -88,24 +118,65 @@ module AuthlogicRpx
88
118
  #
89
119
  def adding_rpx_identifier
90
120
  return true unless session_class && session_class.controller
91
- added_rpx_data = session_class.controller.session['added_rpx_data']
121
+ added_rpx_data = session_class.controller.session['added_rpx_data']
92
122
  unless added_rpx_data.blank?
93
123
  session_class.controller.session['added_rpx_data'] = nil
124
+ rpx_id = added_rpx_data['profile']['identifier']
125
+ rpx_provider_name = added_rpx_data['profile']['providerName']
126
+ unless self.rpx_identifiers.find_by_identifier( rpx_id )
127
+ RAILS_DEFAULT_LOGGER.info "account_merge_enabled? = #{account_merge_enabled?}"
128
+ # identifier not already set for this user
129
+ another_user = self.class.find_by_rpx_identifier( rpx_id )
130
+ if another_user
131
+ return false unless account_merge_enabled?
132
+ # another user already has this id registered
133
+ # merge all IDs from another_user to self, with application callbacks before/after
134
+ before_merge_rpx_data( another_user, self )
135
+ self.rpx_identifiers << another_user.rpx_identifiers
136
+ after_merge_rpx_data( another_user, self )
137
+ else
138
+ self.rpx_identifiers.create( :identifier => rpx_id, :provider_name => rpx_provider_name )
139
+ end
140
+ end
94
141
  map_added_rpx_data( added_rpx_data )
95
142
  end
96
143
  return true
97
- end
98
-
144
+ end
145
+
99
146
  # map_added_rpx_data maps additional fields from the RPX response into the user object during the "add RPX to existing account" process.
100
147
  # Override this in your user model to perform field mapping as may be desired
101
148
  # See https://rpxnow.com/docs#profile_data for the definition of available attributes
102
149
  #
103
- # By default, it only creates a new RPXIdentifier for the user.
150
+ # "self" at this point is the user model. Map details as appropriate from the rpx_data structure provided.
104
151
  #
105
152
  def map_added_rpx_data( rpx_data )
106
- self.rpx_identifiers.create( :identifier => rpx_data['profile']['identifier'] )
153
+
154
+ end
155
+
156
+ # determines if account merging is enabled
157
+ def account_merge_enabled?
158
+ self.class.account_merge_enabled_value
107
159
  end
160
+
161
+ # before_merge_rpx_data provides a hook for application developers to perform data migration prior to the merging of user accounts.
162
+ # This method is called just before authlogic_rpx merges the user registration for 'from_user' into 'to_user'
163
+ # Authlogic_RPX is responsible for merging registration data.
164
+ #
165
+ # By default, it does not merge any other details (e.g. application data ownership)
166
+ #
167
+ def before_merge_rpx_data( from_user, to_user )
108
168
 
169
+ end
170
+
171
+ # after_merge_rpx_data provides a hook for application developers to perform account clean-up after authlogic_rpx has
172
+ # migrated registration details.
173
+ #
174
+ # By default, does nothing. It could, for example, be used to delete or disable the 'from_user' account
175
+ #
176
+ def after_merge_rpx_data( from_user, to_user )
177
+
178
+ end
179
+
109
180
  # experimental - a feature of RPX paid accounts and not properly developed/tested yet
110
181
  def map_id?
111
182
  self.class.map_id
@@ -144,6 +144,7 @@ module AuthlogicRpx
144
144
  end
145
145
 
146
146
  rpx_id = @rpx_data['profile']['identifier']
147
+ rpx_provider_name = @rpx_data['profile']['providerName']
147
148
  if rpx_id.blank?
148
149
  errors.add_to_base("Authentication failed. Please try again.")
149
150
  return false
@@ -162,7 +163,7 @@ module AuthlogicRpx
162
163
  # user objects invoke each other upon save
163
164
  self.new_registration = true
164
165
  self.attempted_record.creating_new_record_from_rpx = true
165
- self.attempted_record.rpx_identifiers.build(:identifier => rpx_id)
166
+ self.attempted_record.rpx_identifiers.build(:identifier => rpx_id, :provider_name => rpx_provider_name )
166
167
  self.attempted_record.save_without_session_maintenance
167
168
  else
168
169
  errors.add_to_base("We did not find any accounts with that login. Enter your details and create an account.")
@@ -40,8 +40,8 @@ module AuthlogicRpx
40
40
  end
41
41
 
42
42
  MAJOR = 1
43
- MINOR = 0
44
- TINY = 4
43
+ MINOR = 1
44
+ TINY = 0
45
45
 
46
46
  # The current version as a Version instance
47
47
  CURRENT = new(MAJOR, MINOR, TINY)
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{sidonath-authlogic_rpx}
5
- s.version = "1.0.4b"
5
+ s.version = "1.0.4em"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Paul Gallagher / tardate", "John J. Bachir / jjb", "Damir Zekic / sidonath"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidonath-authlogic_rpx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4b
4
+ version: 1.0.4em
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Gallagher / tardate