Browse Source

refactor DB organization (prepping for more tables)

kb/add-usage-guide
Trent Larson 2 years ago
parent
commit
cfeabf05a4
  1. 12
      README.md
  2. 10
      src/db/index.ts
  3. 19
      src/db/tables/accounts.ts
  4. 6
      src/libs/crypto/index.ts
  5. 31
      src/views/AccountViewView.vue
  6. 20
      src/views/ImportAccountView.vue

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

10
src/db/index.ts

@ -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);
/** /**

19
src/db/tables/accounts.ts

@ -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",
}; };

6
src/libs/crypto/index.ts

@ -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,

31
src/views/AccountViewView.vue

@ -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;
} }
} }
} }

20
src/views/ImportAccountView.vue

@ -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");

Loading…
Cancel
Save