authlogic_rpx 1.0.4 → 1.1.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.
Files changed (36) hide show
  1. data/CHANGELOG.rdoc +10 -0
  2. data/Manifest +19 -2
  3. data/README.rdoc +284 -72
  4. data/Rakefile +30 -2
  5. data/authlogic_rpx.gemspec +11 -11
  6. data/generators/add_authlogic_rpx_migration/USAGE +18 -0
  7. data/generators/add_authlogic_rpx_migration/add_authlogic_rpx_migration_generator.rb +44 -0
  8. data/generators/add_authlogic_rpx_migration/templates/migration_internal_mapping.rb +34 -0
  9. data/generators/add_authlogic_rpx_migration/templates/migration_no_mapping.rb +29 -0
  10. data/lib/authlogic_rpx.rb +1 -0
  11. data/lib/authlogic_rpx/acts_as_authentic.rb +199 -32
  12. data/lib/authlogic_rpx/helper.rb +21 -13
  13. data/lib/authlogic_rpx/rpx_identifier.rb +5 -0
  14. data/lib/authlogic_rpx/session.rb +23 -16
  15. data/lib/authlogic_rpx/version.rb +2 -2
  16. data/test/fixtures/rpxresponses.yml +20 -0
  17. data/test/fixtures/users.yml +20 -5
  18. data/test/integration/basic_authentication_and_registration_test.rb +53 -0
  19. data/test/integration/internal_mapping/basic_authentication_and_registration_test.rb +3 -0
  20. data/test/integration/internal_mapping/settings_test.rb +10 -0
  21. data/test/integration/no_mapping/basic_authentication_and_registration_test.rb +3 -0
  22. data/test/integration/no_mapping/settings_test.rb +10 -0
  23. data/test/libs/ext_test_unit.rb +30 -0
  24. data/test/libs/mock_rpx_now.rb +34 -0
  25. data/test/libs/rails_trickery.rb +2 -2
  26. data/test/libs/rpxresponse.rb +3 -0
  27. data/test/libs/user_session.rb +1 -1
  28. data/test/test_helper.rb +35 -21
  29. data/test/test_internal_mapping_helper.rb +95 -0
  30. data/test/unit/acts_as_authentic_settings_test.rb +42 -0
  31. data/test/unit/session_settings_test.rb +38 -0
  32. data/test/unit/session_validation_test.rb +16 -0
  33. data/test/unit/verify_rpx_mock_test.rb +29 -0
  34. metadata +34 -8
  35. data/test/acts_as_authentic_test.rb +0 -5
  36. data/test/session_test.rb +0 -10
data/Rakefile CHANGED
@@ -10,11 +10,39 @@ Echoe.new("authlogic_rpx") do |p|
10
10
  p.summary = "Authlogic plug-in for RPX support"
11
11
  p.description = "Authlogic extension/plugin that provides RPX (rpxnow.com) authentication support"
12
12
 
13
- p.runtime_dependencies = ["authlogic >=2.1.1", "rpx_now >=0.6.6" ]
13
+ p.runtime_dependencies = ["authlogic >=2.1.3", "rpx_now >=0.6.11" ]
14
14
  p.development_dependencies = []
15
15
 
16
16
  p.author = "Paul Gallagher / tardate"
17
17
  p.email = "gallagher.paul@gmail.com"
18
18
 
19
19
  p.install_message = ""
