Merge pull request 'Add settings table.' (#12) from db-set-and-bak into master
Reviewed-on: trent_larson/kick-starter-for-time-pwa#12
This commit was merged in pull request #12.
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
nodejs 16.18.0
|
|
||||||
12
README.md
12
README.md
@@ -36,9 +36,9 @@ New users require registration. This can be done with a claim payload like this
|
|||||||
const vcClaim = {
|
const vcClaim = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "RegisterAction",
|
"@type": "RegisterAction",
|
||||||
agent: { did: identity0.did },
|
agent: { identifier: identity0.did },
|
||||||
object: SERVICE_ID,
|
object: SERVICE_ID,
|
||||||
participant: { did: newIdentity.did },
|
participant: { identifier: newIdentity.did },
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -62,6 +62,14 @@ See [this page](openssl_signing_console.rst)
|
|||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
|
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
See https://tea.xyz
|
||||||
|
|
||||||
|
| Project | Version |
|
||||||
|
| ---------- | --------- |
|
||||||
|
| nodejs.org | ^16.0.0 |
|
||||||
|
| npmjs.com | ^8.0.0 |
|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,9 @@
|
|||||||
- replace user-affecting console.logs with error messages (eg. catches)
|
- replace user-affecting console.logs with error messages (eg. catches)
|
||||||
|
|
||||||
- contacts v1:
|
- contacts v1:
|
||||||
- parse input correctly (with CSV lib and not commas)
|
- .5 make advanced "show/hide amounts" button into a nice UI toggle
|
||||||
|
- .2 show error to user when adding a duplicate contact
|
||||||
|
- parse input more robustly (with CSV lib and not commas)
|
||||||
|
|
||||||
- commit screen
|
- commit screen
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
import BaseDexie, { Table } from "dexie";
|
import BaseDexie, { Table } from "dexie";
|
||||||
import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon";
|
import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon";
|
||||||
import { accountsSchema, Account } from "./tables/accounts";
|
import {
|
||||||
import { contactsSchema, Contact } from "./tables/contacts";
|
Account,
|
||||||
|
AccountsSchema,
|
||||||
|
Contact,
|
||||||
|
ContactsSchema,
|
||||||
|
MASTER_SETTINGS,
|
||||||
|
Settings,
|
||||||
|
SettingsSchema,
|
||||||
|
} from "./tables";
|
||||||
|
|
||||||
type AllTables = {
|
type AllTables = {
|
||||||
accounts: Table<Account>;
|
accounts: Table<Account>;
|
||||||
contacts: Table<Contact>;
|
contacts: Table<Contact>;
|
||||||
|
settings: Table<Settings>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,7 +26,13 @@ type AllTables = {
|
|||||||
*/
|
*/
|
||||||
type DexieTables = AllTables;
|
type DexieTables = AllTables;
|
||||||
export type Dexie<T extends unknown = DexieTables> = BaseDexie & T;
|
export type Dexie<T extends unknown = DexieTables> = BaseDexie & T;
|
||||||
export const db = new BaseDexie("kickStarter") as Dexie;
|
export const db = new BaseDexie("KickStart") as Dexie;
|
||||||
|
const AllSchemas = Object.assign(
|
||||||
|
{},
|
||||||
|
AccountsSchema,
|
||||||
|
ContactsSchema,
|
||||||
|
SettingsSchema
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needed to enable a special webpack setting to allow *await* below:
|
* Needed to enable a special webpack setting to allow *await* below:
|
||||||
@@ -32,7 +46,13 @@ const secret =
|
|||||||
if (localStorage.getItem("secret") == null) {
|
if (localStorage.getItem("secret") == null) {
|
||||||
localStorage.setItem("secret", secret);
|
localStorage.setItem("secret", secret);
|
||||||
}
|
}
|
||||||
console.log("DB encryption secretKey:", secret);
|
|
||||||
|
//console.log("IndexedDB Encryption Secret:", secret);
|
||||||
encrypted(db, { secretKey: secret });
|
encrypted(db, { secretKey: secret });
|
||||||
db.version(1).stores(accountsSchema);
|
db.version(1).stores(AllSchemas);
|
||||||
db.version(2).stores(contactsSchema);
|
|
||||||
|
// initialize, a la https://dexie.org/docs/Tutorial/Design#the-populate-event
|
||||||
|
db.on("populate", function () {
|
||||||
|
// ensure there's an initial entry for settings
|
||||||
|
db.settings.add({ id: MASTER_SETTINGS });
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
export type Account = {
|
|
||||||
id?: number;
|
|
||||||
publicKey: string;
|
|
||||||
mnemonic: string;
|
|
||||||
identity: string;
|
|
||||||
dateCreated: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
// mark encrypted field by starting with a $ character
|
|
||||||
export const accountsSchema = {
|
|
||||||
accounts: "++id, publicKey, $mnemonic, $identity, dateCreated",
|
|
||||||
};
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
export interface Contact {
|
|
||||||
did: string;
|
|
||||||
name?: string;
|
|
||||||
publicKeyBase64?: string;
|
|
||||||
seesMe?: boolean;
|
|
||||||
registered?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark encrypted field by starting with a $ character
|
|
||||||
export const contactsSchema = {
|
|
||||||
contacts: "++did, name, publicKeyBase64, seesMe, registered",
|
|
||||||
};
|
|
||||||
41
src/db/tables/index.ts
Normal file
41
src/db/tables/index.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
export type Account = {
|
||||||
|
id?: number; // auto-generated by Dexie
|
||||||
|
dateCreated: string;
|
||||||
|
derivationPath: string;
|
||||||
|
identity: string;
|
||||||
|
publicKeyHex: string;
|
||||||
|
mnemonic: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// mark encrypted field by starting with a $ character
|
||||||
|
// see https://github.com/PVermeer/dexie-addon-suite-monorepo/tree/master/packages/dexie-encrypted-addon
|
||||||
|
export const AccountsSchema = {
|
||||||
|
accounts:
|
||||||
|
"++id, dateCreated, derivationPath, $identity, $mnemonic, publicKeyHex",
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface Contact {
|
||||||
|
did: string;
|
||||||
|
name?: string;
|
||||||
|
publicKeyBase64?: string;
|
||||||
|
seesMe?: boolean;
|
||||||
|
registered?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ContactsSchema = {
|
||||||
|
contacts: "++did, name, publicKeyBase64, registered, seesMe",
|
||||||
|
};
|
||||||
|
|
||||||
|
// a singleton
|
||||||
|
export type Settings = {
|
||||||
|
id: number;
|
||||||
|
firstName?: string;
|
||||||
|
lastName?: string;
|
||||||
|
showContactGivesInline?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SettingsSchema = {
|
||||||
|
settings: "id",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MASTER_SETTINGS = 1;
|
||||||
@@ -65,7 +65,7 @@ export const deriveAddress = (
|
|||||||
*
|
*
|
||||||
* @return {*} {string}
|
* @return {*} {string}
|
||||||
*/
|
*/
|
||||||
export const createIdentifier = (): string => {
|
export const generateSeed = (): string => {
|
||||||
const entropy: Uint8Array = getRandomBytesSync(32);
|
const entropy: Uint8Array = getRandomBytesSync(32);
|
||||||
const mnemonic = entropyToMnemonic(entropy, wordlist);
|
const mnemonic = entropyToMnemonic(entropy, wordlist);
|
||||||
|
|
||||||
@@ -87,9 +87,9 @@ export const accessToken = async (identifier: IIdentifier) => {
|
|||||||
const nowEpoch = Math.floor(Date.now() / 1000);
|
const nowEpoch = Math.floor(Date.now() / 1000);
|
||||||
const endEpoch = nowEpoch + 60; // add one minute
|
const endEpoch = nowEpoch + 60; // add one minute
|
||||||
|
|
||||||
const uportTokenPayload = { exp: endEpoch, iat: nowEpoch, iss: did };
|
const tokenPayload = { exp: endEpoch, iat: nowEpoch, iss: did };
|
||||||
const alg = undefined; // defaults to 'ES256K', more standardized but harder to verify vs ES256K-R
|
const alg = undefined; // defaults to 'ES256K', more standardized but harder to verify vs ES256K-R
|
||||||
const jwt: string = await didJwt.createJWT(uportTokenPayload, {
|
const jwt: string = await didJwt.createJWT(tokenPayload, {
|
||||||
alg,
|
alg,
|
||||||
issuer: did,
|
issuer: did,
|
||||||
signer,
|
signer,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
||||||
import { useAppStore } from "../store/app";
|
import { db } from "@/db";
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
@@ -7,10 +7,10 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: "home",
|
name: "home",
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "start" */ "../views/DiscoverView.vue"),
|
import(/* webpackChunkName: "start" */ "../views/DiscoverView.vue"),
|
||||||
beforeEnter: (to, from, next) => {
|
beforeEnter: async (to, from, next) => {
|
||||||
const appStore = useAppStore();
|
await db.open();
|
||||||
const isAuthenticated = appStore.condition === "registered";
|
const num_accounts = await db.accounts.count();
|
||||||
if (isAuthenticated) {
|
if (num_accounts > 0) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
next({ name: "start" });
|
next({ name: "start" });
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
import { defineStore } from "pinia";
|
|
||||||
|
|
||||||
export const useAccountStore = defineStore({
|
|
||||||
id: "account",
|
|
||||||
state: () => ({
|
|
||||||
account: JSON.parse(
|
|
||||||
typeof localStorage["account"] == "undefined"
|
|
||||||
? null
|
|
||||||
: localStorage["account"]
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
getters: {
|
|
||||||
firstName: (state) => state.account.firstName,
|
|
||||||
lastName: (state) => state.account.lastName,
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
reset() {
|
|
||||||
localStorage.removeItem("account");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -4,30 +4,15 @@ import { defineStore } from "pinia";
|
|||||||
export const useAppStore = defineStore({
|
export const useAppStore = defineStore({
|
||||||
id: "app",
|
id: "app",
|
||||||
state: () => ({
|
state: () => ({
|
||||||
_condition:
|
|
||||||
typeof localStorage["condition"] == "undefined"
|
|
||||||
? "uninitialized"
|
|
||||||
: localStorage["condition"],
|
|
||||||
_lastView:
|
|
||||||
typeof localStorage["lastView"] == "undefined"
|
|
||||||
? "/start"
|
|
||||||
: localStorage["lastView"],
|
|
||||||
_projectId:
|
_projectId:
|
||||||
typeof localStorage.getItem("projectId") === "undefined"
|
typeof localStorage.getItem("projectId") === "undefined"
|
||||||
? ""
|
? ""
|
||||||
: localStorage.getItem("projectId"),
|
: localStorage.getItem("projectId"),
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
condition: (state) => state._condition,
|
|
||||||
projectId: (state): string => state._projectId as string,
|
projectId: (state): string => state._projectId as string,
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
reset() {
|
|
||||||
localStorage.removeItem("condition");
|
|
||||||
},
|
|
||||||
setCondition(newCondition: string) {
|
|
||||||
localStorage.setItem("condition", newCondition);
|
|
||||||
},
|
|
||||||
async setProjectId(newProjectId: string) {
|
async setProjectId(newProjectId: string) {
|
||||||
localStorage.setItem("projectId", newProjectId);
|
localStorage.setItem("projectId", newProjectId);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -111,8 +111,8 @@
|
|||||||
<div class="text-slate-500 text-sm font-bold">Derivation Path</div>
|
<div class="text-slate-500 text-sm font-bold">Derivation Path</div>
|
||||||
<div class="text-sm text-slate-500 mb-1">
|
<div class="text-sm text-slate-500 mb-1">
|
||||||
<span
|
<span
|
||||||
><code>{{ UPORT_ROOT_DERIVATION_PATH }}</code>
|
><code>{{ derivationPath }}</code>
|
||||||
<button @click="copy(UPORT_ROOT_DERIVATION_PATH)">
|
<button @click="copy(derivationPath)">
|
||||||
<fa icon="copy" class="text-slate-400 fa-fw ml-1"></fa>
|
<fa icon="copy" class="text-slate-400 fa-fw ml-1"></fa>
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
@@ -168,86 +168,158 @@
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
|
<h3 class="text-sm uppercase font-semibold mb-3">Advanced</h3>
|
||||||
|
|
||||||
|
<div class="flex">
|
||||||
|
<button
|
||||||
|
href=""
|
||||||
|
class="text-center text-md text-white px-1.5 py-2 rounded-md mb-6"
|
||||||
|
v-bind:class="showContactGivesClassNames()"
|
||||||
|
@click="toggleShowContactAmounts"
|
||||||
|
>
|
||||||
|
{{ showContactGives ? "Showing" : "Hiding" }}
|
||||||
|
amounts given with contacts (Click to
|
||||||
|
{{ showContactGives ? "hide" : "show" }})
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-bind:class="computedAlertClassNames()">
|
||||||
|
<button
|
||||||
|
class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2"
|
||||||
|
@click="onClickClose()"
|
||||||
|
>
|
||||||
|
<fa icon="xmark"></fa>
|
||||||
|
</button>
|
||||||
|
<h4 class="font-bold pr-5">{{ alertTitle }}</h4>
|
||||||
|
<p>{{ alertMessage }}</p>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
import { createIdentifier, deriveAddress, newIdentifier } from "../libs/crypto";
|
import { db } from "@/db";
|
||||||
import { db } from "../db";
|
import { MASTER_SETTINGS } from "@/db/tables";
|
||||||
import { useAppStore } from "@/store/app";
|
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
||||||
import { ref } from "vue";
|
|
||||||
//import { testServerRegisterUser } from "../test";
|
//import { testServerRegisterUser } from "../test";
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class AccountViewView extends Vue {
|
export default class AccountViewView extends Vue {
|
||||||
firstName =
|
|
||||||
localStorage.getItem("firstName") === null
|
|
||||||
? "--"
|
|
||||||
: localStorage.getItem("firstName");
|
|
||||||
lastName =
|
|
||||||
localStorage.getItem("lastName") === null
|
|
||||||
? "--"
|
|
||||||
: localStorage.getItem("lastName");
|
|
||||||
mnemonic = "";
|
|
||||||
address = "";
|
|
||||||
privateHex = "";
|
|
||||||
publicHex = "";
|
|
||||||
UPORT_ROOT_DERIVATION_PATH = "";
|
|
||||||
source = ref("Hello");
|
|
||||||
copy = useClipboard().copy;
|
|
||||||
|
|
||||||
// This registers current user in vue plugin with: $vm.ctx.testRegisterUser()
|
// This registers current user in vue plugin with: $vm.ctx.testRegisterUser()
|
||||||
//testRegisterUser = testServerRegisterUser;
|
//testRegisterUser = testServerRegisterUser;
|
||||||
|
|
||||||
|
address = "";
|
||||||
|
firstName = "";
|
||||||
|
lastName = "";
|
||||||
|
mnemonic = "";
|
||||||
|
publicHex = "";
|
||||||
|
derivationPath = "";
|
||||||
|
showContactGives = false;
|
||||||
|
|
||||||
|
copy = useClipboard().copy;
|
||||||
|
|
||||||
// 'created' hook runs when the Vue instance is first created
|
// 'created' hook runs when the Vue instance is first created
|
||||||
async created() {
|
async created() {
|
||||||
const appCondition = useAppStore().condition;
|
|
||||||
if (appCondition == "uninitialized") {
|
|
||||||
this.mnemonic = createIdentifier();
|
|
||||||
[
|
|
||||||
this.address,
|
|
||||||
this.privateHex,
|
|
||||||
this.publicHex,
|
|
||||||
this.UPORT_ROOT_DERIVATION_PATH,
|
|
||||||
] = deriveAddress(this.mnemonic);
|
|
||||||
|
|
||||||
const newId = newIdentifier(
|
|
||||||
this.address,
|
|
||||||
this.publicHex,
|
|
||||||
this.privateHex,
|
|
||||||
this.UPORT_ROOT_DERIVATION_PATH
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
await db.open();
|
|
||||||
const num_accounts = await db.accounts.count();
|
|
||||||
if (num_accounts === 0) {
|
|
||||||
await db.accounts.add({
|
|
||||||
publicKey: newId.keys[0].publicKeyHex,
|
|
||||||
mnemonic: this.mnemonic,
|
|
||||||
identity: JSON.stringify(newId),
|
|
||||||
dateCreated: new Date().getTime(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
useAppStore().setCondition("registered");
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await db.open();
|
await db.open();
|
||||||
const num_accounts = await db.accounts.count();
|
try {
|
||||||
if (num_accounts === 0) {
|
const settings = await db.settings.get(MASTER_SETTINGS);
|
||||||
console.log("Problem! Should have a profile!");
|
if (settings) {
|
||||||
} else {
|
this.firstName = settings.firstName || "";
|
||||||
const accounts = await db.accounts.toArray();
|
this.lastName = settings.lastName || "";
|
||||||
const identity = JSON.parse(accounts[0].identity);
|
this.showContactGives = !!settings.showContactGivesInline;
|
||||||
this.address = identity.did;
|
}
|
||||||
this.publicHex = identity.keys[0].publicKeyHex;
|
|
||||||
this.UPORT_ROOT_DERIVATION_PATH = identity.keys[0].meta.derivationPath;
|
const numAccounts = await db.accounts.count();
|
||||||
|
if (numAccounts === 0) {
|
||||||
|
let privateHex = "";
|
||||||
|
this.mnemonic = generateSeed();
|
||||||
|
[this.address, privateHex, this.publicHex, this.derivationPath] =
|
||||||
|
deriveAddress(this.mnemonic);
|
||||||
|
|
||||||
|
const newId = newIdentifier(
|
||||||
|
this.address,
|
||||||
|
this.publicHex,
|
||||||
|
privateHex,
|
||||||
|
this.derivationPath
|
||||||
|
);
|
||||||
|
await db.accounts.add({
|
||||||
|
dateCreated: new Date().toISOString(),
|
||||||
|
derivationPath: this.derivationPath,
|
||||||
|
identity: JSON.stringify(newId),
|
||||||
|
mnemonic: this.mnemonic,
|
||||||
|
publicKeyHex: newId.keys[0].publicKeyHex,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.alertMessage =
|
||||||
|
"Clear your cache and start over (after data backup). See console log for more info.";
|
||||||
|
console.log("Telling user to clear cache because:", err);
|
||||||
|
this.alertTitle = "Error Creating Account";
|
||||||
|
this.isAlertVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const accounts = await db.accounts.toArray();
|
||||||
|
const identity = JSON.parse(accounts[0].identity);
|
||||||
|
this.address = identity.did;
|
||||||
|
this.publicHex = identity.keys[0].publicKeyHex;
|
||||||
|
this.derivationPath = identity.keys[0].meta.derivationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async toggleShowContactAmounts() {
|
||||||
|
this.showContactGives = !this.showContactGives;
|
||||||
|
try {
|
||||||
|
await db.open();
|
||||||
|
const settings = await db.settings.get(MASTER_SETTINGS);
|
||||||
|
if (settings) {
|
||||||
|
db.settings.update(MASTER_SETTINGS, {
|
||||||
|
showContactGivesInline: this.showContactGives,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.alertMessage =
|
||||||
|
"Clear your cache and start over (after data backup). See console log for more info.";
|
||||||
|
console.log("Telling user to clear cache because:", err);
|
||||||
|
this.alertTitle = "Error Creating Account";
|
||||||
|
this.isAlertVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public showContactGivesClassNames() {
|
||||||
|
return {
|
||||||
|
"bg-slate-900": !this.showContactGives,
|
||||||
|
"bg-green-600": this.showContactGives,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
alertMessage = "";
|
||||||
|
alertTitle = "";
|
||||||
|
isAlertVisible = false;
|
||||||
|
|
||||||
|
public onClickClose() {
|
||||||
|
this.isAlertVisible = false;
|
||||||
|
this.alertTitle = "";
|
||||||
|
this.alertMessage = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public computedAlertClassNames() {
|
||||||
|
return {
|
||||||
|
hidden: !this.isAlertVisible,
|
||||||
|
"dismissable-alert": true,
|
||||||
|
"bg-slate-100": true,
|
||||||
|
"p-5": true,
|
||||||
|
rounded: true,
|
||||||
|
"drop-shadow-lg": true,
|
||||||
|
absolute: true,
|
||||||
|
"top-3": true,
|
||||||
|
"inset-x-3": true,
|
||||||
|
"transition-transform": true,
|
||||||
|
"ease-in": true,
|
||||||
|
"duration-300": true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ import { AppString } from "@/constants/app";
|
|||||||
import { accessToken, SimpleSigner } from "@/libs/crypto";
|
import { accessToken, SimpleSigner } from "@/libs/crypto";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
import { db } from "../db";
|
import { db } from "../db";
|
||||||
import { Contact } from "../db/tables/contacts";
|
import { Contact } from "../db/tables";
|
||||||
|
|
||||||
export interface GiveVerifiableCredential {
|
export interface GiveVerifiableCredential {
|
||||||
"@context": string;
|
"@context": string;
|
||||||
|
|||||||
@@ -46,7 +46,6 @@
|
|||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { deriveAddress, newIdentifier } from "../libs/crypto";
|
import { deriveAddress, newIdentifier } from "../libs/crypto";
|
||||||
import { db } from "@/db";
|
import { db } from "@/db";
|
||||||
import { useAppStore } from "@/store/app";
|
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
@@ -56,7 +55,7 @@ export default class ImportAccountView extends Vue {
|
|||||||
address = "";
|
address = "";
|
||||||
privateHex = "";
|
privateHex = "";
|
||||||
publicHex = "";
|
publicHex = "";
|
||||||
UPORT_ROOT_DERIVATION_PATH = "";
|
derivationPath = "";
|
||||||
|
|
||||||
public onCancelClick() {
|
public onCancelClick() {
|
||||||
this.$router.back();
|
this.$router.back();
|
||||||
@@ -65,33 +64,28 @@ export default class ImportAccountView extends Vue {
|
|||||||
public async from_mnemonic() {
|
public async from_mnemonic() {
|
||||||
const mne: string = this.mnemonic.trim().toLowerCase();
|
const mne: string = this.mnemonic.trim().toLowerCase();
|
||||||
if (this.mnemonic.trim().length > 0) {
|
if (this.mnemonic.trim().length > 0) {
|
||||||
[
|
[this.address, this.privateHex, this.publicHex, this.derivationPath] =
|
||||||
this.address,
|
deriveAddress(mne);
|
||||||
this.privateHex,
|
|
||||||
this.publicHex,
|
|
||||||
this.UPORT_ROOT_DERIVATION_PATH,
|
|
||||||
] = deriveAddress(mne);
|
|
||||||
|
|
||||||
const newId = newIdentifier(
|
const newId = newIdentifier(
|
||||||
this.address,
|
this.address,
|
||||||
this.publicHex,
|
this.publicHex,
|
||||||
this.privateHex,
|
this.privateHex,
|
||||||
this.UPORT_ROOT_DERIVATION_PATH
|
this.derivationPath
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await db.open();
|
||||||
const num_accounts = await db.accounts.count();
|
const num_accounts = await db.accounts.count();
|
||||||
if (num_accounts === 0) {
|
if (num_accounts === 0) {
|
||||||
console.log("...");
|
|
||||||
await db.accounts.add({
|
await db.accounts.add({
|
||||||
publicKey: newId.keys[0].publicKeyHex,
|
dateCreated: new Date().toISOString(),
|
||||||
mnemonic: mne,
|
derivationPath: this.derivationPath,
|
||||||
identity: JSON.stringify(newId),
|
identity: JSON.stringify(newId),
|
||||||
dateCreated: new Date().getTime(),
|
mnemonic: mne,
|
||||||
|
publicKeyHex: newId.keys[0].publicKeyHex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
useAppStore().setCondition("registered");
|
|
||||||
this.$router.push({ name: "account" });
|
this.$router.push({ name: "account" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("Error!");
|
console.log("Error!");
|
||||||
|
|||||||
@@ -50,6 +50,8 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
|
import { db } from "@/db";
|
||||||
|
import { MASTER_SETTINGS } from "@/db/tables";
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
@@ -64,13 +66,24 @@ export default class NewEditAccountView extends Vue {
|
|||||||
? "--"
|
? "--"
|
||||||
: localStorage.getItem("lastName");
|
: localStorage.getItem("lastName");
|
||||||
|
|
||||||
|
// 'created' hook runs when the Vue instance is first created
|
||||||
|
async created() {
|
||||||
|
await db.open();
|
||||||
|
const settings = await db.settings.get(MASTER_SETTINGS);
|
||||||
|
if (settings) {
|
||||||
|
this.firstName = settings.firstName || "";
|
||||||
|
this.lastName = settings.lastName || "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClickSaveChanges() {
|
onClickSaveChanges() {
|
||||||
|
db.settings.update(MASTER_SETTINGS, {
|
||||||
|
firstName: this.firstName,
|
||||||
|
lastName: this.lastName,
|
||||||
|
});
|
||||||
localStorage.setItem("firstName", this.firstName as string);
|
localStorage.setItem("firstName", this.firstName as string);
|
||||||
localStorage.setItem("lastName", this.lastName as string);
|
localStorage.setItem("lastName", this.lastName as string);
|
||||||
const route = {
|
this.$router.push({ name: "account" });
|
||||||
name: "account",
|
|
||||||
};
|
|
||||||
this.$router.push(route);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickCancel() {
|
onClickCancel() {
|
||||||
|
|||||||
Reference in New Issue
Block a user