-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LG-15216 Handle password reset for in-person enrollments waiting for fraud review #11855
base: main
Are you sure you want to change the base?
Conversation
d8e42d5
to
4ccd4e7
Compare
@@ -223,9 +223,9 @@ def in_person_enrollment_status | |||
pending_profile&.in_person_enrollment&.status | |||
end | |||
|
|||
def ipp_enrollment_status_not_passed? | |||
def ipp_enrollment_status_not_passed_or_in_fraud_review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method could benefit from a comment / usage doc since it's public.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 2edd2c2
# | ||
# @param user [User] The user model | ||
def cancel_establishing_and_pending_enrollments(user) | ||
def cancel_in_progress_enrollments(user) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to update this method to cancel_establishing_and_in_progress_enrollments
to remove confusion as to what an in_progress enrollment means. See user model current_in_progress_in_person_enrollment_profile
method for consistency. Which leads me to think I should add IN_PROGRESS_ENROLLMENT_STATUSES
to the InPersonEnrollment model to help establish this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in 2edd2c2
@@ -62,8 +62,9 @@ def create_document_capture_session | |||
|
|||
def cancel_previous_in_person_enrollments | |||
return unless IdentityConfig.store.in_person_proofing_enabled | |||
UspsInPersonProofing::EnrollmentHelper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is check IdentityConfig.store.in_person_proofing_enabled
needed? (I know this code predates you and you did not change it.)
If we disable in_person_proofing_enabled because of an outage and the user begins again, wouldn't we want a clean slate even if they are not able to move through ipp? Can you think of any disadvantages to deleting the check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good question. I'm not (yet) sure where I fall on this topic, but I am curious to hear more about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cc @matthinz because I feel like this is the type of thing we discussed recently. This method is called from the welcome controller's update method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that makes sense, but I feel that this change would be better in a different PR/User Story.
cc: @eileen-nava
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shanechesnutt-ft Would you be up for writing a ticket to address this feedback in a separate PR?
Ran through all test steps successfully! Great job with this :) |
pending_in_person_enrollment&.profile || | ||
profiles.where.not(activated_at: nil).order(activated_at: :desc).first | ||
def find_in_person_in_progress_or_active_profile | ||
current_in_progress_in_person_enrollment_profile || find_active_profile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally, the only behavior was to find an active profile. When we enabled the epic, the default behavior will be to find an in person in progress or active profile. What do you think about changing the order of this so the default is to first look for an active profile because that was the original behavior? I think it would have a smaller affect on pw reset. (If for some reason in person enrollments was not getting cleaned up properly at some point- it would have a small impact because it would only happen if there was not an active profile.) I did not consider this in your previous pr.
What are your thoughts?
find_active_profile || current_in_progress_in_person_enrollment_profile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So in the last Password Reset PR I prioritized the pending profile first because when the personal key is generated for a profile it will replace the previous personal key. This can occur when the user has an active legacy profile and a pending non-legacy profile. My logic was that since the personal key is replaced, the previous active account is dead when the user performs a password reset. So, rather than having them lose both profiles I would prioritize the latest profile (the pending profile) which would allow the user to use their latest personal key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jmhooper does this sound reasonable? I know you reviewed the last PR and this didn't come up. I just wanted to make sure the way this is implemented makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gina-yamada Good question! I agree with Shane's explanation and logic. Please feel free to say if you have more questions about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shane and I walked through this together prior to his post yesterday. He posted for visibility. I am okay with this now that I have more information. Thank you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved, this looks good.
@@ -62,8 +62,9 @@ def create_document_capture_session | |||
|
|||
def cancel_previous_in_person_enrollments | |||
return unless IdentityConfig.store.in_person_proofing_enabled | |||
UspsInPersonProofing::EnrollmentHelper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good question. I'm not (yet) sure where I fall on this topic, but I am curious to hear more about it.
@@ -104,7 +104,9 @@ def extra_analytics_attributes | |||
|
|||
def pending_profile_invalidated? | |||
if FeatureManagement.pending_in_person_password_reset_enabled? | |||
pending_profile.present? && !pending_profile.in_person_verification_pending? | |||
pending_profile.present? && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating this.
@@ -142,8 +143,7 @@ def check_enrollment(enrollment) | |||
|
|||
def cancel_enrollment(enrollment) | |||
enrollment_outcomes[:enrollments_cancelled] += 1 | |||
enrollment.cancelled! | |||
enrollment.profile.deactivate_due_to_in_person_verification_cancelled | |||
enrollment.cancel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
allow(IdentityConfig.store).to receive(:in_person_proofing_enforce_tmx).and_return(false) | ||
end | ||
|
||
it 'returns nil' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests look clear and thorough.
it 'includes that the profile was not deactivated in the form response' do | ||
expect(@result.extra).to include( | ||
user_id: user.uuid, | ||
profile_deactivated: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻 to testing this
let(:profile) { enrollment.profile } | ||
|
||
before do | ||
@result = form.submit(params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a question about test syntax and will follow up in a synchronous 1:1.
let!(:profile) { enrollment.profile } | ||
|
||
before do | ||
subtask.run(args:, config:) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a question about test syntax and will follow up in a synchronous 1:1.
@@ -509,6 +518,7 @@ | |||
expect(expired_enrollment.eligible_for_notification?).to eq(false) | |||
expect(passed_enrollment_without_notification.eligible_for_notification?).to eq(false) | |||
expect(failed_enrollment_without_notification.eligible_for_notification?).to eq(false) | |||
expect(in_fraud_review_enrollment.eligible_for_notification?).to eq(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
subject.cancel_establishing_and_pending_enrollments(user) | ||
end | ||
before do | ||
subject.cancel_establishing_and_in_progress_enrollments(user) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a question about test syntax and will follow up in a synchronous 1:1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good. 👍🏻
@@ -5,6 +5,7 @@ class FraudRejectionDailyJob < ApplicationJob | |||
|
|||
def perform(_date) | |||
profiles_eligible_for_fraud_rejection.find_each do |profile| | |||
profile.in_person_enrollment&.failed! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
changelog: User-facing Improvement, In-person Proofing, Allow users to perform a password reset on pending in-person profiles in fraud review without losing progress if the user supplies their personal key.
- Update enrollment helper method based on changes
23b9af9
to
38a2b86
Compare
end | ||
|
||
it 'passes the enrollment and activates the profile' do | ||
expect(enrollment.status).to eq('passed') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 Thanks for this spec! I was checking to ensure we updated the InPersonEnrollment status so it was no longer in_fraud_review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not getting to this sooner. There's a lot to make sense of here but it looks good, and I'm grateful that this long-standing issue causing users pain is being fixed. 👏
I have a couple of questions inline, but I'm giving this an approval conditional on the answer not being "Oh no everything is broken." 😉
app/models/user.rb
Outdated
@@ -223,9 +223,14 @@ def in_person_enrollment_status | |||
pending_profile&.in_person_enrollment&.status | |||
end | |||
|
|||
def ipp_enrollment_status_not_passed? | |||
# Whether the user's in person enrollment status is not passed or in_fraud_review. Enrollments use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Whether the user's in person enrollment status is not passed or in_fraud_review. Enrollments use | |
# Whether the user's in person enrollment status is not passed or in_fraud_review. Enrollments used |
The most trivial nit ever, but my eyes noticed it.
@@ -91,13 +91,15 @@ def cancel_stale_establishing_enrollments_for_user(user) | |||
.find_each(&:cancelled!) | |||
end | |||
|
|||
# Cancel a user's associated establishing and pending in-person enrollments. | |||
# Cancel a user's associated establishing, pending, and in_fraud_review in-person enrollments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oxford comma FTW!
@@ -641,7 +641,7 @@ def send_enrollment_status_sms_notification(enrollment:) | |||
end | |||
|
|||
def notification_delivery_params(enrollment) | |||
return {} unless enrollment.passed? || enrollment.failed? | |||
return {} unless enrollment.passed? || enrollment.failed? || enrollment.in_fraud_review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like I've gotten rusty in this section of code. Is the intent here to start sending delayed notices of fraud-review status? It's just not obvious to me what the significance of this is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this isn't very obvious, but in the code before when the user passed at the post office and had been flagged for fraud review we would update the in-person enrollment to have a status of passed and send the please call email. In this PR we are changing things up a little bit by adding the new in_fraud_review
status. We wanted to keep the same behavior with sending the email in the same way (with a delay) so I had to add the status check here.
@@ -281,6 +282,7 @@ def run(args:, config:) | |||
elsif FraudReviewChecker.new(user).fraud_review_eligible? | |||
profile = user.fraud_review_pending_profile | |||
profile_fraud_review_pending_at = profile.fraud_review_pending_at | |||
profile.in_person_enrollment&.passed! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is another "Apologies that I don't remember this so well..." one, but I'm trying to make sure I understand what happens here in non-obvious cases.
- If I have an IPP enrollment, but don't actually go to the post office because I'm a fraudster, this won't mark me as a pass because I'm not
fraud_review_eligible?
, right? - If I get in one of the muddled states where I abandon IPP, and continue with doc auth and get myself into fraud review, this won't mark me as passed because I don't have an enrollment, right?
This is a case where I think the logic is good but I just want to make sure we're not accidentally creating a vulnerability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Yeah that seems to be correct because user has not been to post office for their enrollment/profile to be updated. IPP enrollments profiles are not updated with a fraud_review_pending_at timestamp until the user goes to the post office.
-
Yeah think that is also the case because the profile associated with the enrollment would be different from the one associated with doc auth. I can do some checks around this today. What exactly to do you mean by "muddled states where I abandon IPP, and continue with doc auth"? I want to make sure I test this case correctly.
@shanechesnutt-ft UPDATE: After looking at the code, this email is only kicked off from the USPS job and is on a delay. I think just funny timing. |
🎫 Ticket
Link to the relevant ticket:
LG-15216
🛠 Summary of changes
Enable user's to not lose in-person enrollment progress after a password reset when the user in fraud review.
Changes Include:
in_fraud_review
enrollments_in_fraud_review
📜 Testing Plan
In-Person Password Reset enabled
feature_pending_in_person_password_reset_enabled: true
inapplication.yml.default
Scenario: Fraud review in-person enrollment and user password resets with personal key
in_fraud_review
status.Scenario: Fraud review in-person enrollment and user password resets without personal key
in_fraud_review
status.cancelled
Scenario: Fraud review in-person enrollment and user password resets before deployment
passed
status.Scenario: Fraud review in-person enrollment and user has passed review
in_fraud_review
status.bin/action-account review-passed <user_uuid>
passed
status.Scenario: Fraud review in-person enrollment and user has failed review
in_fraud_review
status.bin/action-account review-reject <user_uuid>
failed
status.In-Person Password Reset disabled
feature_pending_in_person_password_reset_enabled: false
inapplication.yml.default
Scenario: Fraud review in-person enrollment and user password resets
in_fraud_review
status.