Skip to content

Commit

Permalink
Confirm Email
Browse files Browse the repository at this point in the history
  • Loading branch information
joepio committed Dec 27, 2022
1 parent 5711e37 commit f0baa94
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 67 deletions.
11 changes: 11 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@
"isBackground": true,
"group": "build"
},
{
"type": "npm",
"script": "build-server",
"problemMatcher": [
"$tsc-watch"
],
"label": "build server JS assets",
"detail": "pnpm workspace @tomic/data-browser build-server",
"isBackground": true,
"group": "build"
},
{
"type": "npm",
"script": "test",
Expand Down
1 change: 1 addition & 0 deletions data-browser/src/components/Dialog/useDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const useDialog = (): UseDialogReturnType => {
}, []);

const close = useCallback(() => {
console.log('close', close);
setShowDialog(false);
}, []);

Expand Down
8 changes: 7 additions & 1 deletion data-browser/src/components/ErrorLook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ export function ErrorBlock({ error, showTrace }: ErrorBlockProps): JSX.Element {
{showTrace && (
<>
Stack trace:
<CodeBlock>{error.stack}</CodeBlock>
<CodeBlock
style={{
maxHeight: '10rem',
}}
>
{error.stack}
</CodeBlock>
</>
)}
</Column>
Expand Down
54 changes: 15 additions & 39 deletions data-browser/src/components/RegisterSignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,11 @@ import {
import React, { FormEvent, useCallback, useEffect, useState } from 'react';
import { useSettings } from '../helpers/AppSettings';
import { Button } from './Button';
import {
Agent,
nameRegex,
register,
useServerURL,
useStore,
} from '@tomic/react';
import { nameRegex, register, useServerURL, useStore } from '@tomic/react';
import Field from './forms/Field';
import { InputWrapper, InputStyled } from './forms/InputStyles';
import { Row } from './Row';
import { ErrorLook } from './ErrorLook';
import { CodeBlock } from './CodeBlock';
import { SettingsAgent } from './SettingsAgent';

interface RegisterSignInProps {
Expand All @@ -34,9 +27,9 @@ interface RegisterSignInProps {
export function RegisterSignIn({
children,
}: React.PropsWithChildren<RegisterSignInProps>): JSX.Element {
const { dialogProps, show } = useDialog();
const { dialogProps, show, close } = useDialog();
const { agent } = useSettings();
const [isRegister, setRegister] = useState(true);
const [isRegistering, setRegister] = useState(true);

if (agent) {
return <>{children}</>;
Expand All @@ -63,23 +56,19 @@ export function RegisterSignIn({
</Button>
</Row>
<Dialog {...dialogProps}>
{isRegister ? <Register /> : <SignIn />}
{isRegistering ? <Register close={close} /> : <SignIn />}
</Dialog>
</>
);
}

function Register() {
function Register({ close }) {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [secret, setSecret] = useState('');
const [driveURL, setDriveURL] = useState('');
const [newAgent, setNewAgent] = useState<Agent | undefined>(undefined);
const [serverUrlStr] = useServerURL();
const [nameErr, setErr] = useState<Error | undefined>(undefined);
const doRegister = useCallback(register, []);
const { setAgent } = useSettings();
const store = useStore();
const [mailSent, setMailSent] = useState(false);

const serverUrl = new URL(serverUrlStr);
serverUrl.host = `${name}.${serverUrl.host}`;
Expand All @@ -104,44 +93,31 @@ function Register() {
}

try {
const { driveURL: newDriveURL, agent } = await doRegister(
store,
name,
email,
);
setDriveURL(newDriveURL);
setSecret(agent.buildSecret());
setNewAgent(agent);
await register(store, name, email);
setMailSent(true);
} catch (er) {
setErr(er);
}
},
[name, email],
);

const handleSaveAgent = useCallback(() => {
setAgent(newAgent);
}, [newAgent]);

if (driveURL) {
if (mailSent) {
return (
<>
<DialogTitle>
<h1>Save your Passphrase, {name}</h1>
<h1>Go to your email inbox</h1>
</DialogTitle>
<DialogContent>
<p>
Your Passphrase is like your password. Never share it with anyone.
Use a password manager to store it securely. You will need this to
log in next!
{"We've sent a confirmation link to "}
<strong>{email}</strong>
{'.'}
</p>
<CodeBlock content={secret} wrapContent />
<p>Your account will be created when you open that link.</p>
</DialogContent>
<DialogActions>
<Button onClick={handleSaveAgent}>Continue here</Button>
<a href={driveURL} target='_blank' rel='noreferrer'>
Open my new Drive!
</a>
<Button onClick={close}>Ok, I will!</Button>
</DialogActions>
</>
);
Expand Down
73 changes: 73 additions & 0 deletions data-browser/src/routes/ConfirmEmail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { confirmEmail, useStore } from '@tomic/react';
import * as React from 'react';
import { useState } from 'react';
import { CodeBlock } from '../components/CodeBlock';
import { ContainerNarrow } from '../components/Containers';
import { isDev } from '../config';
import { useSettings } from '../helpers/AppSettings';
import { handleError } from '../helpers/handlers';
import {
useCurrentSubject,
useSubjectParam,
} from '../helpers/useCurrentSubject';
import { paths } from './paths';

/** Route that connects to `/confirm-email`, which confirms an email and creates a secret key. */
const ConfirmEmail: React.FunctionComponent = () => {
// Value shown in navbar, after Submitting
const [subject] = useCurrentSubject();
const [secret, setSecret] = useState('');
const store = useStore();
const [token] = useSubjectParam('token');
const { agent, setAgent } = useSettings();
const [destinationToGo, setDestination] = useState<string>();

const handleConfirm = async () => {
let tokenUrl = subject as string;

if (isDev()) {
const url = new URL(store.getServerUrl());
url.pathname = paths.confirmEmail;
url.searchParams.set('token', token as string);
tokenUrl = url.href;
}

try {
const { agent: newAgent, destination } = await confirmEmail(
store,
tokenUrl,
);
setAgent(newAgent);
setSecret(newAgent.buildSecret());
setDestination(destination);
} catch (e) {
handleError(e);
}
};

if (!agent) {
return (
<ContainerNarrow>
<button onClick={handleConfirm}>confirm</button>
</ContainerNarrow>
);
}

return (
<ContainerNarrow>
<h1>Save your Passphrase</h1>
<p>
Your Passphrase is like your password. Never share it with anyone. Use a
password manager to store it securely. You will need this to log in
next!
</p>
<CodeBlock content={secret} wrapContent />
{/* <Button onClick={handleGoToDestination}>Continue here</Button> */}
<a href={destinationToGo} target='_blank' rel='noreferrer'>
Open my new Drive!
</a>
</ContainerNarrow>
);
};

export default ConfirmEmail;
2 changes: 2 additions & 0 deletions data-browser/src/routes/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { paths } from './paths';
import ResourcePage from '../views/ResourcePage';
import { ShareRoute } from './ShareRoute';
import { Sandbox } from './Sandbox';
import ConfirmEmail from './ConfirmEmail';

/** Server URLs should have a `/` at the end */
const homeURL = window.location.origin + '/';
Expand Down Expand Up @@ -44,6 +45,7 @@ export function AppRoutes(): JSX.Element {
<Route path={paths.about} element={<About />} />
<Route path={paths.search} element={<Search />} />
{isDev && <Route path={paths.sandbox} element={<Sandbox />} />}
<Route path={paths.confirmEmail} element={<ConfirmEmail />} />
<Route path='/' element={<ResourcePage subject={homeURL} />} />
<Route path='*' element={<Local />} />
</Routes>
Expand Down
1 change: 1 addition & 0 deletions data-browser/src/routes/paths.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export const paths = {
about: '/app/about',
allVersions: '/all-versions',
sandbox: '/sandbox',
confirmEmail: '/confirm-email',
fetchBookmark: '/fetch-bookmark',
};
29 changes: 28 additions & 1 deletion data-browser/src/views/CrashPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,32 @@ type ErrorPageProps = {
clearError: () => void;
};

const githubIssueTemplate = (
message,
stack,
) => `**Describe what you did to produce the bug**
## Error message
\`\`\`
${message}
\`\`\`
## Stack trace
\`\`\`
${stack}
\`\`\`
`;

function createGithubIssueLink(error: Error): string {
const url = new URL(
'https://github.com/atomicdata-dev/atomic-data-browser/issues/new',
);
url.searchParams.set('body', githubIssueTemplate(error.message, error.stack));
url.searchParams.set('labels', 'bug');

return url.href;
}

/** If the entire app crashes, show this page */
function CrashPage({
resource,
Expand All @@ -26,6 +52,7 @@ function CrashPage({
<Column>
{children ? children : <ErrorBlock error={error} showTrace />}
<Row>
<a href={createGithubIssueLink(error)}>Create Github issue</a>
{clearError && <Button onClick={clearError}>Clear error</Button>}
<Button
onClick={() =>
Expand All @@ -35,7 +62,7 @@ function CrashPage({
)
}
>
Try Again
Refresh page
</Button>
</Row>
</Column>
Expand Down
Loading

0 comments on commit f0baa94

Please sign in to comment.