Skip to content

Commit

Permalink
add unsubscribe functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
asmega committed Dec 4, 2024
1 parent 0cfec39 commit 16bb5de
Show file tree
Hide file tree
Showing 26 changed files with 268 additions and 133 deletions.
37 changes: 37 additions & 0 deletions app/controllers/unsubscribe_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
class UnsubscribeController < ApplicationController
skip_forgery_protection

def show
@form = Unsubscribe::ConfirmationForm.new(form_params)

if @form.reminder.nil?
render "subscription_not_found"
end
end

def create
@form = Unsubscribe::ConfirmationForm.new(form_params)

if @form.reminder.nil?
head :bad_request
else
@form.reminder.destroy
end
end

private

def form_params
params.permit([:id])
end

def current_journey_routing_name
params[:journey]
end
helper_method :current_journey_routing_name

def current_journey
Journeys.for_routing_name(params[:journey])
end
helper_method :current_journey
end
29 changes: 29 additions & 0 deletions app/forms/unsubscribe/confirmation_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Unsubscribe
class ConfirmationForm
include ActiveModel::Model
include ActiveModel::Attributes

attribute :id, :string

def reminder
@reminder ||= Reminder.find_by(id:)
end

def obfuscasted_email
head, tail = reminder.email_address.split("@")

mask = case head.size
when 1, 2, 3
"*" * head.size
else
[head[0], "*" * (head.length - 2), head[-1]].join
end

[mask, "@", tail].join
end

def journey_name
I18n.t("journey_name", scope: reminder.journey::I18N_NAMESPACE).downcase
end
end
end
41 changes: 27 additions & 14 deletions app/mailers/reminder_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ def email_verification(reminder, one_time_password, journey_name)
journey_name:
}

send_mail(OTP_EMAIL_NOTIFY_TEMPLATE_ID, personalisation)
template_mail(
OTP_EMAIL_NOTIFY_TEMPLATE_ID,
to: @reminder.email_address,
reply_to_id: GENERIC_NOTIFY_REPLY_TO_ID,
subject: @subject,
personalisation:
)
end

def reminder_set(reminder)
Expand All @@ -29,10 +35,17 @@ def reminder_set(reminder)
personalisation = {
first_name: extract_first_name(@reminder.full_name),
support_email_address: support_email_address,
next_application_window: @reminder.send_year
next_application_window: @reminder.send_year,
unsubscribe_url: unsubscribe_url(reminder:)
}

send_mail(REMINDER_SET_NOTIFY_TEMPLATE_ID, personalisation)
template_mail(
REMINDER_SET_NOTIFY_TEMPLATE_ID,
to: @reminder.email_address,
reply_to_id: GENERIC_NOTIFY_REPLY_TO_ID,
subject: @subject,
personalisation:
)
end

# TODO: This template only accommodates LUP/ECP claims currently. Needs to
Expand All @@ -47,22 +60,22 @@ def reminder(reminder)
support_email_address: support_email_address
}

send_mail(REMINDER_APPLICATION_WINDOW_OPEN_NOTIFY_TEMPLATE_ID, personalisation)
end

private

def extract_first_name(fullname)
(fullname || "").split(" ").first
end

def send_mail(template_id, personalisation)
template_mail(
template_id,
REMINDER_APPLICATION_WINDOW_OPEN_NOTIFY_TEMPLATE_ID,
to: @reminder.email_address,
reply_to_id: GENERIC_NOTIFY_REPLY_TO_ID,
subject: @subject,
personalisation:
)
end

private

def unsubscribe_url(reminder:)
"https://#{ENV["CANONICAL_HOSTNAME"]}/#{reminder.journey::ROUTING_NAME}/unsubscribe/reminders/#{reminder.id}"
end

def extract_first_name(fullname)
(fullname || "").split(" ").first
end
end
11 changes: 11 additions & 0 deletions app/views/unsubscribe/create.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<%= content_for(:page_title) { "Unsubscribe" } %>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<%= govuk_panel(title_text: "Unsubscribe complete") %>

<p class="govuk-body">
You will no longer receive your <%= @form.journey_name %> reminder to <%= @form.obfuscasted_email %>.
</p>
</div>
</div>
27 changes: 27 additions & 0 deletions app/views/unsubscribe/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<%= content_for(:page_title) { "Unsubscribe" } %>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<%= form_with model: @form,
url: unsubscribe_index_path,
scope: "",
builder: GOVUKDesignSystemFormBuilder::FormBuilder do |f| %>

<%= f.hidden_field :id %>

<h1 class="govuk-heading-l">
Are you sure you wish to unsubscribe from your <%= @form.journey_name %> reminder?
</h1>

<p class="govuk-body">
You will no longer receive your reminder to <%= @form.obfuscasted_email %>.
<p>

<p class="govuk-body">
However, you will still continue to receive updates about your claim as it progresses.
<p>

<%= f.govuk_submit "Unsubscribe" %>
<% end %>
</div>
</div>
15 changes: 15 additions & 0 deletions app/views/unsubscribe/subscription_not_found.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h1 class="govuk-heading-l">
We can’t find your subscription
</h1>

<p class="govuk-body">
You may have already unsubscribed. If you haven’t, check your email and copy the link again.
</p>