20
- end
20
+ end
21
+
22
+
23
+ Rake::Task[:test].clear
24
+
25
+ Rake::TestTask.new(:unit) do |t|
26
+ t.libs << "test/libs"
27
+ t.pattern = 'test/unit/*test.rb'
28
+ t.verbose = true
29
+ end
30
+
31
+ Rake::TestTask.new(:no_mapping) do |t|
32
+ t.libs << "test/libs"
33
+ t.test_files = FileList.new('test/unit/*test.rb', 'test/integration/no_mapping/*test.rb')
34
+ t.verbose = true
35
+ end
36
+
37
+ Rake::TestTask.new(:internal_mapping) do |t|
38
+ t.libs << "test/libs"
39
+ t.test_files = FileList.new('test/integration/internal_mapping/*test.rb')
40
+ t.verbose = true
41
+ end
42
+
43
+ task :test do
44
+ Rake::Task[:no_mapping].invoke
45
+ Rake::Task[:internal_mapping].invoke
46
+ end
47
+
48
+ task :default => :test
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{authlogic_rpx}
5
- s.version = "1.0.4"
5
+ s.version = "1.1.0"
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"]
9
- s.date = %q{2009-10-15}
9
+ s.date = %q{2010-01-05}
10
10
  s.description = %q{Authlogic extension/plugin that provides RPX (rpxnow.com) authentication support}
