1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-02-02 23:11:40 +01:00

[PM-16667] Followup clarifying work (#12665)

* clean up readability

* fix ts-strict violations

* fix consistency with uncertain cases in isCardExpired
This commit is contained in:
Jonathan Prusik 2025-01-07 13:48:18 -05:00 committed by GitHub
parent 9ca3d0653d
commit 966e8d3fb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 24 deletions

View File

@ -93,7 +93,7 @@ function getCardExpiryDateValues() {
[undefined, undefined, false], // no month, no year, invalid values [undefined, undefined, false], // no month, no year, invalid values
["", "", false], // no month, no year, invalid values ["", "", false], // no month, no year, invalid values
["12", "agdredg42grg35grrr. ea3534@#^145345ag$%^ -_#$rdg ", false], // invalid values ["12", "agdredg42grg35grrr. ea3534@#^145345ag$%^ -_#$rdg ", false], // invalid values
["0", `${currentYear}`, true], // invalid month ["0", `${currentYear}`, false], // invalid month
["0", `${currentYear - 1}`, true], // invalid 0 month ["0", `${currentYear - 1}`, true], // invalid 0 month
["00", `${currentYear + 1}`, false], // invalid 0 month ["00", `${currentYear + 1}`, false], // invalid 0 month
[`${currentMonth}`, "0000", true], // current month, in the year 2000 [`${currentMonth}`, "0000", true], // current month, in the year 2000

View File

@ -1,5 +1,3 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { import {
DelimiterPatternExpression, DelimiterPatternExpression,
ExpiryFullYearPattern, ExpiryFullYearPattern,
@ -25,11 +23,11 @@ export function normalizeExpiryYearFormat(yearInput: string | number): Year | nu
let expirationYear = yearInputIsEmpty ? null : `${yearInput}`; let expirationYear = yearInputIsEmpty ? null : `${yearInput}`;
// Exit early if year is already formatted correctly or empty // Exit early if year is already formatted correctly or empty
if (yearInputIsEmpty || /^[1-9]{1}\d{3}$/.test(expirationYear)) { if (yearInputIsEmpty || (expirationYear && /^[1-9]{1}\d{3}$/.test(expirationYear))) {
return expirationYear as Year; return expirationYear as Year;
} }
expirationYear = expirationYear expirationYear = (expirationYear || "")
// For safety, because even input[type="number"] will allow decimals // For safety, because even input[type="number"] will allow decimals
.replace(/[^\d]/g, "") .replace(/[^\d]/g, "")
// remove any leading zero padding (leave the last leading zero if it ends the string) // remove any leading zero padding (leave the last leading zero if it ends the string)
@ -53,7 +51,7 @@ export function normalizeExpiryYearFormat(yearInput: string | number): Year | nu
/** /**
* Takes a cipher card view and returns "true" if the month and year affirmativey indicate * Takes a cipher card view and returns "true" if the month and year affirmativey indicate
* the card is expired. * the card is expired. Uncertain cases return "false".
* *
* @param {CardView} cipherCard * @param {CardView} cipherCard
* @return {*} {boolean} * @return {*} {boolean}
@ -62,30 +60,34 @@ export function isCardExpired(cipherCard: CardView): boolean {
if (cipherCard) { if (cipherCard) {
const { expMonth = null, expYear = null } = cipherCard; const { expMonth = null, expYear = null } = cipherCard;
if (!expYear) {
return false;
}
const now = new Date(); const now = new Date();
const normalizedYear = normalizeExpiryYearFormat(expYear); const normalizedYear = normalizeExpiryYearFormat(expYear);
const parsedYear = parseInt(normalizedYear, 10); const parsedYear = normalizedYear ? parseInt(normalizedYear, 10) : NaN;
const expiryYearIsBeforeThisYear = parsedYear < now.getFullYear(); const expiryYearIsBeforeCurrentYear = parsedYear < now.getFullYear();
const expiryYearIsAfterThisYear = parsedYear > now.getFullYear(); const expiryYearIsAfterCurrentYear = parsedYear > now.getFullYear();
// If the expiry year is before the current year, skip checking the month, since it must be expired // If the expiry year is before the current year, skip checking the month, since it must be expired
if (normalizedYear && expiryYearIsBeforeThisYear) { if (normalizedYear && expiryYearIsBeforeCurrentYear) {
return true; return true;
} }
// If the expiry year is after the current year, skip checking the month, since it cannot be expired // If the expiry year is after the current year, skip checking the month, since it cannot be expired
if (normalizedYear && expiryYearIsAfterThisYear) { if (normalizedYear && expiryYearIsAfterCurrentYear) {
return false; return false;
} }
if (normalizedYear && expMonth) { if (normalizedYear && expMonth) {
const parsedMonthInteger = parseInt(expMonth, 10); const parsedMonthInteger = parseInt(expMonth, 10);
const parsedMonthIsInvalid = !parsedMonthInteger || isNaN(parsedMonthInteger); const parsedMonthIsValid = parsedMonthInteger && !isNaN(parsedMonthInteger);
// If the parsed month value is 0, we don't know when the expiry passes this year, so treat it as expired // If the parsed month value is 0, we don't know when the expiry passes this year, so do not treat it as expired
if (parsedMonthIsInvalid) { if (!parsedMonthIsValid) {
return true; return false;
} }
// `Date` months are zero-indexed // `Date` months are zero-indexed
@ -257,13 +259,18 @@ function parseNonDelimitedYearMonthExpiry(dateInput: string): [string | null, st
parsedMonth = dateInput.slice(-1); parsedMonth = dateInput.slice(-1);
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
const normalizedParsedYear = parseInt(normalizeExpiryYearFormat(parsedYear), 10); const normalizedYearFormat = normalizeExpiryYearFormat(parsedYear);
const normalizedParsedYearAlternative = parseInt( const normalizedParsedYear = normalizedYearFormat && parseInt(normalizedYearFormat, 10);
normalizeExpiryYearFormat(dateInput.slice(-2)), const normalizedExpiryYearFormat = normalizeExpiryYearFormat(dateInput.slice(-2));
10, const normalizedParsedYearAlternative =
); normalizedExpiryYearFormat && parseInt(normalizedExpiryYearFormat, 10);
if (normalizedParsedYear < currentYear && normalizedParsedYearAlternative >= currentYear) { if (
normalizedParsedYear &&
normalizedParsedYear < currentYear &&
normalizedParsedYearAlternative &&
normalizedParsedYearAlternative >= currentYear
) {
parsedYear = dateInput.slice(-2); parsedYear = dateInput.slice(-2);
parsedMonth = dateInput.slice(0, 1); parsedMonth = dateInput.slice(0, 1);
} }
@ -295,17 +302,24 @@ export function parseYearMonthExpiry(combinedExpiryValue: string): [Year | null,
// If there is only one date part, no delimiter was found in the passed value // If there is only one date part, no delimiter was found in the passed value
if (dateParts.length === 1) { if (dateParts.length === 1) {
[parsedYear, parsedMonth] = parseNonDelimitedYearMonthExpiry(sanitizedFirstPart); const [parsedNonDelimitedYear, parsedNonDelimitedMonth] =
parseNonDelimitedYearMonthExpiry(sanitizedFirstPart);
parsedYear = parsedNonDelimitedYear;
parsedMonth = parsedNonDelimitedMonth;
} }
// There are multiple date parts // There are multiple date parts
else { else {
[parsedYear, parsedMonth] = parseDelimitedYearMonthExpiry([ const [parsedDelimitedYear, parsedDelimitedMonth] = parseDelimitedYearMonthExpiry([
sanitizedFirstPart, sanitizedFirstPart,
sanitizedSecondPart, sanitizedSecondPart,
]); ]);
parsedYear = parsedDelimitedYear;
parsedMonth = parsedDelimitedMonth;
} }
const normalizedParsedYear = normalizeExpiryYearFormat(parsedYear); const normalizedParsedYear = parsedYear ? normalizeExpiryYearFormat(parsedYear) : null;
const normalizedParsedMonth = parsedMonth?.replace(/^0+/, "").slice(0, 2); const normalizedParsedMonth = parsedMonth?.replace(/^0+/, "").slice(0, 2);
// Set "empty" values to null // Set "empty" values to null