authlogic_rpx 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/CHANGELOG.rdoc +45 -38
  2. data/MIT-LICENSE +20 -20
  3. data/Manifest +37 -37
  4. data/README.rdoc +751 -747
  5. data/Rakefile +54 -47
  6. data/authlogic_rpx.gemspec +101 -38
  7. data/generators/add_authlogic_rpx_migration/USAGE +18 -18
  8. data/generators/add_authlogic_rpx_migration/add_authlogic_rpx_migration_generator.rb +44 -44
  9. data/generators/add_authlogic_rpx_migration/templates/migration_internal_mapping.rb +34 -34
  10. data/generators/add_authlogic_rpx_migration/templates/migration_no_mapping.rb +29 -29
  11. data/lib/authlogic_rpx.rb +8 -8
  12. data/lib/authlogic_rpx/acts_as_authentic.rb +297 -281
  13. data/lib/authlogic_rpx/helper.rb +53 -43
  14. data/lib/authlogic_rpx/rpx_identifier.rb +4 -5
  15. data/lib/authlogic_rpx/session.rb +224 -218
  16. data/lib/authlogic_rpx/version.rb +50 -50
  17. data/test/fixtures/rpxresponses.yml +20 -20
  18. data/test/fixtures/users.yml +19 -19
  19. data/test/integration/basic_authentication_and_registration_test.rb +52 -52
  20. data/test/integration/internal_mapping/basic_authentication_and_registration_test.rb +3 -3
  21. data/test/integration/internal_mapping/settings_test.rb +9 -9
  22. data/test/integration/no_mapping/basic_authentication_and_registration_test.rb +3 -3
  23. data/test/integration/no_mapping/settings_test.rb +9 -9
  24. data/test/libs/ext_test_unit.rb +30 -30
  25. data/test/libs/mock_rpx_now.rb +33 -33
  26. data/test/libs/rails_trickery.rb +40 -40
  27. data/test/libs/rpxresponse.rb +2 -2
  28. data/test/libs/user.rb +2 -2
  29. data/test/libs/user_session.rb +2 -2
  30. data/test/test_helper.rb +84 -86
  31. data/test/test_internal_mapping_helper.rb +93 -95
  32. data/test/unit/acts_as_authentic_settings_test.rb +41 -41
  33. data/test/unit/session_settings_test.rb +37 -37
  34. data/test/unit/session_validation_test.rb +15 -15
  35. data/test/unit/verify_rpx_mock_test.rb +28 -28
  36. metadata +66 -32
@@ -1,44 +1,54 @@
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
- # The options hash may include other options as supported by rpx_now (see http://github.com/grosser/rpx_now)
11
- #
12
- def rpx_embed(options = {})
13
- app_name = options.delete( :app_name )
14
- token_url = build_token_url!( options )
15
- RPXNow.embed_code(app_name, token_url, options )
16
- end
17
-
18
- # helper to insert a link to pop-up RPX login
19
- # takes options hash:
20
- # * <tt>link_text:</tt> text to use in the link
21
- # * <tt>app_name:</tt> name of the application (will be prepended to RPX domain and used in RPX dialogues)
22
- # * <tt>return_url:</tt> url for the RPX callback (e.g. user_sessions_url)
23
- # * <tt>add_rpx:</tt> if true, requests RPX callback to add to current session. Else runs normal authentication process (default)
24
- # * <tt>unobtrusive:</tt> true/false; sets javascript style for link. Default: true
25
- #
26
- # The options hash may include other options as supported by rpx_now (see http://github.com/grosser/rpx_now)
27
- #
28
- def rpx_popup(options = {})
29
- options = { :unobtrusive => true, :add_rpx => false }.merge( options )
30
- app_name = options.delete( :app_name )
31
- link_text = options.delete( :link_text )
32
- token_url = build_token_url!( options )
33
- RPXNow.popup_code( link_text, app_name, token_url, options )
34
- end
35
-
36
- private
37
-
38
- def build_token_url!( options )
39
- options.delete( :return_url ) + '?' + (
40
- { :authenticity_token => form_authenticity_token, :add_rpx => options.delete( :add_rpx ) }.collect { |n| "#{n[0]}=#{ u(n[1]) }" if n[1] }
41
- ).compact.join('&')
42
- end
43
- end
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
+ # The options hash may include other options as supported by rpx_now (see http://github.com/grosser/rpx_now)
11
+ #
12
+ def rpx_embed(options = {})
13
+ app_name = options.delete( :app_name )
14
+ token_url = build_token_url!( options )
15
+ html = RPXNow.embed_code(app_name, token_url, options )
16
+ if defined? raw
17
+ raw html
18
+ else
19
+ html
20
+ end
21
+ end
22
+
23
+ # helper to insert a link to pop-up RPX login
24
+ # takes options hash:
25
+ # * <tt>link_text:</tt> text to use in the link
26
+ # * <tt>app_name:</tt> name of the application (will be prepended to RPX domain and used in RPX dialogues)
27
+ # * <tt>return_url:</tt> url for the RPX callback (e.g. user_sessions_url)
28
+ # * <tt>add_rpx:</tt> if true, requests RPX callback to add to current session. Else runs normal authentication process (default)
29
+ # * <tt>unobtrusive:</tt> true/false; sets javascript style for link. Default: true
30
+ #
31
+ # The options hash may include other options as supported by rpx_now (see http://github.com/grosser/rpx_now)
32
+ #
33
+ def rpx_popup(options = {})
34
+ options = { :unobtrusive => true, :add_rpx => false }.merge( options )
35
+ app_name = options.delete( :app_name )
36
+ link_text = options.delete( :link_text )
37
+ token_url = build_token_url!( options )
38
+ html = RPXNow.popup_code( link_text, app_name, token_url, options )
39
+ if defined? raw
40
+ raw html
41
+ else
42
+ html
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def build_token_url!( options )
49
+ options.delete( :return_url ) + '?' + (
50
+ { :authenticity_token => form_authenticity_token, :add_rpx => options.delete( :add_rpx ) }.collect { |n| "#{n[0]}=#{ u(n[1]) }" if n[1] }
51
+ ).compact.join('&')
52
+ end
53
+ end
44
54
  end
