From 5501ac1a2f704d4206e40ae6b9ce9192d23e0035 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Sun, 3 Sep 2023 21:08:30 +0800 Subject: [PATCH] Many fixes -- especially and endorserServer --- src/components/AlertMessage.vue | 47 -------- src/components/EntityIcon.vue | 2 +- src/libs/endorserServer.ts | 173 ++++++++++++++++++---------- src/views/AccountViewView.vue | 16 ++- src/views/ContactAmountsView.vue | 18 +-- src/views/ContactGiftingView.vue | 23 ++-- src/views/ContactQRScanShowView.vue | 9 ++ src/views/ContactsView.vue | 18 +-- src/views/DiscoverView.vue | 15 ++- src/views/HomeView.vue | 23 ++-- src/views/IdentitySwitcherView.vue | 19 +-- src/views/NewEditProjectView.vue | 21 ++-- src/views/ProjectViewView.vue | 81 ++++++------- src/views/ProjectsView.vue | 16 ++- src/views/SeedBackupView.vue | 21 +++- src/views/StatisticsView.vue | 16 ++- tsconfig.json | 76 ++++++------ 17 files changed, 312 insertions(+), 282 deletions(-) delete mode 100644 src/components/AlertMessage.vue diff --git a/src/components/AlertMessage.vue b/src/components/AlertMessage.vue deleted file mode 100644 index 62e8c2c36..000000000 --- a/src/components/AlertMessage.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - diff --git a/src/components/EntityIcon.vue b/src/components/EntityIcon.vue index 002984921..ee69c03f8 100644 --- a/src/components/EntityIcon.vue +++ b/src/components/EntityIcon.vue @@ -8,7 +8,7 @@ import { toSvg } from "jdenticon"; @Component export default class EntityIcon extends Vue { @Prop entityId = ""; - @Prop iconSize = ""; + @Prop iconSize = 0; generateIdenticon() { const svgString = toSvg(this.entityId, this.iconSize); diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts index d5f4f86ba..372e81a64 100644 --- a/src/libs/endorserServer.ts +++ b/src/libs/endorserServer.ts @@ -75,7 +75,7 @@ export interface InternalError { // See https://github.com/trentlarson/endorser-ch/blob/0cb626f803028e7d9c67f095858a9fc8542e3dbd/server/api/services/util.js#L6 const HIDDEN_DID = "did:none:HIDDEN"; -export function isHiddenDid(did) { +export function isHiddenDid(did: string) { return did === HIDDEN_DID; } @@ -88,7 +88,7 @@ export function didInfo( allMyDids: Array, contacts: Array, ): string { - const myId: string | undefined = R.find(R.equals(did), allMyDids, did); + const myId: string | undefined = R.find(R.equals(did), allMyDids); if (myId) { return "You" + (myId !== activeDid ? " (Alt ID)" : ""); } else { @@ -105,6 +105,18 @@ export function didInfo( } } +interface SuccessResult { + type: "success"; + response: AxiosResponse; +} + +interface ErrorResult { + type: "error"; + error: InternalError; +} + +type CreateAndSubmitGiveResult = SuccessResult | ErrorResult; + /** * For result, see https://api.endorser.ch/api-docs/#/claims/post_api_v2_claim * @@ -123,71 +135,108 @@ export async function createAndSubmitGive( description: string, hours: number, fulfillsProjectHandleId?: string, -): Promise | InternalError> { - // Make a claim - const vcClaim: GiveVerifiableCredential = { - "@context": "https://schema.org", - "@type": "GiveAction", - recipient: { identifier: toDid }, - }; - if (fromDid) { - vcClaim.agent = { identifier: fromDid }; - } - if (description) { - vcClaim.description = description; - } - if (hours) { - vcClaim.object = { amountOfThisGood: hours, unitCode: "HUR" }; - } - if (fulfillsProjectHandleId) { - vcClaim.fulfills = { - "@type": "PlanAction", - identifier: fulfillsProjectHandleId, +): Promise { + try { + // Make a claim + const vcClaim: GiveVerifiableCredential = { + "@context": "https://schema.org", + "@type": "GiveAction", + recipient: { identifier: toDid }, }; - } - // Make a payload for the claim - const vcPayload = { - vc: { - "@context": ["https://www.w3.org/2018/credentials/v1"], - type: ["VerifiableCredential"], - credentialSubject: vcClaim, - }, - }; - // Create a signature using private key of identity - if (identity.keys[0].privateKeyHex == null) { - return new Promise((resolve, reject) => { - reject({ + if (fromDid) { + vcClaim.agent = { identifier: fromDid }; + } + if (description) { + vcClaim.description = description; + } + if (hours) { + vcClaim.object = { amountOfThisGood: hours, unitCode: "HUR" }; + } + if (fulfillsProjectHandleId) { + vcClaim.fulfills = { + "@type": "PlanAction", + identifier: fulfillsProjectHandleId, + }; + } + // Make a payload for the claim + const vcPayload = { + vc: { + "@context": ["https://www.w3.org/2018/credentials/v1"], + type: ["VerifiableCredential"], + credentialSubject: vcClaim, + }, + }; + + // Create a signature using private key of identity + const firstKey = identity.keys[0]; + if (!firstKey || !firstKey.privateKeyHex) { + throw { + error: "No private key", + message: `Your identifier ${identity.did} is not configured correctly. Use a different identifier.`, + }; + } + + const privateKeyHex = firstKey.privateKeyHex; + + if (!privateKeyHex) { + throw { error: "No private key", - message: - "Your identifier " + - identity.did + - " is not configured correctly. Use a different identifier.", - }); + message: `Your identifier ${identity.did} is not configured correctly. Use a different identifier.`, + }; + } + + const signer = await SimpleSigner(privateKeyHex); + const alg = undefined; + + // Create a JWT for the request + + const vcJwt: string = await didJwt.createJWT(vcPayload, { + alg: alg, + issuer: identity.did, + signer: signer, }); - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const privateKeyHex: string = identity.keys[0].privateKeyHex!; - const signer = await SimpleSigner(privateKeyHex); - const alg = undefined; - // Create a JWT for the request - const vcJwt: string = await didJwt.createJWT(vcPayload, { - alg: alg, - issuer: identity.did, - signer: signer, - }); - - // Make the xhr request payload - - const payload = JSON.stringify({ jwtEncoded: vcJwt }); - const url = apiServer + "/api/v2/claim"; - const token = await accessToken(identity); - const headers = { - "Content-Type": "application/json", - Authorization: "Bearer " + token, - }; + // Make the xhr request payload - return axios.post(url, payload, { headers }); + const payload = JSON.stringify({ jwtEncoded: vcJwt }); + const url = apiServer + "/api/v2/claim"; + const token = await accessToken(identity); + const headers = { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }; + + const response = await axios.post(url, payload, { headers }); + return { + type: "success", + response, + }; + } catch (error: unknown) { + let errorMessage: string; + + if (error instanceof Error) { + // If it's a JavaScript Error object + errorMessage = error.message; + } else if ( + typeof error === "object" && + error !== null && + "message" in error + ) { + // If it's an object that has a 'message' property + errorMessage = (error as { message: string }).message; + } else { + // Unknown error shape, default message + errorMessage = "Unknown error"; + } + + return { + type: "error", + error: { + error: errorMessage, + userMessage: "Failed to create and submit the claim", + }, + }; + } } // from https://stackoverflow.com/a/175787/845494 diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index f0b2b8a98..e73506ae4 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -286,10 +286,6 @@ - @@ -303,15 +299,23 @@ import { db, accountsDB } from "@/db"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { accessToken } from "@/libs/crypto"; import { AxiosError } from "axios/index"; -import AlertMessage from "@/components/AlertMessage"; import QuickNav from "@/components/QuickNav"; import { IIdentifier } from "@veramo/core"; // eslint-disable-next-line @typescript-eslint/no-var-requires const Buffer = require("buffer/").Buffer; -@Component({ components: { AlertMessage, QuickNav } }) +interface Notification { + group: string; + type: string; + title: string; + text: string; +} + +@Component({ components: { QuickNav } }) export default class AccountViewView extends Vue { + $notify!: (notification: Notification, timeout?: number) => void; + Constants = AppString; activeDid = ""; diff --git a/src/views/ContactAmountsView.vue b/src/views/ContactAmountsView.vue index c3a560672..f974cd491 100644 --- a/src/views/ContactAmountsView.vue +++ b/src/views/ContactAmountsView.vue @@ -90,10 +90,6 @@ - @@ -113,17 +109,23 @@ import { } from "@/libs/endorserServer"; import * as didJwt from "did-jwt"; import { AxiosError } from "axios"; -import AlertMessage from "@/components/AlertMessage"; import QuickNav from "@/components/QuickNav"; -@Component({ components: { AlertMessage, QuickNav } }) +interface Notification { + group: string; + type: string; + title: string; + text: string; +} + +@Component({ components: { QuickNav } }) export default class ContactsView extends Vue { + $notify!: (notification: Notification, timeout?: number) => void; + activeDid = ""; apiServer = ""; contact: Contact | null = null; giveRecords: Array = []; - alertTitle = ""; - alertMessage = ""; numAccounts = 0; async beforeCreate() { diff --git a/src/views/ContactGiftingView.vue b/src/views/ContactGiftingView.vue index 0f2a5e3ef..f3af3ffa6 100644 --- a/src/views/ContactGiftingView.vue +++ b/src/views/ContactGiftingView.vue @@ -76,10 +76,6 @@ message="Received from" > - @@ -93,21 +89,27 @@ import { accessToken } from "@/libs/crypto"; import { createAndSubmitGive } from "@/libs/endorserServer"; import { Account } from "@/db/tables/accounts"; import { Contact } from "@/db/tables/contacts"; -import AlertMessage from "@/components/AlertMessage"; import QuickNav from "@/components/QuickNav"; import EntityIcon from "@/components/EntityIcon"; +interface Notification { + group: string; + type: string; + title: string; + text: string; +} + @Component({ - components: { GiftedDialog, AlertMessage, QuickNav, EntityIcon }, + components: { GiftedDialog, QuickNav, EntityIcon }, }) export default class HomeView extends Vue { + $notify!: (notification: Notification, timeout?: number) => void; + activeDid = ""; allAccounts: Array = []; allContacts: Array = []; apiServer = ""; isHiddenSpinner = true; - alertTitle = ""; - alertMessage = ""; accounts: AccountsSchema; numAccounts = 0; @@ -289,11 +291,6 @@ export default class HomeView extends Vue { } } - private setAlert(title, message) { - this.alertTitle = title; - this.alertMessage = message; - } - // Helper functions for readability isGiveCreationError(result) { diff --git a/src/views/ContactQRScanShowView.vue b/src/views/ContactQRScanShowView.vue index c932a4996..cdcb9f6f3 100644 --- a/src/views/ContactQRScanShowView.vue +++ b/src/views/ContactQRScanShowView.vue @@ -34,6 +34,13 @@ import { Account } from "@/db/tables/accounts"; // eslint-disable-next-line @typescript-eslint/no-var-requires const Buffer = require("buffer/").Buffer; +interface Notification { + group: string; + type: string; + title: string; + text: string; +} + @Component({ components: { QRCodeVue3, @@ -41,6 +48,8 @@ const Buffer = require("buffer/").Buffer; }, }) export default class ContactQRScanShow extends Vue { + $notify!: (notification: Notification, timeout?: number) => void; + activeDid = ""; apiServer = ""; qrValue = ""; diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index 740ad8853..56dd7571e 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -202,10 +202,6 @@

This identity has no contacts.

- @@ -224,17 +220,25 @@ import { SERVICE_ID, } from "@/libs/endorserServer"; import { Component, Vue } from "vue-facing-decorator"; -import AlertMessage from "@/components/AlertMessage"; import QuickNav from "@/components/QuickNav"; import EntityIcon from "@/components/EntityIcon"; // eslint-disable-next-line @typescript-eslint/no-var-requires const Buffer = require("buffer/").Buffer; +interface Notification { + group: string; + type: string; + title: string; + text: string; +} + @Component({ - components: { AlertMessage, QuickNav, EntityIcon }, + components: { QuickNav, EntityIcon }, }) export default class ContactsView extends Vue { + $notify!: (notification: Notification, timeout?: number) => void; + activeDid = ""; apiServer = ""; contacts: Array = []; @@ -256,8 +260,6 @@ export default class ContactsView extends Vue { showGiveNumbers = false; showGiveTotals = true; showGiveConfirmed = true; - alertTitle = ""; - alertMessage = ""; async created() { await db.open(); diff --git a/src/views/DiscoverView.vue b/src/views/DiscoverView.vue index 525a92608..a893ffe3d 100644 --- a/src/views/DiscoverView.vue +++ b/src/views/DiscoverView.vue @@ -181,8 +181,6 @@ /> - - @@ -201,7 +199,6 @@ import { Contact } from "@/db/tables/contacts"; import { BoundingBox, MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { accessToken } from "@/libs/crypto"; import { didInfo, ProjectData } from "@/libs/endorserServer"; -import AlertMessage from "@/components/AlertMessage"; import QuickNav from "@/components/QuickNav"; import InfiniteScroll from "@/components/InfiniteScroll"; import EntityIcon from "@/components/EntityIcon"; @@ -210,10 +207,16 @@ const DEFAULT_LAT_LONG_DIFF = 0.01; const WORLD_ZOOM = 2; const DEFAULT_ZOOM = 2; +interface Notification { + group: string; + type: string; + title: string; + text: string; +} + @Component({ components: { LRectangle, - AlertMessage, QuickNav, InfiniteScroll, EntityIcon, @@ -223,13 +226,13 @@ const DEFAULT_ZOOM = 2; }, }) export default class DiscoverView extends Vue { + $notify!: (notification: Notification, timeout?: number) => void; + activeDid = ""; allContacts: Array = []; allMyDids: Array = []; apiServer = ""; searchTerms = ""; - alertMessage = ""; - alertTitle = ""; projects: ProjectData[] = []; isChoosingSearchBox = false; isLocalActive = true; diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 6031e0b6d..4c238bace 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -196,10 +196,6 @@ - @@ -211,14 +207,22 @@ import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { accessToken } from "@/libs/crypto"; import { createAndSubmitGive, didInfo } from "@/libs/endorserServer"; import { Contact } from "@/db/tables/contacts"; -import AlertMessage from "@/components/AlertMessage"; import QuickNav from "@/components/QuickNav"; import EntityIcon from "@/components/EntityIcon"; +interface Notification { + group: string; + type: string; + title: string; + text: string; +} + @Component({ - components: { GiftedDialog, AlertMessage, QuickNav, EntityIcon }, + components: { GiftedDialog, QuickNav, EntityIcon }, }) export default class HomeView extends Vue { + $notify!: (notification: Notification, timeout?: number) => void; + activeDid = ""; allContacts: Array = []; allMyDids: Array = []; @@ -228,8 +232,6 @@ export default class HomeView extends Vue { feedPreviousOldestId = null; feedLastViewedId = null; isHiddenSpinner = true; - alertTitle = ""; - alertMessage = ""; numAccounts = 0; async beforeCreate() { @@ -509,11 +511,6 @@ export default class HomeView extends Vue { } } - private setAlert(title, message) { - this.alertTitle = title; - this.alertMessage = message; - } - // Helper functions for readability isGiveCreationError(result) { diff --git a/src/views/IdentitySwitcherView.vue b/src/views/IdentitySwitcherView.vue index 41fdfef5c..a21d1ac3b 100644 --- a/src/views/IdentitySwitcherView.vue +++ b/src/views/IdentitySwitcherView.vue @@ -62,11 +62,6 @@ > No Identity - -