From 0e424ec5faeec8d2a4276f2315c029b6efb87599 Mon Sep 17 00:00:00 2001 From: Dunemask Date: Sat, 14 Aug 2021 16:28:05 -0600 Subject: [PATCH] Added login integration with Cairo --- package.json | 3 +- src/App.js | 33 ------------- src/Stash.js | 66 +++++++++++++++++++++++++ src/config.json | 8 +++ src/index.js | 4 +- src/{Stash.jsx => stash/StashBoard.jsx} | 35 +++++-------- src/stash/StashContextMenu.jsx | 29 +++++------ src/stash/StashUpload.jsx | 7 ++- src/stash/api.json | 8 ++- 9 files changed, 111 insertions(+), 82 deletions(-) delete mode 100644 src/App.js create mode 100644 src/Stash.js create mode 100644 src/config.json rename src/{Stash.jsx => stash/StashBoard.jsx} (82%) diff --git a/package.json b/package.json index 142c426..d4803fe 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ }, "scripts": { "start": "node server/main.js", - "start:dev": "PORT=52026 react-scripts start", + "start:dev": "nodemon server/main.js", + "start:react": "PORT=52026 react-scripts start", "build": "react-scripts build" }, "eslintConfig": { diff --git a/src/App.js b/src/App.js deleted file mode 100644 index 2c525be..0000000 --- a/src/App.js +++ /dev/null @@ -1,33 +0,0 @@ -//Module Imports -import React from "react"; -import { ToastContainer } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; -//Local Imports -import Stash from "./Stash"; -//Constants -const token = - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYxMDhiMjI1ODBmYWEwMDAxMzQwZDdjMiIsImVtYWlsIjoiZHVuZXFhK3VzZXJAZ21haWwuY29tIiwiaXAiOiI6OmZmZmY6MTkyLjE2OC4yMjQuMSIsImlhdCI6MTYyNzk1OTg0NSwiZXhwIjoxNjMwNTUxODQ1fQ.mGybyFVxGzQ0cSIU4oE-RQpkQM45kIGHVFNAQmwsvvk"; -localStorage.setItem("authToken", token); -class App extends React.Component { - render() { - return ( - <> - - - - ); - } -} - -export default App; diff --git a/src/Stash.js b/src/Stash.js new file mode 100644 index 0000000..e2d6e25 --- /dev/null +++ b/src/Stash.js @@ -0,0 +1,66 @@ +//Module Imports +import React from "react"; +import axios from "axios"; +import { ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +//Local Imports +import StashBoard from "./stash/StashBoard"; +import { api } from "./config.json"; + +const getCairoApiInstance = (cairoAuthToken) => + axios.create({ + headers: { Authorization: `Bearer ${cairoAuthToken}` }, + }); + +class Stash extends React.Component { + constructor(props) { + super(props); + const urlSearchParams = new URLSearchParams(window.location.search); + const params = Object.fromEntries(urlSearchParams.entries()); + this.state = { cairoApi: null }; + if (params.cairoAuthToken) this.setLocalToken(params.cairoAuthToken); + } + + componentDidMount() { + this.verifyLocalToken(); + } + + verifyLocalToken() { + const token = localStorage.getItem("cairoAuthToken"); + axios + .get(api.cairo.verify, { headers: { authorization: `Bearer ${token}` } }) + .then(() => this.setState({ cairoApi: getCairoApiInstance(token) })) + .catch(() => + window.location.replace( + `${api.cairo.login}?redirectUri=${window.location.href}` + ) + ); + } + + setLocalToken(cairoAuthToken) { + localStorage.setItem("cairoAuthToken", cairoAuthToken); + window.history.replaceState({}, document.title, "/"); + } + + render() { + return ( + <> + + {this.state.cairoApi && } + + ); + } +} + +export default Stash; diff --git a/src/config.json b/src/config.json new file mode 100644 index 0000000..895d00b --- /dev/null +++ b/src/config.json @@ -0,0 +1,8 @@ +{ + "api": { + "cairo": { + "verify": "/api/cairo/user/data", + "login": "http://cairo.dunestorm.net:52000/login" + } + } +} diff --git a/src/index.js b/src/index.js index b1ef1c0..75e7b81 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,10 @@ import React from "react"; import ReactDOM from "react-dom"; -import App from "./App"; +import Stash from "./Stash"; ReactDOM.render( - + , document.getElementById("root") ); diff --git a/src/Stash.jsx b/src/stash/StashBoard.jsx similarity index 82% rename from src/Stash.jsx rename to src/stash/StashBoard.jsx index 3b876e9..7a9f53c 100644 --- a/src/Stash.jsx +++ b/src/stash/StashBoard.jsx @@ -1,22 +1,15 @@ //Module Imports import React from "react"; -import axios from "axios"; import { toast } from "react-toastify"; //Local Imports -import Stashbar from "./stash/Stashbar"; -import StashUpload from "./stash/StashUpload"; -import StashContextMenu from "./stash/StashContextMenu"; -import { serverUrls} from "./stash/api.json"; -import "./stash/scss/Stash.scss"; +import Stashbar from "./Stashbar"; +import StashUpload from "./StashUpload"; +import StashContextMenu from "./StashContextMenu"; +import { serverUrls } from "./api.json"; +import "./scss/Stash.scss"; //Constants const filesUrl = `${serverUrls.GET.filesUrl}`; //Class -const getConfig = () => ({ - headers: { - authorization: `Bearer ${localStorage.getItem("authToken")}`, - withCredentials: true, - }, -}); const buildFilebox = (file, index) => ({ file, @@ -31,9 +24,10 @@ const buildDownload = (name, total) => ({ progress: 0.01, }); -class Stash extends React.Component { +class StashBoard extends React.Component { constructor(props) { super(props); + window.cairoApi = props.cairoApi; this.state = { fileBoxes: {}, downloads: {}, @@ -42,13 +36,11 @@ class Stash extends React.Component { } componentDidMount() { - axios - .get(filesUrl, getConfig()) + window.cairoApi + .get(filesUrl) .then((res) => { - if (res.status === 401) return console.log("Would redirect to login"); if (res.data === undefined || res.data.length === undefined) return toast.error("Error Loading Files"); - var fileBoxes = {}; res.data.forEach((file, index) => { fileBoxes[file._id] = buildFilebox(file, index); @@ -56,15 +48,12 @@ class Stash extends React.Component { this.setState({ fileBoxes }); }) .catch((error) => { - if (error.response.status === 401) - console.log("Would redirect to login"); + if (error.response.status === 401) return toast.error("Unauthorized!"); else console.error(error); }); } - fileBoxesChanged(fileBoxes) { - this.setState({ fileBoxes }); - } + fileBoxesChanged = (fileBoxes) => this.setState({ fileBoxes }); getSelectedBoxes() { var selectedBoxes = []; @@ -155,4 +144,4 @@ class Stash extends React.Component { } } -export default Stash; +export default StashBoard; diff --git a/src/stash/StashContextMenu.jsx b/src/stash/StashContextMenu.jsx index 95ffd6a..f2fb7c2 100644 --- a/src/stash/StashContextMenu.jsx +++ b/src/stash/StashContextMenu.jsx @@ -1,5 +1,4 @@ import React from "react"; -import axios from "axios"; import { toast } from "react-toastify"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import FileDownload from "js-file-download"; @@ -18,11 +17,6 @@ const downloadUrl = `${serverUrls.POST.downloadUrl}`; const deleteUrl = `${serverUrls.POST.deleteUrl}`; const publicUrl = `${serverUrls.POST.publicUrl}`; -function getConfig() { - var authToken = localStorage.getItem("authToken"); - return { headers: { authorization: `Bearer ${authToken}` } }; -} - export default class StashContextMenu extends React.Component { infoView() { var selectedCount = this.props.getSelectedBoxes().length; @@ -42,15 +36,15 @@ export default class StashContextMenu extends React.Component { } deleteClick() { const selectedBoxes = this.props.getSelectedBoxes(); - axios - .post(deleteUrl, selectedBoxes, getConfig()) + window.cairoApi + .post(deleteUrl, selectedBoxes) .then((res) => this.handleDelete(res, selectedBoxes)) .catch((e) => this.handleDelete(e.response, selectedBoxes)); } publicClick() { const selectedBoxes = this.props.getSelectedBoxes(); - axios - .post(publicUrl, selectedBoxes, getConfig()) + window.cairoApi + .post(publicUrl, selectedBoxes) .then((res) => this.handlePublic(res, selectedBoxes)) .catch((e) => this.handlePublic(e.response, selectedBoxes)); } @@ -71,14 +65,15 @@ export default class StashContextMenu extends React.Component { } handleDownload(url, file) { const downloadName = `${file.date}-${file.name}`; - const config = getConfig(); - config.method = "GET"; - config["Content-Type"] = "application/octet-stream"; - config.responseType = "blob"; + const config = { + method: "GET", + "Content-Type": "application/octet-stream", + responseType: "blob", + onDownloadProgress: (e) => + this.props.updateDownload(downloadId, e.loaded, e.total), + }; const downloadId = this.props.startDownload(file.name); - config.onDownloadProgress = (e) => - this.props.updateDownload(downloadId, e.loaded, e.total); - axios.request(url, config).then((response) => { + window.cairoApi.request(url, config).then((response) => { if (response.status !== 200) return toast.error("There was an error downloading that!"); FileDownload(response.data, downloadName); diff --git a/src/stash/StashUpload.jsx b/src/stash/StashUpload.jsx index 9c70d70..fb21cf9 100644 --- a/src/stash/StashUpload.jsx +++ b/src/stash/StashUpload.jsx @@ -1,6 +1,6 @@ //Module Imports import React from "react"; -import axios, { CancelToken } from "axios"; +import { CancelToken } from "axios"; import { toast } from "react-toastify"; //Local Imports import StashDropzone from "./StashDropzone"; @@ -13,7 +13,6 @@ const cancelMessage = "User Canceled"; const successClearTime = 200; function buildUpload(file, uploadUuid, onProgress) { - var authToken = localStorage.getItem("authToken"); var upload = { file, uploadUuid, @@ -25,7 +24,7 @@ function buildUpload(file, uploadUuid, onProgress) { upload.cancelUpload = () => cancel(cancelMessage); }); upload.config = { - headers: { authorization: `Bearer ${authToken}`, filesize: file.size }, + headers: { filesize: file.size }, onUploadProgress: (e) => onProgress(e, uploadUuid), cancelToken, }; @@ -69,7 +68,7 @@ export default class StashUpload extends React.Component { startUpload(upload) { const data = new FormData(); data.append(uploadField, upload.file); - axios + window.cairoApi .post(uploadUrl, data, upload.config) .then((res) => this.uploadDone(res, upload)) .catch((e) => this.uploadError(e, upload)); diff --git a/src/stash/api.json b/src/stash/api.json index 7f69f80..539aeed 100644 --- a/src/stash/api.json +++ b/src/stash/api.json @@ -9,10 +9,14 @@ "GET": { "filesUrl": "/api/nubian/stash/files", "rawUrl": "/api/nubian/stash/raw" + }, + "api": { + "cairo": { + "verify": "/api/cairo/user/data" + } } }, "serverFields": { "uploadField": "user-selected-file" - }, - "constants": { "jwtHeader": "authorization" } + } }