@@ -1,5 +1,4 @@
1
- class RPXIdentifier < ActiveRecord::Base
2
- validates_presence_of :identifier
3
- validates_uniqueness_of :identifier
4
- validates_presence_of :user_id
5
- end
1
+ class RPXIdentifier < ActiveRecord::Base
2
+ validates_presence_of :identifier
3
+ validates_uniqueness_of :identifier
4
+ end
@@ -1,219 +1,225 @@
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 || !new_registration.nil?
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? || @rpx_data['profile'].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
- rpx_provider_name = @rpx_data['profile']['providerName']
148
- if rpx_id.blank?
149
- errors.add_to_base("Authentication failed. Please try again.")
150
- return false
151
- end
152
-
153
- self.attempted_record = klass.send(find_by_rpx_identifier_method, rpx_id)
154
-
155
- # so what do we do if we can't find an existing user matching the RPX authentication...
156
- if !attempted_record
157
- if auto_register?
158
- self.attempted_record = klass.new()
159
- map_rpx_data
160
-
161
- # save the new user record - without session maintenance else we
162
- # get caught in a self-referential hell, since both session and
163
- # user objects invoke each other upon save
164
- self.new_registration = true
165
- self.attempted_record.add_rpx_identifier( rpx_id, rpx_provider_name)
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
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 || !new_registration.nil?
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
+ # TODO: rails 3 authlogic monkeypatch. Not sure if this code is quite right yet
84
+ def to_key
85
+ new_record? ? nil : [ self.send(self.class.primary_key) ]
86
+ end
87
+
88
+
89
+ private
90
+ # Tests if current request is for RPX authentication
91
+ #
92
+ def authenticating_with_rpx?
93
+ controller.params[:token] && !controller.params[:add_rpx]
94
+ end
95
+
96
+ # hook instance finder method to class
97
+ #
98
+ def find_by_rpx_identifier_method
99
+ self.class.find_by_rpx_identifier_method
100
+ end
101
+
102
+ # Tests if auto_registration is enabled (on by default)
103
+ #
104
+ def auto_register?
105
+ self.class.auto_register_value
106
+ end
107
+
108
+ # Tests if rpx_extended_info is enabled (off by default)
109
+ #
110
+ def rpx_extended_info?
111
+ self.class.rpx_extended_info_value
112
+ end
113
+
114
+ # Tests if current request is the special case of adding RPX to an existing account
115
+ #
116
+ def adding_rpx_identifier?
117
+ controller.params[:token] && controller.params[:add_rpx]
118
+ end
119
+
120
+ # Handles the special case of RPX being added to an existing account.
121
+ # At this point, a session has been established as a result of a "save" on the user model (which indirectly triggers user session validation).
122
+ # We do not directly add the RPX details to the user record here in order to avoid getting
123
+ # into a recursive dance between the session and user models.
124
+ # Rather, it uses the trick of adding the necessary RPX information to the session object,
125
+ # and the user model will pluck these values out before completing its validation step.
126
+ #
127
+ def add_rpx_identifier
128
+ data = RPXNow.user_data(controller.params[:token], :extended=> rpx_extended_info? ) {|raw| raw }
129
+ controller.session['added_rpx_data'] = data if data
130
+ end
131
+
132
+ # the main RPX magic. At this point, a session is being validated and we know RPX identifier
133
+ # has been provided. We'll callback to RPX to verify the token, and authenticate the matching
134
+ # user.
135
+ # If no user is found, and we have auto_register enabled (default) this method will also
136
+ # create the user registration stub.
137
+ #
138
+ # On return to the controller, you can test for new_registration? and registration_complete?
139
+ # to determine the most appropriate action
140
+ #
141
+ def validate_by_rpx
142
+ @rpx_data = RPXNow.user_data(
143
+ controller.params[:token],
144
+ :extended => rpx_extended_info?) { |raw| raw }
145
+
146
+ # If we don't have a valid sign-in, give-up at this point
147
+ if @rpx_data.nil? || @rpx_data['profile'].nil?
148
+ errors.add_to_base("Authentication failed. Please try again.")
149
+ return false
150
+ end
151
+
152
+ rpx_id = @rpx_data['profile']['identifier']
153
+ rpx_provider_name = @rpx_data['profile']['providerName']
154
+ if rpx_id.blank?
155
+ errors.add_to_base("Authentication failed. Please try again.")
156
+ return false
157
+ end
158
+
159
+ self.attempted_record = klass.send(find_by_rpx_identifier_method, rpx_id)
160
+
161
+ # so what do we do if we can't find an existing user matching the RPX authentication...
162
+ if !attempted_record
163
+ if auto_register?
164
+ self.attempted_record = klass.new()
165
+ map_rpx_data
166
+
167
+ # save the new user record - without session maintenance else we
168
+ # get caught in a self-referential hell, since both session and
169
+ # user objects invoke each other upon save
170
+ self.new_registration = true
171
+ self.attempted_record.add_rpx_identifier( rpx_id, rpx_provider_name)
172
+ self.attempted_record.save_without_session_maintenance
173
+ else
174
+ errors.add_to_base("We did not find any accounts with that login. Enter your details and create an account.")
175
+ return false
176
+ end
177
+ else
178
+ map_rpx_data_each_login
179
+ end
180
+
181
+ end
182
+
183
+ # map_rpx_data maps additional fields from the RPX response into the user object during auto-registration.
184
+ # Override this in your session model to change the field mapping
185
+ # See https://rpxnow.com/docs#profile_data for the definition of available attributes
186
+ #
187
+ # In this procedure, you will be writing to fields of the "self.attempted_record" object, pulling data from the @rpx_data object.
188
+ #
189
+ # WARNING: if you are using auto-registration, any fields you map should NOT have constraints enforced at the database level.
190
+ # authlogic_rpx will optimistically attempt to save the user record during registration, and
191
+ # violating a database constraint will cause the authentication/registration to fail.
192
+ #
193
+ # You can/should enforce any required validations at the model level e.g.
194
+ # validates_uniqueness_of :username, :case_sensitive => false
195
+ # This will allow the auto-registration to proceed, and the user can be given a chance to rectify the validation errors
196
+ # on your user profile page.
197
+ #
198
+ # If it is not acceptable in your application to have user records created with potential validation errors in auto-populated fields, you
199
+ # will need to override map_rpx_data and implement whatever special handling makes sense in your case. For example:
200
+ # - directly check for uniqueness and other validation requirements
201
+ # - automatically "uniquify" fields like username
202
+ # - save conflicting profile information to "pending user review" columns or a seperate table
203
+ #
204
+ def map_rpx_data
205
+ self.attempted_record.send("#{klass.login_field}=", @rpx_data['profile']['preferredUsername'] ) if attempted_record.send(klass.login_field).blank?
206
+ self.attempted_record.send("#{klass.email_field}=", @rpx_data['profile']['email'] ) if attempted_record.send(klass.email_field).blank?
207
+ end
208
+
209
+ # map_rpx_data_each_login provides a hook to allow you to map RPX profile information every time the user
210
+ # logs in.
211
+ # By default, nothing is mapped.
212
+ #
213
+ # This would mainly be used to update relatively volatile information that you are maintaining in the user model (such as profile image url)
214
+ #
215
+ # In this procedure, you will be writing to fields of the "self.attempted_record" object, pulling data from the @rpx_data object.
216
+ #
217
+ #
218
+ def map_rpx_data_each_login
219
+
220
+ end
221
+
222
+ end
223
+
224
+ end
219
225
  end