forked from jsnbuchanan/crowd-funder-for-time-pwa
Merge pull request 'add page to show mnemonic seed phrase for backup' (#20) from seed-backup into switching-servers
Reviewed-on: trent_larson/kick-starter-for-time-pwa#20
This commit is contained in:
@@ -6,13 +6,10 @@
|
||||
- replace user-affecting console.logs with error messages (eg. catches)
|
||||
|
||||
- contacts v1 :
|
||||
- .1 remove 'copy' until it works
|
||||
- .5 Add page to show seed.
|
||||
- 01 Provide a way to import the non-sensitive data.
|
||||
- 01 Provide way to share your contact info.
|
||||
- 01 Provide a way to import the non-sensitive data.
|
||||
- .2 move all "identity" references to temporary account access
|
||||
- .5 make deploy for give-only features
|
||||
- .5 get 'copy' to work on account page
|
||||
|
||||
- contacts v+ :
|
||||
- .5 make advanced "show/hide amounts" button into a nice UI toggle
|
||||
@@ -22,10 +19,12 @@
|
||||
- refactor UI :
|
||||
- .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 Code for "nav" tabs across the bottom is duplicated on each page.
|
||||
- .2 Add "copied" feedback when they click "copy" on /account
|
||||
- 01 Change "nav" tabs across the bottom into a component (eliminating duplicate code).
|
||||
- .5 Fix how icons show on top of bottom bar on ContactAmounts page
|
||||
|
||||
- on stats-world, use all bits of randomness for location
|
||||
- show pop-up confirming that settings & contacts have been downloaded
|
||||
|
||||
- commit screen
|
||||
|
||||
- discover screen
|
||||
@@ -115,6 +115,14 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "projects" */ "../views/ProjectsView.vue"),
|
||||
},
|
||||
{
|
||||
path: "/seed-backup",
|
||||
name: "seed-backup",
|
||||
component: () =>
|
||||
import(
|
||||
/* webpackChunkName: "seed-backup" */ "../views/SeedBackupView.vue"
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/start",
|
||||
name: "start",
|
||||
|
||||
@@ -164,12 +164,13 @@
|
||||
|
||||
<h3 class="text-sm uppercase font-semibold mb-3">Data</h3>
|
||||
|
||||
<a
|
||||
<router-link
|
||||
:to="{ name: 'seed-backup' }"
|
||||
href=""
|
||||
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
|
||||
</a>
|
||||
</router-link>
|
||||
<a
|
||||
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()"
|
||||
@@ -291,6 +292,7 @@
|
||||
</span>
|
||||
</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"
|
||||
@@ -542,16 +544,15 @@ export default class AccountViewView extends Vue {
|
||||
this.apiServerInput = value;
|
||||
}
|
||||
|
||||
// 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,
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
</div>
|
||||
</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"
|
||||
@@ -130,7 +131,6 @@ import { Options, Vue } from "vue-class-component";
|
||||
import { accountsDB, db } from "@/db";
|
||||
import { Contact } from "@/db/tables/contacts";
|
||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||
import { AppString } from "@/constants/app";
|
||||
import { accessToken, SimpleSigner } from "@/libs/crypto";
|
||||
import {
|
||||
AgreeVerifiableCredential,
|
||||
@@ -321,16 +321,15 @@ export default class ContactsView extends Vue {
|
||||
this.isAlertVisible = true;
|
||||
}
|
||||
|
||||
// This same popup code is in many files.
|
||||
alertTitle = "";
|
||||
alertMessage = "";
|
||||
isAlertVisible = false;
|
||||
|
||||
public onClickClose() {
|
||||
this.isAlertVisible = false;
|
||||
this.alertTitle = "";
|
||||
this.alertMessage = "";
|
||||
}
|
||||
|
||||
public computedAlertClassNames() {
|
||||
return {
|
||||
hidden: !this.isAlertVisible,
|
||||
|
||||
@@ -232,6 +232,7 @@
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- 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"
|
||||
@@ -251,7 +252,6 @@ import * as R from "ramda";
|
||||
import { IIdentifier } from "@veramo/core";
|
||||
import { Options, Vue } from "vue-class-component";
|
||||
|
||||
import { AppString } from "@/constants/app";
|
||||
import { accountsDB, db } from "@/db";
|
||||
import { Contact } from "@/db/tables/contacts";
|
||||
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 = "";
|
||||
alertMessage = "";
|
||||
isAlertVisible = false;
|
||||
|
||||
public onClickClose() {
|
||||
this.isAlertVisible = false;
|
||||
this.alertTitle = "";
|
||||
this.alertMessage = "";
|
||||
}
|
||||
|
||||
public computedAlertClassNames() {
|
||||
return {
|
||||
hidden: !this.isAlertVisible,
|
||||
|
||||
@@ -55,12 +55,34 @@
|
||||
</h1>
|
||||
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold">Introduction</h2>
|
||||
<p>
|
||||
This app is a window into data that you and your friends own, focused on
|
||||
gifts and collaboration.
|
||||
</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>
|
||||
<p>
|
||||
There are two parts to backup your data: the identifier secrets and the
|
||||
@@ -147,19 +169,76 @@
|
||||
key.
|
||||
</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">
|
||||
I know there is a record from someone, so why can't I see that info?
|
||||
</h2>
|
||||
<p>
|
||||
Sometimes someone else has made claims -- meaning they have given time,
|
||||
or recognized time given, or declared a project -- but you cannot see
|
||||
anything associated with them. The reason may be because they have not
|
||||
given you permission to see their information. Ask them to add you to
|
||||
their contact list and make sure the eye next to your name is open like
|
||||
this
|
||||
If you don't see anything associated with a person, this is typically
|
||||
because they have not given you permission to see their information. Ask
|
||||
them to add you to 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-slash" class="fa-fw" />.
|
||||
</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>
|
||||
</section>
|
||||
</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>
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 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"
|
||||
@@ -81,7 +83,6 @@ import * as didJwt from "did-jwt";
|
||||
import * as R from "ramda";
|
||||
import { Options, Vue } from "vue-class-component";
|
||||
|
||||
import { AppString } from "@/constants/app";
|
||||
import { accountsDB, db } from "@/db";
|
||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||
import { accessToken, SimpleSigner } from "@/libs/crypto";
|
||||
@@ -105,8 +106,6 @@ export default class NewEditProjectView extends Vue {
|
||||
projectName = "";
|
||||
description = "";
|
||||
errorMessage = "";
|
||||
alertTitle = "";
|
||||
alertMessage = "";
|
||||
|
||||
projectId = localStorage.getItem("projectId") || "";
|
||||
isHiddenSave = false;
|
||||
@@ -249,12 +248,6 @@ export default class NewEditProjectView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
public onClickClose() {
|
||||
this.isAlertVisible = false;
|
||||
this.alertTitle = "";
|
||||
this.alertMessage = "";
|
||||
}
|
||||
|
||||
public async onSaveProjectClick() {
|
||||
this.isHiddenSave = true;
|
||||
this.isHiddenSpinner = false;
|
||||
@@ -274,7 +267,15 @@ export default class NewEditProjectView extends Vue {
|
||||
this.$router.back();
|
||||
}
|
||||
|
||||
// This same popup code is in many files.
|
||||
alertTitle = "";
|
||||
alertMessage = "";
|
||||
isAlertVisible = false;
|
||||
public onClickClose() {
|
||||
this.isAlertVisible = false;
|
||||
this.alertTitle = "";
|
||||
this.alertMessage = "";
|
||||
}
|
||||
public computedAlertClassNames() {
|
||||
return {
|
||||
hidden: !this.isAlertVisible,
|
||||
|
||||
@@ -151,7 +151,6 @@ import * as moment from "moment";
|
||||
import * as R from "ramda";
|
||||
import { Options, Vue } from "vue-class-component";
|
||||
|
||||
import { AppString } from "@/constants/app";
|
||||
import { accountsDB, db } from "@/db";
|
||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||
import { accessToken } from "@/libs/crypto";
|
||||
|
||||
@@ -104,7 +104,6 @@
|
||||
import * as R from "ramda";
|
||||
import { Options, Vue } from "vue-class-component";
|
||||
|
||||
import { AppString } from "@/constants/app";
|
||||
import { accountsDB, db } from "@/db";
|
||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||
import { accessToken } from "@/libs/crypto";
|
||||
|
||||
162
src/views/SeedBackupView.vue
Normal file
162
src/views/SeedBackupView.vue
Normal file
@@ -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>
|
||||
Reference in New Issue
Block a user