@@ -118,12 +118,28 @@ def authorize_resource
118118
119119 # Helper method to find invitation by token
120120 def find_invitation_by_token
121- return nil unless current_invitation_token . present?
121+ # Prefer explicit token param (fresh request) and fall back to the current token
122+ token = params [ :invitation_token ] . presence || params [ :token ] . presence || current_invitation_token
123+ return nil unless token . present?
124+
125+ # Try to scope the invitation to the current event when possible
126+ invitation = if @event
127+ BetterTogether ::EventInvitation . pending . not_expired . find_by ( token : token , invitable : @event )
128+ else
129+ BetterTogether ::EventInvitation . pending . not_expired . find_by ( token : token )
130+ end
131+
132+ # If token came in params and invitation is valid for this event, persist it in session
133+ if invitation && ( params [ :invitation_token ] . present? || params [ :token ] . present? )
134+ session [ :event_invitation_token ] = invitation . token
135+ session [ :event_invitation_expires_at ] = 24 . hours . from_now
136+ I18n . locale = invitation . locale if invitation . locale . present?
137+ session [ :locale ] = I18n . locale
138+ # ensure the authorization concern sees the most recent token
139+ set_current_invitation_token ( invitation . token )
140+ end
122141
123- BetterTogether ::EventInvitation . find_by (
124- token : current_invitation_token ,
125- invitable : @event
126- )
142+ invitation
127143 end
128144
129145 # Process event invitation tokens before inherited (ApplicationController) callbacks
@@ -138,19 +154,35 @@ def check_platform_privacy
138154 # If host platform is public or user is signed in, let ApplicationController handle it
139155 return super if helpers . host_platform . privacy_public? || current_user . present?
140156
141- token = params [ :invitation_token ] . presence || params [ :token ] . presence
157+ # Consider explicit params token first, then session-stored event tokens
158+ token = params [ :invitation_token ] . presence || params [ :token ] . presence || session [ :event_invitation_token ] . presence
142159 if token . present? && params [ :id ] . present?
160+ # Find any invitation by token (including expired) so we can distinguish expired vs non-existent
161+ invitation_any = ::BetterTogether ::EventInvitation . find_by ( token : token )
162+
163+ # If no invitation exists at all, treat as no valid token -> fall back to ApplicationController (redirect to login)
164+ return super unless invitation_any . present?
165+
166+ # If an invitation exists but is not valid (expired or not pending), fall back to ApplicationController
167+ expired = invitation_any . valid_until . present? && Time . current > invitation_any . valid_until
168+ return super unless invitation_any . pending? && !expired
169+
170+ # Now find a valid, pending, not-expired invitation scoped to this event
143171 invitation = ::BetterTogether ::EventInvitation . pending . not_expired . find_by ( token : token )
144- if invitation
145- # Valid invitation: set locale and allow access
172+ if invitation && invitation . invitable . present? && invitation . invitable . slug == params [ :id ]
173+ # Valid invitation for this event: persist token, set locale and allow access
174+ session [ :event_invitation_token ] = invitation . token
175+ session [ :event_invitation_expires_at ] = 24 . hours . from_now
146176 I18n . locale = invitation . locale if invitation . locale . present?
147177 session [ :locale ] = I18n . locale
178+ # ensure the authorization concern sees the most recent token
179+ set_current_invitation_token ( invitation . token )
148180 return true
149- else
150- # Invalid token for this event on a private platform: render 404
151- render_not_found
152- return
153181 end
182+
183+ # Invitation exists but does not match this event -> render 404
184+ render_not_found
185+ return
154186 end
155187
156188 # Fall back to ApplicationController implementation for other cases
0 commit comments