Browse Source

Use Notify rather than Gmail for devise emails

pull/241/head
baarkerlounger 3 years ago
parent
commit
d6fbbf4af9
  1. 2
      Gemfile
  2. 16
      Gemfile.lock
  3. 49
      app/mailers/devise_notify_mailer.rb
  4. 3
      config/initializers/devise.rb
  5. 21
      spec/features/organisation_spec.rb
  6. 29
      spec/features/user_spec.rb
  7. 2
      spec/request_helper.rb
  8. 19
      spec/requests/auth/passwords_controller_spec.rb
  9. 8
      spec/requests/users_controller_spec.rb

2
Gemfile

@ -19,6 +19,8 @@ gem "bootsnap", ">= 1.4.4", require: false
gem "govuk-components"
# GOV UK component form builder DSL
gem "govuk_design_system_formbuilder"
# GOV UK Notify
gem "notifications-ruby-client"
# Turbo and Stimulus
gem "hotwire-rails"
# Soft delete ActiveRecords objects

16
Gemfile.lock

@ -1,6 +1,6 @@
GIT
remote: https://github.com/activeadmin/arbre.git
revision: e4970e683c81c99432b73f0ceb5dff7d3fe50413
revision: 305c221a2131be8dd0d96955f9b0a328dfa4beba
specs:
arbre (1.4.0)
activesupport (>= 3.0.0, < 7.1)
@ -20,7 +20,7 @@ GIT
GIT
remote: https://github.com/tagliala/activeadmin.git
revision: 8ccc35b8144482284c90b0af74a01e940765f7a6
revision: f4fc57251399c0ed452d72ac4b07d0bdd3d047c6
branch: feature/railties-7
specs:
activeadmin (2.9.0)
@ -106,7 +106,7 @@ GEM
ast (2.4.2)
bcrypt (3.1.16)
bindex (0.8.1)
bootsnap (1.10.1)
bootsnap (1.10.2)
msgpack (~> 1.2)
builder (3.2.4)
byebug (11.1.3)
@ -158,7 +158,7 @@ GEM
activemodel (>= 6.1)
railties (>= 6.1)
view_component (~> 2.47.0)
govuk_design_system_formbuilder (3.0.0)
govuk_design_system_formbuilder (3.0.1)
actionview (>= 6.1)
activemodel (>= 6.1)
activesupport (>= 6.1)
@ -186,6 +186,7 @@ GEM
thor (>= 0.14, < 2.0)
json-schema (2.8.1)
addressable (>= 2.4)
jwt (2.3.0)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
@ -211,7 +212,7 @@ GEM
method_source (1.0.0)
mini_mime (1.1.2)
minitest (5.15.0)
msgpack (1.4.3)
msgpack (1.4.4)
net-imap (0.2.3)
digest
net-protocol
@ -234,6 +235,8 @@ GEM
racc (~> 1.4)
nokogiri (1.13.1-x86_64-linux)
racc (~> 1.4)
notifications-ruby-client (5.3.0)
jwt (>= 1.5, < 3)
orm_adapter (0.5.0)
overcommit (0.58.0)
childprocess (>= 0.6.3, < 5)
@ -242,7 +245,7 @@ GEM
parallel (1.21.0)
parser (3.1.0.0)
ast (~> 2.4.1)
pg (1.2.3)
pg (1.3.0)
postcodes_io (0.4.0)
excon (~> 0.39)
pry (0.13.1)
@ -435,6 +438,7 @@ DEPENDENCIES
hotwire-rails
json-schema
listen (~> 3.3)
notifications-ruby-client
overcommit (>= 0.37.0)
pg (~> 1.1)
postcodes_io

49
app/mailers/devise_notify_mailer.rb

@ -0,0 +1,49 @@
class DeviseNotifyMailer < Devise::Mailer
require "notifications/client"
RESET_PASSWORD_TEMPLATE_ID = "4593417c-500f-452c-8111-0f9d311aad0e".freeze
SET_PASSWORD_TEMPLATE_ID = "00cd7163-4213-4596-b4f9-9e72796e0d76".freeze
def notify_client
@notify_client ||= ::Notifications::Client.new(ENV["GOVUK_NOTIFY_API_KEY"])
end
def host
@host ||= ENV["APP_HOST"]
end
def send_email(email, template_id, personalisation)
notify_client.send_email(
email_address: email,
template_id: template_id,
personalisation: personalisation,
)
end
def reset_password_instructions(record, token, _opts = {})
template_id = record.last_sign_in_at ? RESET_PASSWORD_TEMPLATE_ID : SET_PASSWORD_TEMPLATE_ID
personalisation = {
name: record.name,
email: record.email,
organisation: record.organisation.name,
link: "https://#{host}/users/password/edit?reset_password_token=#{token}",
}
send_email(record.email, template_id, personalisation)
end
# def confirmation_instructions(record, token, _opts = {})
# super
# end
#
# def unlock_instructions(record, token, opts = {})
# super
# end
#
# def email_changed(record, opts = {})
# super
# end
#
# def password_change(record, opts = {})
# super
# end
end

3
config/initializers/devise.rb

@ -24,10 +24,11 @@ Devise.setup do |config|
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = ENV["CORE_EMAIL_USERNAME"]
# config.mailer_sender = ENV["CORE_EMAIL_USERNAME"]
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
config.mailer = "DeviseNotifyMailer"
# Configure the parent class responsible to send e-mails.
# config.parent_mailer = 'ActionMailer::Base'

21
spec/features/organisation_spec.rb

