Skip to content
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

feat(sms): Set up flow to add recovery phone from Settings #18276

Merged
merged 1 commit into from
Jan 28, 2025
Merged

Conversation

LZoog
Copy link
Contributor

@LZoog LZoog commented Jan 23, 2025

Because:

  • We want users to be able to add a recovery phone

This commit:

  • Enables the "add" page if the feature flag is on and availability from GQL is true
  • Returns 'availability' with other recovery phone info in the GQL resolver
  • Displays recovery phone info in recovery phone row,
  • Hides 'change' and 'delete' buttons if user doesn't have a recovery phone set up, displays SIM swap link only if user doesn't have a recovery phone

closes FXA-10370


You will need these env vars set:

RECOVERY_PHONE__TWILIO__ACCOUNT_SID=updateMe
RECOVERY_PHONE__TWILIO__AUTH_TOKEN=updateMe
GEODB_LOCATION_OVERRIDE={ "location": { "countryCode": "US", "postalCode": "85001"} }

The magic number 4159929960 works for this flow.

@@ -66,6 +66,12 @@ export class RecoveryPhoneService {
}

const code = await this.otpCode.generateCode();
await this.recoveryPhoneManager.storeUnconfirmed(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure why but I wasn't seeing this show up in Redis, it looked like there was an entry but nothing to expand/look at. When I'm done with this PR I'll circle back and see if it works removing the change in this file.

Copy link
Contributor

@vpomerleau vpomerleau left a comment

Choose a reason for hiding this comment

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

Left some comments from first pass, will have another look once rebased on main!

@@ -13,7 +13,15 @@ export class RecoveryPhone {

@Field({
nullable: true,
description: 'The registered recovery phone number',
description:
'The registered recovery phone number. If the user does not have a verified session, this field will return the last 4 digits of the phone number with a mask on the rest.',
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it return with mask, or just return the last 4 digits?

Copy link
Contributor Author

@LZoog LZoog Jan 28, 2025

Choose a reason for hiding this comment

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

Currently it returns with a mask, but I think it makes sense for it to return with only the last 4 digits. I'll file one issue for the Twilio national_format bit + this since they're related.

/>
</AppContext.Provider>
);
// Recovery phone not shown since `available` is based on region and recovery codes
Copy link
Contributor

Choose a reason for hiding this comment

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

Should these stories be re-enabled or deleted?

Copy link
Contributor Author

@LZoog LZoog Jan 28, 2025

Choose a reason for hiding this comment

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

They're all there I believe, they were just refactored to use createSubject (and I added a couple new ones).

).toContain(MOCK_MASKED_PHONE_NUMBER);
expect(
screen.queryByTestId('backup-authentication-codes-sub-row')
).toBeInTheDocument();
Copy link
Contributor

Choose a reason for hiding this comment

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

Check that recovery phone delete button is unavailable, or tested in sub-component?

).toContain(MOCK_MASKED_PHONE_NUMBER);
expect(
screen.getByTestId('backup-authentication-codes-sub-row').textContent
).toContain('3');
Copy link
Contributor

Choose a reason for hiding this comment

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

test that delete available for phone number?

Comment on lines 157 to 158
config.featureFlags?.enableAdding2FABackupPhone === true &&
(recoveryPhone.available === true || recoveryPhone.exists === true)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
config.featureFlags?.enableAdding2FABackupPhone === true &&
(recoveryPhone.available === true || recoveryPhone.exists === true)
(config.featureFlags?.enableAdding2FABackupPhone === true &&
recoveryPhone.available === true) || recoveryPhone.exists === true

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the row should always be shown if a user has added a recovery phone, regardless of whether adding or using a phone is enabled. They should have the option of removing the phone number from their account even if we've had to disable actually using the feature.

Copy link
Contributor

Choose a reason for hiding this comment

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

Which makes me think that the "remove phone" route option should depend on having a phone configured and not on the feature flags... hm...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh yeah, good catch. When I first wrote this logic, I don't think I realized this would hide the remove option for users if the feature flag was off.

Which makes me think that the "remove phone" route option should depend on having a phone configured and not on the feature flags... hm...

I guess both? The "manage" flag should be on and the user should have a phone number.

@LZoog LZoog force-pushed the FXA-10370 branch 3 times, most recently from 868adab to 5e7431d Compare January 28, 2025 01:54
@LZoog LZoog marked this pull request as ready for review January 28, 2025 01:54
@LZoog LZoog requested review from a team as code owners January 28, 2025 01:54
Copy link
Contributor

@vpomerleau vpomerleau left a comment

Choose a reason for hiding this comment

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

Thanks for the updates! This is looking great 🚀 Approved pending CI passes and your final run of manual testing 🤘

Comment on lines 54 to 57
// Just retry adding the number and another code will send. Note that more than
// one code can be valid at the same time if the user clicks “resend code” to
// account for SMS transmission delay.
// try/catch is in the component that calls this function
Copy link
Contributor

Choose a reason for hiding this comment

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

Noting that @vbudhram recommends invalidating the previous code when a new one is sent one. There's a thread up for discussion in the Slack channel for this project

Copy link
Contributor

Choose a reason for hiding this comment

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

Was the try-catch comment meant to stay in, or a self-review note?

Copy link
Contributor Author

@LZoog LZoog Jan 28, 2025

Choose a reason for hiding this comment

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

Sure - sounds like we have a separate issue filed for that, I can link it here since I need another push anyway. 👍

I left that in because at first I wrapped this in the try/catch since usually our account.whatever methods have a try/catch, and then realized we didn't need it. Can remove if you want though.

navigate(`${SETTINGS_PATH}/recovery_phone/setup`);
}}
onDeleteClick={() => {
navigate(`${SETTINGS_PATH}/recovery_phone/remove`);
Copy link
Contributor

Choose a reason for hiding this comment

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

🙌

@@ -1,3 +1,4 @@
import { existsSync } from 'fs';
Copy link
Contributor

Choose a reason for hiding this comment

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

unused import causing build failure on CI

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahhh dumb auto import, thanks.

@vbudhram
Copy link
Contributor

Looks like removeRecoveryPhone in Account.ts got reverted. It should be this.

  async removeRecoveryPhone() {
    const result = await this.withLoadingStatus(
      this.authClient.recoveryPhoneDelete(sessionToken()!)
    );

    const cache = this.apolloClient.cache;
    cache.modify({
      id: cache.identify({ __typename: 'Account' }),
      fields: {
        recoveryPhone() {
          return {
            exists: false,
            phoneNumber: null,
            available: true,
          };
        },
      },
    });

    return result;
  }

Copy link
Contributor

@vbudhram vbudhram left a comment

Choose a reason for hiding this comment

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

@LZoog Did some manual testing and just noticed the one thing. Thanks!

@LZoog
Copy link
Contributor Author

LZoog commented Jan 28, 2025

@vbudhram ahh thank you, there was a big ol' merge conflict there and I resolved with my changes and totally forgot to add yours back in!

Because:
* We want users to be able to add a recovery phone

This commit:
* Enables the "add" page if the feature flag is on and availability from GQL is true
* Returns 'availability' with other recovery phone info in the GQL resolver
* Displays recovery phone info in recovery phone row,
* Hides 'change' and 'delete' buttons if user doesn't have a recovery phone set up, displays SIM swap link only if user doesn't have a recovery phone

closes FXA-10370
@vpomerleau vpomerleau merged commit de6b0bf into main Jan 28, 2025
23 checks passed
@vpomerleau vpomerleau deleted the FXA-10370 branch January 28, 2025 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants