mirror of
https://github.com/morten-olsen/parcel.git
synced 2026-02-08 01:36:24 +01:00
Updates
This commit is contained in:
@@ -5,8 +5,10 @@ import {
|
||||
Route,
|
||||
} from 'react-router-dom';
|
||||
|
||||
import Intro from './screens/Intro';
|
||||
import Encrypt from './screens/Encrypt';
|
||||
import Decrypt from './screens/Decrypt';
|
||||
import SetupKey from './screens/SetupKey';
|
||||
import Welcome from './screens/Welcome';
|
||||
import Debug from './screens/Debug';
|
||||
|
||||
@@ -19,12 +21,18 @@ const AppRouter: React.FC = () => (
|
||||
<Route path="/welcome">
|
||||
<Welcome />
|
||||
</Route>
|
||||
<Route path="/decrypt">
|
||||
<Route path="/key">
|
||||
<SetupKey />
|
||||
</Route>
|
||||
<Route path="/receive">
|
||||
<Decrypt />
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<Route path="/send">
|
||||
<Encrypt />
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<Intro />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Router>
|
||||
);
|
||||
|
||||
@@ -19,15 +19,22 @@ interface Props {
|
||||
file: FileType;
|
||||
}
|
||||
|
||||
const iconStyle = {
|
||||
style: {
|
||||
fontSize: 18,
|
||||
},
|
||||
};
|
||||
|
||||
const icons: {[name: string]: any} = {
|
||||
processing: <SyncOutlined spin />,
|
||||
failed: <IssuesCloseOutlined />,
|
||||
success: <LockOutlined />,
|
||||
processing: <SyncOutlined spin {...iconStyle} />,
|
||||
failed: <IssuesCloseOutlined {...iconStyle} />,
|
||||
success: <LockOutlined {...iconStyle} />,
|
||||
};
|
||||
|
||||
const IconText = ({ icon, text, ...props }) => (
|
||||
<Button
|
||||
{...props}
|
||||
shape="round"
|
||||
icon={React.createElement(icon)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { createFile } from '../helpers/files';
|
||||
|
||||
interface DecryptionContextType {
|
||||
publicKey: string | undefined;
|
||||
createKey: (name: string, email: string) => void;
|
||||
files: {[id: string]: FileType};
|
||||
addFile: (file: File) => Promise<void>;
|
||||
deleteFile: (id: string) => void;
|
||||
@@ -14,6 +15,7 @@ interface DecryptionContextType {
|
||||
const DecryptionContext = createContext<DecryptionContextType>({
|
||||
publicKey: undefined,
|
||||
files: {},
|
||||
createKey: async () => { throw new Error('Not using provider'); },
|
||||
addFile: async () => { throw new Error('Not using provider'); },
|
||||
deleteFile: async () => { throw new Error('Not using provider'); },
|
||||
});
|
||||
@@ -55,21 +57,23 @@ const DecryptionProvider: React.FC = ({
|
||||
setPrivateKey(currentRawKey);
|
||||
const key = await openpgp.key.readArmored(currentRawKey);
|
||||
setPublicKey(key.keys[0].toPublic().armor());
|
||||
} else {
|
||||
const key = await openpgp.generateKey({
|
||||
userIds: [{ name: 'unknown unknown', email: 'unknown@unknown.foo'}],
|
||||
curve: 'ed25519',
|
||||
});
|
||||
|
||||
setPrivateKey(key.privateKeyArmored);
|
||||
setPublicKey(key.publicKeyArmored);
|
||||
localStorage.setItem('key', key.privateKeyArmored);
|
||||
}
|
||||
};
|
||||
|
||||
run();
|
||||
}, []);
|
||||
|
||||
const createKey = async () => {
|
||||
const key = await openpgp.generateKey({
|
||||
userIds: [{ name: 'unknown unknown', email: 'unknown@unknown.foo'}],
|
||||
curve: 'ed25519',
|
||||
});
|
||||
|
||||
setPrivateKey(key.privateKeyArmored);
|
||||
setPublicKey(key.publicKeyArmored);
|
||||
localStorage.setItem('key', key.privateKeyArmored);
|
||||
}
|
||||
|
||||
const addFile = useCallback(async (file: File) => {
|
||||
if (!keys || !privateKey) return;
|
||||
const addedFile = createFile(setFiles, file.name);
|
||||
@@ -89,6 +93,7 @@ const DecryptionProvider: React.FC = ({
|
||||
<DecryptionContext.Provider
|
||||
value={{
|
||||
publicKey,
|
||||
createKey,
|
||||
files,
|
||||
addFile,
|
||||
deleteFile,
|
||||
|
||||
@@ -1,32 +1,14 @@
|
||||
import React, { useContext, useEffect, useCallback } from 'react';
|
||||
import React, { useContext } from 'react';
|
||||
import { Divider, Button } from 'antd';
|
||||
import { useHistory } from 'react-router';
|
||||
import FileList from '../components/FileList';
|
||||
import Add from '../components/decrypt/AddFile';
|
||||
import DecryptionContext from '../contexts/Decryption';
|
||||
import { downloadLink } from '../helpers/files';
|
||||
|
||||
const Decrypt: React.FC = () => {
|
||||
const history = useHistory();
|
||||
const { publicKey, files, deleteFile } = useContext(DecryptionContext);
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem('welcome') !== 'seen') {
|
||||
history.replace('/welcome');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const downloadPublicKey = useCallback(() => {
|
||||
const publicKeyBlob = new Blob([publicKey!]);
|
||||
downloadLink('public-key.asc', publicKeyBlob);
|
||||
}, []);
|
||||
const { files, deleteFile } = useContext(DecryptionContext);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
onClick={downloadPublicKey}
|
||||
>
|
||||
Download you sharing key
|
||||
</Button>
|
||||
<Add />
|
||||
{Object.keys(files).length > 0 && (
|
||||
<>
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import React, { useContext } from 'react';
|
||||
import { Divider } from 'antd';
|
||||
import { useHistory } from 'react-router';
|
||||
import Add from '../components/encrypt/Add';
|
||||
import FileList from '../components/FileList';
|
||||
import EncryptionContext from '../contexts/Encryption';
|
||||
|
||||
const Encrypt: React.FC = () => {
|
||||
const history = useHistory();
|
||||
const { files, deleteFile } = useContext(EncryptionContext);
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem('welcome') !== 'seen') {
|
||||
history.replace('/welcome');
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
60
src/screens/Intro.tsx
Normal file
60
src/screens/Intro.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import Welcome from './Welcome';
|
||||
import {
|
||||
Button,
|
||||
Space,
|
||||
} from 'antd';
|
||||
import {
|
||||
UploadOutlined,
|
||||
DownloadOutlined,
|
||||
KeyOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
|
||||
const Thumb: React.FC = ({
|
||||
title,
|
||||
Icon,
|
||||
link,
|
||||
}) => {
|
||||
const history = useHistory();
|
||||
return (
|
||||
<Button
|
||||
size="large"
|
||||
shape="round"
|
||||
type="link"
|
||||
icon={<Icon />}
|
||||
onClick={() => history.push(link)}
|
||||
>
|
||||
{title}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
const Intro = () => {
|
||||
return (
|
||||
<>
|
||||
<Welcome />
|
||||
<Space style={{ width: '100%' }} align="center" direction="vertical">
|
||||
<b>What do you want to do?</b>
|
||||
<Thumb
|
||||
title="I want to send a text/file"
|
||||
link="/send"
|
||||
Icon={UploadOutlined}
|
||||
/>
|
||||
<Thumb
|
||||
link="/key"
|
||||
title="I want to receive a file"
|
||||
Icon={KeyOutlined}
|
||||
/>
|
||||
<Thumb
|
||||
link="/receive"
|
||||
title="I have received a file"
|
||||
Icon={DownloadOutlined}
|
||||
/>
|
||||
</Space>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Intro;
|
||||
101
src/screens/SetupKey.tsx
Normal file
101
src/screens/SetupKey.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import React, { useContext, useState, useCallback } from 'react';
|
||||
import { Space, Typography, Input, Button, Form } from 'antd';
|
||||
import DecryptionContext from '../contexts/Decryption';
|
||||
import { downloadLink } from '../helpers/files';
|
||||
import {
|
||||
RocketTwoTone,
|
||||
LockTwoTone,
|
||||
UserOutlined,
|
||||
MailOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const SetupKey: React.FC = () => {
|
||||
const {
|
||||
createKey,
|
||||
publicKey,
|
||||
} = useContext(DecryptionContext);
|
||||
|
||||
const [name, setName] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
|
||||
const downloadPublicKey = useCallback(() => {
|
||||
const publicKeyBlob = new Blob([publicKey!]);
|
||||
downloadLink('public-key.asc', publicKeyBlob);
|
||||
}, []);
|
||||
|
||||
const setupKey = useCallback(() => {
|
||||
createKey(name, email);
|
||||
}, [name, email]);
|
||||
|
||||
if (!publicKey) {
|
||||
return (
|
||||
<>
|
||||
<Space direction="vertical" style={{ textAlign: 'center' }} >
|
||||
<LockTwoTone style={{ fontSize: 150 }} />
|
||||
<Typography.Title>Create your sharing key</Typography.Title>
|
||||
<p>
|
||||
Before I can send protected information to you I need a "sharing" key, which is a key that gets stored this device, allowing this device (and this device only) to read the informations I am sending.
|
||||
</p>
|
||||
<p>
|
||||
After creating it you need to send it to me
|
||||
</p>
|
||||
</Space>
|
||||
<Form>
|
||||
<Form.Item>
|
||||
<Input
|
||||
placeholder="Your name"
|
||||
size="large"
|
||||
prefix={<UserOutlined />}
|
||||
value={name}
|
||||
onChange={evt => setName(evt.target.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Input
|
||||
placeholder="Your e-mail"
|
||||
size="large"
|
||||
prefix={<MailOutlined />}
|
||||
value={email}
|
||||
onChange={evt => setEmail(evt.target.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item style={{ textAlign: 'center' }} >
|
||||
<Button
|
||||
disabled={!name || !email}
|
||||
type="primary"
|
||||
onClick={setupKey}
|
||||
size="large"
|
||||
shape="round"
|
||||
>
|
||||
Create sharing key
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<RocketTwoTone style={{ fontSize: 150 }} />
|
||||
<Typography.Title>Okay, you are all set.</Typography.Title>
|
||||
<p>
|
||||
Just send me your sharing key, and I will send files using it.
|
||||
</p>
|
||||
<p>
|
||||
Remember that you need to go to this website on this device to decrypt the files after receiving them
|
||||
</p>
|
||||
|
||||
<Button
|
||||
onClick={downloadPublicKey}
|
||||
type="primary"
|
||||
size="large"
|
||||
shape="round"
|
||||
>
|
||||
Download sharing key
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SetupKey;
|
||||
@@ -1,51 +1,23 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { Space, Layout, Button, Typography, notification } from 'antd';
|
||||
import { AlignLeftOutlined, EyeInvisibleTwoTone, ArrowRightOutlined } from '@ant-design/icons';
|
||||
import { useHistory } from 'react-router';
|
||||
|
||||
const openNotification = () => {
|
||||
notification.warn({
|
||||
message: 'Slow down!',
|
||||
description: 'I am still working on this, but thanks for the interrest.'
|
||||
});
|
||||
};
|
||||
import React from 'react';
|
||||
import { Space, Layout, Typography } from 'antd';
|
||||
import { EyeInvisibleTwoTone } from '@ant-design/icons';
|
||||
|
||||
const Welcome: React.FC = () => {
|
||||
const history = useHistory();
|
||||
useEffect(() => {
|
||||
localStorage.setItem('welcome', 'seen');
|
||||
});
|
||||
|
||||
return (
|
||||
<Layout style={{ maxWidth: 800, margin: 'auto', textAlign: 'center' }}>
|
||||
<Space direction="vertical">
|
||||
<EyeInvisibleTwoTone style={{ fontSize: 200 }} />
|
||||
<Typography.Title level={1}>Protect before sending</Typography.Title>
|
||||
<p>
|
||||
The internet can seem like a scary place, especially if you want to send sensitiv information across it.
|
||||
The internet can seem like a scary place...
|
||||
</p>
|
||||
<p>
|
||||
The truth is that a lot of systems, including e-mails, was not build for the internet that we have today.
|
||||
Especially because a lot of the tools we use everyday (such as e-mail) wasn't build for the internet that we have today.
|
||||
This is why it is important to have an additional layer of security when sending sensitive information.
|
||||
</p>
|
||||
<p>
|
||||
This is why it is so important to make sure your documents are well protected before sharing.
|
||||
This is a tool that will help you have that extra layer of security when sharing files with me.
|
||||
</p>
|
||||
<p>
|
||||
This tool can be used to protect information before sharing them with me. The documents will be encrypted so that only I can ever unlock them, so no snoppy man in the middle...
|
||||
</p>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<ArrowRightOutlined />}
|
||||
onClick={() => history.push('/')}
|
||||
>
|
||||
Start protecting!
|
||||
</Button>
|
||||
<Button
|
||||
icon={<AlignLeftOutlined />}
|
||||
onClick={openNotification}
|
||||
>
|
||||
Read all the technical stuff
|
||||
</Button>
|
||||
</Space>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user