@ -5,8 +5,15 @@ RSpec.describe "User Features" do
include Helpers
let(:organisation) { user.organisation }
let(:org_id) { organisation.id }
let(:set_password_template_id) { DeviseNotifyMailer::SET_PASSWORD_TEMPLATE_ID }
let(:notify_client) { double(Notifications::Client) }
let(:reset_password_token) { "MCDH5y6Km-U7CFPgAMVS" }
before do
allow_any_instance_of(DeviseNotifyMailer).to receive(:notify_client).and_return(notify_client)
allow_any_instance_of(DeviseNotifyMailer).to receive(:host).and_return("test.com")
allow_any_instance_of(User).to receive(:set_reset_password_token).and_return(reset_password_token)
allow(notify_client).to receive(:send_email).and_return(true)
sign_in user
end
@ -39,7 +46,19 @@ RSpec.describe "User Features" do
fill_in("user[name]", with: "New User")
fill_in("user[email]", with: "new_user@example.com")
choose("user-role-data-provider-field")
expect { click_button("Continue") }.to change { ActionMailer::Base.deliveries.count }.by(1)
expect(notify_client).to receive(:send_email).with(
{
email_address: "new_user@example.com",
template_id: set_password_template_id,
personalisation: {
name: "New User",
email: "new_user@example.com",
organisation: organisation.name,
link: "https://test.com/users/password/edit?reset_password_token=#{reset_password_token}",
},
},
)
click_button("Continue")
expect(page).to have_current_path("/organisations/#{org_id}/users")
expect(User.last.role).to eq("data_provider")
end

29
spec/features/user_spec.rb

@ -1,6 +1,17 @@
require "rails_helper"
RSpec.describe "User Features" do
let!(:user) { FactoryBot.create(:user) }
let!(:user) { FactoryBot.create(:user, last_sign_in_at: Time.zone.now) }
let(:reset_password_template_id) { DeviseNotifyMailer::RESET_PASSWORD_TEMPLATE_ID }
let(:notify_client) { double(Notifications::Client) }
let(:reset_password_token) { "MCDH5y6Km-U7CFPgAMVS" }
before do
allow_any_instance_of(DeviseNotifyMailer).to receive(:notify_client).and_return(notify_client)
allow_any_instance_of(DeviseNotifyMailer).to receive(:host).and_return("test.com")
allow(notify_client).to receive(:send_email).and_return(true)
allow_any_instance_of(User).to receive(:set_reset_password_token).and_return(reset_password_token)
end
context "A user navigating to case logs" do
it " is required to log in" do
visit("/logs")
@ -66,10 +77,22 @@ RSpec.describe "User Features" do
expect(page).to have_current_path("/confirmations/reset?email=idontexist%40example.com")
end
it " is sent a reset password email" do
it " is sent a reset password email via Notify" do
expect(notify_client).to receive(:send_email).with(
{
email_address: user.email,
template_id: reset_password_template_id,
personalisation: {
name: user.name,
email: user.email,
organisation: user.organisation.name,
link: "https://test.com/users/password/edit?reset_password_token=#{reset_password_token}",
},
},
)
visit("/users/password/new")
fill_in("user[email]", with: user.email)
expect { click_button("Send email") }.to change { ActionMailer::Base.deliveries.count }.by(1)
click_button("Send email")
end
end

2
spec/request_helper.rb

@ -5,5 +5,7 @@ module RequestHelper
WebMock.disable_net_connect!(allow_localhost: true)
WebMock.stub_request(:get, /api.postcodes.io/)
.to_return(status: 200, body: "{\"status\":404,\"error\":\"Postcode not found\"}", headers: {})
WebMock.stub_request(:post, /api.notifications.service.gov.uk\/v2\/notifications\/email/)
.to_return(status: 200, body: "", headers: {})
end
end

19
spec/requests/auth/passwords_controller_spec.rb

@ -4,6 +4,12 @@ require_relative "../../support/devise"
RSpec.describe Auth::PasswordsController, type: :request do
let(:params) { { user: { email: email } } }
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:notify_client) { double(Notifications::Client) }
before do
allow_any_instance_of(DeviseNotifyMailer).to receive(:notify_client).and_return(notify_client)
allow(notify_client).to receive(:send_email).and_return(true)
end
context "when a password reset is requested for a valid email" do
let(:user) { FactoryBot.create(:user) }
@ -32,19 +38,6 @@ RSpec.describe Auth::PasswordsController, type: :request do
end
end
context "when a password reset is requested the email" do
let(:user) { FactoryBot.create(:user, last_sign_in_at: Time.zone.now) }
let(:email) { user.email }
it "should contain the correct email" do
post "/users/password", params: params
follow_redirect!
email_ascii_content = ActionMailer::Base.deliveries.last.body.raw_source
email_content = email_ascii_content.encode("ASCII", "UTF-8", undef: :replace)
expect(email_content).to match(email)
end
end
context "#Update - reset password" do
let(:user) { FactoryBot.create(:user) }
let(:token) { user.send(:set_reset_password_token) }

8
spec/requests/user_controller_spec.rb → spec/requests/users_controller_spec.rb

@ -1,12 +1,18 @@
require "rails_helper"
RSpec.describe "password_reset", type: :request do
RSpec.describe UsersController, type: :request do
let(:user) { FactoryBot.create(:user) }
let(:unauthorised_user) { FactoryBot.create(:user) }
let(:headers) { { "Accept" => "text/html" } }
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:new_value) { "new test name" }
let(:params) { { id: user.id, user: { name: new_value } } }
let(:notify_client) { double(Notifications::Client) }
before do
allow_any_instance_of(DeviseNotifyMailer).to receive(:notify_client).and_return(notify_client)
allow(notify_client).to receive(:send_email).and_return(true)
end
context "a not signed in user" do
describe "#show" do
Loading…
Cancel
Save