Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
b72147a
LG-7187: Add follow-up survey field to in-person enrollments table
NavaTim Sep 21, 2022
44b903c
LG-7187: Start implementing email for follow-up survey
NavaTim Sep 22, 2022
ed5d48c
LG-7187: Style survey email and send on next partner sign-in
NavaTim Sep 23, 2022
7ed9379
LG-7187: Send survey when user shares info with partner; add fallback…
NavaTim Sep 24, 2022
7e019a0
LG-7187: Test new survey DB query methods; format code
NavaTim Sep 26, 2022
65e9a8f
LG-7187: Expand tests; require IAL2 usage to send survey email
NavaTim Sep 27, 2022
f00702a
Merge branch 'main' of https://github.com/18F/identity-idp into tbrad…
NavaTim Sep 27, 2022
b648e0c
LG-7187: Add more tests relating to IPP survey email
NavaTim Sep 27, 2022
f8cee4c
LG-7187: Finish writing feature test for in-person proofing survey email
NavaTim Sep 28, 2022
9901546
LG-7187: Fix unreliable tests and make IPP account creation reusable
NavaTim Sep 29, 2022
49ebd45
changelog: Upcoming Features, In-person proofing, Send Customer Exper…
NavaTim Sep 29, 2022
7e3a060
Merge branch 'main' of https://github.com/18F/identity-idp into tbrad…
NavaTim Sep 29, 2022
ec79ee8
LG-7187: Add missing method to UserMailerPreview
NavaTim Sep 29, 2022
2ddaecb
LG-7187: Improve query tests; update English survey email translation
NavaTim Sep 29, 2022
09a5fd0
LG-7187: Combine paragraphs and use default margins/padding for surve…
NavaTim Sep 29, 2022
9fc5791
LG-7187: Reference constant for IAL2 in IPP completion survey logic
NavaTim Sep 29, 2022
b5601ad
LG-7187: Increase margin for paragraph above button
NavaTim Sep 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions app/controllers/sign_up/completions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def show
def update
track_completion_event('agency-page')
update_verified_attributes
send_in_person_completion_survey
if decider.go_back_to_mobile_app?
sign_user_out_and_instruct_to_go_back_to_mobile_app
else
Expand Down Expand Up @@ -89,5 +90,14 @@ def pii
pii_string = Pii::Cacher.new(current_user, user_session).fetch_string
JSON.parse(pii_string || '{}', symbolize_names: true)
end

def send_in_person_completion_survey
return unless sp_session_ial == ::Idp::Constants::IAL2

