From 6931e6ea7f922d3f859e0c130a391c6d2b45dc8c Mon Sep 17 00:00:00 2001 From: Vivek Shah Date: Mon, 3 Apr 2023 12:30:07 +0530 Subject: [PATCH 1/3] #30: Key pairs to generate automatically on upload. - Add restore default option for configuration. - Add directory select option. - Display tooltip for dek and kek type. - Remove uuid from list. --- cmd/web/app.go | 32 +++ cmd/web/frontend/index.html | 21 +- cmd/web/frontend/src/App.css | 13 +- .../Dashboard/ConfigurationPage/index.tsx | 95 +++++++- .../pages/Dashboard/ListContentPage/index.tsx | 4 - .../Dashboard/ManageKeyPairPage/index.tsx | 60 ++++- .../Dashboard/RetrieveContentPage/index.tsx | 213 +++++++++--------- .../RetrieveSharedContentPage/index.tsx | 170 +++++++++----- .../Dashboard/UploadContentPage/index.tsx | 138 +++++++++--- cmd/web/frontend/wailsjs/go/main/App.d.ts | 4 + cmd/web/frontend/wailsjs/go/main/App.js | 8 + 11 files changed, 536 insertions(+), 222 deletions(-) diff --git a/cmd/web/app.go b/cmd/web/app.go index 98c1e21..e369830 100644 --- a/cmd/web/app.go +++ b/cmd/web/app.go @@ -2,6 +2,7 @@ package main import ( "context" + "encloud/config" "encloud/pkg/api" "encloud/pkg/types" "net/http" @@ -57,6 +58,14 @@ func (a *App) SelectFile() string { return file } +func (a *App) SelectDirectory() string { + file, err := runtime.OpenDirectoryDialog(a.ctx, runtime.OpenDialogOptions{}) + if err != nil { + return err.Error() + } + return file +} + // Upload data to esatury func (a *App) Upload(filePath string, kekType string, dekType string, kek string) types.UploadContentResponse { var response types.UploadContentResponse @@ -184,6 +193,29 @@ func (a *App) StoreConfig(conf types.ConfYaml) types.ConfigResponse { return response } +// Restore default config +func (a *App) RestoreDefaultConfig() types.ConfigResponse { + var response types.ConfigResponse + err := config.LoadDefaultConf() + if err != nil { + response = types.ConfigResponse{ + Status: "fail", + StatusCode: http.StatusInternalServerError, + Message: err.Error(), + Data: types.ConfYaml{}, + } + } else { + response = types.ConfigResponse{ + Status: "success", + StatusCode: http.StatusFound, + Message: "Configuration saved successfully", + Data: types.ConfYaml{}, + } + } + + return response +} + // Fetch config func (a *App) FetchConfig() types.ConfigResponse { var response types.ConfigResponse diff --git a/cmd/web/frontend/index.html b/cmd/web/frontend/index.html index d08d738..9dd1939 100644 --- a/cmd/web/frontend/index.html +++ b/cmd/web/frontend/index.html @@ -1,13 +1,16 @@ - - - + + + web - - -
- - + + + +
+ + - diff --git a/cmd/web/frontend/src/App.css b/cmd/web/frontend/src/App.css index 528eb96..05c0c82 100644 --- a/cmd/web/frontend/src/App.css +++ b/cmd/web/frontend/src/App.css @@ -115,6 +115,11 @@ input, border-color: #d94964 !important; } +input, +.form-label { + color: #d94964 !important; +} + input:focus, .form-control:focus { border-color: #d94964 !important; @@ -150,6 +155,10 @@ th { color: #f76e5c; } -th:nth-child(3) { - width: 100px; +th:nth-child(0) { + width: 180px; +} + +.tooltip-inner { + max-width: 960px !important; } \ No newline at end of file diff --git a/cmd/web/frontend/src/pages/Dashboard/ConfigurationPage/index.tsx b/cmd/web/frontend/src/pages/Dashboard/ConfigurationPage/index.tsx index 0ab6984..4d2caf9 100644 --- a/cmd/web/frontend/src/pages/Dashboard/ConfigurationPage/index.tsx +++ b/cmd/web/frontend/src/pages/Dashboard/ConfigurationPage/index.tsx @@ -1,10 +1,23 @@ import * as formik from "formik"; -import { Button, Card, Col, Form, Row, Image } from "react-bootstrap"; +import { + Button, + Card, + Col, + Form, + Row, + Image, + Tooltip, + OverlayTrigger, +} from "react-bootstrap"; import { ColoredBtn, KeyBoxedContent, KeyPairsSection } from "./styles"; import { PageHeader } from "./../../../components/layouts/styles"; import Select, { StylesConfig } from "react-select"; import { CSSProperties, useEffect, useState } from "react"; -import { FetchConfig, StoreConfig } from "../../../../wailsjs/go/main/App"; +import { + FetchConfig, + RestoreDefaultConfig, + StoreConfig, +} from "../../../../wailsjs/go/main/App"; import { toast } from "react-toastify"; import settingsIcon from "../../../assets/images/settings.png"; import ClipLoader from "react-spinners/ClipLoader"; @@ -73,6 +86,19 @@ const colourStyles: StylesConfig = { singleValue: (styles, { data }) => ({ ...styles }), }; +const renderTooltip = (props: any) => ( + + RSA - RSAES-OAEP 3072 bit key with a SHA-256 digest +
+ + ECIES - The ECIES standard combines ECC-based asymmetric cryptography with + symmetric ciphers. ECC is the modern and the more preferable public-key + cryptosystem because of smaller keys, shorter signatures and better + performance, but some people disagree. + +
+); + const ConfigurationPage = () => { const { Formik } = formik; const [loading, setLoading] = useState(false); @@ -130,6 +156,32 @@ const ConfigurationPage = () => { fetchData(); }, [setConfigData]); + const restoreDefault = () => { + setLoading(true); + try { + RestoreDefaultConfig().then((response) => { + if (response && response.Status == "success") { + setLoading(false); + toast.success(response.Message, { + position: toast.POSITION.TOP_RIGHT, + }); + + fetchData(); + } else { + setLoading(false); + toast.error("Something went wrong!", { + position: toast.POSITION.TOP_RIGHT, + }); + } + }); + } catch (error) { + setLoading(false); + toast.error("Something went wrong!", { + position: toast.POSITION.TOP_RIGHT, + }); + } + }; + const save = async (data: any) => { setLoading(true); data.Stat.KekType = data.Stat.KekType.value; @@ -342,7 +394,20 @@ const ConfigurationPage = () => { - Kek Type + + Kek Type + + + + { <> - KEK Type + + KEK Type + + + + { -
Plain text keys
+
+ Plain text keys + + + +
RSA diff --git a/cmd/web/frontend/src/pages/Dashboard/RetrieveContentPage/index.tsx b/cmd/web/frontend/src/pages/Dashboard/RetrieveContentPage/index.tsx index 7f72e71..b3018d3 100644 --- a/cmd/web/frontend/src/pages/Dashboard/RetrieveContentPage/index.tsx +++ b/cmd/web/frontend/src/pages/Dashboard/RetrieveContentPage/index.tsx @@ -1,5 +1,3 @@ -import * as Yup from "yup"; -import * as formik from "formik"; import { Link, useLocation } from "react-router-dom"; import { Button, Card, Col, Image, Row, Modal, Form } from "react-bootstrap"; import { ColoredBtn, SectionBox } from "./styles"; @@ -8,7 +6,10 @@ import { PageHeader } from "../../../components/layouts/styles"; // Images import dsRefreshImg from "../../../assets/images/refresh.png"; import { CSSProperties, useState } from "react"; -import { RetrieveByUUID } from "../../../../wailsjs/go/main/App"; +import { + RetrieveByUUID, + SelectDirectory, +} from "../../../../wailsjs/go/main/App"; import { readKey } from "../../../services/localStorage.service"; import { toast } from "react-toastify"; import ClipLoader from "react-spinners/ClipLoader"; @@ -36,41 +37,57 @@ const RetrieveContentPage = () => { const location = useLocation(); const { metadata } = location.state; - const { Formik } = formik; + const [selectedDirectory, setSelectedDirectory] = useState(); - const schema = Yup.object().shape({ - filePath: Yup.string().required("Please enter download file path"), - }); + const getPath = async (evt: any) => { + evt.preventDefault(); + try { + SelectDirectory() + .then((result: any) => { + var dt = new DataTransfer(); + dt.items.add(new File([], result)); + evt.target.files = dt.files; + setSelectedDirectory(result); + }) + .catch((err: any) => { + console.error(err); + }); + } catch (err) { + console.error(err); + } + }; - const download = (data: any) => { + const download = () => { setDownloadLoading(true); try { - RetrieveByUUID( - metadata.uuid, - readKey().PublicKey, - readKey().PrivateKey, - data.filePath - ) - .then((result: any) => { - if (result && result.Status == "success" && result.Data.uuid) { - setDownloadLoading(false); - setShowDownloadForm(!showDownloadForm); - toast.success("Document downloaded successfully.", { - position: toast.POSITION.TOP_RIGHT, - }); - } else { + if (selectedDirectory) { + RetrieveByUUID( + metadata.uuid, + readKey().PublicKey, + readKey().PrivateKey, + selectedDirectory + ) + .then((result: any) => { + if (result && result.Status == "success" && result.Data.uuid) { + setDownloadLoading(false); + setShowDownloadForm(!showDownloadForm); + toast.success("Document downloaded successfully.", { + position: toast.POSITION.TOP_RIGHT, + }); + } else { + setDownloadLoading(false); + toast.error("Something went wrong!.Please retry", { + position: toast.POSITION.TOP_RIGHT, + }); + } + }) + .catch((err: any) => { setDownloadLoading(false); toast.error("Something went wrong!.Please retry", { position: toast.POSITION.TOP_RIGHT, }); - } - }) - .catch((err: any) => { - setDownloadLoading(false); - toast.error("Something went wrong!.Please retry", { - position: toast.POSITION.TOP_RIGHT, }); - }); + } } catch (err) { setDownloadLoading(false); toast.error("Something went wrong!.Please retry", { @@ -111,88 +128,62 @@ const RetrieveContentPage = () => { {showDownloadForm ? ( - - {({ - handleSubmit, - handleChange, - handleBlur, - values, - touched, - isValid, - errors, - }) => ( -
- - - - {downloadLoading ? "Download is in progress..." : ""} - - - - - - - - {errors.filePath} - - - - - - - setShowDownloadForm(!showDownloadForm)} - style={{ marginRight: 2 }} - > - Close - - - {downloadLoading ? ( -
- - Downloading -
- ) : ( - "Download" - )} -
- - -
-
- )} -
+ <> + + + + {downloadLoading ? "Download is in progress..." : ""} + + + + + + + + + + + + setShowDownloadForm(!showDownloadForm)} + style={{ marginRight: 2 }} + > + Close + + + {downloadLoading ? ( +
+ + Downloading +
+ ) : ( + "Download" + )} +
+ + +
+ ) : ( <> diff --git a/cmd/web/frontend/src/pages/Dashboard/RetrieveSharedContentPage/index.tsx b/cmd/web/frontend/src/pages/Dashboard/RetrieveSharedContentPage/index.tsx index 3a892ce..89ad08a 100644 --- a/cmd/web/frontend/src/pages/Dashboard/RetrieveSharedContentPage/index.tsx +++ b/cmd/web/frontend/src/pages/Dashboard/RetrieveSharedContentPage/index.tsx @@ -1,12 +1,25 @@ import * as Yup from "yup"; import * as formik from "formik"; -import { Button, Card, Col, Form, Image, Row } from "react-bootstrap"; +import { + Button, + Card, + Col, + Form, + Image, + OverlayTrigger, + Row, + Tooltip, +} from "react-bootstrap"; import { KeyBoxedContent, KeyPairsSection } from "./styles"; import { PageHeader } from "../../../components/layouts/styles"; // Images import shareIcon from "../../../assets/images/share.png"; -import { RetrieveSharedContent } from "../../../../wailsjs/go/main/App"; +import { + RetrieveSharedContent, + SelectDirectory, + SelectFile, +} from "../../../../wailsjs/go/main/App"; import { toast } from "react-toastify"; import { CSSProperties, useState } from "react"; import ClipLoader from "react-spinners/ClipLoader"; @@ -72,48 +85,102 @@ const colourStyles: StylesConfig = { singleValue: (styles, { data }) => ({ ...styles }), }; +const renderTooltip = (props: any) => ( + + + AES 256 GCM - GCM throughput rates for state-of-the-art, high-speed + communication channels can be achieved with inexpensive hardware + resources. GCM is limited to encrypting 64 GiB of plain text. + +
+ + ChaCha20-Poly1035 - ChaCha20-Poly1305 is an authenticated encryption with + additional data (AEAD) algorithm, that combines the ChaCha20 stream cipher + with the Poly1305 message authentication code. It has fast software + performance, and without hardware acceleration, is usually faster than + AES-GCM. + +
+); + const RetrieveSharedContentPage = () => { const [loading, setLoading] = useState(false); + const [selectedDirectory, setSelectedDirectory] = useState(); + const [dekPath, setDekPath] = useState(); const { Formik } = formik; const schema = Yup.object().shape({ cid: Yup.string().required("Please enter cid"), - decryptedDekPath: Yup.string().required("Please enter dek path"), fileName: Yup.string().required("Please enter download file name"), - retrievalFileStoragePath: Yup.string().required( - "Please enter download file path" - ), }); + const getFilePath = async (evt: any) => { + evt.preventDefault(); + try { + SelectFile() + .then((result: any) => { + var dt = new DataTransfer(); + dt.items.add(new File([], result)); + evt.target.files = dt.files; + setDekPath(result); + }) + .catch((err: any) => { + console.error(err); + }); + } catch (err) { + console.error(err); + } + }; + + const getDirectoryPath = async (evt: any) => { + evt.preventDefault(); + try { + SelectDirectory() + .then((result: any) => { + var dt = new DataTransfer(); + dt.items.add(new File([], result)); + evt.target.files = dt.files; + setSelectedDirectory(result); + }) + .catch((err: any) => { + console.error(err); + }); + } catch (err) { + console.error(err); + } + }; + const getSharedContent = (data: any) => { setLoading(true); try { - RetrieveSharedContent( - data.decryptedDekPath, - data.dekType.value, - data.cid, - data.fileName, - data.retrievalFileStoragePath - ) - .then((result: any) => { - if (result && result.Status == "success") { - setLoading(false); - toast.success("Document downloaded successfully.", { - position: toast.POSITION.TOP_RIGHT, - }); - } else { + if (selectedDirectory && dekPath) { + RetrieveSharedContent( + dekPath, + data.dekType.value, + data.cid, + data.fileName, + selectedDirectory + ) + .then((result: any) => { + if (result && result.Status == "success") { + setLoading(false); + toast.success("Document downloaded successfully.", { + position: toast.POSITION.TOP_RIGHT, + }); + } else { + setLoading(false); + toast.error("Something went wrong!.Please retry", { + position: toast.POSITION.TOP_RIGHT, + }); + } + }) + .catch((err: any) => { setLoading(false); toast.error("Something went wrong!.Please retry", { position: toast.POSITION.TOP_RIGHT, }); - } - }) - .catch((err: any) => { - setLoading(false); - toast.error("Something went wrong!.Please retry", { - position: toast.POSITION.TOP_RIGHT, }); - }); + } } catch (err) { setLoading(false); toast.error("Something went wrong!.Please retry", { @@ -127,7 +194,7 @@ const RetrieveSharedContentPage = () => {

- Retrieve Shared Content + Retrieve Data Received

@@ -139,9 +206,7 @@ const RetrieveSharedContentPage = () => { initialValues={{ cid: "", dekType: dekTypeOptions[0], - decryptedDekPath: "", fileName: "", - retrievalFileStoragePath: "", }} > {({ @@ -158,7 +223,7 @@ const RetrieveSharedContentPage = () => { -

Retrieve Shared Content

+

Retrieve Data Received

@@ -187,7 +252,20 @@ const RetrieveSharedContentPage = () => { - DEK Type + + DEK Type + + + + { - setDekType(newVal); - }} - /> - - - - - - - - - Chunk Sizes Premium{" "} - - + Document + - - Document - - + + + Advance Options + + + + + + DEK Type + + + + +