forked from trent_larson/crowd-funder-for-time-pwa
WIP: BROKEN FOR ELECTRON: Fixes in progress
This commit is contained in:
@@ -194,7 +194,9 @@ export class PeerSetup {
|
||||
},
|
||||
};
|
||||
|
||||
const credential = await navigator.credentials.get(options) as PublicKeyCredential;
|
||||
const credential = (await navigator.credentials.get(
|
||||
options,
|
||||
)) as PublicKeyCredential;
|
||||
// console.log("nav credential get", credential);
|
||||
|
||||
const response = credential?.response as AuthenticatorAssertionResponse;
|
||||
@@ -229,9 +231,7 @@ export class PeerSetup {
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "");
|
||||
|
||||
const origSignature = Buffer.from(response?.signature).toString(
|
||||
"base64",
|
||||
);
|
||||
const origSignature = Buffer.from(response?.signature).toString("base64");
|
||||
this.signature = origSignature
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
@@ -327,10 +327,7 @@ export async function verifyJwtP256(
|
||||
const publicKeyBytes = peerDidToPublicKeyBytes(issuerDid);
|
||||
|
||||
// Use challenge in preimage construction
|
||||
const preimage = Buffer.concat([
|
||||
authDataFromBase,
|
||||
Buffer.from(challenge),
|
||||
]);
|
||||
const preimage = Buffer.concat([authDataFromBase, Buffer.from(challenge)]);
|
||||
|
||||
const isValid = p256.verify(
|
||||
finalSigBuffer,
|
||||
@@ -391,10 +388,7 @@ export async function verifyJwtWebCrypto(
|
||||
const finalSigBuffer = unwrapEC2Signature(sigBuffer);
|
||||
|
||||
// Use challenge in preimage construction
|
||||
const preimage = Buffer.concat([
|
||||
authDataFromBase,
|
||||
Buffer.from(challenge),
|
||||
]);
|
||||
const preimage = Buffer.concat([authDataFromBase, Buffer.from(challenge)]);
|
||||
|
||||
return verifyPeerSignature(preimage, issuerDid, finalSigBuffer);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ import {
|
||||
ClaimObject,
|
||||
VerifiableCredentialClaim,
|
||||
Agent,
|
||||
QuantitativeValue
|
||||
QuantitativeValue,
|
||||
} from "../interfaces/common";
|
||||
import { logger } from "../utils/logger";
|
||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
||||
@@ -106,11 +106,12 @@ export const CONTACT_CONFIRM_URL_PATH_TIME_SAFARI = "/contact/confirm/";
|
||||
*/
|
||||
export const ENDORSER_CH_HANDLE_PREFIX = "https://endorser.ch/entity/";
|
||||
|
||||
export const BLANK_GENERIC_SERVER_RECORD: GenericCredWrapper<GenericVerifiableCredential> = {
|
||||
claim: {
|
||||
"@context": SCHEMA_ORG_CONTEXT,
|
||||
"@type": ""
|
||||
},
|
||||
export const BLANK_GENERIC_SERVER_RECORD: GenericCredWrapper<GenericVerifiableCredential> =
|
||||
{
|
||||
claim: {
|
||||
"@context": SCHEMA_ORG_CONTEXT,
|
||||
"@type": "",
|
||||
},
|
||||
handleId: "",
|
||||
id: "",
|
||||
issuedAt: "",
|
||||
@@ -200,10 +201,10 @@ const testRecursivelyOnStrings = (
|
||||
return input.some((item) => testRecursivelyOnStrings(item, test));
|
||||
} else if (input && typeof input === "object") {
|
||||
return Object.values(input as Record<string, unknown>).some((value) =>
|
||||
testRecursivelyOnStrings(value, test)
|
||||
testRecursivelyOnStrings(value, test),
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -545,7 +546,7 @@ export async function setPlanInCache(
|
||||
* @returns {string|undefined} User-friendly message or undefined if none found
|
||||
*/
|
||||
export function serverMessageForUser(error: unknown): string | undefined {
|
||||
if (error && typeof error === 'object' && 'response' in error) {
|
||||
if (error && typeof error === "object" && "response" in error) {
|
||||
const err = error as AxiosErrorResponse;
|
||||
return err.response?.data?.error?.message;
|
||||
}
|
||||
@@ -571,21 +572,26 @@ export function errorStringForLog(error: unknown) {
|
||||
// --- property '_value' closes the circle
|
||||
}
|
||||
let fullError = "" + error + " - JSON: " + stringifiedError;
|
||||
|
||||
if (error && typeof error === 'object' && 'response' in error) {
|
||||
|
||||
if (error && typeof error === "object" && "response" in error) {
|
||||
const err = error as AxiosErrorResponse;
|
||||
const errorResponseText = JSON.stringify(err.response);
|
||||
// for some reason, error.response is not included in stringify result (eg. for 400 errors on invite redemptions)
|
||||
if (!R.empty(errorResponseText) && !fullError.includes(errorResponseText)) {
|
||||
// add error.response stuff
|
||||
if (err.response?.config && err.config && R.equals(err.config, err.response.config)) {
|
||||
// but exclude "config" because it's already in there
|
||||
const newErrorResponseText = JSON.stringify(
|
||||
// for some reason, error.response is not included in stringify result (eg. for 400 errors on invite redemptions)
|
||||
if (!R.empty(errorResponseText) && !fullError.includes(errorResponseText)) {
|
||||
// add error.response stuff
|
||||
if (
|
||||
err.response?.config &&
|
||||
err.config &&
|
||||
R.equals(err.config, err.response.config)
|
||||
) {
|
||||
// but exclude "config" because it's already in there
|
||||
const newErrorResponseText = JSON.stringify(
|
||||
R.omit(["config"] as never[], err.response),
|
||||
);
|
||||
fullError += " - .response w/o same config JSON: " + newErrorResponseText;
|
||||
} else {
|
||||
fullError += " - .response JSON: " + errorResponseText;
|
||||
);
|
||||
fullError +=
|
||||
" - .response w/o same config JSON: " + newErrorResponseText;
|
||||
} else {
|
||||
fullError += " - .response JSON: " + errorResponseText;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -664,7 +670,7 @@ export function hydrateGive(
|
||||
"@type": "GiveAction",
|
||||
object: undefined,
|
||||
agent: undefined,
|
||||
fulfills: []
|
||||
fulfills: [],
|
||||
};
|
||||
|
||||
if (lastClaimId) {
|
||||
@@ -679,13 +685,13 @@ export function hydrateGive(
|
||||
vcClaim.recipient = { identifier: toDid };
|
||||
}
|
||||
vcClaim.description = description || undefined;
|
||||
|
||||
|
||||
if (amount && !isNaN(amount)) {
|
||||
const quantitativeValue: QuantitativeValue = {
|
||||
"@context": SCHEMA_ORG_CONTEXT,
|
||||
"@type": "QuantitativeValue",
|
||||
amountOfThisGood: amount,
|
||||
unitCode: unitCode || "HUR"
|
||||
unitCode: unitCode || "HUR",
|
||||
};
|
||||
vcClaim.object = quantitativeValue;
|
||||
}
|
||||
@@ -697,34 +703,34 @@ export function hydrateGive(
|
||||
|
||||
// Filter and add fulfills elements
|
||||
vcClaim.fulfills = vcClaim.fulfills.filter(
|
||||
(elem: { '@type': string }) => elem["@type"] !== "PlanAction"
|
||||
(elem: { "@type": string }) => elem["@type"] !== "PlanAction",
|
||||
);
|
||||
|
||||
|
||||
if (fulfillsProjectHandleId) {
|
||||
vcClaim.fulfills.push({
|
||||
"@type": "PlanAction",
|
||||
identifier: fulfillsProjectHandleId
|
||||
identifier: fulfillsProjectHandleId,
|
||||
});
|
||||
}
|
||||
|
||||
vcClaim.fulfills = vcClaim.fulfills.filter(
|
||||
(elem: { '@type': string }) => elem["@type"] !== "Offer"
|
||||
(elem: { "@type": string }) => elem["@type"] !== "Offer",
|
||||
);
|
||||
|
||||
|
||||
if (fulfillsOfferHandleId) {
|
||||
vcClaim.fulfills.push({
|
||||
"@type": "Offer",
|
||||
identifier: fulfillsOfferHandleId
|
||||
identifier: fulfillsOfferHandleId,
|
||||
});
|
||||
}
|
||||
|
||||
vcClaim.fulfills = vcClaim.fulfills.filter(
|
||||
(elem: { '@type': string }) =>
|
||||
elem["@type"] !== "DonateAction" && elem["@type"] !== "TradeAction"
|
||||
(elem: { "@type": string }) =>
|
||||
elem["@type"] !== "DonateAction" && elem["@type"] !== "TradeAction",
|
||||
);
|
||||
|
||||
vcClaim.fulfills.push({
|
||||
"@type": isTrade ? "TradeAction" : "DonateAction"
|
||||
|
||||
vcClaim.fulfills.push({
|
||||
"@type": isTrade ? "TradeAction" : "DonateAction",
|
||||
});
|
||||
|
||||
vcClaim.image = imageUrl || undefined;
|
||||
@@ -732,7 +738,7 @@ export function hydrateGive(
|
||||
if (providerPlanHandleId) {
|
||||
vcClaim.provider = {
|
||||
"@type": "PlanAction",
|
||||
identifier: providerPlanHandleId
|
||||
identifier: providerPlanHandleId,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -854,7 +860,7 @@ export function hydrateOffer(
|
||||
"@type": "OfferAction",
|
||||
object: undefined,
|
||||
agent: undefined,
|
||||
itemOffered: {}
|
||||
itemOffered: {},
|
||||
};
|
||||
|
||||
if (lastClaimId) {
|
||||
@@ -875,7 +881,7 @@ export function hydrateOffer(
|
||||
"@context": SCHEMA_ORG_CONTEXT,
|
||||
"@type": "QuantitativeValue",
|
||||
amountOfThisGood: amount,
|
||||
unitCode: unitCode || "HUR"
|
||||
unitCode: unitCode || "HUR",
|
||||
};
|
||||
vcClaim.object = quantitativeValue;
|
||||
}
|
||||
@@ -886,7 +892,7 @@ export function hydrateOffer(
|
||||
if (fulfillsProjectHandleId) {
|
||||
vcClaim.itemOffered.isPartOf = {
|
||||
"@type": "PlanAction",
|
||||
identifier: fulfillsProjectHandleId
|
||||
identifier: fulfillsProjectHandleId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1024,12 +1030,14 @@ export async function createAndSubmitClaim(
|
||||
logger.error("Error submitting claim:", error);
|
||||
const errorMessage: string =
|
||||
serverMessageForUser(error) ||
|
||||
(error && typeof error === 'object' && 'message' in error ? String(error.message) : undefined) ||
|
||||
(error && typeof error === "object" && "message" in error
|
||||
? String(error.message)
|
||||
: undefined) ||
|
||||
"Got some error submitting the claim. Check your permissions, network, and error logs.";
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: errorMessage
|
||||
error: errorMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1061,10 +1069,7 @@ export async function generateEndorserJwtUrlForAccount(
|
||||
// Add the next key -- not recommended for the QR code for such a high resolution
|
||||
if (isContact) {
|
||||
const newDerivPath = nextDerivationPath(account.derivationPath);
|
||||
const nextPublicHex = deriveAddress(
|
||||
account.mnemonic,
|
||||
newDerivPath,
|
||||
)[2];
|
||||
const nextPublicHex = deriveAddress(account.mnemonic, newDerivPath)[2];
|
||||
const nextPublicEncKey = Buffer.from(nextPublicHex, "hex");
|
||||
const nextPublicEncKeyHash = sha256(nextPublicEncKey);
|
||||
const nextPublicEncKeyHashBase64 =
|
||||
@@ -1133,13 +1138,15 @@ export const capitalizeAndInsertSpacesBeforeCaps = (text: string) => {
|
||||
similar code is also contained in endorser-mobile
|
||||
**/
|
||||
const claimSummary = (
|
||||
claim: GenericVerifiableCredential | GenericCredWrapper<GenericVerifiableCredential>,
|
||||
claim:
|
||||
| GenericVerifiableCredential
|
||||
| GenericCredWrapper<GenericVerifiableCredential>,
|
||||
) => {
|
||||
if (!claim) {
|
||||
return "something";
|
||||
}
|
||||
let specificClaim: GenericVerifiableCredential;
|
||||
if ('claim' in claim) {
|
||||
if ("claim" in claim) {
|
||||
// It's a GenericCredWrapper
|
||||
specificClaim = claim.claim as GenericVerifiableCredential;
|
||||
} else {
|
||||
@@ -1180,7 +1187,7 @@ export const claimSpecialDescription = (
|
||||
contacts: Array<Contact>,
|
||||
) => {
|
||||
let claim = record.claim;
|
||||
if ('claim' in claim) {
|
||||
if ("claim" in claim) {
|
||||
claim = claim.claim as GenericVerifiableCredential;
|
||||
}
|
||||
|
||||
@@ -1189,12 +1196,23 @@ export const claimSpecialDescription = (
|
||||
const type = claimObj["@type"] || "UnknownType";
|
||||
|
||||
if (type === "AgreeAction") {
|
||||
return issuer + " agreed with " + claimSummary(claimObj.object as GenericVerifiableCredential);
|
||||
return (
|
||||
issuer +
|
||||
" agreed with " +
|
||||
claimSummary(claimObj.object as GenericVerifiableCredential)
|
||||
);
|
||||
} else if (isAccept(claim)) {
|
||||
return issuer + " accepted " + claimSummary(claimObj.object as GenericVerifiableCredential);
|
||||
return (
|
||||
issuer +
|
||||
" accepted " +
|
||||
claimSummary(claimObj.object as GenericVerifiableCredential)
|
||||
);
|
||||
} else if (type === "GiveAction") {
|
||||
const giveClaim = claim as GiveVerifiableCredential;
|
||||
const agent: Agent = giveClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = giveClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1209,7 +1227,10 @@ export const claimSpecialDescription = (
|
||||
return contactInfo + " gave" + offering + recipientInfo;
|
||||
} else if (type === "JoinAction") {
|
||||
const joinClaim = claim as ClaimObject;
|
||||
const agent: Agent = joinClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = joinClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1219,7 +1240,10 @@ export const claimSpecialDescription = (
|
||||
return contactInfo + " joined" + objectInfo;
|
||||
} else if (isOffer(claim)) {
|
||||
const offerClaim = claim as OfferVerifiableCredential;
|
||||
const agent: Agent = offerClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = offerClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1234,7 +1258,10 @@ export const claimSpecialDescription = (
|
||||
return contactInfo + " offered" + offering + offerRecipientInfo;
|
||||
} else if (type === "PlanAction") {
|
||||
const planClaim = claim as ClaimObject;
|
||||
const agent: Agent = planClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = planClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1244,7 +1271,10 @@ export const claimSpecialDescription = (
|
||||
return contactInfo + " planned" + objectInfo;
|
||||
} else if (type === "Tenure") {
|
||||
const tenureClaim = claim as ClaimObject;
|
||||
const agent: Agent = tenureClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = tenureClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1253,11 +1283,7 @@ export const claimSpecialDescription = (
|
||||
const objectInfo = object ? " " + claimSummary(object) : "";
|
||||
return contactInfo + " has tenure" + objectInfo;
|
||||
} else {
|
||||
return (
|
||||
issuer +
|
||||
" declared " +
|
||||
claimSummary(claim)
|
||||
);
|
||||
return issuer + " declared " + claimSummary(claim);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1333,35 +1359,39 @@ export async function register(
|
||||
contact: Contact,
|
||||
): Promise<{ success?: boolean; error?: string }> {
|
||||
try {
|
||||
const vcJwt = await createInviteJwt(activeDid, contact);
|
||||
const url = apiServer + "/api/v2/claim";
|
||||
const resp = await axios.post<{
|
||||
success?: {
|
||||
handleId?: string;
|
||||
const vcJwt = await createInviteJwt(activeDid, contact);
|
||||
const url = apiServer + "/api/v2/claim";
|
||||
const resp = await axios.post<{
|
||||
success?: {
|
||||
handleId?: string;
|
||||
embeddedRecordError?: string;
|
||||
};
|
||||
error?: string;
|
||||
message?: string;
|
||||
}>(url, { jwtEncoded: vcJwt });
|
||||
|
||||
if (resp.data?.success?.handleId) {
|
||||
return { success: true };
|
||||
} else if (resp.data?.success?.embeddedRecordError) {
|
||||
let message = "There was some problem with the registration and so it may not be complete.";
|
||||
|
||||
if (resp.data?.success?.handleId) {
|
||||
return { success: true };
|
||||
} else if (resp.data?.success?.embeddedRecordError) {
|
||||
let message =
|
||||
"There was some problem with the registration and so it may not be complete.";
|
||||
if (typeof resp.data.success.embeddedRecordError === "string") {
|
||||
message += " " + resp.data.success.embeddedRecordError;
|
||||
}
|
||||
return { error: message };
|
||||
} else {
|
||||
message += " " + resp.data.success.embeddedRecordError;
|
||||
}
|
||||
return { error: message };
|
||||
} else {
|
||||
logger.error("Registration error:", JSON.stringify(resp.data));
|
||||
return { error: "Got a server error when registering." };
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (error && typeof error === 'object') {
|
||||
if (error && typeof error === "object") {
|
||||
const err = error as AxiosErrorResponse;
|
||||
const errorMessage = err.message ||
|
||||
(err.response?.data && typeof err.response.data === 'object' && 'message' in err.response.data
|
||||
? (err.response.data as { message: string }).message
|
||||
const errorMessage =
|
||||
err.message ||
|
||||
(err.response?.data &&
|
||||
typeof err.response.data === "object" &&
|
||||
"message" in err.response.data
|
||||
? (err.response.data as { message: string }).message
|
||||
: undefined);
|
||||
logger.error("Registration error:", errorMessage || JSON.stringify(err));
|
||||
return { error: errorMessage || "Got a server error when registering." };
|
||||
|
||||
@@ -30,19 +30,13 @@ import {
|
||||
simpleEncrypt,
|
||||
} from "../libs/crypto";
|
||||
import * as serverUtil from "../libs/endorserServer";
|
||||
import {
|
||||
containsHiddenDid,
|
||||
} from "../libs/endorserServer";
|
||||
import { containsHiddenDid } from "../libs/endorserServer";
|
||||
import {
|
||||
GenericCredWrapper,
|
||||
GenericVerifiableCredential,
|
||||
} from "../interfaces/common";
|
||||
import {
|
||||
GiveSummaryRecord,
|
||||
} from "../interfaces/records";
|
||||
import {
|
||||
OfferVerifiableCredential,
|
||||
} from "../interfaces/claims";
|
||||
import { GiveSummaryRecord } from "../interfaces/records";
|
||||
import { OfferVerifiableCredential } from "../interfaces/claims";
|
||||
import { KeyMeta } from "../interfaces/common";
|
||||
import { createPeerDid } from "../libs/crypto/vc/didPeer";
|
||||
import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer";
|
||||
@@ -406,10 +400,7 @@ export function offerGiverDid(
|
||||
export const canFulfillOffer = (
|
||||
veriClaim: GenericCredWrapper<GenericVerifiableCredential>,
|
||||
) => {
|
||||
return (
|
||||
veriClaim.claimType === "Offer" &&
|
||||
!!offerGiverDid(veriClaim)
|
||||
);
|
||||
return veriClaim.claimType === "Offer" && !!offerGiverDid(veriClaim);
|
||||
};
|
||||
|
||||
// return object with paths and arrays of DIDs for any keys ending in "VisibleToDid"
|
||||
@@ -478,8 +469,10 @@ export function findAllVisibleToDids(
|
||||
*
|
||||
**/
|
||||
|
||||
export interface AccountKeyInfo extends Omit<Account, 'derivationPath'>, Omit<KeyMeta, 'derivationPath'> {
|
||||
derivationPath?: string; // Make it optional to match Account type
|
||||
export interface AccountKeyInfo
|
||||
extends Omit<Account, "derivationPath">,
|
||||
Omit<KeyMeta, "derivationPath"> {
|
||||
derivationPath?: string; // Make it optional to match Account type
|
||||
}
|
||||
|
||||
export const retrieveAccountCount = async (): Promise<number> => {
|
||||
@@ -489,7 +482,7 @@ export const retrieveAccountCount = async (): Promise<number> => {
|
||||
`SELECT COUNT(*) FROM accounts`,
|
||||
);
|
||||
if (dbResult?.values?.[0]?.[0]) {
|
||||
result = dbResult.values[0][0] as number;
|
||||
result = dbResult.values[0][0] as number;
|
||||
}
|
||||
|
||||
if (USE_DEXIE_DB) {
|
||||
@@ -638,7 +631,7 @@ export const retrieveAllFullyDecryptedAccounts = async (): Promise<
|
||||
) as unknown as AccountEncrypted[];
|
||||
if (USE_DEXIE_DB) {
|
||||
const accountsDB = await accountsDBPromise;
|
||||
allAccounts = await accountsDB.accounts.toArray() as AccountEncrypted[];
|
||||
allAccounts = (await accountsDB.accounts.toArray()) as AccountEncrypted[];
|
||||
}
|
||||
return allAccounts;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user