Idv::InPerson::CompletionSurveySender.send_completion_survey(
current_user,
current_sp.issuer,
)
end
end
end
12 changes: 12 additions & 0 deletions app/mailers/user_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,18 @@ def account_verified(user, email_address, date_time:, sp_name:, disavowal_token:
end
end

def in_person_completion_survey(user, email_address)
with_user_locale(user) do
@header = t('user_mailer.in_person_completion_survey.header')
@privacy_url = MarketingSite.security_and_privacy_practices_url
@survey_url = IdentityConfig.store.in_person_completion_survey_url
mail(
to: email_address.email,
subject: t('user_mailer.in_person_completion_survey.subject', app_name: APP_NAME),
)
end
end

def in_person_ready_to_verify(user, email_address, first_name:, enrollment:)
attachments.inline['barcode.png'] = BarcodeOutputter.new(
code: enrollment.enrollment_code,
Expand Down
26 changes: 26 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,32 @@ def default_phone_configuration
phone_configurations.order('made_default_at DESC NULLS LAST, created_at').first
end

##
# @param [String] issuer
# @return [Boolean] Whether the user should receive a survey for completing in-person proofing
def should_receive_in_person_completion_survey?(issuer)
Idv::InPersonConfig.enabled_for_issuer?(issuer) &&
in_person_enrollments.
where(issuer: issuer, status: :passed).order(created_at: :desc).
pick(:follow_up_survey_sent) == false
end

##
# Record that the in-person proofing survey was sent
# @param [String] issuer
def mark_in_person_completion_survey_sent(issuer)
enrollment_id, follow_up_survey_sent = in_person_enrollments.
where(issuer: issuer, status: :passed).
order(created_at: :desc).
pick(:id, :follow_up_survey_sent)

if follow_up_survey_sent == false
# Enrollment record is present and survey was not previously sent
InPersonEnrollment.update(enrollment_id, follow_up_survey_sent: true)
end
nil
end

MINIMUM_LIKELY_ENCRYPTED_DATA_LENGTH = 1000

def broken_personal_key?
Expand Down
21 changes: 21 additions & 0 deletions app/services/idv/in_person/completion_survey_sender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Idv
module InPerson
class CompletionSurveySender
##
# @param [User] user
# @param [String] issuer
def self.send_completion_survey(user, issuer)
return unless user.should_receive_in_person_completion_survey?(issuer)

user.confirmed_email_addresses.each do |email_address|
UserMailer.in_person_completion_survey(
user,
email_address,
).deliver_now_or_later
end

user.mark_in_person_completion_survey_sent(issuer)
end
end
end
end
38 changes: 38 additions & 0 deletions app/views/user_mailer/in_person_completion_survey.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<p><%= t('user_mailer.in_person_completion_survey.body.greeting') %></p>
<p><%= t('user_mailer.in_person_completion_survey.body.thanks', app_name: APP_NAME) %></p>
<p>
<%= t('user_mailer.in_person_completion_survey.body.intent') %>
<%= t('user_mailer.in_person_completion_survey.body.request_description') %>
<%= t(
'user_mailer.in_person_completion_survey.body.privacy_html',
url: @privacy_url,
) %>
</p>
<p class="margin-bottom-4"><%= t('user_mailer.in_person_completion_survey.body.cta.callout') %></p>

<table class="button expanded large radius">
<tbody>
<tr>
<td>
<table>
<tbody>
<tr>
<td>
<center>
<%= link_to t('user_mailer.in_person_completion_survey.body.cta.label'),
@survey_url,
target: '_blank',
class: 'float-center',
align: 'center',
rel: 'noopener' %>
</center>
</td>
</tr>
</tbody>
</table>
</td>
<td class="expander">
</td>
</tr>
</tbody>
</table>
1 change: 1 addition & 0 deletions config/application.yml.default
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ idv_sp_required: false
in_person_proofing_enabled: false
in_person_enrollment_validity_in_days: 30
in_person_results_delay_in_hours: 1
in_person_completion_survey_url: 'https://login.gov'
include_slo_in_saml_metadata: false
inherited_proofing_enabled: false
inherited_proofing_va_base_url: 'https://staging-api.va.gov'
Expand Down
15 changes: 15 additions & 0 deletions config/locales/user_mailer/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,21 @@ en:
%{app_name} %{help_link} or %{contact_link}.
subject: Email address deleted
help_link_text: Help Center
in_person_completion_survey:
body:
cta:
callout: Click the button below to get started.
label: Take our survey
greeting: Hello,
intent: We want to hear about your experience verifying your identity in person
at the Post Office.
privacy_html: Your answers to this survey will be protected according to the
following <a href="%{url}">privacy and security standards</a>.
request_description: Fill out a short, anonymous survey and we’ll use your input
to help us get better at serving your needs.
thanks: Thanks for using %{app_name}.
header: Take a minute to tell us how we did
subject: Tell us about your recent experience with %{app_name}
in_person_failed:
body:
with_cta: Click the button or copy the link below to try verifying your identity
Expand Down
15 changes: 15 additions & 0 deletions config/locales/user_mailer/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,21 @@ es:
%{app_name} %{help_link} o el %{contact_link}.
subject: Dirección de correo electrónico eliminada
help_link_text: Centro de Ayuda
in_person_completion_survey:
body:
cta:
callout: Haga clic en el botón de abajo para empezar.
label: Tome nuestra encuesta
greeting: Hola,
intent: Queremos conocer su experiencia al verificar su identidad en persona en
la oficina de correos.
privacy_html: Sus respuestas a esta encuesta estarán protegidas conforme a <a
href="%{url}">los siguientes estándares de privacidad y seguridad</a>.
request_description: Responde una breve encuesta anónima y su opinión nos
ayudará a atender mejor tus necesidades.
thanks: Gracias por utilizar %{app_name}.
header: Tómese un minuto para decirnos cómo lo hicimos
subject: Cuéntenos su experiencia reciente con %{app_name}
in_person_failed:
body:
with_cta: Haga clic en el botón o copie el enlace siguiente para volver a
Expand Down
15 changes: 15 additions & 0 deletions config/locales/user_mailer/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,21 @@ fr:
veuillez visiter le %{help_link} de %{app_name} ou %{contact_link}.
subject: Adresse email supprimée
help_link_text: Centre d’aide
in_person_completion_survey:
body:
cta:
callout: Cliquez sur le bouton ci-dessous pour commencer.
label: Répondez à notre enquête
greeting: Bonjour,
intent: Nous voulons connaître votre expérience en matière de vérification de
votre identité en personne au bureau de poste.
privacy_html: Vos réponses à cette enquête seront protégées conformément aux <a
href="%{url}">normes de confidentialité et de sécurité</a> suivantes.
request_description: Remplissez une courte enquête anonyme et nous utiliserons
vos commentaires pour nous aider à mieux répondre à vos besoins.
thanks: Merci d’utiliser %{app_name}.
header: Prenez une minute pour nous faire part de vos impressions
subject: Parlez-nous de votre expérience récente avec %{app_name}
in_person_failed:
body:
with_cta: Cliquez sur le bouton ou copiez le lien ci-dessous pour essayer de
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddFollowUpSurveySentToInPersonEnrollment < ActiveRecord::Migration[7.0]
def change
add_column :in_person_enrollments, :follow_up_survey_sent, :boolean, default: false
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2022_09_09_021833) do
ActiveRecord::Schema[7.0].define(version: 2022_09_21_233413) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "pgcrypto"
Expand Down Expand Up @@ -294,6 +294,7 @@
t.string "unique_id", comment: "Unique ID to use with the USPS service"
t.datetime "enrollment_established_at", comment: "When the enrollment was successfully established"
t.string "issuer", comment: "Issuer associated with the enrollment at time of creation"
t.boolean "follow_up_survey_sent", default: false
t.index ["profile_id"], name: "index_in_person_enrollments_on_profile_id"
t.index ["unique_id"], name: "index_in_person_enrollments_on_unique_id", unique: true
t.index ["user_id", "status"], name: "index_in_person_enrollments_on_user_id_and_status", unique: true, where: "(status = 1)"
Expand Down
1 change: 1 addition & 0 deletions lib/identity_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ def self.build_store(config_map)
config.add(:in_person_proofing_enabled, type: :boolean)
config.add(:in_person_enrollment_validity_in_days, type: :integer)
config.add(:in_person_results_delay_in_hours, type: :integer)
config.add(:in_person_completion_survey_url, type: :string)
config.add(:include_slo_in_saml_metadata, type: :boolean)
config.add(:inherited_proofing_enabled, type: :boolean)
config.add(:inherited_proofing_va_base_url, type: :string)
Expand Down
26 changes: 26 additions & 0 deletions spec/controllers/sign_up/completions_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,32 @@
last_consented_at: now,
clear_deleted_at: true,
)
allow(Idv::InPerson::CompletionSurveySender).to receive(:send_completion_survey).
with(user, sp.issuer)
freeze_time do
travel_to(now)
patch :update
end
end

