Browse Source

add page to show mnemonic seed phrase for backup

kb/add-usage-guide
Trent Larson 2 years ago
parent
commit
55b53955fc
  1. 7
      project.yaml
  2. 8
      src/router/index.ts
  3. 9
      src/views/AccountViewView.vue
  4. 5
      src/views/ContactAmountsView.vue
  5. 5
      src/views/ContactsView.vue
  6. 93
      src/views/HelpView.vue
  7. 19
      src/views/NewEditProjectView.vue
  8. 1
      src/views/ProjectViewView.vue
  9. 1
      src/views/ProjectsView.vue
  10. 162
      src/views/SeedBackupView.vue

7
project.yaml

@ -6,13 +6,11 @@
- replace user-affecting console.logs with error messages (eg. catches) - replace user-affecting console.logs with error messages (eg. catches)
- contacts v1 : - contacts v1 :
- .1 remove 'copy' until it works
- .5 Add page to show seed. - .5 Add page to show seed.
- 01 Provide a way to import the non-sensitive data. - 01 Provide a way to import the non-sensitive data.
- 01 Provide way to share your contact info. - 01 Provide way to share your contact info.
- .2 move all "identity" references to temporary account access - .2 move all "identity" references to temporary account access
- .5 make deploy for give-only features - .5 make deploy for give-only features
- .5 get 'copy' to work on account page
- contacts v+ : - contacts v+ :
- .5 make advanced "show/hide amounts" button into a nice UI toggle - .5 make advanced "show/hide amounts" button into a nice UI toggle
@ -22,10 +20,11 @@
- refactor UI : - refactor UI :
- .5 Alerts show at the top and can be missed, eg. account data download - .5 Alerts show at the top and can be missed, eg. account data download
- 01 Change alerts into a component (to cut down duplicate code) - 01 Change alerts into a component (to cut down duplicate code)
- 01 Code for "nav" tabs across the bottom is duplicated on each page. - 01 Change "nav" tabs across the bottom into a component (eliminating duplicate code).
- .2 Add "copied" feedback when they click "copy" on /account
- .5 Fix how icons show on top of bottom bar on ContactAmounts page - .5 Fix how icons show on top of bottom bar on ContactAmounts page
- on stats-world, use all bits of randomness for location
- commit screen - commit screen
- discover screen - discover screen

8
src/router/index.ts

