From 3f98843067a045c263fecac3739ea566192637f0 Mon Sep 17 00:00:00 2001 From: esaminu Date: Tue, 31 Oct 2023 01:22:26 +0400 Subject: [PATCH 1/4] fix: throw if no account exists --- src/components/AddDevice/AddDevice.tsx | 11 ++++++++++- src/components/AuthCallback/AuthCallback.tsx | 3 +++ src/components/CreateAccount/CreateAccount.tsx | 7 ++++++- src/components/VerifyEmail/verify-email.tsx | 5 +++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/components/AddDevice/AddDevice.tsx b/src/components/AddDevice/AddDevice.tsx index 887296a9..11fb859a 100644 --- a/src/components/AddDevice/AddDevice.tsx +++ b/src/components/AddDevice/AddDevice.tsx @@ -1,6 +1,6 @@ import { createKey, isPassKeyAvailable } from '@near-js/biometric-ed25519/lib'; import BN from 'bn.js'; -import { sendSignInLinkToEmail } from 'firebase/auth'; +import { fetchSignInMethodsForEmail, sendSignInLinkToEmail } from 'firebase/auth'; import React, { useCallback, useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { useNavigate, useSearchParams } from 'react-router-dom'; @@ -138,6 +138,10 @@ function SignInPage() { const methodNames = searchParams.get('methodNames'); try { + const result = await fetchSignInMethodsForEmail(firebaseAuth, data.email); + if (!result.length) { + throw new Error('Account not found, please create an account and try again'); + } const { publicKey: publicKeyFak, email, privateKey } = await handleCreateAccount({ accountId: null, email: data.email, @@ -162,6 +166,11 @@ function SignInPage() { navigate(`/verify-email?${newSearchParams.toString()}#${hashParams.toString()}`); } catch (error: any) { console.log(error); + const { message } = error; + const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); + parsedUrl.searchParams.set('code', error.code); + parsedUrl.searchParams.set('reason', message); + window.location.replace(parsedUrl.href); if (typeof error?.message === 'string') { openToast({ diff --git a/src/components/AuthCallback/AuthCallback.tsx b/src/components/AuthCallback/AuthCallback.tsx index 7ce86c29..c0cfadef 100644 --- a/src/components/AuthCallback/AuthCallback.tsx +++ b/src/components/AuthCallback/AuthCallback.tsx @@ -135,6 +135,9 @@ export const onSignIn = async ({ throw new Error('Unable to retrieve account Id'); }); + if (!accountIds.length) { + throw new Error('Account not found, please create an account and try again'); + } // TODO: If we want to remove old LAK automatically, use below code and add deleteKeyActions to signAndSendActionsWithRecoveryKey // const existingDevice = await window.firestoreController.getDeviceCollection(publicKeyFak); // // delete old lak key attached to webAuthN public Key diff --git a/src/components/CreateAccount/CreateAccount.tsx b/src/components/CreateAccount/CreateAccount.tsx index 1dfaeae0..aa9f4db6 100644 --- a/src/components/CreateAccount/CreateAccount.tsx +++ b/src/components/CreateAccount/CreateAccount.tsx @@ -12,7 +12,7 @@ import InputContainer from './styles/InputContainer'; import { Button } from '../../lib/Button'; import { openToast } from '../../lib/Toast'; import { inIframe } from '../../utils'; -import { network } from '../../utils/config'; +import { basePath, network } from '../../utils/config'; import { accountAddressPatternNoSubaccount, emailPattern, getEmailId, isValidEmail } from '../../utils/form-validation'; @@ -87,6 +87,11 @@ function CreateAccount() { navigate(`/verify-email?${newSearchParams.toString()}#${hashParams.toString()}`); } catch (error: any) { console.log('error', error); + const { message } = error; + const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); + parsedUrl.searchParams.set('code', error.code); + parsedUrl.searchParams.set('reason', message); + window.location.replace(parsedUrl.href); // currently running handleCreateAccount() will throw an error as: // error DOMException: The following credential operations can only occur in a document which is same-origin with all of its ancestors: storage/retrieval of 'PasswordCredential' and 'FederatedCredential', storage of 'PublicKeyCredential'. diff --git a/src/components/VerifyEmail/verify-email.tsx b/src/components/VerifyEmail/verify-email.tsx index 9a2ce0d5..7133e406 100644 --- a/src/components/VerifyEmail/verify-email.tsx +++ b/src/components/VerifyEmail/verify-email.tsx @@ -112,6 +112,11 @@ function VerifyEmailPage() { }); } catch (error: any) { console.log(error); + const { message } = error; + const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); + parsedUrl.searchParams.set('code', error.code); + parsedUrl.searchParams.set('reason', message); + window.location.replace(parsedUrl.href); if (typeof error?.message === 'string') { openToast({ From b5f23e8a382cc891851e501ebffe3830920062ae Mon Sep 17 00:00:00 2001 From: esaminu Date: Wed, 1 Nov 2023 01:03:08 +0400 Subject: [PATCH 2/4] refactor: redirectWithError function --- src/components/AddDevice/AddDevice.tsx | 16 ++++------------ src/components/AuthCallback/AuthCallback.tsx | 10 +++------- src/components/CreateAccount/CreateAccount.tsx | 8 ++------ src/components/Sign/Sign.tsx | 5 ++--- src/utils/index.ts | 13 +++++++++++++ 5 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/components/AddDevice/AddDevice.tsx b/src/components/AddDevice/AddDevice.tsx index 11fb859a..a5b66a1b 100644 --- a/src/components/AddDevice/AddDevice.tsx +++ b/src/components/AddDevice/AddDevice.tsx @@ -10,7 +10,7 @@ import { Button } from '../../lib/Button'; import FirestoreController from '../../lib/firestoreController'; import { openToast } from '../../lib/Toast'; import { useAuthState } from '../../lib/useAuthState'; -import { decodeIfTruthy, inIframe } from '../../utils'; +import { decodeIfTruthy, inIframe, redirectWithError } from '../../utils'; import { basePath } from '../../utils/config'; import { checkFirestoreReady, firebaseAuth } from '../../utils/firebase'; import { isValidEmail } from '../../utils/form-validation'; @@ -166,11 +166,7 @@ function SignInPage() { navigate(`/verify-email?${newSearchParams.toString()}#${hashParams.toString()}`); } catch (error: any) { console.log(error); - const { message } = error; - const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); - parsedUrl.searchParams.set('code', error.code); - parsedUrl.searchParams.set('reason', message); - window.location.replace(parsedUrl.href); + redirectWithError({ success_url, failure_url, error }); if (typeof error?.message === 'string') { openToast({ @@ -274,14 +270,10 @@ function SignInPage() { }); }).catch((error) => { console.log('error', error); - const { message } = error; - const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); - parsedUrl.searchParams.set('code', error.code); - parsedUrl.searchParams.set('reason', message); - window.location.replace(parsedUrl.href); + redirectWithError({ success_url, failure_url, error }); openToast({ type: 'ERROR', - title: message, + title: error.message, }); }); } else if (email && !authenticated) { diff --git a/src/components/AuthCallback/AuthCallback.tsx b/src/components/AuthCallback/AuthCallback.tsx index c0cfadef..98726089 100644 --- a/src/components/AuthCallback/AuthCallback.tsx +++ b/src/components/AuthCallback/AuthCallback.tsx @@ -9,7 +9,7 @@ import styled from 'styled-components'; import FastAuthController from '../../lib/controller'; import FirestoreController from '../../lib/firestoreController'; import { openToast } from '../../lib/Toast'; -import { decodeIfTruthy, inIframe } from '../../utils'; +import { decodeIfTruthy, inIframe, redirectWithError } from '../../utils'; import { basePath, network, networkId } from '../../utils/config'; import { checkFirestoreReady, firebaseAuth } from '../../utils/firebase'; import { @@ -286,14 +286,10 @@ function AuthCallbackPage() { } }).catch((e) => { console.log('error:', e); - const { message } = e; - const parsedUrl = new URL(failure_url || success_url || window.location.origin); - parsedUrl.searchParams.set('code', e.code); - parsedUrl.searchParams.set('reason', message); - window.location.replace(parsedUrl.href); + redirectWithError({ success_url, failure_url, error: e }); openToast({ type: 'ERROR', - title: message, + title: e.message, }); }); } else { diff --git a/src/components/CreateAccount/CreateAccount.tsx b/src/components/CreateAccount/CreateAccount.tsx index aa9f4db6..36f1cf8e 100644 --- a/src/components/CreateAccount/CreateAccount.tsx +++ b/src/components/CreateAccount/CreateAccount.tsx @@ -11,7 +11,7 @@ import FormContainer from './styles/FormContainer'; import InputContainer from './styles/InputContainer'; import { Button } from '../../lib/Button'; import { openToast } from '../../lib/Toast'; -import { inIframe } from '../../utils'; +import { inIframe, redirectWithError } from '../../utils'; import { basePath, network } from '../../utils/config'; import { accountAddressPatternNoSubaccount, emailPattern, getEmailId, isValidEmail @@ -87,11 +87,7 @@ function CreateAccount() { navigate(`/verify-email?${newSearchParams.toString()}#${hashParams.toString()}`); } catch (error: any) { console.log('error', error); - const { message } = error; - const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); - parsedUrl.searchParams.set('code', error.code); - parsedUrl.searchParams.set('reason', message); - window.location.replace(parsedUrl.href); + redirectWithError({ success_url, failure_url, error }); // currently running handleCreateAccount() will throw an error as: // error DOMException: The following credential operations can only occur in a document which is same-origin with all of its ancestors: storage/retrieval of 'PasswordCredential' and 'FederatedCredential', storage of 'PublicKeyCredential'. diff --git a/src/components/Sign/Sign.tsx b/src/components/Sign/Sign.tsx index 9151781c..48050092 100644 --- a/src/components/Sign/Sign.tsx +++ b/src/components/Sign/Sign.tsx @@ -17,6 +17,7 @@ import { Button } from '../../lib/Button'; import { useAuthState } from '../../lib/useAuthState'; import { basePath, network } from '../../utils/config'; import TableContent from '../TableContent/TableContent'; +import { redirectWithError } from '../../utils'; const formatActionType = (action: string) => { switch (action) { @@ -181,9 +182,7 @@ function Sign() { signedTransactions.push(base64); } catch (err) { const failure_url = searchParams.get('failure_url'); - const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); - parsedUrl.searchParams.set('message', err); - window.location.replace(parsedUrl.href); + redirectWithError({ success_url, failure_url, error: err }); window.parent.postMessage({ signedDelegates: '', error: err.message }, '*'); return; } diff --git a/src/utils/index.ts b/src/utils/index.ts index bc89746b..3b58720d 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,3 +1,5 @@ +import { basePath } from "./config"; + /* eslint-disable import/prefer-default-export */ export function inIframe() { try { @@ -14,3 +16,14 @@ export const decodeIfTruthy = (paramVal) => { return paramVal; }; + +export const redirectWithError = ({ + failure_url, + success_url, + error +}: { failure_url: string; success_url: string; error: Error }): void => { + const { message } = error; + const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); + parsedUrl.searchParams.set('reason', message); + window.location.replace(parsedUrl.href); +}; From db25fc968549738453f17fec003959174fb3d75d Mon Sep 17 00:00:00 2001 From: esaminu Date: Wed, 1 Nov 2023 01:07:28 +0400 Subject: [PATCH 3/4] refactor: redirectWIthError --- src/components/VerifyEmail/verify-email.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/VerifyEmail/verify-email.tsx b/src/components/VerifyEmail/verify-email.tsx index 7133e406..d25aa031 100644 --- a/src/components/VerifyEmail/verify-email.tsx +++ b/src/components/VerifyEmail/verify-email.tsx @@ -8,6 +8,7 @@ import { Button } from '../../lib/Button'; import { openToast } from '../../lib/Toast'; import { basePath } from '../../utils/config'; import { firebaseAuth } from '../../utils/firebase'; +import { redirectWithError } from '../../utils'; const StyledContainer = styled.div` width: 100%; @@ -112,11 +113,7 @@ function VerifyEmailPage() { }); } catch (error: any) { console.log(error); - const { message } = error; - const parsedUrl = new URL(failure_url || success_url || window.location.origin + (basePath ? `/${basePath}` : '')); - parsedUrl.searchParams.set('code', error.code); - parsedUrl.searchParams.set('reason', message); - window.location.replace(parsedUrl.href); + redirectWithError({ success_url, failure_url, error }); if (typeof error?.message === 'string') { openToast({ From 4f519d4d913e91be9e0dd1b0ecf90a611304cbe2 Mon Sep 17 00:00:00 2001 From: esaminu Date: Wed, 1 Nov 2023 01:09:21 +0400 Subject: [PATCH 4/4] fix: lint --- src/components/CreateAccount/CreateAccount.tsx | 2 +- src/components/Sign/Sign.tsx | 2 +- src/components/VerifyEmail/verify-email.tsx | 2 +- src/utils/index.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/CreateAccount/CreateAccount.tsx b/src/components/CreateAccount/CreateAccount.tsx index 36f1cf8e..7b251325 100644 --- a/src/components/CreateAccount/CreateAccount.tsx +++ b/src/components/CreateAccount/CreateAccount.tsx @@ -12,7 +12,7 @@ import InputContainer from './styles/InputContainer'; import { Button } from '../../lib/Button'; import { openToast } from '../../lib/Toast'; import { inIframe, redirectWithError } from '../../utils'; -import { basePath, network } from '../../utils/config'; +import { network } from '../../utils/config'; import { accountAddressPatternNoSubaccount, emailPattern, getEmailId, isValidEmail } from '../../utils/form-validation'; diff --git a/src/components/Sign/Sign.tsx b/src/components/Sign/Sign.tsx index 48050092..8da6da1d 100644 --- a/src/components/Sign/Sign.tsx +++ b/src/components/Sign/Sign.tsx @@ -15,9 +15,9 @@ import ArrowUpSvg from '../../Images/arrow-up'; import InternetSvg from '../../Images/Internet'; import { Button } from '../../lib/Button'; import { useAuthState } from '../../lib/useAuthState'; +import { redirectWithError } from '../../utils'; import { basePath, network } from '../../utils/config'; import TableContent from '../TableContent/TableContent'; -import { redirectWithError } from '../../utils'; const formatActionType = (action: string) => { switch (action) { diff --git a/src/components/VerifyEmail/verify-email.tsx b/src/components/VerifyEmail/verify-email.tsx index d25aa031..bad6939d 100644 --- a/src/components/VerifyEmail/verify-email.tsx +++ b/src/components/VerifyEmail/verify-email.tsx @@ -6,9 +6,9 @@ import styled from 'styled-components'; import EmailSvg from './icons/EmailSvg'; import { Button } from '../../lib/Button'; import { openToast } from '../../lib/Toast'; +import { redirectWithError } from '../../utils'; import { basePath } from '../../utils/config'; import { firebaseAuth } from '../../utils/firebase'; -import { redirectWithError } from '../../utils'; const StyledContainer = styled.div` width: 100%; diff --git a/src/utils/index.ts b/src/utils/index.ts index 3b58720d..abfe93e1 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,4 @@ -import { basePath } from "./config"; +import { basePath } from './config'; /* eslint-disable import/prefer-default-export */ export function inIframe() {