From 9b65fb7ef95d6966cf4e05aa5549d55660ef3949 Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Mon, 15 Jul 2024 20:47:10 -0600
Subject: [PATCH] remove remaining getIdentity calls & fix QR code for did:peer
---
src/libs/crypto/vc/didPeer.ts | 12 ++---
src/libs/crypto/vc/index.ts | 2 +
src/libs/endorserServer.ts | 5 +-
src/libs/util.ts | 12 -----
src/views/ContactAmountsView.vue | 6 +--
src/views/ContactQRScanShowView.vue | 78 +++++++++++++++++++++--------
src/views/GiftedDetails.vue | 3 +-
src/views/NewEditProjectView.vue | 13 ++---
src/views/ProjectsView.vue | 26 ++++------
9 files changed, 86 insertions(+), 71 deletions(-)
diff --git a/src/libs/crypto/vc/didPeer.ts b/src/libs/crypto/vc/didPeer.ts
index 9c0fa73c0..3c62dd0f2 100644
--- a/src/libs/crypto/vc/didPeer.ts
+++ b/src/libs/crypto/vc/didPeer.ts
@@ -1,10 +1,10 @@
-import {Buffer} from "buffer/";
-import {decode as cborDecode} from "cbor-x";
-import {bytesToMultibase, multibaseToBytes} from "did-jwt";
+import { Buffer } from "buffer/";
+import { decode as cborDecode } from "cbor-x";
+import { bytesToMultibase, multibaseToBytes } from "did-jwt";
-import {getWebCrypto} from "@/libs/crypto/vc/passkeyHelpers";
+import { getWebCrypto } from "@/libs/crypto/vc/passkeyHelpers";
-const PEER_DID_PREFIX = "did:peer:";
+export const PEER_DID_PREFIX = "did:peer:";
const PEER_DID_MULTIBASE_PREFIX = PEER_DID_PREFIX + "0";
/**
@@ -93,4 +93,4 @@ export function createPeerDid(publicKeyBytes: Uint8Array) {
"p256-pub",
);
return PEER_DID_MULTIBASE_PREFIX + methodSpecificId;
-}
\ No newline at end of file
+}
diff --git a/src/libs/crypto/vc/index.ts b/src/libs/crypto/vc/index.ts
index 7736708db..308f71c4b 100644
--- a/src/libs/crypto/vc/index.ts
+++ b/src/libs/crypto/vc/index.ts
@@ -13,6 +13,8 @@ import * as u8a from "uint8arrays";
import { createDidPeerJwt } from "@/libs/crypto/vc/passkeyDidPeer";
+export const ETHR_DID_PREFIX = "did:ethr:";
+
/**
* Meta info about a key
*/
diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts
index ff4bbd600..26954cd69 100644
--- a/src/libs/endorserServer.ts
+++ b/src/libs/endorserServer.ts
@@ -6,7 +6,7 @@ import { DEFAULT_IMAGE_API_SERVER } from "@/constants/app";
import { Contact } from "@/db/tables/contacts";
import { accessToken } from "@/libs/crypto";
import { NonsensitiveDexie } from "@/db/index";
-import { getAccount, getIdentity } from "@/libs/util";
+import { getAccount } from "@/libs/util";
import { createEndorserJwtForKey, KeyMeta } from "@/libs/crypto/vc";
export const SCHEMA_ORG_CONTEXT = "https://schema.org";
@@ -1001,8 +1001,7 @@ export async function setVisibilityUtil(
}
const url =
apiServer + "/api/report/" + (visibility ? "canSeeMe" : "cannotSeeMe");
- const identity = await getIdentity(activeDid);
- const headers = await getHeaders(identity.did);
+ const headers = await getHeaders(activeDid);
const payload = JSON.stringify({ did: contact.did });
try {
diff --git a/src/libs/util.ts b/src/libs/util.ts
index c5f3b39b7..c0292ac07 100644
--- a/src/libs/util.ts
+++ b/src/libs/util.ts
@@ -211,18 +211,6 @@ export const getAccount = async (
return account;
};
-export const getIdentity = async (activeDid: string): Promise => {
- const account = await getAccount(activeDid);
- const identity = JSON.parse(account?.identity || "null");
-
- if (!identity) {
- throw new Error(
- `Attempted to load identity ${activeDid} but no identifier was found`,
- );
- }
- return identity;
-};
-
/**
* Generates a new identity, saves it to the database, and sets it as the active identity.
* @return {Promise} with the DID of the new identity
diff --git a/src/views/ContactAmountsView.vue b/src/views/ContactAmountsView.vue
index cefb27ce1..157f2438f 100644
--- a/src/views/ContactAmountsView.vue
+++ b/src/views/ContactAmountsView.vue
@@ -124,7 +124,6 @@ import {
GiveVerifiableCredential,
SCHEMA_ORG_CONTEXT,
} from "@/libs/endorserServer";
-import * as libsUtil from "@/libs/util";
@Component({ components: { QuickNav } })
export default class ContactAmountssView extends Vue {
@@ -175,12 +174,11 @@ export default class ContactAmountssView extends Vue {
async loadGives(activeDid: string, contact: Contact) {
try {
- const identity = await libsUtil.getIdentity(this.activeDid);
let result: Array = [];
const url =
this.apiServer +
"/api/v2/report/gives?agentDid=" +
- encodeURIComponent(identity.did) +
+ encodeURIComponent(this.activeDid) +
"&recipientDid=" +
encodeURIComponent(contact.did);
const headers = await getHeaders(activeDid);
@@ -209,7 +207,7 @@ export default class ContactAmountssView extends Vue {
"/api/v2/report/gives?agentDid=" +
encodeURIComponent(contact.did) +
"&recipientDid=" +
- encodeURIComponent(identity.did);
+ encodeURIComponent(this.activeDid);
const headers2 = await getHeaders(activeDid);
const resp2 = await this.axios.get(url2, { headers: headers2 });
if (resp2.status === 200) {
diff --git a/src/views/ContactQRScanShowView.vue b/src/views/ContactQRScanShowView.vue
index c14f350dd..0a7109c72 100644
--- a/src/views/ContactQRScanShowView.vue
+++ b/src/views/ContactQRScanShowView.vue
@@ -34,7 +34,11 @@
-
+
+
+ Click here to copy your DID to your clipboard.
+
+
+ Then give it to them so they can paste it in their list of People.
+
You have no identitifiers yet, so
@@ -92,13 +106,14 @@ import {
nextDerivationPath,
} from "@/libs/crypto";
import {
- CONTACT_URL_PREFIX, createEndorserJwtForDid,
+ CONTACT_URL_PREFIX,
+ createEndorserJwtForDid,
ENDORSER_JWT_URL_LOCATION,
isDid,
register,
setVisibilityUtil,
} from "@/libs/endorserServer";
-import * as libsUtil from "@/libs/util";
+import { ETHR_DID_PREFIX } from "@/libs/crypto/vc";
@Component({
components: {
@@ -117,6 +132,8 @@ export default class ContactQRScanShow extends Vue {
isRegistered = false;
qrValue = "";
+ ETHR_DID_PREFIX = ETHR_DID_PREFIX;
+
async created() {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
@@ -131,20 +148,9 @@ export default class ContactQRScanShow extends Vue {
const accounts = await accountsDB.accounts.toArray();
const account = R.find((acc) => acc.did === this.activeDid, accounts);
if (account) {
- const identity = await libsUtil.getIdentity(this.activeDid);
- const publicKeyHex = identity.keys[0].publicKeyHex;
+ const publicKeyHex = account.publicKeyHex;
const publicEncKey = Buffer.from(publicKeyHex, "hex").toString("base64");
- const newDerivPath = nextDerivationPath(account.derivationPath as string);
- const nextPublicHex = deriveAddress(
- account.mnemonic as string,
- newDerivPath,
- )[2];
- const nextPublicEncKey = Buffer.from(nextPublicHex, "hex");
- const nextPublicEncKeyHash = sha256(nextPublicEncKey);
- const nextPublicEncKeyHashBase64 =
- Buffer.from(nextPublicEncKeyHash).toString("base64");
-
const contactInfo = {
iat: Date.now(),
iss: this.activeDid,
@@ -153,13 +159,28 @@ export default class ContactQRScanShow extends Vue {
(settings?.firstName || "") +
(settings?.lastName ? ` ${settings.lastName}` : ""), // deprecated, pre v 0.1.3
publicEncKey,
- nextPublicEncKeyHash: nextPublicEncKeyHashBase64,
profileImageUrl: settings?.profileImageUrl,
registered: settings?.isRegistered,
},
};
- const vcJwt: string = await createEndorserJwtForDid(identity.did, contactInfo);
+ if (account?.mnemonic && account?.derivationPath) {
+ const newDerivPath = nextDerivationPath(
+ account.derivationPath as string,
+ );
+ const nextPublicHex = deriveAddress(
+ account.mnemonic as string,
+ newDerivPath,
+ )[2];
+ const nextPublicEncKey = Buffer.from(nextPublicHex, "hex");
+ const nextPublicEncKeyHash = sha256(nextPublicEncKey);
+ const nextPublicEncKeyHashBase64 =
+ Buffer.from(nextPublicEncKeyHash).toString("base64");
+ contactInfo.own.nextPublicEncKeyHash = nextPublicEncKeyHashBase64;
+ }
+
+ const vcJwt = await createEndorserJwtForDid(this.activeDid, contactInfo);
+
const viewPrefix = CONTACT_URL_PREFIX + ENDORSER_JWT_URL_LOCATION;
this.qrValue = viewPrefix + vcJwt;
}
@@ -409,7 +430,7 @@ export default class ContactQRScanShow extends Vue {
);
}
- onCopyToClipboard() {
+ onCopyUrlToClipboard() {
//this.onScanDetect([{ rawValue: this.qrValue }]); // good for testing
useClipboard()
.copy(this.qrValue)
@@ -426,5 +447,22 @@ export default class ContactQRScanShow extends Vue {
);
});
}
+
+ onCopyDidToClipboard() {
+ //this.onScanDetect([{ rawValue: this.qrValue }]); // good for testing
+ useClipboard()
+ .copy(this.activeDid)
+ .then(() => {
+ this.$notify(
+ {
+ group: "alert",
+ type: "info",
+ title: "Copied",
+ text: "Your DID was copied to the clipboard. Have them paste it on their 'People' screen to add you.",
+ },
+ 10000,
+ );
+ });
+ }
}
diff --git a/src/views/GiftedDetails.vue b/src/views/GiftedDetails.vue
index 1ac570c69..626a0c85c 100644
--- a/src/views/GiftedDetails.vue
+++ b/src/views/GiftedDetails.vue
@@ -313,12 +313,11 @@ export default class GiftedDetails extends Vue {
if (this.projectId) {
// console.log("Getting project name from cache", this.projectId);
- const identity = await libsUtil.getIdentity(this.activeDid);
const project = await getPlanFromCache(
this.projectId,
this.axios,
this.apiServer,
- identity.did,
+ this.activeDid,
);
this.projectName = project?.name
? "the project: " + project.name
diff --git a/src/views/NewEditProjectView.vue b/src/views/NewEditProjectView.vue
index b9ba94edd..0ebf62ac8 100644
--- a/src/views/NewEditProjectView.vue
+++ b/src/views/NewEditProjectView.vue
@@ -175,7 +175,6 @@
import "leaflet/dist/leaflet.css";
import { AxiosError } from "axios";
import { DateTime } from "luxon";
-import { IIdentifier } from "@veramo/core";
import { Component, Vue } from "vue-facing-decorator";
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
@@ -189,7 +188,6 @@ import {
createEndorserJwtVcFromClaim,
PlanVerifiableCredential,
} from "@/libs/endorserServer";
-import * as libsUtil from "@/libs/util";
import { useAppStore } from "@/store/app";
@Component({
@@ -229,8 +227,6 @@ export default class NewEditProjectView extends Vue {
zoneName = DateTime.local().zoneName;
zoom = 2;
- libsUtil = libsUtil;
-
async mounted() {
await accountsDB.open();
this.numAccounts = await accountsDB.accounts.count();
@@ -365,7 +361,7 @@ export default class NewEditProjectView extends Vue {
}
}
- private async saveProject(identity: IIdentifier) {
+ private async saveProject(issuerDid: string) {
// Make a claim
const vcClaim: PlanVerifiableCredential = this.fullClaim;
if (this.projectId) {
@@ -416,13 +412,13 @@ export default class NewEditProjectView extends Vue {
} else {
delete vcClaim.startTime;
}
- const vcJwt = await createEndorserJwtVcFromClaim(identity.did, vcClaim);
+ const vcJwt = await createEndorserJwtVcFromClaim(issuerDid, vcClaim);
// Make the xhr request payload
const payload = JSON.stringify({ jwtEncoded: vcJwt });
const url = this.apiServer + "/api/v2/claim";
- const token = await accessToken(identity.did);
+ const token = await accessToken(issuerDid);
const headers = {
"Content-Type": "application/json",
Authorization: "Bearer " + token,
@@ -508,8 +504,7 @@ export default class NewEditProjectView extends Vue {
if (this.numAccounts === 0) {
console.error("Error: there is no account.");
} else {
- const identity = await libsUtil.getIdentity(this.activeDid);
- this.saveProject(identity);
+ this.saveProject(this.activeDid);
}
}
diff --git a/src/views/ProjectsView.vue b/src/views/ProjectsView.vue
index 4ff0c4350..d8a1f9691 100644
--- a/src/views/ProjectsView.vue
+++ b/src/views/ProjectsView.vue
@@ -235,7 +235,6 @@ import { accountsDB, db } from "@/db/index";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto";
import * as libsUtil from "@/libs/util";
-import { IIdentifier } from "@veramo/core";
import InfiniteScroll from "@/components/InfiniteScroll.vue";
import QuickNav from "@/components/QuickNav.vue";
import ProjectIcon from "@/components/ProjectIcon.vue";
@@ -255,9 +254,9 @@ export default class ProjectsView extends Vue {
);
}
+ activeDid = "";
apiServer = "";
projects: PlanData[] = [];
- currentIid: IIdentifier;
isLoading = false;
isRegistered = false;
numAccounts = 0;
@@ -271,7 +270,7 @@ export default class ProjectsView extends Vue {
try {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
- const activeDid: string = (settings?.activeDid as string) || "";
+ this.activeDid = (settings?.activeDid as string) || "";
this.apiServer = (settings?.apiServer as string) || "";
this.isRegistered = !!settings?.isRegistered;
@@ -281,7 +280,6 @@ export default class ProjectsView extends Vue {
console.error("No accounts found.");
this.errNote("You need an identifier to load your projects.");
} else {
- this.currentIid = await libsUtil.getIdentity(activeDid);
await this.loadOffers();
}
} catch (err) {
@@ -342,7 +340,7 @@ export default class ProjectsView extends Vue {
if (this.projects.length > 0 && payload) {
const latestProject = this.projects[this.projects.length - 1];
await this.loadProjects(
- this.currentIid,
+ this.activeDid,
`beforeId=${latestProject.rowid}`,
);
}
@@ -350,13 +348,12 @@ export default class ProjectsView extends Vue {
/**
* Load projects initially
- * @param identifier of the user
+ * @param issuerDid of the user
* @param urlExtra additional url parameters in a string
**/
- async loadProjects(identifier?: IIdentifier, urlExtra: string = "") {
- const identity = identifier || this.currentIid;
+ async loadProjects(activeDid?: string, urlExtra: string = "") {
const url = `${this.apiServer}/api/v2/report/plansByIssuer?${urlExtra}`;
- const token: string = await accessToken(identity.did);
+ const token: string = await accessToken(activeDid);
await this.projectDataLoader(url, token);
}
@@ -446,19 +443,18 @@ export default class ProjectsView extends Vue {
async loadMoreOfferData(payload: boolean) {
if (this.offers.length > 0 && payload) {
const latestOffer = this.offers[this.offers.length - 1];
- await this.loadOffers(this.currentIid, `&beforeId=${latestOffer.jwtId}`);
+ await this.loadOffers(this.activeDid, `&beforeId=${latestOffer.jwtId}`);
}
}
/**
* Load offers initially
- * @param identifier of the user
+ * @param issuerDid of the user
* @param urlExtra additional url parameters in a string
**/
- async loadOffers(identifier?: IIdentifier, urlExtra: string = "") {
- const identity = identifier || this.currentIid;
- const url = `${this.apiServer}/api/v2/report/offers?offeredByDid=${identity.did}${urlExtra}`;
- const token: string = await accessToken(identity.did);
+ async loadOffers(issuerDid?: string, urlExtra: string = "") {
+ const url = `${this.apiServer}/api/v2/report/offers?offeredByDid=${issuerDid}${urlExtra}`;
+ const token: string = await accessToken(issuerDid);
await this.offerDataLoader(url, token);
}