diff --git a/app/mailers/resend_invitation_mailer.rb b/app/mailers/resend_invitation_mailer.rb new file mode 100644 index 000000000..144972d0f --- /dev/null +++ b/app/mailers/resend_invitation_mailer.rb @@ -0,0 +1,7 @@ +class ResendInvitationMailer < NotifyMailer + include Rails.application.routes.url_helpers + + def resend_invitation_email(user) + user.send_confirmation_instructions + end +end diff --git a/app/models/user.rb b/app/models/user.rb index c9ef7cd02..bd0433b6e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -174,6 +174,10 @@ class User < ApplicationRecord super && active? end + def resend_invitation_email + ResendInvitationMailer.resend_invitation_email(self).deliver_later + end + protected # Checks whether a password is needed or not. For validations only. diff --git a/lib/tasks/resend_invitation_emails.rake b/lib/tasks/resend_invitation_emails.rake index cf8c1168e..c3d2be9dd 100644 --- a/lib/tasks/resend_invitation_emails.rake +++ b/lib/tasks/resend_invitation_emails.rake @@ -2,8 +2,8 @@ namespace :emails do desc "Resend invitation emails" task :resend_invitation_emails, %i[] => :environment do |_task, _args| users = User.where(sign_in_count: 0, active: true) - users.each(&:send_confirmation_instructions) + users.each { |user| ResendInvitationMailer.resend_invitation_email(user).deliver_later } - Rails.logger.info("Sent invitation emails to #{users.count} users.") + Rails.logger.info("Sent invitation emails to #{users.count} user.") end end diff --git a/spec/lib/tasks/resend_invitation_emails_spec.rb b/spec/lib/tasks/resend_invitation_emails_spec.rb index f66a8fc0b..a3cb97afd 100644 --- a/spec/lib/tasks/resend_invitation_emails_spec.rb +++ b/spec/lib/tasks/resend_invitation_emails_spec.rb @@ -7,8 +7,13 @@ RSpec.describe "emails" do let(:notify_client) { instance_double(Notifications::Client) } let(:devise_notify_mailer) { DeviseNotifyMailer.new } + let(:resend_invitation_mailer) { ResendInvitationMailer.new } + let(:resend_invitation_email) { { deliver_later: nil } } before do + allow(ResendInvitationMailer).to receive(:new).and_return(resend_invitation_mailer) + allow(resend_invitation_mailer).to receive(:resend_invitation_email).and_return(resend_invitation_email) + organisation.users.destroy_all Rake.application.rake_require("tasks/resend_invitation_emails") Rake::Task.define_task(:environment) task.reenable @@ -16,107 +21,46 @@ RSpec.describe "emails" do context "when the rake task is run" do let(:organisation) { create(:organisation, name: "test organisation") } - - before do - allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer) - allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client) - allow(notify_client).to receive(:send_email).and_return(true) - - organisation.users.destroy_all - create(:user, name: "new active user", email: "new_active_user@example.com", organisation:, confirmation_token: "abc", initial_confirmation_sent: false, old_user_id: nil, sign_in_count: 0) - create(:user, name: "active user", email: "active_user@example.com", organisation:, confirmation_token: "ghi", initial_confirmation_sent: true, old_user_id: "234", sign_in_count: 0) - LegacyUser.destroy_all - create(:user, name: "new active migrated user", email: "new_active_migrated_user@example.com", organisation:, confirmation_token: "def", initial_confirmation_sent: false, old_user_id: "123", sign_in_count: 0) - create(:user, name: "inactive user", email: "inactive_user@example.com", organisation:, confirmation_token: "jkl", initial_confirmation_sent: true, old_user_id: "345", active: false, sign_in_count: 0) - create(:user, name: "logged in user", email: "logged_in_user@example.com", organisation:, confirmation_token: "mno", initial_confirmation_sent: true, old_user_id: "456", sign_in_count: 1) - end - - context "with active non migrated user before the initial invitation has been sent" do - let(:personalisation) do - { - name: "new active user", - email: "new_active_user@example.com", - organisation: "test organisation", - link: include("/account/confirmation?confirmation_token=abc"), - } - end - - it "sends an initial invitation" do - expect(notify_client).to receive(:send_email).with(email_address: "new_active_user@example.com", template_id: User::CONFIRMABLE_TEMPLATE_ID, personalisation:).once - task.invoke - end - end - - context "with active migrated user before the initial invitation has been sent" do - let(:personalisation) do - { - name: "new active migrated user", - email: "new_active_migrated_user@example.com", - organisation: "test organisation", - link: include("/account/confirmation?confirmation_token=def"), - } - end - - it "sends an initial invitation" do - expect(notify_client).to receive(:send_email).with(email_address: "new_active_migrated_user@example.com", template_id: User::BETA_ONBOARDING_TEMPLATE_ID, personalisation:).once - task.invoke - end - end - - context "with active user after the initial invitation has been sent" do - let(:personalisation) do - { - name: "active user", - email: "active_user@example.com", - organisation: "test organisation", - link: include("/account/confirmation?confirmation_token=ghi"), - } - end - - it "sends a reinvitation" do - expect(notify_client).to receive(:send_email).with(email_address: "active_user@example.com", template_id: User::RECONFIRMABLE_TEMPLATE_ID, personalisation:).once - task.invoke + let!(:active_user) { create(:user, name: "active user", email: "active_user@example.com", organisation:, confirmation_token: "ghi", initial_confirmation_sent: true, old_user_id: "234", sign_in_count: 0) } + let!(:inactive_user) { create(:user, name: "inactive user", email: "inactive_user@example.com", organisation:, confirmation_token: "jkl", initial_confirmation_sent: true, old_user_id: "345", active: false, sign_in_count: 0) } + let!(:logged_in_user) { create(:user, name: "logged in user", email: "logged_in_user@example.com", organisation:, confirmation_token: "mno", initial_confirmation_sent: true, old_user_id: "456", sign_in_count: 1) } + + context "with active user" do + it "sends an invitation" do + expect { task.invoke }.to enqueue_job(ActionMailer::MailDeliveryJob).with( + "ResendInvitationMailer", + "resend_invitation_email", + "deliver_now", + args: [active_user], + ) end end context "with inactive user" do - let(:personalisation) do - { - name: "inactive user", - email: "inactive_user@example.com", - organisation: "test organisation", - link: include("/account/confirmation?confirmation_token=jkl"), - } - end - it "does not send an invitation" do - expect(notify_client).not_to receive(:send_email).with(email_address: "inactive_user@example.com", template_id: User::CONFIRMABLE_TEMPLATE_ID, personalisation:) - expect(notify_client).not_to receive(:send_email).with(email_address: "inactive_user@example.com", template_id: User::RECONFIRMABLE_TEMPLATE_ID, personalisation:) - expect(notify_client).not_to receive(:send_email).with(email_address: "inactive_user@example.com", template_id: User::BETA_ONBOARDING_TEMPLATE_ID, personalisation:) - task.invoke + expect { task.invoke }.not_to enqueue_job(ActionMailer::MailDeliveryJob).with( + "ResendInvitationMailer", + "resend_invitation_email", + "deliver_now", + args: [inactive_user], + ) end end context "with logged in user" do - let(:personalisation) do - { - name: "logged in user", - email: "logged_in_user@example.com", - organisation: "test organisation", - link: include("/account/confirmation?confirmation_token=mno"), - } - end - it "does not send an invitation" do - expect(notify_client).not_to receive(:send_email).with(email_address: "logged_in_user@example.com", template_id: User::CONFIRMABLE_TEMPLATE_ID, personalisation:) - expect(notify_client).not_to receive(:send_email).with(email_address: "logged_in_user@example.com", template_id: User::RECONFIRMABLE_TEMPLATE_ID, personalisation:) - expect(notify_client).not_to receive(:send_email).with(email_address: "logged_in_user@example.com", template_id: User::BETA_ONBOARDING_TEMPLATE_ID, personalisation:) - task.invoke + expect { task.invoke }.not_to enqueue_job(ActionMailer::MailDeliveryJob).with( + "ResendInvitationMailer", + "resend_invitation_email", + "deliver_now", + args: [logged_in_user], + ) end end it "prints out the total number of invitations sent" do - expect(Rails.logger).to receive(:info).with("Sent invitation emails to 3 users.") + expect(Rails.logger).to receive(:info).with(nil) + expect(Rails.logger).to receive(:info).with("Sent invitation emails to 1 user.") task.invoke end end diff --git a/spec/mailers/resend_invitation_mailer_spec.rb b/spec/mailers/resend_invitation_mailer_spec.rb new file mode 100644 index 000000000..02a6189d4 --- /dev/null +++ b/spec/mailers/resend_invitation_mailer_spec.rb @@ -0,0 +1,65 @@ +require "rails_helper" + +RSpec.describe ResendInvitationMailer do + describe "#resend_invitation_email" do + let(:notify_client) { instance_double(Notifications::Client) } + let(:organisation) { create(:organisation, name: "test organisation") } + let!(:active_user) { create(:user, name: "active user", email: "active_user@example.com", organisation:, confirmation_token: "ghi", initial_confirmation_sent: true, old_user_id: "234", sign_in_count: 0) } + let!(:new_active_user) { create(:user, name: "new active user", email: "new_active_user@example.com", organisation:, confirmation_token: "abc", initial_confirmation_sent: false, old_user_id: nil, sign_in_count: 0) } + let(:new_active_migrated_user) { create(:user, name: "new active migrated user", email: "new_active_migrated_user@example.com", organisation:, confirmation_token: "def", initial_confirmation_sent: false, old_user_id: "123", sign_in_count: 0) } + + before do + LegacyUser.destroy_all + allow(Notifications::Client).to receive(:new).and_return(notify_client) + allow(notify_client).to receive(:send_email).and_return(true) + end + + context "with a new active user" do + let(:personalisation) do + { + name: "new active user", + email: "new_active_user@example.com", + organisation: "test organisation", + link: include("/account/confirmation?confirmation_token=abc"), + } + end + + it "sends invitation email to user" do + expect(notify_client).to receive(:send_email).with(email_address: "new_active_user@example.com", template_id: User::CONFIRMABLE_TEMPLATE_ID, personalisation:).once + described_class.new.resend_invitation_email(new_active_user) + end + end + + context "with active migrated user before the initial invitation has been sent" do + let(:personalisation) do + { + name: "new active migrated user", + email: "new_active_migrated_user@example.com", + organisation: "test organisation", + link: include("/account/confirmation?confirmation_token=def"), + } + end + + it "sends an initial invitation" do + expect(notify_client).to receive(:send_email).with(email_address: "new_active_migrated_user@example.com", template_id: User::BETA_ONBOARDING_TEMPLATE_ID, personalisation:).once + described_class.new.resend_invitation_email(new_active_migrated_user) + end + end + + context "with active user after the initial invitation has been sent" do + let(:personalisation) do + { + name: "active user", + email: "active_user@example.com", + organisation: "test organisation", + link: include("/account/confirmation?confirmation_token=ghi"), + } + end + + it "sends a reinvitation" do + expect(notify_client).to receive(:send_email).with(email_address: "active_user@example.com", template_id: User::RECONFIRMABLE_TEMPLATE_ID, personalisation:).once + described_class.new.resend_invitation_email(active_user) + end + end + end +end