catch more errors if something catastrophic happens to encrypted data

This commit is contained in:
2024-12-10 20:02:49 -07:00
parent 870d279526
commit af197f7c11
16 changed files with 238 additions and 70 deletions

View File

@@ -4,10 +4,10 @@ import { sha256 } from "ethereum-cryptography/sha256";
import { LRUCache } from "lru-cache";
import * as R from "ramda";
import { DEFAULT_IMAGE_API_SERVER } from "@/constants/app";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "@/constants/app";
import { Contact } from "@/db/tables/contacts";
import { accessToken, deriveAddress, nextDerivationPath } from "@/libs/crypto";
import { NonsensitiveDexie } from "@/db/index";
import { logConsoleAndDb, NonsensitiveDexie } from "@/db/index";
import {
retrieveAccountMetadata,
retrieveFullyDecryptedAccount,
@@ -501,35 +501,72 @@ export function tokenExpiryTimeDescription() {
/**
* Get the headers for a request, potentially including Authorization
*/
export async function getHeaders(did?: string) {
export async function getHeaders(
did?: string,
$notify?: (notification: NotificationIface, timeout?: number) => void,
failureMessage?: string,
) {
const headers: { "Content-Type": string; Authorization?: string } = {
"Content-Type": "application/json",
};
if (did) {
let token;
const account = await retrieveAccountMetadata(did);
if (account?.passkeyCredIdHex) {
if (
passkeyAccessToken &&
passkeyTokenExpirationEpochSeconds > Date.now() / 1000
) {
// there's an active current passkey token
token = passkeyAccessToken;
} else {
// there's no current passkey token or it's expired
token = await accessToken(did);
try {
let token;
const account = await retrieveAccountMetadata(did);
if (account?.passkeyCredIdHex) {
if (
passkeyAccessToken &&
passkeyTokenExpirationEpochSeconds > Date.now() / 1000
) {
// there's an active current passkey token
token = passkeyAccessToken;
} else {
// there's no current passkey token or it's expired
token = await accessToken(did);
passkeyAccessToken = token;
const passkeyExpirationSeconds = await getPasskeyExpirationSeconds();
passkeyTokenExpirationEpochSeconds =
Date.now() / 1000 + passkeyExpirationSeconds;
passkeyAccessToken = token;
const passkeyExpirationSeconds = await getPasskeyExpirationSeconds();
passkeyTokenExpirationEpochSeconds =
Date.now() / 1000 + passkeyExpirationSeconds;
}
} else {
token = await accessToken(did);
}
headers["Authorization"] = "Bearer " + token;
} catch (error) {
// This rarely happens: we've seen it when they have account info but the
// encryption secret got lost. But in most cases we want users to at
// least see their feed -- and anything else that returns results for
// anonymous users.
// We'll continue with an anonymous request... still want to show feed and other things, but ideally let them know.
logConsoleAndDb(
"Something failed in getHeaders call (will proceed anonymously" +
($notify ? " and notify user" : "") +
"): " +
// IntelliJ type system complains about getCircularReplacer() with: Argument of type '(obj: any, key: string, value: any) => any' is not assignable to parameter of type '(this: any, key: string, value: any) => any'.
//JSON.stringify(error, getCircularReplacer()), // JSON.stringify(error) on a Dexie error throws another error about: Converting circular structure to JSON
error,
true,
);
if ($notify) {
// remember: only want to do this if they supplied a DID, expecting personal results
const notifyMessage =
failureMessage ||
"Showing anonymous data. See the Help page for help with personal data.";
$notify(
{
group: "alert",
type: "danger",
title: "Personal Data Error",
text: notifyMessage,
},
3000,
);
}
} else {
token = await accessToken(did);
}
headers["Authorization"] = "Bearer " + token;
} else {
// it's often OK to request without auth; we assume necessary checks are done earlier
// it's usually OK to request without auth; we assume we're only here when allowed
}
return headers;
}
@@ -611,6 +648,7 @@ export async function getNewOffersToUser(
url += "&beforeId=" + beforeOfferJwtId;
}
const headers = await getHeaders(activeDid);
console.log("Using headers: ", headers);
const response = await axios.get(url, { headers });
return response.data;
}