diff --git a/app/controllers/concerns/verify_sp_attributes_concern.rb b/app/controllers/concerns/verify_sp_attributes_concern.rb index 65db253fbd0..6a168bb07b8 100644 --- a/app/controllers/concerns/verify_sp_attributes_concern.rb +++ b/app/controllers/concerns/verify_sp_attributes_concern.rb @@ -8,6 +8,8 @@ def needs_completion_screen_reason :new_sp elsif !requested_attributes_verified?(sp_session_identity) :new_attributes + elsif reverified_after_consent?(sp_session_identity) + :reverified_after_consent elsif consent_has_expired?(sp_session_identity) :consent_expired elsif consent_was_revoked?(sp_session_identity) @@ -30,10 +32,9 @@ def update_verified_attributes def consent_has_expired?(sp_session_identity) return false unless sp_session_identity return false if sp_session_identity.deleted_at.present? - last_estimated_consent = sp_session_identity.last_consented_at || sp_session_identity.created_at + last_estimated_consent = last_estimated_consent_for(sp_session_identity) !last_estimated_consent || - last_estimated_consent < ServiceProviderIdentity::CONSENT_EXPIRATION.ago || - verified_after_consent?(last_estimated_consent) + last_estimated_consent < ServiceProviderIdentity::CONSENT_EXPIRATION.ago end def consent_was_revoked?(sp_session_identity) @@ -41,8 +42,20 @@ def consent_was_revoked?(sp_session_identity) sp_session_identity.deleted_at.present? end + def reverified_after_consent?(sp_session_identity) + return false unless sp_session_identity + return false if sp_session_identity.deleted_at.present? + last_estimated_consent = last_estimated_consent_for(sp_session_identity) + return false if last_estimated_consent.nil? + verified_after_consent?(last_estimated_consent) + end + private + def last_estimated_consent_for(sp_session_identity) + sp_session_identity.last_consented_at || sp_session_identity.created_at + end + def verified_after_consent?(last_estimated_consent) verification_timestamp = current_user.active_profile&.verified_at diff --git a/app/presenters/completions_presenter.rb b/app/presenters/completions_presenter.rb index 47fbe124289..f913f3ab9d2 100644 --- a/app/presenters/completions_presenter.rb +++ b/app/presenters/completions_presenter.rb @@ -50,6 +50,11 @@ def heading if ial2_requested? if consent_has_expired? I18n.t('titles.sign_up.completion_consent_expired_ial2') + elsif reverified_after_consent? + I18n.t( + 'titles.sign_up.completion_reverified_consent', + sp: sp_name, + ) else I18n.t('titles.sign_up.completion_ial2', sp: sp_name) end @@ -71,6 +76,11 @@ def intro 'help_text.requested_attributes.ial2_consent_reminder_html', sp: sp_name, ) + elsif reverified_after_consent? + I18n.t( + 'help_text.requested_attributes.ial2_reverified_consent_info', + sp: sp_name, + ) else I18n.t( 'help_text.requested_attributes.ial2_intro_html', @@ -121,6 +131,10 @@ def consent_has_expired? completion_context == :consent_expired end + def reverified_after_consent? + completion_context == :reverified_after_consent + end + def displayable_attribute_keys sorted_attribute_mapping = if ial2_requested? SORTED_IAL2_ATTRIBUTE_MAPPING diff --git a/config/locales/help_text/en.yml b/config/locales/help_text/en.yml index d6ad8eaf5cb..a5169c9caaa 100644 --- a/config/locales/help_text/en.yml +++ b/config/locales/help_text/en.yml @@ -18,6 +18,8 @@ en: information with %{sp}. We’ll share this information: ' ial2_intro_html: '%{sp} needs to know who you are to connect your account. We’ll share this information with %{sp}: ' + ial2_reverified_consent_info: 'Because you verified your identity again, we need + your permission to share this information with %{sp}: ' phone: Phone number social_security_number: Social Security number verified_at: Updated on diff --git a/config/locales/help_text/es.yml b/config/locales/help_text/es.yml index c4f596f906c..21090ee05a0 100644 --- a/config/locales/help_text/es.yml +++ b/config/locales/help_text/es.yml @@ -19,6 +19,8 @@ es: información:' ial2_intro_html: '%{sp} necesita saber quién es para conectar su cuenta. Compartiremos esta información con el organismo asociado: ' + ial2_reverified_consent_info: 'Como volvió a verificar su identidad, necesitamos + su permiso para compartir esta información con %{sp}: ' phone: Teléfono social_security_number: Número de Seguro Social verified_at: Actualizado en diff --git a/config/locales/help_text/fr.yml b/config/locales/help_text/fr.yml index e39fae0ced1..3f3d539f854 100644 --- a/config/locales/help_text/fr.yml +++ b/config/locales/help_text/fr.yml @@ -21,6 +21,9 @@ fr: ial2_intro_html: '%{sp} a besoin de savoir qui vous êtes pour connecter votre compte. Nous partagerons ces informations avec l’agence partenaire:' + ial2_reverified_consent_info: 'Puisque vous avez à nouveau vérifié votre + identité, nous avons besoin de votre autorisation pour partager ces + informations avec %{sp}:' phone: Numéro de téléphone social_security_number: Numéro de sécurité sociale verified_at: Mis à jour le diff --git a/config/locales/titles/en.yml b/config/locales/titles/en.yml index bf277e6f84e..a50677038a1 100644 --- a/config/locales/titles/en.yml +++ b/config/locales/titles/en.yml @@ -75,6 +75,7 @@ en: completion_ial2: Connect your verified information to %{sp} completion_new_attributes: '%{sp} is requesting new information' completion_new_sp: You are now signing in for the first time + completion_reverified_consent: Update your verified information with %{sp} confirmation: Continue to sign in spam_protection: Protecting against spam totp_setup: diff --git a/config/locales/titles/es.yml b/config/locales/titles/es.yml index ede5b863559..ed9b7a7ff02 100644 --- a/config/locales/titles/es.yml +++ b/config/locales/titles/es.yml @@ -77,6 +77,7 @@ es: completion_ial2: Conecte su información verificada a %{sp} completion_new_attributes: '%{sp} está solicitando nueva información' completion_new_sp: Acabas de iniciar sesión por primera vez + completion_reverified_consent: Actualice su información verificados con %{sp} confirmation: Continuar para iniciar sesión spam_protection: Protección contra el correo no deseado totp_setup: diff --git a/config/locales/titles/fr.yml b/config/locales/titles/fr.yml index 94a79aa4070..739fa7374eb 100644 --- a/config/locales/titles/fr.yml +++ b/config/locales/titles/fr.yml @@ -77,6 +77,7 @@ fr: completion_ial2: Connectez vos informations vérifiées à %{sp} completion_new_attributes: '%{sp} demande de nouvelles informations' completion_new_sp: Vous vous connectez pour la première fois + completion_reverified_consent: Mettez à jour vos informations vérifiées avec %{sp} confirmation: Continuer à vous connecter spam_protection: Protection contre les pourriels totp_setup: diff --git a/spec/controllers/concerns/verify_sp_attributes_concern_spec.rb b/spec/controllers/concerns/verify_sp_attributes_concern_spec.rb index d6be336fdfa..1d6977ecd62 100644 --- a/spec/controllers/concerns/verify_sp_attributes_concern_spec.rb +++ b/spec/controllers/concerns/verify_sp_attributes_concern_spec.rb @@ -80,30 +80,6 @@ expect(consent_has_expired?).to eq(false) end end - - context 'when there is an active profile' do - let(:sp_session_identity) do - create(:service_provider_identity, last_consented_at: 15.days.ago, user: user) - end - - before do - create(:profile, :active, verified_at: verified_at, user: user) - end - - context 'when the active profile was verified after last_consented_at' do - let(:verified_at) { 5.days.ago } - it 'is true because the new verified data needs to be consented to sharing' do - expect(consent_has_expired?).to eq(true) - end - end - - context 'when the active profile was verified before last_consented_at' do - let(:verified_at) { 20.days.ago } - it 'is false' do - expect(consent_has_expired?).to eq(false) - end - end - end end describe '#consent_was_revoked?' do @@ -199,6 +175,23 @@ expect(needs_completion_screen_reason).to be_nil end end + + context 'when user is reverified' do + let(:verified_at) { 5.days.ago } + let(:sp_session_identity) do + build( + :service_provider_identity, + user: user, + last_consented_at: 15.days.ago, + ) + end + before do + create(:profile, :active, verified_at: verified_at, user: user) + end + it 'is reverified_after_consent' do + expect(needs_completion_screen_reason).to eq(:reverified_after_consent) + end + end end end @@ -208,4 +201,107 @@ end end end + + describe '#reverified_after_consent?' do + let(:sp_session_identity) { build(:service_provider_identity, user: user) } + let(:user) { build(:user) } + + before do + allow(controller).to receive(:current_user).and_return(user) + allow(controller).to receive(:sp_session_identity).and_return(sp_session_identity) + end + + subject(:reverified_after_consent?) do + controller.reverified_after_consent?(sp_session_identity) + end + + context 'when there is no sp_session_identity' do + let(:sp_session_identity) { nil } + it 'is false' do + expect(reverified_after_consent?).to eq(false) + end + end + + context 'when there is no last_consented_at' do + it 'is false' do + expect(reverified_after_consent?).to eq(false) + end + end + + context 'when last_consented_at within one year' do + let(:sp_session_identity) { build(:service_provider_identity, last_consented_at: 5.days.ago) } + + it 'is false' do + expect(reverified_after_consent?).to eq(false) + end + end + + context 'when the last_consented_at is older than a year ago' do + let(:sp_session_identity) do + build(:service_provider_identity, last_consented_at: 2.years.ago) + end + + it 'is false' do + expect(reverified_after_consent?).to eq(false) + end + end + + context 'when last_consented_at is nil but created_at is within a year' do + let(:sp_session_identity) do + build(:service_provider_identity, last_consented_at: nil, created_at: 4.days.ago) + end + + it 'is false' do + expect(reverified_after_consent?).to eq(false) + end + end + + context 'when last_consented_at is nil and created_at is older than a year' do + let(:sp_session_identity) do + build(:service_provider_identity, last_consented_at: nil, created_at: 4.years.ago) + end + + it 'is false' do + expect(reverified_after_consent?).to eq(false) + end + end + + context 'when the identity has been soft-deleted (consent has been revoked)' do + let(:sp_session_identity) do + build( + :service_provider_identity, + deleted_at: 1.day.ago, + last_consented_at: 2.years.ago, + ) + end + + it 'is false' do + expect(reverified_after_consent?).to eq(false) + end + end + + context 'when there is an active profile' do + let(:sp_session_identity) do + create(:service_provider_identity, last_consented_at: 15.days.ago, user: user) + end + + before do + create(:profile, :active, verified_at: verified_at, user: user) + end + + context 'when the active profile was verified after last_consented_at' do + let(:verified_at) { 5.days.ago } + it 'is true because the new verified data needs to be consented to sharing' do + expect(reverified_after_consent?).to eq(true) + end + end + + context 'when the active profile was verified before last_consented_at' do + let(:verified_at) { 20.days.ago } + it 'is false' do + expect(reverified_after_consent?).to eq(false) + end + end + end + end end diff --git a/spec/presenters/completions_presenter_spec.rb b/spec/presenters/completions_presenter_spec.rb index 48e75c79b70..2265157fbbe 100644 --- a/spec/presenters/completions_presenter_spec.rb +++ b/spec/presenters/completions_presenter_spec.rb @@ -224,6 +224,27 @@ end end + context 'user has reverified since last consent for sp' do + let(:identities) do + [ + build( + :service_provider_identity, + service_provider: current_sp.issuer, + last_consented_at: 2.months.ago, + ), + ] + end + let(:completion_context) { :reverified_after_consent } + it 'renders the reverified IAL2 consent intro message' do + expect(presenter.intro).to eq( + I18n.t( + 'help_text.requested_attributes.ial2_reverified_consent_info', + sp: current_sp.friendly_name, + ), + ) + end + end + context 'when consent has not expired' do it 'renders the standard intro message' do expect(presenter.intro).to eq(