Skip to content

feat(recovery-phone): Display phone number in desired format (masking + Twilio's nationalFormat)#18340

Merged
LZoog merged 1 commit intomainfrom
FXA-11044
Feb 13, 2025
Merged

feat(recovery-phone): Display phone number in desired format (masking + Twilio's nationalFormat)#18340
LZoog merged 1 commit intomainfrom
FXA-11044

Conversation

@LZoog
Copy link
Copy Markdown
Contributor

@LZoog LZoog commented Feb 8, 2025

Because:

  • We want to show the national format provided by Twilio to better display phone numbers for users, but want to hide the formatting when a user's session is not verified

This commit:

  • Adds a Twilio lookup call at recovery phone number add for nationalFormat, reads nationalFormat from DB when querying recovery phone data
  • Updates our server response to return the last 4 digits of a phone number instead of the mask, displays accordingly on the client including new copy
  • Updates account resolver recovery phone auth-server call to ensure only the last 4 digits are returned if a user's session is not verified
  • postAddRecoveryPhone email copy tweak

closes FXA-11044

image image image image image image

Comment thread packages/fxa-auth-server/lib/routes/recovery-phone.ts
@LZoog LZoog force-pushed the FXA-11044 branch 4 times, most recently from 92dd1a7 to a8c9e68 Compare February 11, 2025 17:37
Comment thread packages/fxa-settings/src/components/Settings/PageRecoveryPhoneSetup/index.tsx Outdated
Comment thread packages/fxa-settings/src/pages/Signin/SigninRecoveryChoice/container.tsx Outdated
Comment thread packages/fxa-settings/src/pages/Signin/SigninRecoveryChoice/container.tsx Outdated
return undefined;
}
const { uid: userId, phoneNumber, lookupData } = row;
const nationalFormat = isLookupDataObject(lookupData)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This seems a lot simpler to me:

const nationalFormat = lookupData?.['nationalFormat']

We are at the DB layer here, so there might be some casting going on here. We know what we store is either null or a JsonObject, and if it's object it should contain nationalFormat, but might not. Either way the type guard doesn't do much for me, and I like the cleanliness of optimistic resolution. Just my two cents.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah this was meant to be a thing to clean up for sure. I had tried that, and I get this:

Element implicitly has an 'any' type because expression of type '"nationalFormat"' can't be used to index type 'string | number | boolean | JsonArray | JsonObject'.
  Property 'nationalFormat' does not exist on type 'string | number | boolean | JsonArray | JsonObject'.

I wasn't sure if there was a better way to pull JSON out? But I can just go with
const nationalFormat = (lookupData as { nationalFormat?: string })?.nationalFormat which works. 👍

new RecoveryPhoneNotEnabled()
);
expect(() => service.maskPhoneNumber('+15550005555')).toThrow(
expect(() => service.stripPhoneNumber('+15550005555')).toThrow(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In someone ways I'd prefer both things to exist. Seems like UX flip flops a lot, and additive changes are easier to track.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure if I like the back-end handling adding the bullet points. Since that feels more presentation layer to me, I think it's nicer for the front-end to handle it - so if we want to change this in the future, we can in those new recovery-phone-utils functions.

phoneNumber
);
} catch (e) {
// This should not fail since the number was already validated with Twilio but
Copy link
Copy Markdown
Contributor

@dschom dschom Feb 11, 2025

Choose a reason for hiding this comment

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

I'd remove this... If it shouldn't fail, let's not worry about the try catch. If we are worried about the twilio call failing, then let's manually capture a sentry error so we at least know this feature isn't functioning properly.

Copy link
Copy Markdown
Contributor Author

@LZoog LZoog Feb 12, 2025

Choose a reason for hiding this comment

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

There is just the possibility of a network error here for whatever reason. I can remove it if we want though.

// Clamp lastN between 0 and digits.length
if (lastN > digits.length) {
lastN = digits.length;
} else if (lastN <= 0) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Semantically this doesn't make sense to me. Would would a negaive lastN digits even mean? I'd error or set to 0 as I did above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree - I actually wasn't sure why we allowed a negative number in the other function, but right now this basically treats negative numbers the same as 0. I've changed this locally to just return an empty string for <= 0 as I think that's more clear.

Comment thread packages/fxa-auth-client/lib/client.ts Outdated
phoneNumber: string,
headers?: Headers
) {
): Promise<{ nationalFormat?: string }> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This also has a success flag. Might nice to include it too.

// OTP confirm page before then. "Basic lookups" from Twilio are free, so don't
// bother persisting in redis.
// https://www.twilio.com/en-us/user-authentication-identity/pricing/lookup
const { nationalFormat } = await this.smsManager.phoneNumberLookup(
Copy link
Copy Markdown
Contributor

@dschom dschom Feb 11, 2025

Choose a reason for hiding this comment

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

I think this is true, but we might still hit twilio API rate limits. I am pretty sure customs will keep us safe, and we wouldn't encounter this type of volume, but just wanted to mention it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah yeah. I was so torn on sticking this into redis or not, we only store OTP codes there now from what I can tell. Maybe this is worth noting somewhere in some docs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I decided to leave this and just updated the comment noting it would be a network problem. I'm OK if we remove this later though.

uid,
}
);
return { nationalFormat };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we maybe return both the phoneNumber and the nationalFormat, might be a better API design. Also it's unlikely but possible that the phoneNumber exists, but the nationalFormat does not...

Comment thread packages/fxa-graphql-api/src/gql/model/recoveryPhone.ts
Comment thread packages/fxa-settings/src/components/Settings/SubRow/index.test.tsx Outdated
Comment thread packages/fxa-settings/src/lib/recovery-phone-utils.test.tsx Outdated
Comment thread packages/fxa-settings/src/pages/Signin/SigninRecoveryPhone/container.tsx Outdated
Copy link
Copy Markdown
Contributor

@dschom dschom left a comment

Choose a reason for hiding this comment

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

Looks good to me. r+wc

@LZoog
Copy link
Copy Markdown
Contributor Author

LZoog commented Feb 12, 2025

I'm going to go ahead and open this out of draft but still want to add a few more tests.

@LZoog LZoog marked this pull request as ready for review February 12, 2025 17:15
@LZoog LZoog requested review from a team as code owners February 12, 2025 17:15
@LZoog LZoog force-pushed the FXA-11044 branch 2 times, most recently from cac5e46 to b85d415 Compare February 13, 2025 17:47
uid,
}
);
return { phoneNumber, nationalFormat };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is the problem... Missing { status: RecoveryPhoneStatus.SUCCESS }

@LZoog LZoog force-pushed the FXA-11044 branch 2 times, most recently from 28346ca to b28bd9c Compare February 13, 2025 21:11
… + Twilio's nationalFormat)

Because:
* We want to show the national format provided by Twilio to better display phone numbers for users

This commit:
* Adds a Twilio lookup call at recovery phone number add for nationalFormat, reads nationalFormat from DB when querying recovery phone data
* Updates our server response to return the last 4 digits of a phone number instead of the mask, displays accordingly on the client including new copy
* Updates account resolver recovery phone auth-server call to ensure only the last 4 digits are returned if a user's session is not verified

closes FXA-11044
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.

3 participants