|
|
@ -344,7 +344,7 @@ import { |
|
|
|
updateDefaultSettings, |
|
|
|
} from "@/db/index"; |
|
|
|
import { Contact } from "@/db/tables/contacts"; |
|
|
|
import { getContactPayloadFromJwtUrl } from "@/libs/crypto"; |
|
|
|
import { getContactJwtFromJwtUrl } from "@/libs/crypto"; |
|
|
|
import { decodeEndorserJwt } from "@/libs/crypto/vc"; |
|
|
|
import { |
|
|
|
CONTACT_CSV_HEADER, |
|
|
@ -416,6 +416,11 @@ export default class ContactsView extends Vue { |
|
|
|
this.apiServer = settings.apiServer || ""; |
|
|
|
this.isRegistered = !!settings.isRegistered; |
|
|
|
|
|
|
|
// if these detect a query parameter, they can and then redirect to this URL without a query parameter |
|
|
|
// to avoid problems when they reload or they go forward & back and it tries to reprocess |
|
|
|
await this.processContactJwt(); |
|
|
|
await this.processInviteJwt(); |
|
|
|
|
|
|
|
this.showGiveNumbers = !!settings.showContactGivesInline; |
|
|
|
this.hideRegisterPromptOnNewContact = |
|
|
|
!!settings.hideRegisterPromptOnNewContact; |
|
|
@ -430,11 +435,13 @@ export default class ContactsView extends Vue { |
|
|
|
this.contacts = baseContacts.sort((a, b) => |
|
|
|
(a.name || "").localeCompare(b.name || ""), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
private async processContactJwt() { |
|
|
|
// handle a contact sent via URL |
|
|
|
// |
|
|
|
// Prefer use of /contact-import/:jwt with a JWT that has an array of contacts |
|
|
|
// unless you want them to import a single contact without confirmation. |
|
|
|
// For external links, use /contact-import/:jwt with a JWT that has an array of contacts |
|
|
|
// because that will do better error checking for things like missing data on iOS platforms. |
|
|
|
const importedContactJwt = (this.$route as RouteLocationNormalizedLoaded) |
|
|
|
.query["contactJwt"] as string; |
|
|
|
if (importedContactJwt) { |
|
|
@ -442,21 +449,25 @@ export default class ContactsView extends Vue { |
|
|
|
const { payload } = decodeEndorserJwt(importedContactJwt); |
|
|
|
const userInfo = payload["own"] as UserInfo; |
|
|
|
const newContact = { |
|
|
|
did: payload["iss"], |
|
|
|
did: userInfo.did || payload["iss"], // ".did" is reliable as of v 0.3.49 |
|
|
|
name: userInfo.name, |
|
|
|
nextPubKeyHashB64: userInfo.nextPublicEncKeyHash, |
|
|
|
profileImageUrl: userInfo.profileImageUrl, |
|
|
|
publicKeyBase64: userInfo.publicEncKey, |
|
|
|
registered: userInfo.registered, |
|
|
|
} as Contact; |
|
|
|
this.addContact(newContact); |
|
|
|
await this.addContact(newContact); |
|
|
|
// if we're here, they haven't redirected anywhere, so we'll redirect here without a query parameter |
|
|
|
(this.$router as Router).push({ path: "/contacts" }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private async processInviteJwt() { |
|
|
|
// handle an invite JWT sent via URL |
|
|
|
const importedInviteJwt = (this.$route as RouteLocationNormalizedLoaded) |
|
|
|
.query["inviteJwt"] as string; |
|
|
|
if (importedInviteJwt === "") { |
|
|
|
// this happens when a platform (usually iOS) doesn't include anything after the "=" in a shared link. |
|
|
|
// this happens when a platform (eg iOS) doesn't include anything after the "=" in a shared link. |
|
|
|
this.$notify( |
|
|
|
{ |
|
|
|
group: "alert", |
|
|
@ -555,6 +566,8 @@ export default class ContactsView extends Vue { |
|
|
|
5000, |
|
|
|
); |
|
|
|
} |
|
|
|
// if we're here, they haven't redirected anywhere, so we'll redirect here without a query parameter |
|
|
|
(this.$router as Router).push({ path: "/contacts" }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -717,12 +730,30 @@ export default class ContactsView extends Vue { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (contactInput.includes(CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI)) { |
|
|
|
const jwt = getContactJwtFromJwtUrl(contactInput); |
|
|
|
(this.$router as Router).push({ |
|
|
|
path: "/contact-import/" + jwt, |
|
|
|
}); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if ( |
|
|
|
contactInput.includes(CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI) || |
|
|
|
contactInput.includes(CONTACT_IMPORT_ONE_URL_PATH_TIME_SAFARI) || |
|
|
|
contactInput.includes(CONTACT_URL_PATH_ENDORSER_CH_OLD) |
|
|
|
) { |
|
|
|
await this.addContactFromScan(contactInput); |
|
|
|
const jwt = getContactJwtFromJwtUrl(contactInput); |
|
|
|
const { payload } = decodeEndorserJwt(jwt); |
|
|
|
const userInfo = payload["own"] as UserInfo; |
|
|
|
const newContact = { |
|
|
|
did: userInfo.did || payload["iss"], // "did" is reliable as of v 0.3.49 |
|
|
|
name: userInfo.name, |
|
|
|
nextPubKeyHashB64: userInfo.nextPublicEncKeyHash, |
|
|
|
profileImageUrl: userInfo.profileImageUrl, |
|
|
|
publicKeyBase64: userInfo.publicEncKey, |
|
|
|
registered: userInfo.registered, |
|
|
|
} as Contact; |
|
|
|
await this.addContact(newContact); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
@ -870,38 +901,6 @@ export default class ContactsView extends Vue { |
|
|
|
return db.contacts.add(newContact); |
|
|
|
} |
|
|
|
|
|
|
|
private async addContactFromScan(url: string): Promise<void> { |
|
|
|
const payload = getContactPayloadFromJwtUrl(url); |
|
|
|
if (!payload) { |
|
|
|
this.$notify( |
|
|
|
{ |
|
|
|
group: "alert", |
|
|
|
type: "danger", |
|
|
|
title: "No Contact Info", |
|
|
|
text: "The contact info could not be parsed.", |
|
|
|
}, |
|
|
|
3000, |
|
|
|
); |
|
|
|
return; |
|
|
|
} else { |
|
|
|
if (Array.isArray(payload.contacts)) { |
|
|
|
// reroute to the ContactsImport |
|
|
|
(this.$router as Router).push({ |
|
|
|
path: "/contact-import/" + url.substring(url.lastIndexOf("/") + 1), |
|
|
|
}); |
|
|
|
return; |
|
|
|
} |
|
|
|
return this.addContact({ |
|
|
|
did: payload.iss, |
|
|
|
name: payload.own.name, |
|
|
|
nextPubKeyHashB64: payload.own.nextPublicEncKeyHash, |
|
|
|
profileImageUrl: payload.own.profileImageUrl, |
|
|
|
publicKeyBase64: payload.own.publicEncKey, |
|
|
|
registered: payload.own.registered, |
|
|
|
} as Contact); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private async addContact(newContact: Contact) { |
|
|
|
if (!newContact.did) { |
|
|
|
this.danger("Cannot add a contact without a DID.", "Incomplete Contact"); |
|
|
@ -961,7 +960,7 @@ export default class ContactsView extends Vue { |
|
|
|
}, |
|
|
|
-1, |
|
|
|
); |
|
|
|
}, 500); |
|
|
|
}, 1000); |
|
|
|
} |
|
|
|
} |
|
|
|
this.$notify( |
|
|
|