@@ -7,6 +7,7 @@ class RegistrationsController < ::Devise::RegistrationsController # rubocop:todo
77 include DeviseLocales
88
99 skip_before_action :check_platform_privacy
10+ before_action :configure_permitted_parameters
1011 before_action :set_required_agreements , only : %i[ new create ]
1112 before_action :set_event_invitation_from_session , only : %i[ new create ]
1213 before_action :configure_account_update_params , only : [ :update ]
@@ -63,18 +64,12 @@ def update # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
6364
6465 def new
6566 super do |user |
66- # Pre-fill email from platform invitation
67- user . email = @platform_invitation . invitee_email if @platform_invitation && user . email . empty?
68-
69- if @event_invitation
70- # Pre-fill email from event invitation
71- user . email = @event_invitation . invitee_email if @event_invitation && user . email . empty?
72- user . person = @event_invitation . invitee if @event_invitation . invitee . present?
73- end
67+ setup_user_from_invitations ( user )
68+ user . build_person unless user . person
7469 end
7570 end
7671
77- def create # rubocop:todo Metrics/MethodLength
72+ def create # rubocop:todo Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
7873 unless agreements_accepted?
7974 handle_agreements_not_accepted
8075 return
@@ -87,11 +82,25 @@ def create # rubocop:todo Metrics/MethodLength
8782 return
8883 end
8984
85+ # Use transaction for all user creation and associated records
9086 ActiveRecord ::Base . transaction do
91- super do |user |
92- handle_user_creation ( user ) if user . persisted?
87+ # Call Devise's default create behavior
88+ super
89+
90+ # Handle post-registration setup if user was created successfully
91+ if resource . persisted? && resource . errors . empty?
92+ handle_user_creation ( resource )
93+ elsif resource . persisted?
94+ # User was created but has errors - rollback to maintain consistency
95+ raise ActiveRecord ::Rollback
9396 end
9497 end
98+ rescue ActiveRecord ::RecordInvalid , ActiveRecord ::InvalidForeignKey => e
99+ # Clean up and show user-friendly error
100+ Rails . logger . error "Registration failed: #{ e . message } "
101+ build_resource ( sign_up_params ) if resource . nil?
102+ resource &.errors &.add ( :base , 'Registration could not be completed. Please try again.' )
103+ respond_with resource
95104 end
96105
97106 protected
@@ -105,6 +114,10 @@ def configure_account_update_params
105114 keys : %i[ email password password_confirmation current_password ] )
106115 end
107116
117+ def configure_permitted_parameters
118+ devise_parameter_sanitizer . permit ( :sign_up , keys : [ person_attributes : %i[ identifier name description ] ] )
119+ end
120+
108121 def set_required_agreements
109122 @privacy_policy_agreement = BetterTogether ::Agreement . find_by ( identifier : 'privacy_policy' )
110123 @terms_of_service_agreement = BetterTogether ::Agreement . find_by ( identifier : 'terms_of_service' )
@@ -170,32 +183,116 @@ def handle_agreements_not_accepted
170183 respond_with resource
171184 end
172185
186+ def setup_user_from_invitations ( user )
187+ # Pre-fill email from platform invitation
188+ user . email = @platform_invitation . invitee_email if @platform_invitation && user . email . empty?
189+
190+ return unless @event_invitation
191+
192+ # Pre-fill email from event invitation
193+ user . email = @event_invitation . invitee_email if @event_invitation && user . email . empty?
194+ user . person = @event_invitation . invitee if @event_invitation . invitee . present?
195+ end
196+
173197 def handle_user_creation ( user )
174- setup_person_for_user ( user )
175- return unless user . save!
198+ return unless event_invitation_person_updated? ( user )
176199
200+ # Reload user to ensure all nested attributes and associations are properly loaded
177201 user . reload
178- setup_community_membership ( user )
202+ person = user . person
203+
204+ return unless person_persisted? ( user , person )
205+
206+ setup_community_membership ( user , person )
179207 handle_platform_invitation ( user )
180208 handle_event_invitation ( user )
181- create_agreement_participants ( user . person )
209+ create_agreement_participants ( person )
210+ end
211+
212+ def event_invitation_person_updated? ( user )
213+ return true unless @event_invitation &.invitee . present?
214+
215+ return true if user . person . update ( person_params )
216+
217+ Rails . logger . error "Failed to update person for event invitation: #{ user . person . errors . full_messages } "
218+ false
219+ end
220+
221+ def person_persisted? ( user , person )
222+ return true if person &.persisted?
223+
224+ Rails . logger . error "Person not found or not persisted for user #{ user . id } "
225+ false
182226 end
183227
184228 def setup_person_for_user ( user )
185- if @event_invitation && @event_invitation . invitee . present?
186- user . person = @event_invitation . invitee
187- user . person . update ( person_params )
188- else
189- user . build_person ( person_params )
190- end
229+ return update_existing_person_for_event ( user ) if @event_invitation &.invitee . present?
230+
231+ create_new_person_for_user ( user )
232+ end
233+
234+ def update_existing_person_for_event ( user )
235+ user . person = @event_invitation . invitee
236+ return if user . person . update ( person_params )
237+
238+ Rails . logger . error "Failed to update person for event invitation: #{ user . person . errors . full_messages } "
239+ user . errors . add ( :person , 'Could not update person information' )
191240 end
192241
193- def setup_community_membership ( user )
242+ def create_new_person_for_user ( user )
243+ return handle_empty_person_params ( user ) if person_params . empty?
244+
245+ user . build_person ( person_params )
246+ return unless person_validated_and_saved? ( user )
247+
248+ save_person_identification ( user )
249+ end
250+
251+ def handle_empty_person_params ( user )
252+ Rails . logger . error 'Person params are empty, cannot build person'
253+ user . errors . add ( :person , 'Person information is required' )
254+ end
255+
256+ def person_validated_and_saved? ( user )
257+ return save_person? ( user ) if user . person . valid?
258+
259+ Rails . logger . error "Person validation failed: #{ user . person . errors . full_messages } "
260+ user . errors . add ( :person , 'Person information is invalid' )
261+ false
262+ end
263+
264+ def save_person? ( user )
265+ return true if user . person . save
266+
267+ Rails . logger . error "Failed to save person: #{ user . person . errors . full_messages } "
268+ user . errors . add ( :person , 'Could not save person information' )
269+ false
270+ end
271+
272+ def save_person_identification ( user )
273+ person_identification = user . person_identification
274+ return if person_identification &.save
275+
276+ Rails . logger . error "Failed to save person identification: #{ person_identification &.errors &.full_messages } "
277+ user . errors . add ( :person , 'Could not link person to user' )
278+ end
279+
280+ def setup_community_membership ( user , person_param = nil )
281+ person = person_param || user . person
194282 community_role = determine_community_role
195- helpers . host_community . person_community_memberships . find_or_create_by! (
196- member : user . person ,
197- role : community_role
198- )
283+
284+ begin
285+ helpers . host_community . person_community_memberships . find_or_create_by! (
286+ member : person ,
287+ role : community_role
288+ )
289+ rescue ActiveRecord ::InvalidForeignKey => e
290+ Rails . logger . error "Foreign key violation creating community membership: #{ e . message } "
291+ raise e
292+ rescue StandardError => e
293+ Rails . logger . error "Unexpected error creating community membership: #{ e . message } "
294+ raise e
295+ end
199296 end
200297
201298 def handle_platform_invitation ( user )
@@ -235,10 +332,18 @@ def after_update_path_for(_resource)
235332 end
236333
237334 def person_params
335+ return { } unless params [ :user ] && params [ :user ] [ :person_attributes ]
336+
238337 params . require ( :user ) . require ( :person_attributes ) . permit ( %i[ identifier name description ] )
338+ rescue ActionController ::ParameterMissing => e
339+ Rails . logger . error "Missing person parameters: #{ e . message } "
340+ { }
239341 end
240342
241343 def agreements_accepted?
344+ # Ensure required agreements are set
345+ set_required_agreements if @privacy_policy_agreement . nil?
346+
242347 required = [ params [ :privacy_policy_agreement ] , params [ :terms_of_service_agreement ] ]
243348 # If a code of conduct agreement exists, require it as well
244349 required << params [ :code_of_conduct_agreement ] if @code_of_conduct_agreement . present?
@@ -247,11 +352,21 @@ def agreements_accepted?
247352 end
248353
249354 def create_agreement_participants ( person )
355+ unless person &.persisted?
356+ Rails . logger . error 'Cannot create agreement participants - person not persisted'
357+ return
358+ end
359+
250360 identifiers = %w[ privacy_policy terms_of_service ]
251361 identifiers << 'code_of_conduct' if BetterTogether ::Agreement . exists? ( identifier : 'code_of_conduct' )
252362 agreements = BetterTogether ::Agreement . where ( identifier : identifiers )
363+
253364 agreements . find_each do |agreement |
254- BetterTogether ::AgreementParticipant . create! ( agreement : agreement , person : person , accepted_at : Time . current )
365+ BetterTogether ::AgreementParticipant . create! (
366+ agreement : agreement ,
367+ person : person ,
368+ accepted_at : Time . current
369+ )
255370 end
256371 end
257372 end
0 commit comments