From ea354d46c438d3689a4f640ae7c4373b283caa24 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Tue, 23 Jul 2024 10:52:51 +0200 Subject: [PATCH 1/3] Create new invitation email if expert not confirm --- .../concerns/create_avis_concern.rb | 6 +++- app/controllers/experts/avis_controller.rb | 1 + .../instructeurs/avis_controller.rb | 6 +++- app/mailers/avis_mailer.rb | 19 +++++++++++ app/models/targeted_user_link.rb | 6 ++-- app/models/user.rb | 14 +++++--- .../avis_mailer/avis_invitation.html.haml | 8 ++--- ...vis_invitation_and_confirm_email.html.haml | 33 +++++++++++++++++++ 8 files changed, 78 insertions(+), 15 deletions(-) create mode 100644 app/views/avis_mailer/avis_invitation_and_confirm_email.html.haml diff --git a/app/controllers/concerns/create_avis_concern.rb b/app/controllers/concerns/create_avis_concern.rb index ad29b06c0..47a51c1f2 100644 --- a/app/controllers/concerns/create_avis_concern.rb +++ b/app/controllers/concerns/create_avis_concern.rb @@ -60,7 +60,11 @@ module CreateAvisConcern avis.dossier.demander_un_avis!(avis) if avis.dossier == dossier if avis.experts_procedure.notify_on_new_avis? - AvisMailer.avis_invitation(avis).deliver_later + if avis.expert.user.unverified_email? + avis.expert.user.invite_expert_and_send_avis!(avis) + else + AvisMailer.avis_invitation(avis).deliver_later + end end sent_emails_addresses << avis.expert.email # the email format is already verified, we update value to nil diff --git a/app/controllers/experts/avis_controller.rb b/app/controllers/experts/avis_controller.rb index c7f3bfde4..d0d238b4f 100644 --- a/app/controllers/experts/avis_controller.rb +++ b/app/controllers/experts/avis_controller.rb @@ -144,6 +144,7 @@ module Experts if user.valid? sign_in(user) + user.update!(email_verified_at: Time.zone.now) if user.unverified_email? redirect_to url_for(expert_all_avis_path) else flash[:alert] = user.errors.full_messages diff --git a/app/controllers/instructeurs/avis_controller.rb b/app/controllers/instructeurs/avis_controller.rb index 9f5cb46b2..3fd9f75b3 100644 --- a/app/controllers/instructeurs/avis_controller.rb +++ b/app/controllers/instructeurs/avis_controller.rb @@ -17,7 +17,11 @@ module Instructeurs def remind avis = Avis.find(params[:id]) if avis.remind_by!(current_instructeur) - AvisMailer.avis_invitation(avis).deliver_later + if avis.expert.user.unverified_email? + avis.expert.user.invite_expert_and_send_avis!(avis) + else + AvisMailer.avis_invitation(avis).deliver_later + end flash.notice = "Un mail de relance a été envoyé à #{avis.expert.email}" redirect_back(fallback_location: avis_instructeur_dossier_path(avis.procedure, avis.dossier)) end diff --git a/app/mailers/avis_mailer.rb b/app/mailers/avis_mailer.rb index 1efa8116f..702420253 100644 --- a/app/mailers/avis_mailer.rb +++ b/app/mailers/avis_mailer.rb @@ -20,6 +20,25 @@ class AvisMailer < ApplicationMailer end end + def avis_invitation_and_confirm_email(user, token, avis, targeted_user_link = nil) # ensure re-entrance if existing AvisMailer.avis_invitation in queue + if avis.dossier.visible_by_administration? + targeted_user_link = avis.targeted_user_links + .find_or_create_by(target_context: 'avis', + target_model_type: Avis.name, + target_model_id: avis.id, + user: avis.expert.user) + email = user.email + @token = token + @avis = avis + @url = targeted_user_link_url(targeted_user_link) + subject = "Donnez votre avis sur le dossier nº #{@avis.dossier.id} (#{@avis.dossier.procedure.libelle})" + + bypass_unverified_mail_protection! + + mail(to: email, subject: subject) + end + end + # i18n-tasks-use t("avis_mailer.#{action}.subject") def notify_new_commentaire_to_expert(dossier, avis, expert) I18n.with_locale(dossier.user_locale) do diff --git a/app/models/targeted_user_link.rb b/app/models/targeted_user_link.rb index 2d3d53660..a2d41a8d5 100644 --- a/app/models/targeted_user_link.rb +++ b/app/models/targeted_user_link.rb @@ -31,9 +31,11 @@ class TargetedUserLink < ApplicationRecord url_helper.invite_path(invite, params: { email: invite.email }) when "avis" avis = target_model - avis.expert.user.active? ? - url_helper.expert_avis_path(avis.procedure, avis) : + if avis.expert.user.active? + url_helper.expert_avis_path(avis.procedure, avis) + else url_helper.sign_up_expert_avis_path(avis.procedure, avis, email: avis.expert.email) + end end end diff --git a/app/models/user.rb b/app/models/user.rb index ee80ce46a..cb7234590 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -89,6 +89,12 @@ class User < ApplicationRecord UserMailer.invite_tiers(self, token, dossier).deliver_later end + def invite_expert_and_send_avis!(avis) + token = SecureRandom.hex(10) + self.update!(confirmation_token: token, confirmation_sent_at: Time.zone.now) + AvisMailer.avis_invitation_and_confirm_email(self, token, avis).deliver_later + end + def invite_gestionnaire!(groupe_gestionnaire) UserMailer.invite_gestionnaire(self, set_reset_password_token, groupe_gestionnaire).deliver_later end @@ -161,13 +167,11 @@ class User < ApplicationRecord def self.create_or_promote_to_expert(email, password) user = User - .create_with(password: password, confirmed_at: Time.zone.now, email_verified_at: Time.zone.now) + .create_with(password: password, confirmed_at: Time.zone.now) .find_or_create_by(email: email) - if user.valid? - if user.expert.nil? - user.create_expert! - end + if user.valid? && user.expert.nil? + user.create_expert! end user diff --git a/app/views/avis_mailer/avis_invitation.html.haml b/app/views/avis_mailer/avis_invitation.html.haml index e4bb0db96..262029b0d 100644 --- a/app/views/avis_mailer/avis_invitation.html.haml +++ b/app/views/avis_mailer/avis_invitation.html.haml @@ -22,11 +22,7 @@ %p{ style: "padding: 8px; color: #333333; background-color: #EEEEEE; font-size: 14px;" } = @avis.introduction -- if @avis.expert.user.active?.present? - %p - = round_button("Donner votre avis", @url, :primary) -- else - %p - = round_button("Inscrivez-vous pour donner votre avis", @url, :primary) +%p + = round_button("Donner votre avis", @url, :primary) = render partial: "layouts/mailers/signature" diff --git a/app/views/avis_mailer/avis_invitation_and_confirm_email.html.haml b/app/views/avis_mailer/avis_invitation_and_confirm_email.html.haml new file mode 100644 index 000000000..ce4db376a --- /dev/null +++ b/app/views/avis_mailer/avis_invitation_and_confirm_email.html.haml @@ -0,0 +1,33 @@ +- content_for(:title, 'Invitation à donner votre avis') + +- content_for(:footer) do + Merci de ne pas répondre à cet email. Donnez votre avis + = link_to("sur #{Current.application_name}", @url) + ou + = succeed '.' do + = mail_to(@avis.claimant.email, "contactez la personne qui vous a invité") + +%p + Bonjour, + +%p + Vous avez été invité par + %strong= @avis.claimant.email + = "à donner votre avis sur le dossier nº #{@avis.dossier.id} de la démarche :" + %strong= @avis.procedure.libelle + +%p + = "#{@avis.claimant.email} vous a écrit :" + %br +%p{ style: "padding: 8px; color: #333333; background-color: #EEEEEE; font-size: 14px;" } + = @avis.introduction + +- if @avis.expert.user.active? + %p + = round_button("Confirmer le mail pour donner votre avis", @url, :primary) +- else + %p + = round_button("Inscrivez-vous pour donner votre avis", @url, :primary) + + += render partial: "layouts/mailers/signature" From 3cf3dc462353008ebba0762b0ff0929275d3bc35 Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Wed, 21 Aug 2024 16:23:56 +0200 Subject: [PATCH 2/3] make email confirmation more generic --- app/controllers/users/activate_controller.rb | 2 +- app/mailers/user_mailer.rb | 14 ++++++++++++++ app/models/user.rb | 6 ++++++ ...avis_invitation_and_confirm_email.html.haml | 2 +- .../resend_confirmation_email.html.haml | 18 ++++++++++++++++++ 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 app/views/user_mailer/resend_confirmation_email.html.haml diff --git a/app/controllers/users/activate_controller.rb b/app/controllers/users/activate_controller.rb index 4ab7c47ac..f5dd798c8 100644 --- a/app/controllers/users/activate_controller.rb +++ b/app/controllers/users/activate_controller.rb @@ -40,7 +40,7 @@ class Users::ActivateController < ApplicationController else if user.present? flash[:alert] = "Ce lien n'est plus valable, un nouveau lien a été envoyé à l'adresse #{user.email}" - User.create_or_promote_to_tiers(user.email, SecureRandom.hex) + user.resend_confirmation_email! else flash[:alert] = "Un problème est survenu, vous pouvez nous contacter sur #{Current.contact_email}" end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index d6fb81b49..cff0e4649 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -63,6 +63,20 @@ class UserMailer < ApplicationMailer reply_to: Current.contact_email) end + def resend_confirmation_email(user, token) + @token = token + @user = user + subject = "Vérification de votre mail" + + configure_defaults_for_user(user) + + bypass_unverified_mail_protection! + + mail(to: user.email, + subject: subject, + reply_to: Current.contact_email) + end + def invite_gestionnaire(user, reset_password_token, groupe_gestionnaire) @reset_password_token = reset_password_token @user = user diff --git a/app/models/user.rb b/app/models/user.rb index cb7234590..98806a5d2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -95,6 +95,12 @@ class User < ApplicationRecord AvisMailer.avis_invitation_and_confirm_email(self, token, avis).deliver_later end + def resend_confirmation_email! + token = SecureRandom.hex(10) + self.update!(confirmation_token: token, confirmation_sent_at: Time.zone.now) + UserMailer.resend_confirmation_email(self, token).deliver_later + end + def invite_gestionnaire!(groupe_gestionnaire) UserMailer.invite_gestionnaire(self, set_reset_password_token, groupe_gestionnaire).deliver_later end diff --git a/app/views/avis_mailer/avis_invitation_and_confirm_email.html.haml b/app/views/avis_mailer/avis_invitation_and_confirm_email.html.haml index ce4db376a..aab81b459 100644 --- a/app/views/avis_mailer/avis_invitation_and_confirm_email.html.haml +++ b/app/views/avis_mailer/avis_invitation_and_confirm_email.html.haml @@ -24,7 +24,7 @@ - if @avis.expert.user.active? %p - = round_button("Confirmer le mail pour donner votre avis", @url, :primary) + = round_button('Confirmez votre adresse email pour donner votre avis', users_confirm_email_url(token: @token), :primary) - else %p = round_button("Inscrivez-vous pour donner votre avis", @url, :primary) diff --git a/app/views/user_mailer/resend_confirmation_email.html.haml b/app/views/user_mailer/resend_confirmation_email.html.haml new file mode 100644 index 000000000..a189423c4 --- /dev/null +++ b/app/views/user_mailer/resend_confirmation_email.html.haml @@ -0,0 +1,18 @@ +- content_for(:title, "Vérification de votre mail sur #{Current.application_name}") + +%p + Bonjour, + +%p + Votre précédente confirmation de mail n'a pas fonctionné, vous pouvez essayer de nouveau en cliquant sur ce bouton : + = round_button 'Je confirme', users_confirm_email_url(token: @token), :primary + +%p + Vous pouvez aussi utiliser ce lien : + = link_to(users_confirm_email_url(token: @token), users_confirm_email_url(token: @token)) + +%p + Nous restons à votre disposition si vous avez besoin d’accompagnement à l'adresse #{link_to CONTACT_EMAIL, "mailto:#{CONTACT_EMAIL}"}. + + += render partial: "layouts/mailers/signature" From fae81d0a58bd54e57cc825e31ba1dcff6883ec6d Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Thu, 22 Aug 2024 11:27:28 +0200 Subject: [PATCH 3/3] fix test --- spec/controllers/instructeurs/avis_controller_spec.rb | 6 +++--- spec/controllers/users/activate_controller_spec.rb | 2 +- spec/models/user_spec.rb | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/controllers/instructeurs/avis_controller_spec.rb b/spec/controllers/instructeurs/avis_controller_spec.rb index 819a8887d..eee5bfe2e 100644 --- a/spec/controllers/instructeurs/avis_controller_spec.rb +++ b/spec/controllers/instructeurs/avis_controller_spec.rb @@ -27,14 +27,14 @@ describe Instructeurs::AvisController, type: :controller do describe 'remind' do before do - allow(AvisMailer).to receive(:avis_invitation).and_return(double(deliver_later: nil)) + allow(AvisMailer).to receive(:avis_invitation_and_confirm_email).and_return(double(deliver_later: nil)) end context 'without question' do let!(:avis) { create(:avis, dossier: dossier, claimant: instructeur, experts_procedure: experts_procedure) } it 'sends a reminder to the expert' do get :remind, params: { procedure_id: procedure.id, id: avis.id } - expect(AvisMailer).to have_received(:avis_invitation).once.with(avis) + expect(AvisMailer).to have_received(:avis_invitation_and_confirm_email) expect(flash.notice).to eq("Un mail de relance a été envoyé à #{avis.expert.email}") expect(avis.reload.reminded_at).to be_present end @@ -45,7 +45,7 @@ describe Instructeurs::AvisController, type: :controller do it 'sends a reminder to the expert' do get :remind, params: { procedure_id: procedure.id, id: avis.id } - expect(AvisMailer).to have_received(:avis_invitation).once.with(avis) + expect(AvisMailer).to have_received(:avis_invitation_and_confirm_email) expect(flash.notice).to eq("Un mail de relance a été envoyé à #{avis.expert.email}") expect(avis.reload.reminded_at).to be_present end diff --git a/spec/controllers/users/activate_controller_spec.rb b/spec/controllers/users/activate_controller_spec.rb index c1aa7cc6d..70a4d7b2b 100644 --- a/spec/controllers/users/activate_controller_spec.rb +++ b/spec/controllers/users/activate_controller_spec.rb @@ -81,7 +81,7 @@ describe Users::ActivateController, type: :controller do end it 'redirects to root path with an explanation notice and it send a new link if user present' do - expect { subject }.to have_enqueued_mail(UserMailer, :invite_tiers) + expect { subject }.to have_enqueued_mail(UserMailer, :resend_confirmation_email) expect(response).to redirect_to(root_path(user)) expect(flash[:alert]).to eq("Ce lien n'est plus valable, un nouveau lien a été envoyé à l'adresse #{user.email}") end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 5bc4f467b..57ea99250 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -191,7 +191,7 @@ describe User, type: :model do user = subject expect(user.valid_password?(password)).to be true expect(user.confirmed_at).to be_present - expect(user.email_verified_at).to be_present + expect(user.email_verified_at).to be_nil expect(user.expert).to be_present end end