forked from jsnbuchanan/crowd-funder-for-time-pwa
refactor DB organization (prepping for more tables)
This commit is contained in:
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
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import BaseDexie 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, AccountsTable } from "./tables/accounts";
|
import { Account, accountsSchema } from "./tables/accounts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In order to make the next line be acceptable, the program needs to have its linter suppress a rule:
|
* In order to make the next line be acceptable, the program needs to have its linter suppress a rule:
|
||||||
@@ -10,9 +10,11 @@ import { accountsSchema, AccountsTable } from "./tables/accounts";
|
|||||||
*
|
*
|
||||||
* https://9to5answer.com/how-to-bypass-warning-unexpected-any-specify-a-different-type-typescript-eslint-no-explicit-any
|
* https://9to5answer.com/how-to-bypass-warning-unexpected-any-specify-a-different-type-typescript-eslint-no-explicit-any
|
||||||
*/
|
*/
|
||||||
type DexieTables = AccountsTable;
|
type DexieTables = {
|
||||||
|
accounts: Table<Account>;
|
||||||
|
};
|
||||||
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 schema = Object.assign({}, accountsSchema);
|
const schema = Object.assign({}, accountsSchema);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
import { Table } from "dexie";
|
|
||||||
|
|
||||||
export type Account = {
|
export type Account = {
|
||||||
id?: number;
|
id?: number; // auto-generated by Dexie
|
||||||
publicKey: string;
|
dateCreated: Date;
|
||||||
mnemonic: string;
|
derivationPath: string;
|
||||||
identity: string;
|
identity: string;
|
||||||
dateCreated: number;
|
publicKeyHex: string;
|
||||||
};
|
mnemonic: string;
|
||||||
|
|
||||||
export type AccountsTable = {
|
|
||||||
accounts: Table<Account>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// mark encrypted field by starting with a $ character
|
// 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 = {
|
export const accountsSchema = {
|
||||||
accounts: "++id, publicKey, $mnemonic, $identity, dateCreated",
|
accounts:
|
||||||
|
"++id, dateCreated, derivationPath, $identity, $mnemonic, publicKeyHex",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -174,10 +174,9 @@
|
|||||||
<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 { deriveAddress, generateSeed, newIdentifier } from "../libs/crypto";
|
||||||
import { db } from "../db";
|
import { db } from "../db";
|
||||||
import { useAppStore } from "@/store/app";
|
import { useAppStore } from "@/store/app";
|
||||||
import { ref } from "vue";
|
|
||||||
//import { testServerRegisterUser } from "../test";
|
//import { testServerRegisterUser } from "../test";
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
@@ -196,8 +195,7 @@ export default class AccountViewView extends Vue {
|
|||||||
address = "";
|
address = "";
|
||||||
privateHex = "";
|
privateHex = "";
|
||||||
publicHex = "";
|
publicHex = "";
|
||||||
UPORT_ROOT_DERIVATION_PATH = "";
|
derivationPath = "";
|
||||||
source = ref("Hello");
|
|
||||||
copy = useClipboard().copy;
|
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()
|
||||||
@@ -207,29 +205,26 @@ export default class AccountViewView extends Vue {
|
|||||||
async created() {
|
async created() {
|
||||||
const appCondition = useAppStore().condition;
|
const appCondition = useAppStore().condition;
|
||||||
if (appCondition == "uninitialized") {
|
if (appCondition == "uninitialized") {
|
||||||
this.mnemonic = createIdentifier();
|
this.mnemonic = generateSeed();
|
||||||
[
|
[this.address, this.privateHex, this.publicHex, this.derivationPath] =
|
||||||
this.address,
|
deriveAddress(this.mnemonic);
|
||||||
this.privateHex,
|
|
||||||
this.publicHex,
|
|
||||||
this.UPORT_ROOT_DERIVATION_PATH,
|
|
||||||
] = deriveAddress(this.mnemonic);
|
|
||||||
|
|
||||||
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) {
|
||||||
await db.accounts.add({
|
await db.accounts.add({
|
||||||
publicKey: newId.keys[0].publicKeyHex,
|
dateCreated: new Date(),
|
||||||
mnemonic: this.mnemonic,
|
derivationPath: this.derivationPath,
|
||||||
identity: JSON.stringify(newId),
|
identity: JSON.stringify(newId),
|
||||||
dateCreated: new Date().getTime(),
|
mnemonic: this.mnemonic,
|
||||||
|
publicKeyHex: newId.keys[0].publicKeyHex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
useAppStore().setCondition("registered");
|
useAppStore().setCondition("registered");
|
||||||
@@ -246,7 +241,7 @@ export default class AccountViewView extends Vue {
|
|||||||
const identity = JSON.parse(accounts[0].identity);
|
const identity = JSON.parse(accounts[0].identity);
|
||||||
this.address = identity.did;
|
this.address = identity.did;
|
||||||
this.publicHex = identity.keys[0].publicKeyHex;
|
this.publicHex = identity.keys[0].publicKeyHex;
|
||||||
this.UPORT_ROOT_DERIVATION_PATH = identity.keys[0].meta.derivationPath;
|
this.derivationPath = identity.keys[0].meta.derivationPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,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,30 +65,26 @@ 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(),
|
||||||
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");
|
useAppStore().setCondition("registered");
|
||||||
|
|||||||
Reference in New Issue
Block a user