aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2022-12-24 05:22:50 -0800
committerAdam Soltys <[email protected]>2022-12-24 05:22:50 -0800
commit10c20c0c5b130c389680e37e4e4aba8e2abdbf1e (patch)
tree6862c7f94c899b3dad177b16698c08abc678eefb
parente1a34bbc86600c6dfb782ac936030379deb6365a (diff)
downloadcoinos-ui-10c20c0c5b130c389680e37e4e4aba8e2abdbf1e.tar.gz
coinos-ui-10c20c0c5b130c389680e37e4e4aba8e2abdbf1e.zip
password prompt and pin fixes
-rw-r--r--src/components/Feed.svelte74
-rw-r--r--src/components/Password.svelte77
-rw-r--r--src/components/Pin.svelte3
-rw-r--r--src/components/index.js1
-rw-r--r--src/lib/nostr.js30
-rw-r--r--src/lib/store.js1
-rw-r--r--src/lib/utils.js5
-rw-r--r--src/routes/(app)/[username]/generate/+page.svelte6
-rw-r--r--src/routes/(app)/[username]/settings/[...tab]/+page.svelte8
-rw-r--r--src/routes/(app)/login/+server.js6
-rw-r--r--src/routes/(app)/password/+server.js8
11 files changed, 173 insertions, 46 deletions
diff --git a/src/components/Feed.svelte b/src/components/Feed.svelte
index 00226692..0ccda7b8 100644
--- a/src/components/Feed.svelte
+++ b/src/components/Feed.svelte
@@ -1,55 +1,51 @@
<script>
+ import { onMount } from 'svelte';
import { Avatar } from '$comp';
import { browser } from '$app/environment';
import VirtualScroll from 'svelte-virtual-scroll-list';
- import { punk } from '$lib/utils';
- import { Buffer } from 'buffer';
- import { entropyToMnemonic, mnemonicToSeedSync } from 'bip39';
import { enhance } from '$app/forms';
- import { bech32m } from 'bech32';
- import { calculateId, signId } from 'nostr';
- import { bip32, stretch, post } from '$lib/utils';
+ import { post, punk, failure } from '$lib/utils';
+ import { Password } from '$comp';
+ import { password, passwordPrompt } from '$lib/store';
+ import { send } from '$lib/nostr';
export let events;
export let user;
- const { decode, fromWords } = bech32m;
-
- let message;
+ let message, submitting;
+ $: submitting && $password && submit();
let submit = async () => {
- let mnemonic, key, password, seed, entropy, child, privkey;
- entropy = Buffer.from(
- await crypto.subtle.decrypt(
- { name: 'AES-GCM', iv: new Uint8Array(16) },
- await stretch(password, Buffer.from(user.salt, 'hex')),
- Uint8Array.from(fromWords(decode(user.cipher, 180).words))
- ),
- 'hex'
- ).toString('hex');
+ submitting = true;
+ try {
+ let mnemonic, key, seed, entropy, child, privkey;
+ if (!$password) return ($passwordPrompt = true);
+
+ try {
+ await post('/password', { password: $password });
+ } catch (e) {
+ return ($passwordPrompt = true);
+ }
- mnemonic = entropyToMnemonic(entropy);
- seed = mnemonicToSeedSync(mnemonic);
- key = bip32.fromSeed(seed);
- child = key.derivePath("m/44'/1237'/0'/0/0");
- privkey = child.privateKey;
+ let event = {
+ pubkey: user.pubkey,
+ created_at: Math.floor(Date.now() / 1000),
+ kind: 1,
+ content: message,
+ tags: []
+ };
- let event = {
- pubkey: user.pubkey,
- created_at: Math.floor(Date.now() / 1000),
- kind: 1,
- content: message,
- tags: []
- };
+ await send(event, user, $password);
- event.id = await calculateId(event);
- event.sig = await signId(privkey, event.id);
- await post(`/${user.username}`, { event });
+ event.user = user;
+ event.seen = event.created_at;
- event.user = user;
- event.seen = event.created_at;
- events[event.id] = event;
- events = events;
+ events[event.id] = event;
+ events = events;
+ } catch (e) {
+ failure('Problem posting event');
+ console.log(e);
+ }
};
let distance = (date) => {
@@ -78,6 +74,10 @@
<svelte:window bind:innerWidth={w} />
+{#if $passwordPrompt}
+ <Password {user} />
+{/if}
+
<form on:submit|preventDefault={submit} class="flex justify-center gap-4 max-w-2xl mx-auto">
<div class="grow">
<input
diff --git a/src/components/Password.svelte b/src/components/Password.svelte
new file mode 100644
index 00000000..c9318201
--- /dev/null
+++ b/src/components/Password.svelte
@@ -0,0 +1,77 @@
+<script>
+ import { Icon } from "$comp";
+ import { failure, post } from '$lib/utils';
+ import { password as pw, passwordPrompt } from '$lib/store';
+
+ export let user;
+
+ let password;
+ let { username } = user;
+ let revealPassword = false;
+
+ let cancel = () => ($passwordPrompt = false);
+
+ let submit = async () => {
+ try {
+ await post('/password', { password });
+ $passwordPrompt = false;
+ $pw = password;
+ } catch (e) {
+ failure('Invalid password, try again');
+ }
+ };
+</script>
+
+<div class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-20">
+ <div class="relative top-1/3 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white space-y-5">
+ <h1 class="text-center text-2xl font-semibold">Please enter your password</h1>
+ <form on:submit|preventDefault={submit}>
+ <div class="relative mb-5">
+ {#if revealPassword}
+ <input
+ name="password"
+ type="text"
+ required
+ class="bg-primary"
+ bind:value={password}
+ autocapitalize="none"
+ autofocus
+ />
+ {:else}
+ <input
+ name="password"
+ type="password"
+ required
+ class="bg-primary"
+ bind:value={password}
+ autocapitalize="none"
+ autofocus
+ />
+ {/if}
+ <button
+ type="button"
+ on:click={() => (revealPassword = !revealPassword)}
+ class="absolute right-5 top-5"
+ >
+ <Icon icon={revealPassword ? 'eye' : 'eye-off'} />
+ </button>
+ </div>
+ <div class="w-full flex">
+ <button
+ type="button"
+ class="border-2 border-black rounded-xl font-semibold mx-auto py-3 w-40 hover:opacity-80 mx-auto"
+ on:click={cancel}
+ on:keydown={cancel}
+ >
+ <div class="my-auto">Cancel</div>
+ </button>
+ <button
+ type="submit"
+ class="border-2 border-black rounded-xl font-semibold mx-auto py-3 w-40 hover:opacity-80 mx-auto"
+ >
+ <div class="my-auto">Submit</div>
+ </button>
+ </div>
+ </form>
+ </div>
+</div>
diff --git a/src/components/Pin.svelte b/src/components/Pin.svelte
index 80e003b9..9b1bb4ea 100644
--- a/src/components/Pin.svelte
+++ b/src/components/Pin.svelte
@@ -4,6 +4,8 @@
let pinCode = '';
let pinInput;
+ let cancel = () => ($pin = '000000');
+
$: pinCode.length > 5 && ($pin = pinCode);
</script>
@@ -15,6 +17,7 @@
<button
type="submit"
class="border-2 border-black rounded-xl font-semibold mx-auto py-3 w-40 hover:opacity-80 mx-auto"
+ on:click={cancel}
>
<div class="my-auto">Cancel</div>
</button>
diff --git a/src/components/index.js b/src/components/index.js
index 90bc1e7e..b0802c25 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -1,3 +1,4 @@
+export { default as Password } from './Password.svelte';
export { default as Feed } from './Feed.svelte';
export { default as Invoice } from './Invoice.svelte';
export { default as Request } from './Request.svelte';
diff --git a/src/lib/nostr.js b/src/lib/nostr.js
new file mode 100644
index 00000000..df63d5d8
--- /dev/null
+++ b/src/lib/nostr.js
@@ -0,0 +1,30 @@
+import { entropyToMnemonic, mnemonicToSeedSync } from 'bip39';
+import { Buffer } from 'buffer';
+import { bech32m } from 'bech32';
+import { bip32, post, stretch } from '$lib/utils';
+import { calculateId, signId } from 'nostr';
+
+const { decode, fromWords } = bech32m;
+
+export let send = async (event, { cipher, username, salt }, password) => {
+ let mnemonic, key, seed, entropy, child, privkey;
+ entropy = Buffer.from(
+ await crypto.subtle.decrypt(
+ { name: 'AES-GCM', iv: new Uint8Array(16) },
+ await stretch(password, Buffer.from(salt, 'hex')),
+ Uint8Array.from(fromWords(decode(cipher, 180).words))
+ ),
+ 'hex'
+ ).toString('hex');
+
+ mnemonic = entropyToMnemonic(entropy);
+ seed = mnemonicToSeedSync(mnemonic);
+ key = bip32.fromSeed(seed);
+ child = key.derivePath("m/44'/1237'/0'/0/0");
+ privkey = child.privateKey;
+
+ event.id = await calculateId(event);
+ event.sig = await signId(privkey, event.id);
+
+ await post(`/${username}`, { event });
+};
diff --git a/src/lib/store.js b/src/lib/store.js
index 1a1a88c2..9660bf55 100644
--- a/src/lib/store.js
+++ b/src/lib/store.js
@@ -56,3 +56,4 @@ export const invoice = writable();
export const txns = persistLocal('transactions', []);
export const events = writable({});
export const password = writable();
+export const passwordPrompt = writable();
diff --git a/src/lib/utils.js b/src/lib/utils.js
index 79509cc1..d4d78007 100644
--- a/src/lib/utils.js
+++ b/src/lib/utils.js
@@ -49,9 +49,10 @@ export const post = (url, body, headers) => {
try {
let { message } = JSON.parse(text);
if (message) return JSON.stringify({ name: 'Error', message });
- } catch (e) {}
+ } catch (e) {
+ }
- return text;
+ return { error: text };
})
.then((body) => {
try {
diff --git a/src/routes/(app)/[username]/generate/+page.svelte b/src/routes/(app)/[username]/generate/+page.svelte
index 559d0d14..330ccedb 100644
--- a/src/routes/(app)/[username]/generate/+page.svelte
+++ b/src/routes/(app)/[username]/generate/+page.svelte
@@ -7,7 +7,7 @@
import * as ecc from 'tiny-secp256k1';
import { bip32, stretch, post } from '$lib/utils';
import { goto, invalidate } from '$app/navigation';
- import { loginRedirect } from '$lib/store';
+ import { loginRedirect, password } from '$lib/store';
import { Pin } from '$comp';
import { pin } from '$lib/store';
@@ -16,7 +16,7 @@
const { encode, toWords } = bech32m;
- let loaded, mnemonic, key, password, seed, entropy, cipher, pubkey, salt, child;
+ let loaded, mnemonic, key, seed, entropy, cipher, pubkey, salt, child;
onMount(async () => {
setTimeout(() => (loaded = true), 50);
@@ -35,7 +35,7 @@
let bytes = new Uint8Array(
await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: new Uint8Array(16) },
- await stretch(password, salt),
+ await stretch($password, salt),
Uint8Array.from(Buffer.from(entropy, 'hex'))
)
);
diff --git a/src/routes/(app)/[username]/settings/[...tab]/+page.svelte b/src/routes/(app)/[username]/settings/[...tab]/+page.svelte
index d47ce0de..3b213a11 100644
--- a/src/routes/(app)/[username]/settings/[...tab]/+page.svelte
+++ b/src/routes/(app)/[username]/settings/[...tab]/+page.svelte
@@ -28,10 +28,10 @@
$: form?.success && success('Settings saved!');
- // $: if (form?.message?.startsWith('Pin')) {
- // failure('Wrong pin, try again');
- // $pin = '';
- // }
+ $: if (form?.message?.startsWith('Pin')) {
+ failure('Wrong pin, try again');
+ $pin = '';
+ }
let tabs = [
{ name: 'account', key: 'ACCOUNT', comp: Account },
diff --git a/src/routes/(app)/login/+server.js b/src/routes/(app)/login/+server.js
new file mode 100644
index 00000000..e08356a0
--- /dev/null
+++ b/src/routes/(app)/login/+server.js
@@ -0,0 +1,6 @@
+import { json } from "@sveltejs/kit";
+import { post } from "$lib/utils";
+
+export async function POST({ request }) {
+ return json(await post('/checkPassword', await request.json()));
+}
diff --git a/src/routes/(app)/password/+server.js b/src/routes/(app)/password/+server.js
new file mode 100644
index 00000000..ed9b4dbb
--- /dev/null
+++ b/src/routes/(app)/password/+server.js
@@ -0,0 +1,8 @@
+import { json } from '@sveltejs/kit';
+import { auth, post } from '$lib/utils';
+
+export async function POST({ cookies, request }) {
+ let result = await post('/checkPassword', await request.json(), auth(cookies));
+ return json(result);
+}
+