async function getBreachesForEmail()

in src/utils/hibp.ts [342:417]


async function getBreachesForEmail(
  sha1: string,
  allBreaches: HibpLikeDbBreach[],
  includeSensitive = false,
  filterBreaches = true,
): Promise<HibpLikeDbBreach[]> {
  let foundBreaches: HibpLikeDbBreach[] = [];
  const sha1Prefix = sha1.slice(0, 6).toUpperCase();
  const path = `/range/search/${sha1Prefix}`;

  const qaToggles = await getQaToggleRow(sha1);
  let showCustomBreaches = false;
  let showRealBreaches = true;
  if (qaToggles) {
    showCustomBreaches = qaToggles.show_custom_breaches;
    showRealBreaches = qaToggles.show_real_breaches;
  }

  const qaBreaches = !showCustomBreaches
    ? []
    : await getAllQaCustomBreaches(sha1Prefix);
  if (!showRealBreaches) return qaBreaches as HibpLikeDbBreach[];

  const response = (await kAnonReq(path)) as
    | BreachedAccountResponse
    | undefined;
  if (!response || (response && response.length < 1)) {
    logger.error("failed_kAnonReq_call: no response or empty response");
    return [...qaBreaches] as HibpLikeDbBreach[];
  }
  if (isUsingMockHIBPEndpoint()) {
    const mockDataBreaches = response[0];
    return [
      ...(qaBreaches as HibpLikeDbBreach[]),
      ...allBreaches
        .filter((breach) => mockDataBreaches.websites.includes(breach.Name))
        .sort((a, b) => {
          // @ts-ignore TODO: Turn dates into a number
          return new Date(b.AddedDate) - new Date(a.AddedDate);
        }),
    ];
  }
  // Parse response body, format:
  // [
  //   {"hashSuffix":<suffix>,"websites":[<breach1Name>,...]},
  //   {"hashSuffix":<suffix>,"websites":[<breach1Name>,...]},
  // ]
  for (const breachedAccount of response) {
    if (sha1.toUpperCase() === sha1Prefix + breachedAccount.hashSuffix) {
      foundBreaches = allBreaches.filter((breach) =>
        breachedAccount.websites.includes(breach.Name),
      );
      if (filterBreaches) {
        foundBreaches = getFilteredBreaches(foundBreaches);
      }

      // NOTE: DO NOT CHANGE THIS SORT LOGIC
      // We store breach resolutions by recency indices,
      // so that our DB does not contain any part of any user's list of accounts
      foundBreaches.sort((a, b) => {
        // @ts-ignore TODO: Turn dates into a number
        return new Date(b.AddedDate) - new Date(a.AddedDate);
      });

      break;
    }
  }

  if (includeSensitive) {
    return [...foundBreaches, ...(qaBreaches as HibpLikeDbBreach[])];
  }
  return [
    ...(qaBreaches as HibpLikeDbBreach[]),
    ...foundBreaches.filter((breach) => !breach.IsSensitive),
  ];
}