diff --git a/packages/renderer/src/Router.tsx b/packages/renderer/src/Router.tsx index 7cfa972..484a174 100644 --- a/packages/renderer/src/Router.tsx +++ b/packages/renderer/src/Router.tsx @@ -1,4 +1,4 @@ -import { useContext } from "react"; +import { useContext, useEffect } from "react"; import ServerConnection from "./components/ServerConnection"; import Sidebar from "./components/Sidebar"; import TwoPanel from "./components/TwoPanel"; @@ -21,13 +21,17 @@ export default function Router(props: RouterProps) { const { clientId } = useClientId(); const { sessionToken } = useSessionToken(); const { homeServer } = useHomeServer(); - const { isSettingsOpen } = useContext(SettingsContext); + const { isSettingsOpen, closeSettings } = useContext(SettingsContext); const configured = homeServer !== null && clientId !== null && sessionToken !== null; + useEffect(() => { + if(!configured) closeSettings(); + }, [configured]) + return ( configured ? ( diff --git a/packages/renderer/src/contexts/EphemeralState/EphemeralState.tsx b/packages/renderer/src/contexts/EphemeralState/EphemeralState.tsx index 922aa7a..d30e960 100644 --- a/packages/renderer/src/contexts/EphemeralState/EphemeralState.tsx +++ b/packages/renderer/src/contexts/EphemeralState/EphemeralState.tsx @@ -26,7 +26,7 @@ export default function EphemeralState(props: { const [channel, setChannel] = useState(null); const [transparent, setTransparent] = useState(false); - const [settings, setSettings] = useState(true); + const [settings, setSettings] = useState(false); const channelContextValue = useMemo(() => { return { channel, setChannel }; diff --git a/packages/renderer/src/pages/NewAccount.tsx b/packages/renderer/src/pages/NewAccount.tsx index 0d200e2..298a32a 100644 --- a/packages/renderer/src/pages/NewAccount.tsx +++ b/packages/renderer/src/pages/NewAccount.tsx @@ -11,6 +11,7 @@ import { AiOutlineEdit } from "react-icons/ai"; import { useApi } from "../lib/useApi"; import useSessionToken from "../hooks/useSessionToken"; import useClientId from "../hooks/useClientId"; +import QR from 'qrcode'; export default function NewAccount() { @@ -399,37 +400,119 @@ interface SignUpProps { function SignUp(props: SignUpProps) { const [usernameInput, setUsernameInput] = useState(''); + const [displayNameInput, setDisplayNameInput] = useState(''); const [authCodeInput, setAuthCodeInput] = useState(''); + const [tempClientId, setTempClientId] = useState(null); + const [qr, setQr] = useState(null); - const next = () => { + const { setClientId } = useClientId(); + const { setSessionToken } = useSessionToken(); - } + useEffect(() => { + send('totp:propose', { + clientId: tempClientId + }) + }, [tempClientId]) + + useEffect(() => { + setDisplayNameInput(usernameInput); + }, [usernameInput]) + + const { send } = useApi({ + 'client:new'({clientId}) { + setTempClientId(clientId) + }, + async 'totp:propose'(data: any) { + const { key } = data; + const totpUrl = + 'otpauth://totp/' + + (usernameInput ?? '') + + '?secret=' + + key + + '&issuer=xyz-valnet-corner'; + console.log(totpUrl); + setQr(await QR.toDataURL(totpUrl)); + }, + 'totp:confirm'(data: any) { + console.log(data); + const { sessionToken } = data; + setClientId(tempClientId); + setSessionToken(sessionToken); + console.log(sessionToken, tempClientId); + } + }, [usernameInput, tempClientId]); + + + + const next = useCallback(() => { + if(!tempClientId) { + send('client:new', { + displayName: displayNameInput, + username: usernameInput + }) + } else { + send('totp:confirm', { + clientId: tempClientId, + code: authCodeInput + }) + } + }, [tempClientId, displayNameInput, usernameInput, authCodeInput]); return ( <> - -
- -
- -
- -
+ {!tempClientId ? ( + <> + +
+ +
+ +
+ +
+ + ) : ( + <> + {qr && ( +
+ +

+
+ )} + +
+ +
+ + )} {!props.disabled && } ) diff --git a/packages/server/src/routers/client.ts b/packages/server/src/routers/client.ts index 4a941f1..36e71b7 100644 --- a/packages/server/src/routers/client.ts +++ b/packages/server/src/routers/client.ts @@ -14,7 +14,9 @@ export default router({ data.username, ); if(response === null) return; - return reply(response[0][0].uid); + return reply({ + clientId: response[0][0].uid + }); }, async 'get'(data: any) { const response = await query(_get, data.clientId); diff --git a/packages/server/src/routers/totp.ts b/packages/server/src/routers/totp.ts index 20cf31d..bacb4a7 100644 --- a/packages/server/src/routers/totp.ts +++ b/packages/server/src/routers/totp.ts @@ -9,16 +9,16 @@ import { generateTotpKey } from "../lib/generateTotpKey"; const proposals: any = {} export default router({ - 'propose'(clientId: string) { + 'propose'(data: any) { + const { clientId } = data; + if(!clientId) return; if(clientId in proposals) return reply(proposals[clientId]); const key = generateTotpKey(); proposals[clientId] = key; - console.log(clientId, proposals) setTimeout(() => { delete proposals[clientId]; }, 5 * 60 * 1000); - console.log('created totp proposal'); - return reply(key) + return reply({ key }); }, async 'confirm'(data: any) { const { clientId, code } = data; @@ -34,8 +34,9 @@ export default router({ err: 'unknown database error, contact server admin.' }); + delete proposals[clientId]; return reply({ - token: await generateSessionToken(clientId), + sessionToken: await generateSessionToken(clientId), err: null }); }