11
11
  s.email = %q{gallagher.paul@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", "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"]
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/rpx_identifier.rb", "lib/authlogic_rpx/session.rb", "lib/authlogic_rpx/version.rb"]
13
+ s.files = ["CHANGELOG.rdoc", "MIT-LICENSE", "Manifest", "README.rdoc", "Rakefile", "authlogic_rpx.gemspec", "generators/add_authlogic_rpx_migration/USAGE", "generators/add_authlogic_rpx_migration/add_authlogic_rpx_migration_generator.rb", "generators/add_authlogic_rpx_migration/templates/migration_internal_mapping.rb", "generators/add_authlogic_rpx_migration/templates/migration_no_mapping.rb", "init.rb", "lib/authlogic_rpx.rb", "lib/authlogic_rpx/acts_as_authentic.rb", "lib/authlogic_rpx/helper.rb", "lib/authlogic_rpx/rpx_identifier.rb", "lib/authlogic_rpx/session.rb", "lib/authlogic_rpx/version.rb", "rails/init.rb", "test/fixtures/rpxresponses.yml", "test/fixtures/users.yml", "test/integration/basic_authentication_and_registration_test.rb", "test/integration/internal_mapping/basic_authentication_and_registration_test.rb", "test/integration/internal_mapping/settings_test.rb", "test/integration/no_mapping/basic_authentication_and_registration_test.rb", "test/integration/no_mapping/settings_test.rb", "test/libs/ext_test_unit.rb", "test/libs/mock_rpx_now.rb", "test/libs/rails_trickery.rb", "test/libs/rpxresponse.rb", "test/libs/user.rb", "test/libs/user_session.rb", "test/test_helper.rb", "test/test_internal_mapping_helper.rb", "test/unit/acts_as_authentic_settings_test.rb", "test/unit/session_settings_test.rb", "test/unit/session_validation_test.rb", "test/unit/verify_rpx_mock_test.rb"]
14
14
  s.homepage = %q{http://github.com/tardate/authlogic_rpx}
15
15
  s.post_install_message = %q{}
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Authlogic_rpx", "--main", "README.rdoc"]
@@ -18,21 +18,21 @@ Gem::Specification.new do |s|
18
18
  s.rubyforge_project = %q{authlogic_rpx}
19
19
  s.rubygems_version = %q{1.3.5}
20
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"]
21
+ s.test_files = ["test/integration/basic_authentication_and_registration_test.rb", "test/integration/internal_mapping/basic_authentication_and_registration_test.rb", "test/integration/internal_mapping/settings_test.rb", "test/integration/no_mapping/basic_authentication_and_registration_test.rb", "test/integration/no_mapping/settings_test.rb", "test/test_helper.rb", "test/test_internal_mapping_helper.rb", "test/unit/acts_as_authentic_settings_test.rb", "test/unit/session_settings_test.rb", "test/unit/session_validation_test.rb", "test/unit/verify_rpx_mock_test.rb"]
22
22
 
23
23
  if s.respond_to? :specification_version then
24
24
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
25
  s.specification_version = 3
26
26
 
27
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"])
28
+ s.add_runtime_dependency(%q<authlogic>, [">= 2.1.3"])
29
+ s.add_runtime_dependency(%q<rpx_now>, [">= 0.6.11"])
30
30
  else
31
- s.add_dependency(%q<authlogic>, [">= 2.1.1"])
32
- s.add_dependency(%q<rpx_now>, [">= 0.6.6"])
31
+ s.add_dependency(%q<authlogic>, [">= 2.1.3"])
32
+ s.add_dependency(%q<rpx_now>, [">= 0.6.11"])
33
33
  end
34
34
  else
35
- s.add_dependency(%q<authlogic>, [">= 2.1.1"])
36
- s.add_dependency(%q<rpx_now>, [">= 0.6.6"])
35
+ s.add_dependency(%q<authlogic>, [">= 2.1.3"])
36
+ s.add_dependency(%q<rpx_now>, [">= 0.6.11"])
37
37
  end
38
38
  end
@@ -0,0 +1,18 @@
1
+ Description:
2
+ ruby script/generate add_authlogic_rpx_migration [mapping:mapping_mode] [user_model:model_name]
3
+
4
+ Creates an add_authlogic_rpx_migration file in db/migrate.
5
+
6
+ The mapping_mode parameter indicates which style of Authlogic_RPX-supported identity
7
+ mapping should be used. Allowed values for mapping_mode are:
8
+ none
9
+ internal
10
+ Default mapping_mode is 'internal'
11
+
12
+ The user_model parameter specifies the name of the user/member model in your application.
13
+ Default model_name is 'User'
14
+
15
+ e.g. to generate the RPX migration where the user model is called 'Member' and you do not
16
+ want to support identity mapping:
17
+
18
+ ruby script/generate add_authlogic_rpx_migration mapping:none user_model:member
@@ -0,0 +1,44 @@
1
+ class AddAuthlogicRpxMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+
4
+ record do |m|
5
+
6
+ m.migration_template template_name, 'db/migrate', :assigns => {
7
+ :user_model_base => user_model_base,
8
+ :user_model => user_model,
9
+ :user_model_collection => user_model_collection
10
+ }
11
+ end
12
+ end
13
+
14
+ def file_name
15
+ "add_authlogic_rpx_migration"
16
+ end
17
+
18
+ protected
19
+ # Override with your own usage banner.
20
+ def banner
21
+ "Usage: #{$0} #{spec.name} [options] [mapping:mapping_mode] [user_model:model_name]"
22
+ end
23
+
24
+ attr_writer :params
25
+ def params
26
+ @params ||= {"mapping" => "internal", "user_model" => "User"}.merge( Hash[*(@args.collect { |arg| arg.split(":") }.flatten)] )
27
+ end
28
+
29
+ def user_model_base
30
+ params['user_model'].singularize.downcase
31
+ end
32
+ def user_model
33
+ params['user_model'].singularize.capitalize
34
+ end
35
+ def user_model_collection
36
+ params['user_model'].pluralize.downcase
37
+ end
38
+ def mapping
39
+ params['mapping']
40
+ end
41
+ def template_name
42
+ mapping == 'none' ? 'migration_no_mapping.rb' : 'migration_internal_mapping.rb'
43
+ end
44
+ end
@@ -0,0 +1,34 @@
1
+ class AddAuthlogicRpxMigration < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :rpx_identifiers do |t|
4
+ t.string :identifier, :null => false
5
+ t.string :provider_name
6
+ t.integer :<%= user_model_base %>_id, :null => false
7
+ t.timestamps
8
+ end
9
+ add_index :rpx_identifiers, :identifier, :unique => true, :null => false
10
+ add_index :rpx_identifiers, :<%= user_model_base %>_id, :unique => false, :null => false
11
+
12
+ # == Customisation may be required here ==
13
+ # You may need to remove database constraints on other fields if they will be unused in the RPX case
14
+ # (e.g. crypted_password and password_salt to make password authentication optional).
15
+ # If you are using auto-registration, you must also remove any database constraints for fields that will be automatically mapped
16
+ # e.g.:
17
+ #change_column :<%= user_model_collection %>, :crypted_password, :string, :default => nil, :null => true
18
+ #change_column :<%= user_model_collection %>, :password_salt, :string, :default => nil, :null => true
19
+
20
+ end
21
+
22
+ def self.down
23
+ drop_table :rpx_identifiers
24
+
25
+ # == Customisation may be required here ==
26
+ # Restore user model database constraints as appropriate
27
+ # e.g.:
28
+ #[:crypted_password, :password_salt].each do |field|
29
+ # <%= user_model %>.all(:conditions => "#{field} is NULL").each { |user| user.update_attribute(field, "") if user.send(field).nil? }
30
+ # change_column :<%= user_model_collection %>, field, :string, :default => "", :null => false
31
+ #end
32
+
33
+ end
34
+ end
@@ -0,0 +1,29 @@
1
+ class AddAuthlogicRpxMigration < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ add_column :<%= user_model_collection %>, :rpx_identifier, :string
5
+ add_index :<%= user_model_collection %>, :rpx_identifier
6
+
7
+ # == Customisation may be required here ==
8
+ # You may need to remove database constraints on other fields if they will be unused in the RPX case
9
+ # (e.g. crypted_password and password_salt to make password authentication optional).
10
+ # If you are using auto-registration, you must also remove any database constraints for fields that will be automatically mapped
11
+ # e.g.:
12
+ #change_column :<%= user_model_collection %>, :crypted_password, :string, :default => nil, :null => true
13
+ #change_column :<%= user_model_collection %>, :password_salt, :string, :default => nil, :null => true
14
+
15
+ end
16
+
17
+ def self.down
18
+ remove_column :<%= user_model_collection %>, :rpx_identifier
19
+
20
+ # == Customisation may be required here ==
21
+ # Restore user model database constraints as appropriate
22
+ # e.g.:
23
+ #[:crypted_password, :password_salt].each do |field|
24
+ # <%= user_model %>.all(:conditions => "#{field} is NULL").each { |user| user.update_attribute(field, "") if user.send(field).nil? }
25
+ # change_column :<%= user_model_collection %>, field, :string, :default => "", :null => false
26
+ #end
27
+
28
+ end
29
+ end
@@ -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)
@@ -7,24 +7,73 @@ module AuthlogicRpx
7
7
  # Adds in the neccesary modules for acts_as_authentic to include and also disabled password validation if
8
8
  # RPX is being used.
9
9
  def self.included(klass)
10
- klass.class_eval do
11
- extend Config
12
- add_acts_as_authentic_module(Methods, :prepend)
13
- end
10
+ klass.class_eval do
11
+ extend Config
12
+ add_acts_as_authentic_module(Methods, :prepend)
13
+ end
14
14
  end
15
15
 
16
+ class GeneralError < StandardError
17
+ end
18
+ class ConfigurationError < StandardError
19
+ end
20
+
16
21
  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
22
+
23
+ # account_merge_enabled is used to enable merging of accounts.
20
24
  #
21
25
  # * <tt>Default:</tt> false
22
26
  # * <tt>Accepts:</tt> boolean
23
- def map_id(value = false)
24
- rw_config(:map_id, value, false)
27
+ def account_merge_enabled(value=false)
28
+ account_merge_enabled_value(value)
29
+ end
30
+ def account_merge_enabled_value(value=nil)
31
+ rw_config(:account_merge_enabled,value,false)
32
+ end
33
+ alias_method :account_merge_enabled=,:account_merge_enabled
34
+
35
+
36
+ # account_mapping_mode is used to explicitly set/override the mapping behaviour.
37
+ #
38
+ # * <tt>Default:</tt> :auto
39
+ # * <tt>Accepts:</tt> :auto, :none, :internal, :rpxnow
40
+ def account_mapping_mode(value=:auto)
41
+ account_mapping_mode_value(value)
25
42
  end
26
- alias_method :map_id=, :map_id
43
+ def account_mapping_mode_value(value=nil)
44
+ raise AuthlogicRpx::ActsAsAuthentic::ConfigurationError.new unless value.nil? || [:auto,:none,:internal].include?( value )
45
+ rw_config(:account_mapping_mode,value,:auto)
46
+ end
47
+ alias_method :account_mapping_mode=,:account_mapping_mode
48
+
49
+ # returns the actual account mapping mode in use - resolves :auto to actual mechanism
50
+ #
51
+ attr_writer :account_mapping_mode_used
52
+ def account_mapping_mode_used
53
+ @account_mapping_mode_used ||= (
54
+ account_mapping_mode_value == :auto ?
55
+ ( RPXIdentifier.table_exists? ?
56
+ :internal :
57
+ ( self.column_names.include?("rpx_identifier") ? :none : AuthlogicRpx::ActsAsAuthentic::ConfigurationError.new )
58
+ ) :
59
+ account_mapping_mode_value
60
+ )
61
+ end
62
+
27
63
 
64
+ # determines if no account mapping is supported (the only behaviour in authlogic_rpx v1.0.4)
65
+ def using_no_mapping?
66
+ account_mapping_mode_used == :none
67
+ end
68
+ # determines if internal account mapping is enabled (behaviour added in authlogic_rpx v1.1.0)
69
+ def using_internal_mapping?
70
+ account_mapping_mode_used == :internal
71
+ end
72
+ # determines if rpxnow account mapping is enabled (currently not implemented)
73
+ def using_rpx_mapping?
74
+ account_mapping_mode_used == :rpxnow
75
+ end
76
+
28
77
  end
29
78
 
30
79
  module Methods
@@ -32,12 +81,60 @@ module AuthlogicRpx
32
81
  # Set up some simple validations
33
82
  def self.included(klass)
34
83
  klass.class_eval do
35
- validates_uniqueness_of :rpx_identifier, :scope => validations_scope, :if => :using_rpx?
84
+
85
+ case
86
+ when using_no_mapping?
87
+ alias_method :using_rpx?, :using_rpx__nomap?
88
+ alias_method :add_rpx_identifier, :add_rpx_identifier__nomap
89
+ alias_method :identified_by?, :identified_by__nomap?
90
+ alias_method :merge_user_id, :merge_user_id__nomap
91
+
92
+ # Uses default find_by_rpx_identifier class method
93
+
94
+ # Add an rpx_identifier collection method
95
+ def rpx_identifiers
96
+ [{ :identifier => rpx_identifier, :provider_name => "Unknown" }]
97
+ end
98
+
99
+ when using_internal_mapping?
100
+ alias_method :using_rpx?, :using_rpx__internal?
101
+ alias_method :add_rpx_identifier, :add_rpx_identifier__internal
102
+ alias_method :identified_by?, :identified_by__internal?
103
+ alias_method :merge_user_id, :merge_user_id__internal
104
+ has_many :rpx_identifiers, :class_name => 'RPXIdentifier', :dependent => :destroy
105
+
106
+ # Add custom find_by_rpx_identifier class method
107
+ def self.find_by_rpx_identifier(id)
108
+ identifier = RPXIdentifier.find_by_identifier(id)
109
+ if identifier.nil?
110
+ if self.column_names.include? 'rpx_identifier'
111
+ # check for authentication using <=1.0.4, migrate identifier to rpx_identifiers table
112
+ user = self.find( :first, :conditions => [ "rpx_identifier = ?", id ] )
113
+ unless user.nil?
114
+ user.add_rpx_identifier( id, 'Unknown' )
115
+ end
116
+ return user
117
+ else
118
+ return nil
119
+ end
120
+ else
121
+ identifier.user
122
+ end
123
+ end
124
+
125
+ else
126
+ raise AuthlogicRpx::ActsAsAuthentic::ConfigurationError.new( "invalid or unsupported account_mapping_mode" )
127
+ end
128
+
36
129
  validates_length_of_password_field_options validates_length_of_password_field_options.merge(:if => :validate_password_with_rpx?)
37
130
  validates_confirmation_of_password_field_options validates_confirmation_of_password_field_options.merge(:if => :validate_password_with_rpx?)
38
131
  validates_length_of_password_confirmation_field_options validates_length_of_password_confirmation_field_options.merge(:if => :validate_password_with_rpx?)
132
+
39
133
  before_validation :adding_rpx_identifier
40
- after_create :map_rpx_identifier
134
+ end
135
+
136
+ RPXIdentifier.class_eval do
137
+ belongs_to klass.name.downcase.to_sym
41
138
  end
42
139
  end
43
140
 
@@ -49,65 +146,135 @@ module AuthlogicRpx
49
146
  end
50
147
 
51
148
  # test if account it using RPX authentication
52
- def using_rpx?
53
- !rpx_identifier.blank?
149
+ # aliased to using_rpx based on authlogic_rpx configuration mode
150
+ def using_rpx__nomap?
151
+ !rpx_identifier.blank?
54
152
  end
55
-
153
+ def using_rpx__internal?
154
+ !rpx_identifiers.empty?
155
+ end
156
+
56
157
  # test if account it using normal password authentication
57
158
  def using_password?
58
159
  !send(crypted_password_field).blank?
59
160
  end
60
161
 
162
+ # adds RPX identification to the instance.
163
+ # Abstracts how the RPX identifier is added to allow for multiplicity of underlying implementations
164
+ # aliased to add_rpx_identifier based on authlogic_rpx configuration mode
165
+ def add_rpx_identifier__nomap( rpx_id, rpx_provider_name )
166
+ self.rpx_identifier = rpx_id
167
+ #TODO: make rpx_provider_name a std param?
168
+ end
169
+ def add_rpx_identifier__internal( rpx_id, rpx_provider_name )
170
+ self.rpx_identifiers.build(:identifier => rpx_id, :provider_name => rpx_provider_name )
171
+ end
172
+
173
+ # Checks if given identifier is an identity for this account
174
+ # aliased to identified_by based on authlogic_rpx configuration mode
175
+ def identified_by__nomap?( id )
176
+ self.rpx_identifier == id
177
+ end
178
+ def identified_by__internal?( id )
179
+ self.rpx_identifiers.find_by_identifier( id )
180
+ end
181
+
61
182
  private
62
183
 
184
+ # tests if password authentication should be checked: if rpx is enabled (but not used by this user)
63
185
  def validate_password_with_rpx?
64
186
  !using_rpx? && require_password?
65
187
  end
188
+
189
+ # determines if account merging is enabled; delegates to class method
190
+ def account_merge_enabled?
191
+ self.class.account_merge_enabled_value
192
+ end
66
193
 
67
194
  # hook for adding RPX identifier to an existing account. This is invoked prior to model validation.
68
195
  # RPX information is plucked from the controller session object (where it was placed by the session model as a result
69
196
  # of the RPX callback)
70
- # The minimal action taken is to populate the rpx_identifier field in the user model.
197
+ # The minimal action taken is to add an RPXIdentifier object to the user.
71
198
  #
72
199
  # This procedure chains to the map_added_rpx_data, which may be over-ridden in your project to perform
73
200
  # additional mapping of RPX information to the user model as may be desired.
74
201
  #
75
202
  def adding_rpx_identifier
76
203
  return true unless session_class && session_class.controller
77
- added_rpx_data = session_class.controller.session['added_rpx_data']
204
+
205
+ added_rpx_data = session_class.controller.session['added_rpx_data']
78
206
  unless added_rpx_data.blank?
79
207
  session_class.controller.session['added_rpx_data'] = nil
208
+ rpx_id = added_rpx_data['profile']['identifier']
209
+ rpx_provider_name = added_rpx_data['profile']['providerName']
210
+
211
+ unless self.identified_by?( rpx_id )
212
+ # identifier not already set for this user..
213
+
214
+ another_user = self.class.find_by_rpx_identifier( rpx_id )
215
+ if another_user
216
+ return false unless account_merge_enabled?
217
+ # another user already has this id registered..
218
+
219
+ # merge all IDs from another_user to self, with application callbacks before/after
220
+ before_merge_rpx_data( another_user, self )
221
+ merge_user_id another_user
222
+ after_merge_rpx_data( another_user, self )
223
+
224
+ else
225
+ self.add_rpx_identifier( rpx_id, rpx_provider_name )
226
+ end
227
+ end
228
+
80
229
  map_added_rpx_data( added_rpx_data )
81
230
  end
231
+
82
232
  return true
233
+ end
234
+
235
+ # merge_user_id is an internal method used to merge the actual RPX identifiers
236
+ # aliased to merge_user_id based on authlogic_rpx configuration mode
237
+ def merge_user_id__nomap( from_user )
238
+ self.rpx_identifier = from_user.rpx_identifier
239
+ from_user.rpx_identifier = nil
240
+ from_user.save
241
+ from_user.reload
242
+ end
243
+ def merge_user_id__internal( from_user )
244
+ self.rpx_identifiers << from_user.rpx_identifiers
245
+ from_user.reload
83
246
  end
84
247
 
248
+
85
249
  # map_added_rpx_data maps additional fields from the RPX response into the user object during the "add RPX to existing account" process.
86
250
  # Override this in your user model to perform field mapping as may be desired
87
251
  # See https://rpxnow.com/docs#profile_data for the definition of available attributes
88
252
  #
89
- # By default, it only maps the rpx_identifier field.
253
+ # "self" at this point is the user model. Map details as appropriate from the rpx_data structure provided.
90
254
  #
91
255
  def map_added_rpx_data( rpx_data )
92
- self.rpx_identifier = rpx_data['profile']['identifier']
256
+
93
257
  end
258
+
259
+ # before_merge_rpx_data provides a hook for application developers to perform data migration prior to the merging of user accounts.
260
+ # This method is called just before authlogic_rpx merges the user registration for 'from_user' into 'to_user'
261
+ # Authlogic_RPX is responsible for merging registration data.
262
+ #
263
+ # By default, it does not merge any other details (e.g. application data ownership)
264
+ #
265
+ def before_merge_rpx_data( from_user, to_user )
94
266
 
95
-
96
-
97
- # experimental - a feature of RPX paid accounts and not properly developed/tested yet
98
- def map_id?
99
- self.class.map_id
100
- end
101
-
102
- # experimental - a feature of RPX paid accounts and not properly developed/tested yet
103
- def map_rpx_identifier
104
- RPXNow.map(rpx_identifier, id) if using_rpx? && map_id?
105
267
  end
106
268
 
107
- # experimental - a feature of RPX paid accounts and not properly developed/tested yet
108
- def unmap_rpx_identifer
109
- RPXNow.unmap(rpx_identifier, id) if using_rpx? && map_id?
269
+ # after_merge_rpx_data provides a hook for application developers to perform account clean-up after authlogic_rpx has
270
+ # migrated registration details.
271
+ #
272
+ # By default, does nothing. It could, for example, be used to delete or disable the 'from_user' account
273
+ #
274
+ def after_merge_rpx_data( from_user, to_user )
275
+
110
276
  end
277
+
111
278
 
112
279
  end
113
280
  end