add waffle library, handle file upload, authenticate user with oauth and see if they have the link's email associated to their account
This commit is contained in:
@@ -14,15 +14,17 @@ import "../css/app.css"
|
||||
// import {Socket} from "phoenix"
|
||||
// import socket from "./socket"
|
||||
//
|
||||
import "phoenix_html"
|
||||
import {Socket} from "phoenix"
|
||||
import topbar from "topbar"
|
||||
import {LiveSocket} from "phoenix_live_view"
|
||||
import "phoenix_html";
|
||||
import {Socket} from "phoenix";
|
||||
import topbar from "topbar";
|
||||
import {LiveSocket} from "phoenix_live_view";
|
||||
|
||||
import SplashPage from './pages/SplashPage';
|
||||
import JustPage from './pages/JustPage'
|
||||
import ForPage from './pages/ForPage'
|
||||
import YouPage from './pages/YouPage'
|
||||
import JustPage from './pages/JustPage';
|
||||
import ForPage from './pages/ForPage';
|
||||
import YouPage from './pages/YouPage';
|
||||
import AuthPage from './pages/AuthPage';
|
||||
import RevealPage from './pages/RevealPage';
|
||||
|
||||
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
|
||||
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
|
||||
@@ -42,5 +44,5 @@ liveSocket.connect()
|
||||
window.liveSocket = liveSocket
|
||||
|
||||
window.Components = {
|
||||
SplashPage, JustPage, ForPage, YouPage
|
||||
SplashPage, JustPage, ForPage, YouPage, AuthPage, RevealPage
|
||||
}
|
||||
|
||||
@@ -1,16 +1,54 @@
|
||||
// import HexMix from "../utils/hexmix";
|
||||
// const fragmentData = window.location.hash.split('.');
|
||||
// if (fragmentData.length <= 0) {
|
||||
// alert("No key found in fragment URI");
|
||||
// return;
|
||||
// }
|
||||
// const key = HexMix.hexToUint8(fragmentData[0]);
|
||||
// const iv = HexMix.hexToUint8(fragmentData[1]);
|
||||
import { Button, CenteredContainer, GlobalStyle, Header2, Header3, Input, Label, Spacer, TextAlignWrapper } from "@intended/intended-ui";
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
// const importedKey = await window.crypto.subtle.importKey(
|
||||
// 'raw',
|
||||
// key,
|
||||
// 'AES-GCM',
|
||||
// true,
|
||||
// ['encrypt', 'decrypt']
|
||||
// );
|
||||
type AuthPageProps = {
|
||||
csrf: string,
|
||||
service: string,
|
||||
recipient: string
|
||||
}
|
||||
|
||||
const AuthPage = (props: AuthPageProps) => {
|
||||
const { service, recipient } = props;
|
||||
// const [recipientInput, setRecipientInput] = useState("");
|
||||
// const [serviceSelect, setServiceSelect] = useState("github");
|
||||
|
||||
// useEffect(() => {
|
||||
|
||||
// }, [])
|
||||
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<GlobalStyle />
|
||||
<CenteredContainer fullscreen>
|
||||
<CenteredContainer>
|
||||
<Header2 style={{ margin: ".4rem" }}>Someone sent you a secret</Header2>
|
||||
<Header3 small>
|
||||
Please verify your identity to reveal this message.
|
||||
</Header3>
|
||||
<Spacer space="3rem" />
|
||||
<TextAlignWrapper align="left">
|
||||
<Label htmlFor="usernameEmail">Username / Email</Label>
|
||||
</TextAlignWrapper>
|
||||
<Input
|
||||
variant="disabled-medium"
|
||||
id="usernameEmail"
|
||||
value={recipient}
|
||||
/>
|
||||
<Spacer space="3rem" />
|
||||
<TextAlignWrapper align="left">
|
||||
<Label htmlFor="service">Service</Label>
|
||||
</TextAlignWrapper>
|
||||
<Input variant="disabled-medium" id="service" value={service} />
|
||||
<Spacer space="3rem" />
|
||||
<a href={`https://intended.link/auth/${service}`}>
|
||||
<Button variant="primary" wide onClick={() => {}}>
|
||||
Verify
|
||||
</Button>
|
||||
</a>
|
||||
</CenteredContainer>
|
||||
</CenteredContainer>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
|
||||
export default AuthPage;
|
||||
|
||||
@@ -3,9 +3,13 @@ import React, { useState } from "react";
|
||||
import { ProgressIndicator, Header2, Button, IconArrow, Label, Input, Select, CenteredContainer, SpaceBetweenContainer, Spacer, TextAlignWrapper, GlobalStyle } from "@intended/intended-ui";
|
||||
|
||||
|
||||
const ForPage = () => {
|
||||
type ForPageProps = {
|
||||
csrf: string
|
||||
}
|
||||
|
||||
const ForPage = (props: ForPageProps) => {
|
||||
const [recipientInput, setRecipientInput] = useState("");
|
||||
const [serviceSelect, setServiceSelect] = useState("");
|
||||
const [serviceSelect, setServiceSelect] = useState("github");
|
||||
|
||||
const handleRecipientInputChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement>
|
||||
@@ -18,14 +22,14 @@ const ForPage = () => {
|
||||
};
|
||||
|
||||
const postContacts = async () => {
|
||||
const fragmentData = window.location.hash.split('.');
|
||||
if (fragmentData.length <= 0) {
|
||||
alert("No key found in fragment URI");
|
||||
return;
|
||||
}
|
||||
// const fragmentData = window.location.hash.split('.');
|
||||
// if (fragmentData.length <= 0) {
|
||||
// alert("No key found in fragment URI");
|
||||
// return;
|
||||
// }
|
||||
|
||||
const linkId = sessionStorage.getItem("link_id");
|
||||
if (linkId == null || linkId == "") {
|
||||
if (!linkId) {
|
||||
alert("No created link found in storage");
|
||||
return;
|
||||
}
|
||||
@@ -36,10 +40,18 @@ const ForPage = () => {
|
||||
formData.append("link_id", linkId);
|
||||
|
||||
try {
|
||||
await fetch(`${window.location.origin}/just/for`, {
|
||||
const results = await fetch(`${window.location.origin}/just/for`, {
|
||||
headers: {
|
||||
"X-CSRF-Token": props.csrf
|
||||
},
|
||||
body: formData,
|
||||
method: "POST"
|
||||
});
|
||||
if (!results.ok) {
|
||||
throw new Error('Network response was not OK');
|
||||
}
|
||||
|
||||
await results.json();
|
||||
window.location.href = `${window.location.origin}/just/for/you`;
|
||||
} catch (err: any) {
|
||||
alert(err.message);
|
||||
@@ -74,7 +86,9 @@ const ForPage = () => {
|
||||
id="serviceSelector"
|
||||
onChange={handleServiceChange}
|
||||
value={serviceSelect}
|
||||
/>
|
||||
>
|
||||
<option value='github'>Github</option>
|
||||
</Select>
|
||||
<Spacer space="3rem" />
|
||||
<SpaceBetweenContainer>
|
||||
<Button variant="secondary" onClick={() => window.location.href = "/just"}>
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { ProgressIndicator, Header2, Button, IconArrow, Label, FileInput, TextArea, CenteredContainer, Spacer, TextAlignWrapper, GlobalStyle } from '@intended/intended-ui';
|
||||
import HexMix from "../utils/hexmix";
|
||||
|
||||
const JustPage = (props) => {
|
||||
type JustPageProps = {
|
||||
csrf: string
|
||||
}
|
||||
|
||||
const JustPage = (props: JustPageProps) => {
|
||||
const [secretInput, setSecretInput] = useState("");
|
||||
const [fileInput, setFileInput] = useState<File | null>(null);
|
||||
const [fileName, setFileName] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
sessionStorage.clear();
|
||||
}, [])
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setSecretInput(e.target.value);
|
||||
};
|
||||
@@ -51,18 +59,20 @@ const JustPage = (props) => {
|
||||
const blobData = new Blob([encrypted]);
|
||||
|
||||
formData.append('text_content', blobData);
|
||||
formData.append('filetype', 'text/plain');
|
||||
formData.append('filename', 'secret.txt');
|
||||
// formData.append('filetype', 'text/plain');
|
||||
// formData.append('filename', 'secret.txt');
|
||||
|
||||
try {
|
||||
const link: unknown = await fetch(`${window.location.origin}/just`, {
|
||||
const link: Response = await fetch(`${window.location.origin}/just`, {
|
||||
headers: {
|
||||
"X-CSRF-Token": props.csrf
|
||||
},
|
||||
body: formData,
|
||||
method: "POST"
|
||||
});
|
||||
sessionStorage.setItem("link_id", (link as Link).id);
|
||||
const { id: link_id } = await link.json()
|
||||
|
||||
sessionStorage.setItem("link_id", link_id);
|
||||
sessionStorage.setItem("key_hex", keyHex);
|
||||
sessionStorage.setItem("iv_hex", ivHex);
|
||||
window.location.href = `${window.location.origin}/just/for`;
|
||||
|
||||
61
assets/js/pages/RevealPage.tsx
Normal file
61
assets/js/pages/RevealPage.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { Button, CenteredContainer, GlobalStyle, Header2, Header3, InputButtonWithIcon, Label, SpaceBetweenContainer, Spacer, TextAlignWrapper, TextAreaParagraph } from "@intended/intended-ui";
|
||||
import React, { useEffect, useState } from "react";
|
||||
// import HexMix from "../utils/hexmix";
|
||||
// const fragmentData = window.location.hash.split('.');
|
||||
// if (fragmentData.length <= 0) {
|
||||
// alert("No key found in fragment URI");
|
||||
// return;
|
||||
// }
|
||||
// const key = HexMix.hexToUint8(fragmentData[0]);
|
||||
// const iv = HexMix.hexToUint8(fragmentData[1]);
|
||||
|
||||
// const importedKey = await window.crypto.subtle.importKey(
|
||||
// 'raw',
|
||||
// key,
|
||||
// 'AES-GCM',
|
||||
// true,
|
||||
// ['encrypt', 'decrypt']
|
||||
// );
|
||||
|
||||
|
||||
const RevealPage = () => {
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<GlobalStyle />
|
||||
<CenteredContainer fullscreen>
|
||||
<CenteredContainer>
|
||||
<Header2 style={{ margin: ".4rem" }}>Someone sent you a secret</Header2>
|
||||
<Header3 small>
|
||||
Please verify your identity to reveal this message.
|
||||
</Header3>
|
||||
<Spacer space="3rem" />
|
||||
|
||||
<SpaceBetweenContainer>
|
||||
<Label htmlFor="secretMessage">Secret message</Label>
|
||||
<Label htmlFor="secretMessage">Sent 8/24/21 @ 1:27pm</Label>
|
||||
</SpaceBetweenContainer>
|
||||
<TextAreaParagraph id="secretMessage">
|
||||
"Sup. What are you doing for lunch?"
|
||||
</TextAreaParagraph>
|
||||
|
||||
<Spacer space="3rem" />
|
||||
<TextAlignWrapper align="left">
|
||||
<Label htmlFor="service">Secret File</Label>
|
||||
</TextAlignWrapper>
|
||||
<InputButtonWithIcon
|
||||
variant="download"
|
||||
id="downloadfile"
|
||||
value="1780983.jpg"
|
||||
onClick={() => {}}
|
||||
/>
|
||||
<Spacer space="3rem" />
|
||||
<Button variant="secondary" wide onClick={() => {}}>
|
||||
Send a secret
|
||||
</Button>
|
||||
</CenteredContainer>
|
||||
</CenteredContainer>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
|
||||
export default RevealPage;
|
||||
@@ -8,11 +8,10 @@ const YouPage = () => {
|
||||
const keyHex = sessionStorage.getItem("key_hex");
|
||||
const ivHex = sessionStorage.getItem("iv_hex");
|
||||
|
||||
`${window.location.origin}/just/for/you/${linkId}#${keyHex}.${ivHex}`
|
||||
return "";
|
||||
return `${window.location.origin}/just/for/you/${linkId}#${keyHex}.${ivHex}`;
|
||||
};
|
||||
|
||||
const [url, setUrl] = useState(calculateUrl());
|
||||
const [url, _setUrl] = useState(calculateUrl());
|
||||
|
||||
const copyUrl = async () => {
|
||||
try {
|
||||
@@ -51,7 +50,7 @@ const YouPage = () => {
|
||||
<Input
|
||||
variant="disabled-light"
|
||||
id="encodedSecret"
|
||||
value="\4RÏÇmÄyÆFÕ¬Ð$CÑÓÃyÛ"
|
||||
value={url}
|
||||
/>
|
||||
<Spacer space="3rem" />
|
||||
<SpaceBetweenContainer>
|
||||
|
||||
31
assets/package-lock.json
generated
31
assets/package-lock.json
generated
@@ -1079,6 +1079,7 @@
|
||||
"version": "7.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz",
|
||||
"integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
@@ -1142,9 +1143,9 @@
|
||||
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
||||
},
|
||||
"@intended/intended-ui": {
|
||||
"version": "0.1.19",
|
||||
"resolved": "https://registry.npmjs.org/@intended/intended-ui/-/intended-ui-0.1.19.tgz",
|
||||
"integrity": "sha512-dOQZBvBm5UyKhyilTE6y/3KL1suyjbAuu+kn4b3tKhpy/Y23AglVlHLj4oi/AUgGRMtcRT/o9eySJWkNWQ9weA==",
|
||||
"version": "0.1.21",
|
||||
"resolved": "https://registry.npmjs.org/@intended/intended-ui/-/intended-ui-0.1.21.tgz",
|
||||
"integrity": "sha512-rNyJOGLOw8iKP0AaSYSytZXFssPhlE1FbUjxEze8F4iOgXxs6iu7B9+gSIF4QJg/IrQUVu76tkevBGDk2nTQNg==",
|
||||
"requires": {
|
||||
"polished": "^4.1.3",
|
||||
"react": "^17.0.2",
|
||||
@@ -1719,9 +1720,9 @@
|
||||
}
|
||||
},
|
||||
"babel-plugin-styled-components": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.1.tgz",
|
||||
"integrity": "sha512-U3wmORxerYBiqcRCo6thItIosEIga3F+ph0jJPkiOZJjyhpZyUZFQV9XvrZ2CbBIihJ3rDBC/itQ+Wx3VHMauw==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.2.tgz",
|
||||
"integrity": "sha512-7eG5NE8rChnNTDxa6LQfynwgHTVOYYaHJbUYSlOhk8QBXIQiMBKq4gyfHBBKPrxUcVBXVJL61ihduCpCQbuNbw==",
|
||||
"requires": {
|
||||
"@babel/helper-annotate-as-pure": "^7.16.0",
|
||||
"@babel/helper-module-imports": "^7.16.0",
|
||||
@@ -5896,11 +5897,21 @@
|
||||
}
|
||||
},
|
||||
"polished": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/polished/-/polished-4.1.3.tgz",
|
||||
"integrity": "sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA==",
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/polished/-/polished-4.1.4.tgz",
|
||||
"integrity": "sha512-Nq5Mbza+Auo7N3sQb1QMFaQiDO+4UexWuSGR7Cjb4Sw11SZIJcrrFtiZ+L0jT9MBsUsxDboHVASbCLbE1rnECg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.14.0"
|
||||
"@babel/runtime": "^7.16.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
|
||||
"integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"posix-character-classes": {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"watch": "webpack --mode development --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@intended/intended-ui": "0.1.19",
|
||||
"@intended/intended-ui": "0.1.21",
|
||||
"phoenix": "file:../deps/phoenix",
|
||||
"phoenix_html": "file:../deps/phoenix_html",
|
||||
"phoenix_live_view": "file:../deps/phoenix_live_view",
|
||||
|
||||
Reference in New Issue
Block a user