forked from jsnbuchanan/crowd-funder-for-time-pwa
add ability to import from Endorser Mobile CSV
This commit is contained in:
@@ -26,10 +26,10 @@
|
||||
>
|
||||
<fa icon="qrcode" class="fa-fw text-2xl" />
|
||||
</router-link>
|
||||
<input
|
||||
<textarea
|
||||
type="text"
|
||||
placeholder="URL or DID, Name, Public Key, Next Public Key Hash"
|
||||
class="block w-full rounded-l border border-r-0 border-slate-400 px-3 py-2"
|
||||
class="block w-full rounded-l border border-r-0 border-slate-400 px-3 py-2 h-10"
|
||||
v-model="contactInput"
|
||||
/>
|
||||
<button
|
||||
@@ -297,6 +297,7 @@ import {
|
||||
SimpleSigner,
|
||||
} from "@/libs/crypto";
|
||||
import {
|
||||
CONTACT_CSV_HEADER,
|
||||
CONTACT_URL_PREFIX,
|
||||
GiveServerRecord,
|
||||
GiveVerifiableCredential,
|
||||
@@ -307,6 +308,7 @@ import * as libsUtil from "@/libs/util";
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
import EntityIcon from "@/components/EntityIcon.vue";
|
||||
import { Account } from "@/db/tables/accounts";
|
||||
import { IndexableType } from "dexie";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const Buffer = require("buffer/").Buffer;
|
||||
@@ -365,7 +367,7 @@ export default class ContactsView extends Vue {
|
||||
);
|
||||
|
||||
if (this.contactEndorserUrl) {
|
||||
await this.newContactFromScan(this.contactEndorserUrl);
|
||||
await this.addContactFromScan(this.contactEndorserUrl);
|
||||
localStorage.removeItem("contactEndorserUrl");
|
||||
this.contactEndorserUrl = "";
|
||||
}
|
||||
@@ -535,7 +537,46 @@ export default class ContactsView extends Vue {
|
||||
}
|
||||
|
||||
if (this.contactInput.startsWith(CONTACT_URL_PREFIX)) {
|
||||
await this.newContactFromScan(this.contactInput);
|
||||
await this.addContactFromScan(this.contactInput);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.contactInput.startsWith(CONTACT_CSV_HEADER)) {
|
||||
const lines = this.contactInput.split(/\n/);
|
||||
const lineAdded = [];
|
||||
for (const line of lines) {
|
||||
if (!line.trim() || line.startsWith(CONTACT_CSV_HEADER)) {
|
||||
continue;
|
||||
}
|
||||
lineAdded.push(this.addContactFromEndorserMobileLine(line));
|
||||
}
|
||||
try {
|
||||
await Promise.all(lineAdded);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Contacts Added",
|
||||
text: "Each contact was added. Nothing was sent to the server.",
|
||||
},
|
||||
-1, // keeping it up so that the "visibility" message is seen
|
||||
);
|
||||
} catch (e) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Contacts Maybe Added",
|
||||
text: "An error occurred. Some contacts may have been added.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
const allContacts = await db.contacts.toArray();
|
||||
this.contacts = R.sort(
|
||||
(a: Contact, b) => (a.name || "").localeCompare(b.name || ""),
|
||||
allContacts,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -576,7 +617,48 @@ export default class ContactsView extends Vue {
|
||||
await this.addContact(newContact);
|
||||
}
|
||||
|
||||
async newContactFromScan(url: string): Promise<void> {
|
||||
async addContactFromEndorserMobileLine(line: string): Promise<IndexableType> {
|
||||
// Note that Endorser Mobile puts name first, then did, etc.
|
||||
let name = line;
|
||||
let did = "";
|
||||
let publicKeyInput, seesMe, registered;
|
||||
const commaPos1 = line.indexOf(",");
|
||||
if (commaPos1 > -1) {
|
||||
name = line.substring(0, commaPos1).trim();
|
||||
did = line.substring(commaPos1 + 1).trim();
|
||||
const commaPos2 = line.indexOf(",", commaPos1 + 1);
|
||||
if (commaPos2 > -1) {
|
||||
did = line.substring(commaPos1 + 1, commaPos2).trim();
|
||||
publicKeyInput = line.substring(commaPos2 + 1).trim();
|
||||
const commaPos3 = line.indexOf(",", commaPos2 + 1);
|
||||
if (commaPos3 > -1) {
|
||||
publicKeyInput = line.substring(commaPos2 + 1, commaPos3).trim();
|
||||
seesMe = line.substring(commaPos3 + 1).trim() == "true";
|
||||
const commaPos4 = line.indexOf(",", commaPos3 + 1);
|
||||
if (commaPos4 > -1) {
|
||||
seesMe = line.substring(commaPos3 + 1, commaPos4).trim() == "true";
|
||||
registered = line.substring(commaPos4 + 1).trim() == "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// help with potential mistakes while this sharing requires copy-and-paste
|
||||
let publicKeyBase64 = publicKeyInput;
|
||||
if (publicKeyBase64 && /^[0-9A-Fa-f]{66}$/i.test(publicKeyBase64)) {
|
||||
// it must be all hex (compressed public key), so convert
|
||||
publicKeyBase64 = Buffer.from(publicKeyBase64, "hex").toString("base64");
|
||||
}
|
||||
const newContact = {
|
||||
did,
|
||||
name,
|
||||
publicKeyBase64,
|
||||
seesMe,
|
||||
registered,
|
||||
};
|
||||
return db.contacts.add(newContact);
|
||||
}
|
||||
|
||||
async addContactFromScan(url: string): Promise<void> {
|
||||
const payload = getContactPayloadFromJwtUrl(url);
|
||||
if (!payload) {
|
||||
this.$notify(
|
||||
@@ -661,7 +743,7 @@ export default class ContactsView extends Vue {
|
||||
}
|
||||
if (err.name === "ConstraintError") {
|
||||
message +=
|
||||
"Check that the contact doesn't conflict with any you already have.";
|
||||
" Check that the contact doesn't conflict with any you already have.";
|
||||
}
|
||||
this.$notify(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user