<p class="govuk-body">
If you need more help, contact support at <%= govuk_mail_to I18n.t("support_email_address", scope: [current_journey::I18N_NAMESPACE]), I18n.t("support_email_address", scope: [current_journey::I18N_NAMESPACE]) %>
</p>
</div>
</div>
3 changes: 1 addition & 2 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true

# Raise an exception if parameters that are not explicitly permitted are found
config.action_controller.action_on_unpermitted_parameters = :raise
config.action_controller.action_on_unpermitted_parameters = :log

# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
Expand Down
3 changes: 1 addition & 2 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false

# Raise an exception if parameters that are not explicitly permitted are found
config.action_controller.action_on_unpermitted_parameters = :raise
config.action_controller.action_on_unpermitted_parameters = :log

config.action_mailer.perform_caching = false

Expand Down
5 changes: 5 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ def matches?(request)
end
end

resources :unsubscribe,
path: "/unsubscribe/:resource_class",
constraints: {resource_class: /reminders/},
only: [:create, :show]

scope constraints: {journey: /further-education-payments|additional-payments/} do
resources :reminders,
only: [:show, :update],
Expand Down
26 changes: 26 additions & 0 deletions spec/features/unsubscribe_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require "rails_helper"

RSpec.feature "unsubscribe from reminders" do
let(:reminder) do
create(
:reminder,
journey_class: Journeys::FurtherEducationPayments.to_s
)
end

scenario "happy path" do
visit "/#{reminder.journey::ROUTING_NAME}/unsubscribe/reminders/#{reminder.id}"
expect(page).to have_content "Are you sure you wish to unsub"

expect {
click_button("Unsubscribe")
}.to change(Reminder, :count).by(-1)

expect(page).to have_content "Unsubscribe complete"
end

scenario "when reminder does not exist" do
visit "/#{reminder.journey::ROUTING_NAME}/unsubscribe/reminders/idonotexist"
expect(page).to have_content "We can’t find your subscription"
end
end
8 changes: 0 additions & 8 deletions spec/forms/current_school_form_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@
)
end

context "unpermitted claim param" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {nonsense_id: 1}}) }

it "raises an error" do
expect { form }.to raise_error ActionController::UnpermittedParameters
end
end

describe "#schools" do
context "new form" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {}}) }
Expand Down
8 changes: 0 additions & 8 deletions spec/forms/employed_directly_form_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@
)
end

context "unpermitted claim param" do
let(:params) { ActionController::Parameters.new({slug:, claim: {random_param: 1}}) }

it "raises an error" do
expect { form }.to raise_error ActionController::UnpermittedParameters
end
end

describe "#employed_directly" do
let(:params) { ActionController::Parameters.new({slug:, claim: {}}) }

Expand Down
16 changes: 0 additions & 16 deletions spec/forms/form_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,6 @@ def initialize(journey_session)
let(:claim_params) { {first_name: "test-name"} }

describe "#initialize" do
context "with unpermitted params" do
let(:claim_params) { {unpermitted: "my-name"} }

it "raises an error" do
expect { form }.to raise_error(ActionController::UnpermittedParameters)
end
end

context "with valid params" do
let(:claim_params) { {first_name: "my-name"} }

Expand Down Expand Up @@ -218,13 +210,5 @@ def initialize(journey_session)
expect(form.permitted_params).to eql(ActionController::Parameters.new(claim_params.stringify_keys).permit!)
end
end

context "with params containing attributes not defined on the form" do
let(:claim_params) { super().merge(unpermitted_attribute: "test-value") }

it "raises an error" do
expect { form.permitted_params }.to raise_error(ActionController::UnpermittedParameters)
end
end
end
end
8 changes: 0 additions & 8 deletions spec/forms/gender_form_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@
)
end

context "unpermitted claim param" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {nonsense_id: 1}}) }

it "raises an error" do
expect { form }.to raise_error ActionController::UnpermittedParameters
end
end

describe "#payroll_gender" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {}}) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@
)
end

context "unpermitted claim param" do
let(:params) { ActionController::Parameters.new({slug:, claim: {random_param: 1}}) }

it "raises an error" do
expect { form }.to raise_error ActionController::UnpermittedParameters
end
end

describe "#has_entire_term_contract" do
let(:params) { ActionController::Parameters.new({slug:, claim: {}}) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@
)
end

context "unpermitted claim param" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {nonsense_id: 1}}) }

it "raises an error" do
expect { form }.to raise_error ActionController::UnpermittedParameters
end
end

describe "#save" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {induction_completed: true}}) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@
)
end

context "unpermitted claim param" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {nonsense_id: 1}}) }

it "raises an error" do
expect { form }.to raise_error ActionController::UnpermittedParameters
end
end

describe "#itt_academic_year" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {}}) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,6 @@
)
end

context "unpermitted claim param" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {nonsense_id: 1}}) }

it "raises an error" do
expect { form }.to raise_error ActionController::UnpermittedParameters
end
end

describe "#schools" do
context "new form" do
let(:params) { ActionController::Parameters.new({slug: slug, claim: {}}) }
Expand Down
Loading

0 comments on commit 16bb5de

Please sign in to comment.