From 746ff92118fed503181de300d4b246645711aaf8 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 24 Jul 2024 17:01:22 +0200 Subject: [PATCH] Add PhishingAlert maintenance task and mailer --- app/mailers/phishing_alert_mailer.rb | 14 ++++++ app/tasks/maintenance/phishing_alert_task.rb | 21 ++++++++ .../phishing_alert_mailer/notify.html.haml | 17 +++++++ .../previews/phishing_alert_mailer_preview.rb | 5 ++ .../maintenance/phishing_alert_task_spec.rb | 48 +++++++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 app/mailers/phishing_alert_mailer.rb create mode 100644 app/tasks/maintenance/phishing_alert_task.rb create mode 100644 app/views/phishing_alert_mailer/notify.html.haml create mode 100644 spec/mailers/previews/phishing_alert_mailer_preview.rb create mode 100644 spec/tasks/maintenance/phishing_alert_task_spec.rb diff --git a/app/mailers/phishing_alert_mailer.rb b/app/mailers/phishing_alert_mailer.rb new file mode 100644 index 000000000..eca029388 --- /dev/null +++ b/app/mailers/phishing_alert_mailer.rb @@ -0,0 +1,14 @@ +class PhishingAlertMailer < ApplicationMailer + helper MailerHelper + + layout 'mailers/layout' + + def notify(user) + @user = user + @subject = "Détection d'une possible usurpation de votre compte" + + mail(to: user.email, subject: @subject) + end + + def self.critical_email?(action_name) = false +end diff --git a/app/tasks/maintenance/phishing_alert_task.rb b/app/tasks/maintenance/phishing_alert_task.rb new file mode 100644 index 000000000..0f0efa535 --- /dev/null +++ b/app/tasks/maintenance/phishing_alert_task.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Maintenance + class PhishingAlertTask < MaintenanceTasks::Task + csv_collection + + def process(row) + email = row["Identity"].delete('"') + user = User.find_by(email: email) + + # if the user has been updated less than a minute ago + # we guess that the user has already been processed + # in another row of the csv + return if user.nil? || 1.minute.ago < user.updated_at + + user.update(password: SecureRandom.hex) + + PhishingAlertMailer.notify(user).deliver_later + end + end +end diff --git a/app/views/phishing_alert_mailer/notify.html.haml b/app/views/phishing_alert_mailer/notify.html.haml new file mode 100644 index 000000000..131a86784 --- /dev/null +++ b/app/views/phishing_alert_mailer/notify.html.haml @@ -0,0 +1,17 @@ += content_for(:title, @subject) + +%p Bonjour + +%p Nous pensons que votre compte #{@user.email} a été la cible d'une tentative #{link_to("d'hameçonnage (phishing)", "https://www.service-public.fr/particuliers/vosdroits/F34800") }. + +%p Par mesure de précaution, nous avons réinitialisé votre mot de passe. + +%h3 Que devez-vous faire maintenant ? + +%ol + %li Pour accéder à votre compte, vous devez définir un nouveau mot de passe sur le site #{Current.application_name}. Sur la page de connexion, cliquez sur le lien "Mot de passe oublié" et suivez les instructions. + %li Nous vous recommandons de vérifier vos dossiers et de nous signaler tout problème en nous contactant à l'adresse suivante : #{mail_to(CONTACT_EMAIL)}. + +%p Nous restons à votre disposition pour toute question. + += render partial: "layouts/mailers/signature" diff --git a/spec/mailers/previews/phishing_alert_mailer_preview.rb b/spec/mailers/previews/phishing_alert_mailer_preview.rb new file mode 100644 index 000000000..f0548184e --- /dev/null +++ b/spec/mailers/previews/phishing_alert_mailer_preview.rb @@ -0,0 +1,5 @@ +class PhishingAlertMailerPreview < ActionMailer::Preview + def notify + PhishingAlertMailer.notify(User.first) + end +end diff --git a/spec/tasks/maintenance/phishing_alert_task_spec.rb b/spec/tasks/maintenance/phishing_alert_task_spec.rb new file mode 100644 index 000000000..0c1b5dd1d --- /dev/null +++ b/spec/tasks/maintenance/phishing_alert_task_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require "rails_helper" + +module Maintenance + RSpec.describe PhishingAlertTask do + describe "#process" do + subject(:process) { described_class.process(element) } + let(:element) { { 'Identity' => '"' + email + '"' } } + + describe "when the user does not exist" do + let(:email) { "not@existing.com" } + + it { expect { process }.not_to raise_error } + end + + describe "when the user exist" do + let(:user) { create(:user, updated_at: 1.day.ago) } + let(:email) { user.email } + + before { allow(PhishingAlertMailer).to receive(:notify).and_return(double(deliver_later: true)) } + + it "resets its password and send a mail" do + previous_password = user.encrypted_password + + process + + expect(user.reload.encrypted_password).not_to eq(previous_password) + expect(PhishingAlertMailer).to have_received(:notify).with(user) + end + end + + describe "when the emails is present several times" do + let(:user) { create(:user, updated_at: 1.day.ago) } + let(:email) { user.email } + + before { allow(PhishingAlertMailer).to receive(:notify).and_return(double(deliver_later: true)) } + + it "resets its password and send a mail" do + described_class.process(element) + described_class.process(element) + + expect(PhishingAlertMailer).to have_received(:notify).with(user).once + end + end + end + end +end