From 4d2b9b490f4bc78b82399d7342d9daff529863ac Mon Sep 17 00:00:00 2001 From: balzack Date: Mon, 12 Aug 2024 15:03:08 +0200 Subject: [PATCH] adding otp support --- app/client/web/src/access/Access.module.css | 23 ++++++++ app/client/web/src/access/Access.tsx | 53 +++++++++++++++---- app/client/web/src/access/useAccess.hook.ts | 20 ++++++- .../web/src/context/useAppContext.hook.ts | 4 +- 4 files changed, 87 insertions(+), 13 deletions(-) diff --git a/app/client/web/src/access/Access.module.css b/app/client/web/src/access/Access.module.css index 8993b27a..569e6f96 100644 --- a/app/client/web/src/access/Access.module.css +++ b/app/client/web/src/access/Access.module.css @@ -1,3 +1,26 @@ +.mfa { + display: flex; + flex-direction: column; + align-items: center; + + .mfaTitle { + font-size: 1.5rem; + } + + .mfaPin { + padding: 32px; + } + + .mfaDescription { + font-size: 1.1rem; + } + + .mfaControl { + display: flex; + gap: 8px; + } +} + .split { display: flex; height: 100%; diff --git a/app/client/web/src/access/Access.tsx b/app/client/web/src/access/Access.tsx index 039dbe20..77cfbf8f 100644 --- a/app/client/web/src/access/Access.tsx +++ b/app/client/web/src/access/Access.tsx @@ -10,6 +10,7 @@ import { Modal, PasswordInput, TextInput, + PinInput, } from '@mantine/core' import { useDisclosure } from '@mantine/hooks' import left from '../images/login.png' @@ -26,13 +27,20 @@ export function Access() { const [alertOpened, { open: alertOpen, close: alertClose }] = useDisclosure(false) const [urlOpened, { open: urlOpen, close: urlClose }] = useDisclosure(false) + const [otpOpened, { open: otpOpen, close: otpClose }] = useDisclosure(false) const login = async () => { - try { - await actions.accountLogin() - } catch (err) { - console.log(err) - alertOpen() + if (!state.loading) { + actions.setLoading(true) + otpClose() + try { + await new Promise((r) => setTimeout(r, 2000)) + await actions.accountLogin() + } catch (err) { + console.log(err) + alertOpen() + } + actions.setLoading(false) } } @@ -104,6 +112,7 @@ export function Access() { variant="filled" className={classes.submit} onClick={login} + loading={state.loading} disabled={!state.username || !state.password} > {state.strings.login} @@ -118,13 +127,13 @@ export function Access() { )} - {state.mode === 'access' && ( + {state.mode === 'reset' && ( <> {state.strings.accessAccount} @@ -138,9 +147,10 @@ export function Access() { } - placeholder={state.strings.accessCode} + placeholder={state.strings.resetCode} onChange={(event) => actions.setToken(event.currentTarget.value) } @@ -173,10 +183,11 @@ export function Access() { } - placeholder={state.strings.accessCode} + placeholder={state.strings.resetCode} onChange={(event) => actions.setToken(event.currentTarget.value) } @@ -292,6 +303,30 @@ export function Access() { > {state.strings.tryAgain} + +
+
{state.strings.mfaTitle}
+
{state.strings.mfaEnter}
+ actions.setCode(event.currentTarget.value)} + /> +
+ + +
+
+
) } diff --git a/app/client/web/src/access/useAccess.hook.ts b/app/client/web/src/access/useAccess.hook.ts index 10265d89..5433193c 100644 --- a/app/client/web/src/access/useAccess.hook.ts +++ b/app/client/web/src/access/useAccess.hook.ts @@ -10,14 +10,16 @@ export function useAccess() { const [state, setState] = useState({ display: null, strings: settings.state.strings, - mode: 'login', + mode: '', username: '', password: '', confirm: '', token: '', + code: '', theme: '', language: '', node: '', + loading: false, secure: false, host: '', available: 0, @@ -32,6 +34,16 @@ export function useAccess() { } useEffect(() => { + const params = new URLSearchParams(location) + const search = params.get('search') + if (search && search.startsWith('?create=')) { + updateState({ mode: 'create', token: search.substring(8) }) + } else if (search && search.startsWith('?reset=')) { + updateState({ mode: 'reset', token: search.substring(7) }) + } else { + updateState({ mode: 'login' }) + } + const { protocol, host } = location setUrl(`${protocol}//${host}`) }, []) @@ -92,6 +104,9 @@ export function useAccess() { setToken: (token: string) => { updateState({ token }) }, + setCode: (code: string) => { + updateState({ code }) + }, setNode: (node: string) => { setUrl(node) }, @@ -101,6 +116,9 @@ export function useAccess() { setTheme: (theme: string) => { settings.actions.setTheme(theme) }, + setLoading: (loading: boolean) => { + updateState({ loading }) + }, accountLogin: async () => { const { username, password, host, secure } = state await app.actions.accountLogin(username, password, host, secure) diff --git a/app/client/web/src/context/useAppContext.hook.ts b/app/client/web/src/context/useAppContext.hook.ts index 086984b5..c1f029e3 100644 --- a/app/client/web/src/context/useAppContext.hook.ts +++ b/app/client/web/src/context/useAppContext.hook.ts @@ -32,8 +32,6 @@ export function useAppContext() { node: string, secure: boolean ) => { - console.log('LOGIN:', username, password, node, secure) - const params = { topicBatch: 16, tagBatch: 16, @@ -50,7 +48,7 @@ export function useAppContext() { password, node, secure, - null, + code, params ) updateState({ session: login })