forked from trent_larson/crowd-funder-for-time-pwa
fix registration, separate ID creation to allow new random ones, and refactor warning and other verbiage
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
- add infinite scroll assignee:matthew
|
- add infinite scroll assignee:matthew
|
||||||
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
|
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
|
||||||
|
|
||||||
|
- allow new (random) user creation, and make accurate message about registration
|
||||||
- allow type annotations in World.js & landmarks.js (since we get this error: "Types are not supported by current JavaScript version")
|
- allow type annotations in World.js & landmarks.js (since we get this error: "Types are not supported by current JavaScript version")
|
||||||
- replace user-affecting console.log & console.error with error messages (eg. catches)
|
- replace user-affecting console.log & console.error with error messages (eg. catches)
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,14 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
/* webpackChunkName: "new-edit-project" */ "../views/NewEditProjectView.vue"
|
/* webpackChunkName: "new-edit-project" */ "../views/NewEditProjectView.vue"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/new-identifier",
|
||||||
|
name: "new-identifier",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "new-identifier" */ "../views/NewIdentifierView.vue"
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/project",
|
path: "/project",
|
||||||
name: "project",
|
name: "project",
|
||||||
|
|||||||
@@ -66,20 +66,22 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Friend referral requirement notice -->
|
<!-- Registration notice -->
|
||||||
|
<!-- We won't show any loading indicator; we'll just pop the message in once we know they need it. -->
|
||||||
<div
|
<div
|
||||||
|
v-if="!loadingLimits && !limits?.nextWeekBeginDateTime"
|
||||||
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
|
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
|
||||||
>
|
>
|
||||||
<p class="mb-4">
|
<p class="mb-4">
|
||||||
<b>Important:</b> before you can create a new project or commit time to
|
<b>Note:</b> Before you can publicly announce a new project or time
|
||||||
one, you need a friend to register you.
|
commitment, a friend needs to register you.
|
||||||
</p>
|
</p>
|
||||||
<button
|
<router-link
|
||||||
id="btnShowQR"
|
:to="{ name: 'contact-qr' }"
|
||||||
class="inline-block text-md uppercase bg-amber-600 text-white px-4 py-2 rounded-md"
|
class="inline-block text-md uppercase bg-amber-600 text-white px-4 py-2 rounded-md"
|
||||||
>
|
>
|
||||||
Share Your ID
|
Share Your Info
|
||||||
</button>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Identity Details -->
|
<!-- Identity Details -->
|
||||||
@@ -181,7 +183,7 @@
|
|||||||
<div class="text-slate-500 text-center">
|
<div class="text-slate-500 text-center">
|
||||||
<b>ID:</b> <code>did:peer:kl45kj41lk451kl3</code>
|
<b>ID:</b> <code>did:peer:kl45kj41lk451kl3</code>
|
||||||
</div>
|
</div>
|
||||||
<img src="img/sample-qr-code.png" class="w-full mb-3" />
|
<img src="/img/sample-qr-code.png" class="w-full mb-3" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
value="cancel"
|
value="cancel"
|
||||||
@@ -229,6 +231,13 @@
|
|||||||
<button class="text-center text-md text-blue-500" @click="checkLimits()">
|
<button class="text-center text-md text-blue-500" @click="checkLimits()">
|
||||||
Check Limits
|
Check Limits
|
||||||
</button>
|
</button>
|
||||||
|
<!-- show spinner if loading limits -->
|
||||||
|
<div v-if="loadingLimits" class="ml-2">
|
||||||
|
Checking... <fa icon="spinner" class="fa-spin"></fa>
|
||||||
|
</div>
|
||||||
|
<div class="ml-2">
|
||||||
|
{{ limitsMessage }}
|
||||||
|
</div>
|
||||||
<div v-if="!!limits?.nextWeekBeginDateTime" class="px-9">
|
<div v-if="!!limits?.nextWeekBeginDateTime" class="px-9">
|
||||||
<span class="font-bold">Rate Limits</span>
|
<span class="font-bold">Rate Limits</span>
|
||||||
<p>
|
<p>
|
||||||
@@ -280,7 +289,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="numAccounts > 0" class="flex py-2">
|
<div v-if="numAccounts > 0" class="flex py-2">
|
||||||
Switch Account
|
Switch Identifier
|
||||||
<span v-for="accountNum in numAccounts" :key="accountNum">
|
<span v-for="accountNum in numAccounts" :key="accountNum">
|
||||||
<button class="text-blue-500 px-2" @click="switchAccount(accountNum)">
|
<button class="text-blue-500 px-2" @click="switchAccount(accountNum)">
|
||||||
#{{ accountNum }}
|
#{{ accountNum }}
|
||||||
@@ -357,6 +366,8 @@ export default class AccountViewView extends Vue {
|
|||||||
publicHex = "";
|
publicHex = "";
|
||||||
publicBase64 = "";
|
publicBase64 = "";
|
||||||
limits: RateLimits | null = null;
|
limits: RateLimits | null = null;
|
||||||
|
limitsMessage = "";
|
||||||
|
loadingLimits = true; // might as well now that we do it on mount, to avoid flashing the registration message
|
||||||
showContactGives = false;
|
showContactGives = false;
|
||||||
|
|
||||||
showDidCopy = false;
|
showDidCopy = false;
|
||||||
@@ -388,6 +399,7 @@ export default class AccountViewView extends Vue {
|
|||||||
// assign this to a class variable, eg. "registerThisUser = testServerRegisterUser",
|
// assign this to a class variable, eg. "registerThisUser = testServerRegisterUser",
|
||||||
// select a component in the extension, and enter in the console: $vm.ctx.registerThisUser()
|
// select a component in the extension, and enter in the console: $vm.ctx.registerThisUser()
|
||||||
//testServerRegisterUser();
|
//testServerRegisterUser();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await db.open();
|
||||||
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||||
@@ -441,6 +453,8 @@ export default class AccountViewView extends Vue {
|
|||||||
this.alertTitle = "Error Creating Account";
|
this.alertTitle = "Error Creating Account";
|
||||||
this.isAlertVisible = true;
|
this.isAlertVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.checkLimits();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateShowContactAmounts() {
|
public async updateShowContactAmounts() {
|
||||||
@@ -482,6 +496,9 @@ export default class AccountViewView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async checkLimits() {
|
async checkLimits() {
|
||||||
|
this.loadingLimits = true;
|
||||||
|
this.limitsMessage = "";
|
||||||
|
|
||||||
const url = this.apiServer + "/api/report/rateLimits";
|
const url = this.apiServer + "/api/report/rateLimits";
|
||||||
await accountsDB.open();
|
await accountsDB.open();
|
||||||
const accounts = await accountsDB.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
@@ -502,18 +519,14 @@ export default class AccountViewView extends Vue {
|
|||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const serverError = error as AxiosError;
|
const serverError = error as AxiosError;
|
||||||
|
|
||||||
this.alertTitle = "Error from Server";
|
|
||||||
console.error("Bad response retrieving limits: ", serverError);
|
console.error("Bad response retrieving limits: ", serverError);
|
||||||
// Anybody know how to access items inside "response.data" without this?
|
// Anybody know how to access items inside "response.data" without this?
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const data: any = serverError.response?.data;
|
const data: any = serverError.response?.data;
|
||||||
if (data.error.message) {
|
this.limitsMessage = data?.error?.message || "Bad server response.";
|
||||||
this.alertMessage = data.error.message;
|
|
||||||
} else {
|
|
||||||
this.alertMessage = "Bad server response. See logs for details.";
|
|
||||||
}
|
|
||||||
this.isAlertVisible = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.loadingLimits = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async switchAccount(accountNum: number) {
|
async switchAccount(accountNum: number) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
<section id="Content" class="p-6 pb-24">
|
<section id="Content" class="p-6 pb-24">
|
||||||
<!-- Heading -->
|
<!-- Heading -->
|
||||||
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
|
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
|
||||||
Contact Info
|
Your Contact Info
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|||||||
@@ -495,7 +495,7 @@ export default class ContactsView extends Vue {
|
|||||||
"@type": "RegisterAction",
|
"@type": "RegisterAction",
|
||||||
agent: { identifier: identity.did },
|
agent: { identifier: identity.did },
|
||||||
object: SERVICE_ID,
|
object: SERVICE_ID,
|
||||||
recipient: { identifier: contact.did },
|
participant: { identifier: contact.did },
|
||||||
};
|
};
|
||||||
// Make a payload for the claim
|
// Make a payload for the claim
|
||||||
const vcPayload = {
|
const vcPayload = {
|
||||||
|
|||||||
@@ -60,14 +60,14 @@
|
|||||||
gifts and collaboration.
|
gifts and collaboration.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold">How is this app useful?</h2>
|
<h2 class="text-xl font-semibold">What is the philosophy here?</h2>
|
||||||
<p>
|
<p>
|
||||||
We are building networks of people who want to grow a gifting society.
|
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
|
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
|
leaves a permanent record -- one that came from you, and the recipient
|
||||||
personally gratifying, but it extends to broader work: volunteers can
|
can prove it was for them. This is personally gratifying, but it extends
|
||||||
get confirmation of activity and selectively show off their
|
to broader work: volunteers can get confirmation of activity and
|
||||||
contributions and network.
|
selectively show off their contributions and network.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You can also record projects and plans and invite others to collaborate.
|
You can also record projects and plans and invite others to collaborate.
|
||||||
@@ -83,10 +83,25 @@
|
|||||||
the control; this app gives you the control.
|
the control; this app gives you the control.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-xl font-semibold">How do I take my first action?</h2>
|
||||||
|
<p>
|
||||||
|
You need someone to register you -- usually the person who told you
|
||||||
|
about this app, on the Contacts
|
||||||
|
<fa icon="circle-user" class="fa-fw" /> page. After they register you,
|
||||||
|
and after you have contacts, you can select any contact on the home page
|
||||||
|
and record your appreciation for... whatever. That is a claim recorded
|
||||||
|
on a custom ledger. The day after being registered, you'll be able to
|
||||||
|
register others; later, you can create projects, too.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note that there are limits to how many each person can register, so you
|
||||||
|
may have to wait.
|
||||||
|
</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 sets of data to backup: the identifier secrets and the
|
||||||
other data such as settings, contacts, etc.
|
other data that isn't quite a secret such as settings, contacts, etc.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="px-4">
|
<div class="px-4">
|
||||||
@@ -100,6 +115,10 @@
|
|||||||
<li>
|
<li>
|
||||||
Click on "Backup Identifier Seed" and follow the instructions.
|
Click on "Backup Identifier Seed" and follow the instructions.
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
If you have other identifiers, switch to each one and repeat those
|
||||||
|
steps.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold">
|
<h2 class="text-xl font-semibold">
|
||||||
@@ -156,28 +175,6 @@
|
|||||||
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>
|
||||||
|
|||||||
112
src/views/NewIdentifierView.vue
Normal file
112
src/views/NewIdentifierView.vue
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<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">
|
||||||
|
Your Identity
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="flex justify-between py-2">
|
||||||
|
<span />
|
||||||
|
<span v-if="loading">
|
||||||
|
Creating... <i class="fa-solid fa-loader fa-spin"></i>
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
Created!
|
||||||
|
<i
|
||||||
|
class="fa-solid fa-burst fa-beat"
|
||||||
|
style="--fa-animation-duration: 3s"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import "dexie-export-import";
|
||||||
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
import { accountsDB, db } from "@/db";
|
||||||
|
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
||||||
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class AccountViewView extends Vue {
|
||||||
|
loading = true;
|
||||||
|
|
||||||
|
async mounted() {
|
||||||
|
await accountsDB.open();
|
||||||
|
const mnemonic = generateSeed();
|
||||||
|
// address is 0x... ETH address, without "did:eth:"
|
||||||
|
const [address, privateHex, publicHex, derivationPath] =
|
||||||
|
deriveAddress(mnemonic);
|
||||||
|
|
||||||
|
const newId = newIdentifier(address, publicHex, privateHex, derivationPath);
|
||||||
|
const identity = JSON.stringify(newId);
|
||||||
|
await accountsDB.accounts.add({
|
||||||
|
dateCreated: new Date().toISOString(),
|
||||||
|
derivationPath: derivationPath,
|
||||||
|
did: newId.did,
|
||||||
|
identity: identity,
|
||||||
|
mnemonic: mnemonic,
|
||||||
|
publicKeyHex: newId.keys[0].publicKeyHex,
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
|
activeDid: newId.did,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.loading = false;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$router.push({ name: "account" });
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -35,7 +35,7 @@ import { Options, Vue } from "vue-class-component";
|
|||||||
})
|
})
|
||||||
export default class StartView extends Vue {
|
export default class StartView extends Vue {
|
||||||
public onClickYes() {
|
public onClickYes() {
|
||||||
this.$router.push({ name: "account" });
|
this.$router.push({ name: "new-identifier" });
|
||||||
}
|
}
|
||||||
|
|
||||||
public onClickNo() {
|
public onClickNo() {
|
||||||
|
|||||||
Reference in New Issue
Block a user