@ -115,6 +115,14 @@ const routes: Array<RouteRecordRaw> = [
component: () => component: () =>
import(/* webpackChunkName: "projects" */ "../views/ProjectsView.vue"), import(/* webpackChunkName: "projects" */ "../views/ProjectsView.vue"),
}, },
{
path: "/seed-backup",
name: "seed-backup",
component: () =>
import(
/* webpackChunkName: "seed-backup" */ "../views/SeedBackupView.vue"
),
},
{ {
path: "/start", path: "/start",
name: "start", name: "start",

9
src/views/AccountViewView.vue

@ -164,12 +164,13 @@
<h3 class="text-sm uppercase font-semibold mb-3">Data</h3> <h3 class="text-sm uppercase font-semibold mb-3">Data</h3>
<a <router-link
:to="{ name: 'seed-backup' }"
href="" href=""
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2" class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
> >
Backup Identifier Seed Backup Identifier Seed
</a> </router-link>
<a <a
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6" class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6"
@click="exportDatabase()" @click="exportDatabase()"
@ -291,6 +292,7 @@
</span> </span>
</div> </div>
<!-- This same popup code is in many files. -->
<div v-bind:class="computedAlertClassNames()"> <div v-bind:class="computedAlertClassNames()">
<button <button
class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2" class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2"
@ -542,16 +544,15 @@ export default class AccountViewView extends Vue {
this.apiServerInput = value; this.apiServerInput = value;
} }
// This same popup code is in many files.
alertMessage = ""; alertMessage = "";
alertTitle = ""; alertTitle = "";
isAlertVisible = false; isAlertVisible = false;
public onClickClose() { public onClickClose() {
this.isAlertVisible = false; this.isAlertVisible = false;
this.alertTitle = ""; this.alertTitle = "";
this.alertMessage = ""; this.alertMessage = "";
} }
public computedAlertClassNames() { public computedAlertClassNames() {
return { return {
hidden: !this.isAlertVisible, hidden: !this.isAlertVisible,

5
src/views/ContactAmountsView.vue

@ -110,6 +110,7 @@
</div> </div>
</div> </div>
<!-- This same popup code is in many files. -->
<div v-bind:class="computedAlertClassNames()"> <div v-bind:class="computedAlertClassNames()">
<button <button
class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2" class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2"
@ -130,7 +131,6 @@ import { Options, Vue } from "vue-class-component";
import { accountsDB, db } from "@/db"; import { accountsDB, db } from "@/db";
import { Contact } from "@/db/tables/contacts"; import { Contact } from "@/db/tables/contacts";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import { AppString } from "@/constants/app";
import { accessToken, SimpleSigner } from "@/libs/crypto"; import { accessToken, SimpleSigner } from "@/libs/crypto";
import { import {
AgreeVerifiableCredential, AgreeVerifiableCredential,
@ -321,16 +321,15 @@ export default class ContactsView extends Vue {
this.isAlertVisible = true; this.isAlertVisible = true;
} }
// This same popup code is in many files.
alertTitle = ""; alertTitle = "";
alertMessage = ""; alertMessage = "";
isAlertVisible = false; isAlertVisible = false;
public onClickClose() { public onClickClose() {
this.isAlertVisible = false; this.isAlertVisible = false;
this.alertTitle = ""; this.alertTitle = "";
this.alertMessage = ""; this.alertMessage = "";
} }
public computedAlertClassNames() { public computedAlertClassNames() {
return { return {
hidden: !this.isAlertVisible, hidden: !this.isAlertVisible,

5
src/views/ContactsView.vue

@ -232,6 +232,7 @@
</ul> </ul>
</section> </section>
<!-- This same popup code is in many files. -->
<div v-bind:class="computedAlertClassNames()"> <div v-bind:class="computedAlertClassNames()">
<button <button
class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2" class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2"
@ -251,7 +252,6 @@ import * as R from "ramda";
import { IIdentifier } from "@veramo/core"; import { IIdentifier } from "@veramo/core";
import { Options, Vue } from "vue-class-component"; import { Options, Vue } from "vue-class-component";
import { AppString } from "@/constants/app";
import { accountsDB, db } from "@/db"; import { accountsDB, db } from "@/db";
import { Contact } from "@/db/tables/contacts"; import { Contact } from "@/db/tables/contacts";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
@ -828,16 +828,15 @@ export default class ContactsView extends Vue {
} }
} }
// This same popup code is in many files.
alertTitle = ""; alertTitle = "";
alertMessage = ""; alertMessage = "";
isAlertVisible = false; isAlertVisible = false;
public onClickClose() { public onClickClose() {
this.isAlertVisible = false; this.isAlertVisible = false;
this.alertTitle = ""; this.alertTitle = "";
this.alertMessage = ""; this.alertMessage = "";
} }
public computedAlertClassNames() { public computedAlertClassNames() {
return { return {
hidden: !this.isAlertVisible, hidden: !this.isAlertVisible,

93
src/views/HelpView.vue

@ -55,12 +55,34 @@
</h1> </h1>
<div> <div>
<h2 class="text-xl font-semibold">Introduction</h2>
<p> <p>
This app is a window into data that you and your friends own, focused on This app is a window into data that you and your friends own, focused on
gifts and collaboration. gifts and collaboration.
</p> </p>
<h2 class="text-xl font-semibold">How is this app useful?</h2>
<p>
We are building networks of people who want to grow a gifting society.
First of all, you can record ways you've seen people give, and that
leaves a permanent record... one that they show came from you. This is
personally gratifying, but it extends to broader work: volunteers can
get confirmation of activity and selectively show off their
contributions and network.
</p>
<p>
You can also record projects and plans and invite others to collaborate.
Soon you'll be able to see when others are interested and see how much
they're willing to contribute, even if there are conditions.
</p>
<p>
This app uses the power of cryptography to build a reputation, recording
activity that you can share at your discretion. You put some activity
public, but your sensitive information is not shared with anyone,
including our services. This is in contrast to Meta and Google, who hold
your data and allow you use it. Those services are useful, but they have
the control; this app gives you the control.
</p>
<h2 class="text-xl font-semibold">How do I backup all my data?</h2> <h2 class="text-xl font-semibold">How do I backup all my data?</h2>
<p> <p>
There are two parts to backup your data: the identifier secrets and the There are two parts to backup your data: the identifier secrets and the
@ -147,19 +169,76 @@
key. key.
</p> </p>
<h2 class="text-xl font-semibold">
How do I get permission to store claims on the server?
</h2>
<p>
Get registered by someone else with the app; they can register you on
the Contacts <fa icon="circle-user" class="fa-fw" /> page. There are
limits to how many each person can register, so you may have to wait.
</p>
<h2 class="text-xl font-semibold">What do you mean by "claims"?</h2>
<p>
Certain actions in this app are signed by your private keys, and these
are often called "claims". For example, when you give time to a person
or project, you sign a claim declaring that you gave that time. When you
declare a project, you sign a claim declaring it to the world. When you
confirm someone else's claim, you sign a claim of agreement.
</p>
<p>
Some of the data in this app does not involve claims, such as your
contact list and your identifier.
</p>
<h2 class="text-xl font-semibold"> <h2 class="text-xl font-semibold">
I know there is a record from someone, so why can't I see that info? I know there is a record from someone, so why can't I see that info?
</h2> </h2>
<p> <p>
Sometimes someone else has made claims -- meaning they have given time, If you don't see anything associated with a person, this is typically
or recognized time given, or declared a project -- but you cannot see because they have not given you permission to see their information. Ask
anything associated with them. The reason may be because they have not them to add you to their contact list and make sure the eye next to your
given you permission to see their information. Ask them to add you to name is open like this
their contact list and make sure the eye next to your name is open like
this
<fa icon="eye" class="fa-fw" /> and not closed like this <fa icon="eye" class="fa-fw" /> and not closed like this
<fa icon="eye-slash" class="fa-fw" />. <fa icon="eye-slash" class="fa-fw" />.
</p> </p>
<p>
Sometimes the reason you don't see something is because the search time
is limited. Go to the bottom and make sure to load all the data on a
list. If you still don't see it, try a search or view on a different
page.
</p>
<h2 class="text-xl font-semibold">How do I create another identity?</h2>
<p>
Go
<router-link to="import-account" class="text-blue-500">
import another mnemonic here.
</router-link>
</p>
<h2 class="text-xl font-semibold">What is your privacy policy?</h2>
<p>
See
<a href="https://endorser.ch/privacy-policy" class="text-blue-500">
the Endorser Service Privacy Policy.
</a>
</p>
<h2 class="text-xl font-semibold">What app version is this?</h2>
<p>
{{ package.version }}
</p>
</div> </div>
</section> </section>
</template> </template>
<script lang="ts">
import * as Package from "../../package.json";
import { Component, Vue } from "vue-facing-decorator";
@Component
export default class Help extends Vue {
package = Package;
}
</script>

19
src/views/NewEditProjectView.vue

@ -63,6 +63,8 @@
</button> </button>
</div> </div>
</section> </section>
<!-- This same popup code is in many files. -->
<div v-bind:class="computedAlertClassNames()"> <div v-bind:class="computedAlertClassNames()">
<button <button
class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2" class="close-button bg-slate-200 w-8 leading-loose rounded-full absolute top-2 right-2"
@ -81,7 +83,6 @@ import * as didJwt from "did-jwt";
import * as R from "ramda"; import * as R from "ramda";
import { Options, Vue } from "vue-class-component"; import { Options, Vue } from "vue-class-component";
import { AppString } from "@/constants/app";
import { accountsDB, db } from "@/db"; import { accountsDB, db } from "@/db";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import { accessToken, SimpleSigner } from "@/libs/crypto"; import { accessToken, SimpleSigner } from "@/libs/crypto";
@ -105,8 +106,6 @@ export default class NewEditProjectView extends Vue {
projectName = ""; projectName = "";
description = ""; description = "";
errorMessage = ""; errorMessage = "";
alertTitle = "";
alertMessage = "";
projectId = localStorage.getItem("projectId") || ""; projectId = localStorage.getItem("projectId") || "";
isHiddenSave = false; isHiddenSave = false;
@ -249,12 +248,6 @@ export default class NewEditProjectView extends Vue {
} }
} }
public onClickClose() {
this.isAlertVisible = false;
this.alertTitle = "";
this.alertMessage = "";
}
public async onSaveProjectClick() { public async onSaveProjectClick() {
this.isHiddenSave = true; this.isHiddenSave = true;
this.isHiddenSpinner = false; this.isHiddenSpinner = false;
@ -274,7 +267,15 @@ export default class NewEditProjectView extends Vue {
this.$router.back(); this.$router.back();
} }
// This same popup code is in many files.
alertTitle = "";
alertMessage = "";
isAlertVisible = false; isAlertVisible = false;
public onClickClose() {
this.isAlertVisible = false;
this.alertTitle = "";
this.alertMessage = "";
}
public computedAlertClassNames() { public computedAlertClassNames() {
return { return {
hidden: !this.isAlertVisible, hidden: !this.isAlertVisible,

1
src/views/ProjectViewView.vue

@ -151,7 +151,6 @@ import * as moment from "moment";
import * as R from "ramda"; import * as R from "ramda";
import { Options, Vue } from "vue-class-component"; import { Options, Vue } from "vue-class-component";
import { AppString } from "@/constants/app";
import { accountsDB, db } from "@/db"; import { accountsDB, db } from "@/db";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto"; import { accessToken } from "@/libs/crypto";

1
src/views/ProjectsView.vue

@ -104,7 +104,6 @@
import * as R from "ramda"; import * as R from "ramda";
import { Options, Vue } from "vue-class-component"; import { Options, Vue } from "vue-class-component";
import { AppString } from "@/constants/app";
import { accountsDB, db } from "@/db"; import { accountsDB, db } from "@/db";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto"; import { accessToken } from "@/libs/crypto";

162
src/views/SeedBackupView.vue

@ -0,0 +1,162 @@
<template>
<!-- QUICK NAV -->
<nav id="QuickNav" class="fixed bottom-0 left-0 right-0 bg-slate-200 z-50">
<ul class="flex text-2xl p-2 gap-2">
<!-- Home Feed -->
<li class="basis-1/5 rounded-md text-slate-500">
<router-link :to="{ name: 'home' }" class="block text-center py-3 px-1">
<fa icon="house-chimney" class="fa-fw"></fa>
</router-link>
</li>
<!-- Search -->
<li class="basis-1/5 rounded-md text-slate-500">
<router-link
:to="{ name: 'discover' }"
class="block text-center py-3 px-1"
>
<fa icon="magnifying-glass" class="fa-fw"></fa>
</router-link>
</li>
<!-- Projects -->
<li class="basis-1/5 rounded-md text-slate-500">
<router-link
:to="{ name: 'projects' }"
class="block text-center py-3 px-1"
>
<fa icon="folder-open" class="fa-fw"></fa>
</router-link>
</li>
<!-- Contacts -->
<li class="basis-1/5 rounded-md text-slate-500">
<router-link
:to="{ name: 'contacts' }"
class="block text-center py-3 px-1"
>
<fa icon="users" class="fa-fw"></fa>
</router-link>
</li>
<!-- Profile -->
<li class="basis-1/5 rounded-md bg-slate-400 text-white">
<router-link
:to="{ name: 'account' }"
class="block text-center py-3 px-1"
>
<fa icon="circle-user" class="fa-fw"></fa>
</router-link>
</li>
</ul>
</nav>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Seed Backup
</h1>
<div class="flex justify-between py-2">
<span />
<span>
<router-link
:to="{ name: 'help' }"
class="text-xs uppercase bg-blue-500 text-white px-1.5 py-1 rounded-md ml-1"
>
Help
</router-link>
</span>
</div>
<div v-if="activeAccount">
<p>
BEWARE: Anyone who gets hold of this mnemonic seed phrase will be able
impersonate you and take over any digital holdings based on it. So only
reveal it when you are in a private place out of sight of other eyes,
and only record it in something private -- don't take a screenshot or
send it to any online service.
</p>
<button
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
@click="showSeedPhrase"
>
Click here when you're ready to see it.
</button>
<p v-if="showSeed">{{ activeAccount.mnemonic }}</p>
</div>
<div v-else>You do not have an active identity.</div>
<!-- This same popup code is in many files. -->
<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>
</template>
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { accountsDB, db } from "@/db";
import * as R from "ramda";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
@Component
export default class SeedBackupView extends Vue {
activeAccount = null;
showSeed = false;
// 'created' hook runs when the Vue instance is first created
async created() {
try {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
const activeDid = settings?.activeDid || "";
await accountsDB.open();
const accounts = await accountsDB.accounts.toArray();
this.activeAccount = R.find((acc) => acc.did === activeDid, accounts);
} catch (err) {
console.log("Got an error loading an identity:", err);
this.alertTitle = "Error Loading Account";
this.alertMessage = "Got an error loading your seed data.";
this.isAlertVisible = true;
}
}
showSeedPhrase() {
this.showSeed = true;
}
// This same popup code is in many files.
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,
fixed: true,
"top-3": true,
"inset-x-3": true,
"transition-transform": true,
"ease-in": true,
"duration-300": true,
};
}
}
</script>
Loading…
Cancel
Save