it 'sends the in-person proofing completion survey' do
user = create(:user, profiles: [create(:profile, :verified, :active)])
stub_sign_in(user)
sp = create(:service_provider, issuer: 'https://awesome')
subject.session[:sp] = {
issuer: sp.issuer,
ial: 2,
request_url: 'http://example.com',
requested_attributes: %w[email first_name verified_at],
}
allow(@linker).to receive(:link_identity).with(
ial: 2,
verified_attributes: %w[email first_name verified_at],
last_consented_at: now,
clear_deleted_at: true,
)
expect(Idv::InPerson::CompletionSurveySender).to receive(:send_completion_survey).
with(user, sp.issuer)
freeze_time do
travel_to(now)
patch :update
Expand Down
24 changes: 24 additions & 0 deletions spec/features/idv/in_person_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

RSpec.describe 'In Person Proofing', js: true do
include IdvStepHelper
include SpAuthHelper
include InPersonHelper

before do
Expand Down Expand Up @@ -176,6 +177,29 @@
end
end

context 'after in-person proofing is completed and passed for a partner' do
let(:sp) { nil }
before do
create_in_person_ial2_account_go_back_to_sp_and_sign_out(sp)
end

[
:oidc,
:saml,
].each do |service_provider|
Comment on lines +186 to +189
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think there's value in exercising this for both SP protocols, or could we just do one? Reason I ask is that these tests can be quite slow to run.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's valuable to have at least one IPP feature test covering both SP protocols, and to my knowledge this is the only one.

context "using #{service_provider}" do
let(:sp) { service_provider }
it 'sends a survey when they share information with that partner',
allow_browser_log: true do
expect(last_email.html_part.body).
to have_selector(
"a[href='#{IdentityConfig.store.in_person_completion_survey_url}']",
)
end
end
end
end

context 'with hybrid document capture' do
before do
allow(FeatureManagement).to receive(:doc_capture_polling_enabled?).and_return(true)
Expand Down
7 changes: 7 additions & 0 deletions spec/mailers/previews/user_mailer_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ def account_verified
)
end

def in_person_completion_survey
UserMailer.in_person_completion_survey(
user,
email_address_record,
)
end

def in_person_ready_to_verify
UserMailer.in_person_ready_to_verify(
user,
Expand Down
41 changes: 41 additions & 0 deletions spec/mailers/user_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,47 @@ def expect_email_body_to_have_help_and_contact_links
it_behaves_like 'an email that respects user email locale preference'
end

describe '#in_person_completion_survey' do
let(:mail) do
UserMailer.in_person_completion_survey(
user,
email_address,
)
end

it_behaves_like 'a system email'
it_behaves_like 'an email that respects user email locale preference'

it 'sends to the current email' do
expect(mail.to).to eq [email_address.email]
end

it 'renders the subject' do
expect(mail.subject).to eq t(
'user_mailer.in_person_completion_survey.subject',
app_name: APP_NAME,
)
end

it 'renders the body' do
expect(mail.html_part.body).
to have_content(
t(
'user_mailer.in_person_completion_survey.body.thanks',
app_name: APP_NAME,
),
)
expect(mail.html_part.body).
to have_selector(
"a[href='#{MarketingSite.security_and_privacy_practices_url}']",
)
expect(mail.html_part.body).
to have_selector(
"a[href='#{IdentityConfig.store.in_person_completion_survey_url}']",
)
end
end

def strip_tags(str)
ActionController::Base.helpers.strip_tags(str)
end
Expand Down
Loading