aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2022-08-31 13:50:03 -0700
committerAdam Soltys <[email protected]>2022-08-31 13:50:03 -0700
commitbd1e9ee212541c8f6236bea6256cad082b2ea35a (patch)
tree023bb3b21046add5fe231724aa178ad285d942fe
parentfe2e2b7760d82ba25676cd96035379c6570b7cb0 (diff)
downloadcoinos-ui-bd1e9ee212541c8f6236bea6256cad082b2ea35a.tar.gz
coinos-ui-bd1e9ee212541c8f6236bea6256cad082b2ea35a.zip
hook up 2fa setting
-rw-r--r--src/components/Qr.svelte53
-rw-r--r--src/components/index.js1
-rw-r--r--src/locales/en.json6
-rw-r--r--src/locales/fr.json1
-rw-r--r--src/routes/[username]/dashboard/+page.svelte2
-rw-r--r--src/routes/[username]/settings/+page.svelte2
-rw-r--r--src/routes/[username]/settings/_security.svelte101
-rw-r--r--src/routes/disable2fa/+server.js8
-rw-r--r--src/routes/enable2fa/+server.js8
9 files changed, 160 insertions, 22 deletions
diff --git a/src/components/Qr.svelte b/src/components/Qr.svelte
new file mode 100644
index 00000000..fcdc6c7d
--- /dev/null
+++ b/src/components/Qr.svelte
@@ -0,0 +1,53 @@
+<script>
+ import { browser } from "$app/env";
+ import { onMount } from 'svelte';
+ import { copy } from '$lib/utils';
+
+ export let image, text;
+
+ let qr;
+
+ onMount(async () => {
+ if (!(browser && text)) return;
+ let { default: QRCodeStyling } = await import('qr-code-styling');
+
+ const qrCode = new QRCodeStyling({
+ width: window.screen.width < 640 ? 250 : 300,
+ type: 'canvas',
+ data: text,
+ backgroundOptions: {
+ color: 'rgba(0, 0, 0, 0)'
+ },
+ dotsOptions: {
+ type: 'rounded'
+ },
+ imageOptions: {
+ hideBackgroundDots: false
+ }
+ });
+
+ while (qr.firstChild) qr.removeChild(qr.lastChild);
+ qrCode.append(qr);
+ });
+</script>
+
+<div bind:this={qr} on:click={() => copy(text)} />
+
+<style>
+ div {
+ @apply
+ px-5
+ md:px-0
+ w-[292px]
+ h-[302px]
+ md:w-[300px]
+ md:h-[300px]
+ rounded-3xl
+ block
+ md:flex
+ justify-center
+ items-center
+ cursor-pointer
+ mx-auto;
+ }
+</style>
diff --git a/src/components/index.js b/src/components/index.js
index eed5d3f3..969e2107 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -14,3 +14,4 @@ export { default as About } from './About.svelte';
export { default as Footer } from './Footer.svelte';
export { default as Toggle } from './Toggle.svelte';
export { default as LocationsMap } from './LocationsMap.svelte';
+export { default as Qr } from './Qr.svelte';
diff --git a/src/locales/en.json b/src/locales/en.json
index 3dae530c..d246377d 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -127,7 +127,6 @@
"support": "Support"
},
"user": {
- "addressGoesHere": "Address goes here",
"follow": "Follow",
"remove": "Remove",
"scanToPayBTC": "Scan to pay with bitcoin",
@@ -146,6 +145,8 @@
"showQR": "Show QR"
},
"settings": {
+ "oneTimeCode": "Enter one-time code to enable",
+ "accountId": "Account ID",
"header": "Settings",
"ACCOUNT": "ACCOUNT",
"POINT_OF_SALE": "POINT OF SALE",
@@ -172,7 +173,8 @@
"autoLockDescription": "Your account will go into a secure mode automatically after a specified time:",
"twofa": "2-Factor Authentication",
"twofaDescription": "Add an extra level of security to your device by enableing 2-factor authentication.",
- "twofaSetup": "Set up 2FA"
+ "twofaSetup": "Set up 2FA",
+ "twofaDisable": "Disable 2FA"
},
"support": {
"header": "Support",
diff --git a/src/locales/fr.json b/src/locales/fr.json
index e97ca264..ffa8a1f5 100644
--- a/src/locales/fr.json
+++ b/src/locales/fr.json
@@ -127,7 +127,6 @@
"pitch3": "Si vous pensez que vous pouvez exercer une influence positive, nous voulons que vous contribuez. Envoyer votre CV à"
},
"user": {
- "addressGoesHere": "Addresse ici",
"follow": "Suivre",
"remove": "Enlève",
"scanToPayBTC": "Scanner pour payer avec Bitcoin",
diff --git a/src/routes/[username]/dashboard/+page.svelte b/src/routes/[username]/dashboard/+page.svelte
index 969717df..bd5f2bba 100644
--- a/src/routes/[username]/dashboard/+page.svelte
+++ b/src/routes/[username]/dashboard/+page.svelte
@@ -48,7 +48,7 @@
<div class="text-center mx-auto lg:text-left lg:mx-0 lg:ml-[calc(15vw-48px)] mt-12 w-full md:w-72">
<h2 class="text-2xl font-semibold">{user.username}</h2>
- <span class="text-secondary">{$t('user.addressGoesHere')}</span>
+ <span class="text-secondary">{user.address}</span>
</div>
<div class="px-3 md:px-0 flex justify-center items-center mt-10 lg:mt-0 mb-20">
diff --git a/src/routes/[username]/settings/+page.svelte b/src/routes/[username]/settings/+page.svelte
index aa19c68f..8270ad51 100644
--- a/src/routes/[username]/settings/+page.svelte
+++ b/src/routes/[username]/settings/+page.svelte
@@ -30,7 +30,7 @@
<AppHeader />
-<form on:submit|preventDefault={save}>
+<form on:submit|preventDefault={save} class="mb-20">
<div class="my-20 px-3 md:px-0 w-full md:w-[400px] mx-auto space-y-8">
<h1 class="text-center text-3xl md:text-4xl font-semibold mb-10">
{$t('user.settings.header')}
diff --git a/src/routes/[username]/settings/_security.svelte b/src/routes/[username]/settings/_security.svelte
index 65f73a10..dd184fe4 100644
--- a/src/routes/[username]/settings/_security.svelte
+++ b/src/routes/[username]/settings/_security.svelte
@@ -1,18 +1,52 @@
<script>
- import { tick } from "svelte";
+ import { tick } from 'svelte';
import { t } from '$lib/translations';
- import { Icon } from '$comp';
+ import { Icon, Qr } from '$comp';
import { Pincode, PincodeInput } from 'svelte-pincode';
import { user } from '$lib/store';
+ import { put, success, failure } from '$lib/utils';
+
+ let settingPin, setting2fa, disabling2fa;
- let settingPin, setting2fa;
- let togglePin = () => (settingPin = !settingPin);
- let toggle2fa = () => (setting2fa = !setting2fa);
let code = [];
let pin = '';
- let pinInput;
+ let token = '';
+ let tokenInput, pinInput;
+
+ $: if (settingPin) pinInput && tick().then(pinInput.focusFirstInput);
+ $: if (setting2fa) tokenInput && tick().then(tokenInput.focusFirstInput);
+
+ let togglePin = () => (settingPin = !settingPin);
+ let toggleEnabling = () => (setting2fa = !setting2fa);
+ let toggleDisabling = () => (disabling2fa = !disabling2fa);
- $: if (settingPin) pinInput && tick().then(pinInput.focusFirstInput)
+ $: enable2fa(token);
+ let enable2fa = async (twoFa) => {
+ try {
+ if (setting2fa && token.length === 6) {
+ await put('/enable2fa', { token });
+ success('2fa enabled');
+ $user.twofa = 1;
+ toggleEnabling();
+ }
+ } catch (e) {
+ failure('Failed to enable 2fa, try again');
+ }
+ };
+
+ $: disable2fa(token);
+ let disable2fa = async () => {
+ try {
+ if (disabling2fa && token.length === 6) {
+ await put('/disable2fa', { token });
+ success('2fa disabled');
+ $user.twofa = 0;
+ toggleDisabling();
+ }
+ } catch (e) {
+ failure('Failed to disable 2fa, try again');
+ }
+ };
</script>
<div>
@@ -23,8 +57,8 @@
{#if settingPin}
<div class="flex my-4">
<div class="mx-auto">
- <Pincode bind:code bind:value={$user.pin} bind:this={pinInput}>
- <PincodeInput />
+ <Pincode bind:code bind:value={$user.pin} bind:this={pinInput}>
+ <PincodeInput />
<PincodeInput />
<PincodeInput />
<PincodeInput />
@@ -55,16 +89,49 @@
</div>
{#if setting2fa}
- QR
+ <Qr text={$user.otpsecret} />
+
+ <div class="text-center my-4">
+ {$t('user.settings.accountId')}<br />
+ <b>{$user.otpsecret}</b>
+ </div>
+ <div class="text-center my-4">
+ {$t('user.settings.oneTimeCode')}<br />
+ <Pincode bind:code bind:value={token} bind:this={tokenInput}>
+ <PincodeInput />
+ <PincodeInput />
+ <PincodeInput />
+ <PincodeInput />
+ <PincodeInput />
+ <PincodeInput />
+ </Pincode>
+ </div>
+{:else if disabling2fa}
+ <div class="text-center my-4">
+ {$t('user.settings.oneTimeCode')}<br />
+ <Pincode bind:code bind:value={token} bind:this={tokenInput}>
+ <PincodeInput />
+ <PincodeInput />
+ <PincodeInput />
+ <PincodeInput />
+ <PincodeInput />
+ <PincodeInput />
+ </Pincode>
+ </div>
{:else}
- <div>
- <span class="font-bold mb-1">{$t('user.settings.twofa')}</span>
- <p class="text-secondary mb-1">
- {$t('user.settings.twofaDescription')}
- </p>
- <button type="button" class="primary">
+ <span class="font-bold mb-1">{$t('user.settings.twofa')}</span>
+ <p class="text-secondary mb-1">
+ {$t('user.settings.twofaDescription')}
+ </p>
+ {#if $user.twofa}
+ <button type="button" class="primary" on:click={toggleDisabling}>
+ <Icon icon="mobile" style="mr-1" />
+ {$t('user.settings.twofaDisable')}
+ </button>
+ {:else}
+ <button type="button" class="primary" on:click={toggleEnabling}>
<Icon icon="mobile" style="mr-1" />
{$t('user.settings.twofaSetup')}
</button>
- </div>
+ {/if}
{/if}
diff --git a/src/routes/disable2fa/+server.js b/src/routes/disable2fa/+server.js
new file mode 100644
index 00000000..98063773
--- /dev/null
+++ b/src/routes/disable2fa/+server.js
@@ -0,0 +1,8 @@
+import { auth, post } from '$lib/utils';
+
+export async function PUT({ request }) {
+ let body = await request.json();
+ let res = await post('/disable2fa', body, auth(request));
+
+ return new Response(JSON.stringify(res));
+}
diff --git a/src/routes/enable2fa/+server.js b/src/routes/enable2fa/+server.js
new file mode 100644
index 00000000..7bee4f4b
--- /dev/null
+++ b/src/routes/enable2fa/+server.js
@@ -0,0 +1,8 @@
+import { auth, post } from '$lib/utils';
+
+export async function PUT({ request }) {
+ let body = await request.json();
+ let res = await post('/2fa', body, auth(request));
+
+ return new Response(JSON.stringify(res));
+}