in src/utils/hibp.ts [221:285]
async function getAllBreachesFromDb(): Promise<HibpLikeDbBreach[]> {
let dbBreaches: BreachRow[] = [];
const rClient = redisClient();
try {
// attempts to fetch breaches from Redis first
let redisBreaches;
if (rClient) {
redisBreaches = JSON.parse(
(await rClient.get(REDIS_ALL_BREACHES_KEY)) || "[]",
) as BreachRow[];
}
if (!redisBreaches || redisBreaches.length < 1) {
// if Redis fails, attempt to get breaches from Postgres and set Redis
logger.warn("get_all_breaches_from_db", {
exception: "Failed to fetch breaches in redis",
});
dbBreaches = await getAllBreaches();
logger.info("get_all_breaches_from_db_successful", {
numOfBreaches: dbBreaches.length,
});
await rClient.set(REDIS_ALL_BREACHES_KEY, JSON.stringify(dbBreaches));
await rClient.expire(REDIS_ALL_BREACHES_KEY, 3600 * 12); // 12 hour expiration
logger.info("set_breaches_in_redis_successful");
} else {
dbBreaches = redisBreaches;
logger.info("get_breaches_from_redis_successful", {
numOfBreaches: dbBreaches.length,
});
}
} catch (e) {
logger.error("get_all_breaches_from_db", {
exception: "No breaches exist in the database: " + (e as string),
});
return [];
}
// TODO: we can do some filtering here for the most commonly used fields
// TODO: change field names to camel case
return dbBreaches.map(
(breach) =>
({
Id: breach.id,
Name: breach.name,
Title: breach.title,
Domain: breach.domain,
BreachDate: breach.breach_date,
AddedDate: breach.added_date,
ModifiedDate: breach.modified_date,
PwnCount: breach.pwn_count,
Description: breach.description,
LogoPath: breach.logo_path,
DataClasses: breach.data_classes,
IsVerified: breach.is_verified,
IsFabricated: breach.is_fabricated,
IsSensitive: breach.is_sensitive,
IsRetired: breach.is_retired,
IsSpamList: breach.is_spam_list,
IsMalware: breach.is_malware,
FaviconUrl: breach.favicon_url,
}) as HibpLikeDbBreach,
);
}