mailers: add procedure context to the confirmation link

This allows to redirect the user to the procedure they signed up for
even when the browser session is not available (like if they changed
of browser).

Fix #4738
This commit is contained in:
Pierre de La Morinerie 2020-02-24 10:55:29 +00:00 committed by GitHub Action
parent 10c940c188
commit 6664965961
8 changed files with 50 additions and 5 deletions

View file

@ -42,9 +42,19 @@ class Users::ConfirmationsController < Devise::ConfirmationsController
if sign_in_after_confirmation?(resource)
resource.remember_me = true
sign_in(resource)
end
if procedure_from_params
commencer_path(path: procedure_from_params.path)
elsif signed_in?
# Will try to use `stored_location_for` to find a path
after_sign_in_path_for(resource_name)
else
super(resource_name, resource)
end
end
def procedure_from_params
params[:procedure_id] && Procedure.find_by(id: params[:procedure_id])
end
end

View file

@ -21,6 +21,12 @@ class Users::RegistrationsController < Devise::RegistrationsController
# POST /resource
def create
# We may need the confirmation mailer to access the current procedure.
# But there's no easy way to pass an argument to the mailer through
# all Devise code.
# So instead we use a per-request global variable.
CurrentConfirmation.procedure_after_confirmation = @procedure
# Handle existing user trying to sign up again
existing_user = User.find_by(email: params[:user][:email])
if existing_user.present?

View file

@ -15,6 +15,7 @@ class DeviseUserMailer < Devise::Mailer
def confirmation_instructions(record, token, opts = {})
opts[:from] = NO_REPLY_EMAIL
@procedure = CurrentConfirmation.procedure_after_confirmation || nil
super
end
end

View file

@ -0,0 +1,3 @@
class CurrentConfirmation < ActiveSupport::CurrentAttributes
attribute :procedure_after_confirmation
end

View file

@ -7,7 +7,8 @@
%p
Pour activer votre compte sur demarches-simplifiees.fr, veuillez cliquer sur le lien suivant :
= link_to(confirmation_url(@user, confirmation_token: @token), confirmation_url(@user, confirmation_token: @token))
- link = confirmation_url(@user, confirmation_token: @token, procedure_id: @procedure&.id)
= link_to(link, link)
- else
- content_for(:title, "Changement d'adresse email")

View file

@ -77,8 +77,10 @@ feature 'Signing up:' do
sign_up_with user_email, user_password
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
click_confirmation_link_for user_email
click_confirmation_link_for(user_email, in_another_browser: true)
# After confirmation, the user is redirected to the procedure they were initially starting
# (even when confirming the account in another browser).
expect(page).to have_current_path(commencer_path(path: procedure.path))
expect(page).to have_content 'Votre compte a été activé'
click_on 'Commencer la démarche'
@ -106,6 +108,14 @@ feature 'Signing up:' do
# The confirmation email is sent again
confirmation_email = open_email(user_email)
expect(confirmation_email.body).to have_text('Pour activer votre compte')
click_confirmation_link_for(user_email, in_another_browser: true)
# After confirmation, the user is redirected to the procedure they were initially starting
# (even when confirming the account in another browser).
expect(page).to have_current_path(commencer_path(path: procedure.path))
expect(page).to have_content 'Votre compte a été activé'
expect(page).to have_content 'Commencer la démarche'
end
end

View file

@ -3,6 +3,11 @@ class DeviseUserMailerPreview < ActionMailer::Preview
DeviseUserMailer.confirmation_instructions(user, "faketoken", {})
end
def confirmation_instructions___with_procedure
CurrentConfirmation.procedure_after_confirmation = procedure
DeviseUserMailer.confirmation_instructions(user, "faketoken", {})
end
def reset_password_instructions
DeviseUserMailer.reset_password_instructions(user, "faketoken", {})
end
@ -12,4 +17,8 @@ class DeviseUserMailerPreview < ActionMailer::Preview
def user
User.new(id: 10, email: "usager@example.com")
end
def procedure
Procedure.new(id: 20, libelle: 'Dotation dÉquipement des Territoires Ruraux - Exercice 2019', path: 'dotation-etr')
end
end

View file

@ -48,11 +48,16 @@ module FeatureHelpers
end
end
def click_confirmation_link_for(email)
def click_confirmation_link_for(email, in_another_browser: false)
confirmation_email = open_email(email)
token_params = confirmation_email.body.match(/confirmation_token=[^"]+/)
confirmation_link = confirmation_email.body.match(/href="[^"]*(\/users\/confirmation[^"]*)"/)[1]
visit "/users/confirmation?#{token_params}"
if in_another_browser
# Simulate the user opening the link in another browser, thus loosing the session cookie
Capybara.reset_session!
end
visit confirmation_link
end
def click_procedure_sign_in_link_for(email)