Added login integration with Cairo
This commit is contained in:
parent
3b75eff883
commit
0e424ec5fa
9 changed files with 111 additions and 82 deletions
|
@ -25,7 +25,8 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server/main.js",
|
"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"
|
"build": "react-scripts build"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
|
33
src/App.js
33
src/App.js
|
@ -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 (
|
|
||||||
<>
|
|
||||||
<ToastContainer
|
|
||||||
position="top-right"
|
|
||||||
autoClose={5000}
|
|
||||||
hideProgressBar={false}
|
|
||||||
newestOnTop={false}
|
|
||||||
closeOnClick={true}
|
|
||||||
rtl={false}
|
|
||||||
limit={3}
|
|
||||||
pauseOnFocusLoss
|
|
||||||
draggable
|
|
||||||
pauseOnHover={false}
|
|
||||||
/>
|
|
||||||
<Stash />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
66
src/Stash.js
Normal file
66
src/Stash.js
Normal file
|
@ -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 (
|
||||||
|
<>
|
||||||
|
<ToastContainer
|
||||||
|
position="top-right"
|
||||||
|
autoClose={5000}
|
||||||
|
hideProgressBar={false}
|
||||||
|
newestOnTop={false}
|
||||||
|
closeOnClick={true}
|
||||||
|
rtl={false}
|
||||||
|
limit={3}
|
||||||
|
pauseOnFocusLoss
|
||||||
|
draggable
|
||||||
|
pauseOnHover={false}
|
||||||
|
/>
|
||||||
|
{this.state.cairoApi && <StashBoard cairoApi={this.state.cairoApi} />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Stash;
|
8
src/config.json
Normal file
8
src/config.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"api": {
|
||||||
|
"cairo": {
|
||||||
|
"verify": "/api/cairo/user/data",
|
||||||
|
"login": "http://cairo.dunestorm.net:52000/login"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import App from "./App";
|
import Stash from "./Stash";
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<Stash />
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,22 +1,15 @@
|
||||||
//Module Imports
|
//Module Imports
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import axios from "axios";
|
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
//Local Imports
|
//Local Imports
|
||||||
import Stashbar from "./stash/Stashbar";
|
import Stashbar from "./Stashbar";
|
||||||
import StashUpload from "./stash/StashUpload";
|
import StashUpload from "./StashUpload";
|
||||||
import StashContextMenu from "./stash/StashContextMenu";
|
import StashContextMenu from "./StashContextMenu";
|
||||||
import { serverUrls} from "./stash/api.json";
|
import { serverUrls } from "./api.json";
|
||||||
import "./stash/scss/Stash.scss";
|
import "./scss/Stash.scss";
|
||||||
//Constants
|
//Constants
|
||||||
const filesUrl = `${serverUrls.GET.filesUrl}`;
|
const filesUrl = `${serverUrls.GET.filesUrl}`;
|
||||||
//Class
|
//Class
|
||||||
const getConfig = () => ({
|
|
||||||
headers: {
|
|
||||||
authorization: `Bearer ${localStorage.getItem("authToken")}`,
|
|
||||||
withCredentials: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildFilebox = (file, index) => ({
|
const buildFilebox = (file, index) => ({
|
||||||
file,
|
file,
|
||||||
|
@ -31,9 +24,10 @@ const buildDownload = (name, total) => ({
|
||||||
progress: 0.01,
|
progress: 0.01,
|
||||||
});
|
});
|
||||||
|
|
||||||
class Stash extends React.Component {
|
class StashBoard extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
window.cairoApi = props.cairoApi;
|
||||||
this.state = {
|
this.state = {
|
||||||
fileBoxes: {},
|
fileBoxes: {},
|
||||||
downloads: {},
|
downloads: {},
|
||||||
|
@ -42,13 +36,11 @@ class Stash extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
axios
|
window.cairoApi
|
||||||
.get(filesUrl, getConfig())
|
.get(filesUrl)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === 401) return console.log("Would redirect to login");
|
|
||||||
if (res.data === undefined || res.data.length === undefined)
|
if (res.data === undefined || res.data.length === undefined)
|
||||||
return toast.error("Error Loading Files");
|
return toast.error("Error Loading Files");
|
||||||
|
|
||||||
var fileBoxes = {};
|
var fileBoxes = {};
|
||||||
res.data.forEach((file, index) => {
|
res.data.forEach((file, index) => {
|
||||||
fileBoxes[file._id] = buildFilebox(file, index);
|
fileBoxes[file._id] = buildFilebox(file, index);
|
||||||
|
@ -56,15 +48,12 @@ class Stash extends React.Component {
|
||||||
this.setState({ fileBoxes });
|
this.setState({ fileBoxes });
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
if (error.response.status === 401)
|
if (error.response.status === 401) return toast.error("Unauthorized!");
|
||||||
console.log("Would redirect to login");
|
|
||||||
else console.error(error);
|
else console.error(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fileBoxesChanged(fileBoxes) {
|
fileBoxesChanged = (fileBoxes) => this.setState({ fileBoxes });
|
||||||
this.setState({ fileBoxes });
|
|
||||||
}
|
|
||||||
|
|
||||||
getSelectedBoxes() {
|
getSelectedBoxes() {
|
||||||
var selectedBoxes = [];
|
var selectedBoxes = [];
|
||||||
|
@ -155,4 +144,4 @@ class Stash extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Stash;
|
export default StashBoard;
|
|
@ -1,5 +1,4 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import axios from "axios";
|
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import FileDownload from "js-file-download";
|
import FileDownload from "js-file-download";
|
||||||
|
@ -18,11 +17,6 @@ const downloadUrl = `${serverUrls.POST.downloadUrl}`;
|
||||||
const deleteUrl = `${serverUrls.POST.deleteUrl}`;
|
const deleteUrl = `${serverUrls.POST.deleteUrl}`;
|
||||||
const publicUrl = `${serverUrls.POST.publicUrl}`;
|
const publicUrl = `${serverUrls.POST.publicUrl}`;
|
||||||
|
|
||||||
function getConfig() {
|
|
||||||
var authToken = localStorage.getItem("authToken");
|
|
||||||
return { headers: { authorization: `Bearer ${authToken}` } };
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class StashContextMenu extends React.Component {
|
export default class StashContextMenu extends React.Component {
|
||||||
infoView() {
|
infoView() {
|
||||||
var selectedCount = this.props.getSelectedBoxes().length;
|
var selectedCount = this.props.getSelectedBoxes().length;
|
||||||
|
@ -42,15 +36,15 @@ export default class StashContextMenu extends React.Component {
|
||||||
}
|
}
|
||||||
deleteClick() {
|
deleteClick() {
|
||||||
const selectedBoxes = this.props.getSelectedBoxes();
|
const selectedBoxes = this.props.getSelectedBoxes();
|
||||||
axios
|
window.cairoApi
|
||||||
.post(deleteUrl, selectedBoxes, getConfig())
|
.post(deleteUrl, selectedBoxes)
|
||||||
.then((res) => this.handleDelete(res, selectedBoxes))
|
.then((res) => this.handleDelete(res, selectedBoxes))
|
||||||
.catch((e) => this.handleDelete(e.response, selectedBoxes));
|
.catch((e) => this.handleDelete(e.response, selectedBoxes));
|
||||||
}
|
}
|
||||||
publicClick() {
|
publicClick() {
|
||||||
const selectedBoxes = this.props.getSelectedBoxes();
|
const selectedBoxes = this.props.getSelectedBoxes();
|
||||||
axios
|
window.cairoApi
|
||||||
.post(publicUrl, selectedBoxes, getConfig())
|
.post(publicUrl, selectedBoxes)
|
||||||
.then((res) => this.handlePublic(res, selectedBoxes))
|
.then((res) => this.handlePublic(res, selectedBoxes))
|
||||||
.catch((e) => this.handlePublic(e.response, selectedBoxes));
|
.catch((e) => this.handlePublic(e.response, selectedBoxes));
|
||||||
}
|
}
|
||||||
|
@ -71,14 +65,15 @@ export default class StashContextMenu extends React.Component {
|
||||||
}
|
}
|
||||||
handleDownload(url, file) {
|
handleDownload(url, file) {
|
||||||
const downloadName = `${file.date}-${file.name}`;
|
const downloadName = `${file.date}-${file.name}`;
|
||||||
const config = getConfig();
|
const config = {
|
||||||
config.method = "GET";
|
method: "GET",
|
||||||
config["Content-Type"] = "application/octet-stream";
|
"Content-Type": "application/octet-stream",
|
||||||
config.responseType = "blob";
|
responseType: "blob",
|
||||||
|
onDownloadProgress: (e) =>
|
||||||
|
this.props.updateDownload(downloadId, e.loaded, e.total),
|
||||||
|
};
|
||||||
const downloadId = this.props.startDownload(file.name);
|
const downloadId = this.props.startDownload(file.name);
|
||||||
config.onDownloadProgress = (e) =>
|
window.cairoApi.request(url, config).then((response) => {
|
||||||
this.props.updateDownload(downloadId, e.loaded, e.total);
|
|
||||||
axios.request(url, config).then((response) => {
|
|
||||||
if (response.status !== 200)
|
if (response.status !== 200)
|
||||||
return toast.error("There was an error downloading that!");
|
return toast.error("There was an error downloading that!");
|
||||||
FileDownload(response.data, downloadName);
|
FileDownload(response.data, downloadName);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//Module Imports
|
//Module Imports
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import axios, { CancelToken } from "axios";
|
import { CancelToken } from "axios";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
//Local Imports
|
//Local Imports
|
||||||
import StashDropzone from "./StashDropzone";
|
import StashDropzone from "./StashDropzone";
|
||||||
|
@ -13,7 +13,6 @@ const cancelMessage = "User Canceled";
|
||||||
const successClearTime = 200;
|
const successClearTime = 200;
|
||||||
|
|
||||||
function buildUpload(file, uploadUuid, onProgress) {
|
function buildUpload(file, uploadUuid, onProgress) {
|
||||||
var authToken = localStorage.getItem("authToken");
|
|
||||||
var upload = {
|
var upload = {
|
||||||
file,
|
file,
|
||||||
uploadUuid,
|
uploadUuid,
|
||||||
|
@ -25,7 +24,7 @@ function buildUpload(file, uploadUuid, onProgress) {
|
||||||
upload.cancelUpload = () => cancel(cancelMessage);
|
upload.cancelUpload = () => cancel(cancelMessage);
|
||||||
});
|
});
|
||||||
upload.config = {
|
upload.config = {
|
||||||
headers: { authorization: `Bearer ${authToken}`, filesize: file.size },
|
headers: { filesize: file.size },
|
||||||
onUploadProgress: (e) => onProgress(e, uploadUuid),
|
onUploadProgress: (e) => onProgress(e, uploadUuid),
|
||||||
cancelToken,
|
cancelToken,
|
||||||
};
|
};
|
||||||
|
@ -69,7 +68,7 @@ export default class StashUpload extends React.Component {
|
||||||
startUpload(upload) {
|
startUpload(upload) {
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
data.append(uploadField, upload.file);
|
data.append(uploadField, upload.file);
|
||||||
axios
|
window.cairoApi
|
||||||
.post(uploadUrl, data, upload.config)
|
.post(uploadUrl, data, upload.config)
|
||||||
.then((res) => this.uploadDone(res, upload))
|
.then((res) => this.uploadDone(res, upload))
|
||||||
.catch((e) => this.uploadError(e, upload));
|
.catch((e) => this.uploadError(e, upload));
|
||||||
|
|
|
@ -9,10 +9,14 @@
|
||||||
"GET": {
|
"GET": {
|
||||||
"filesUrl": "/api/nubian/stash/files",
|
"filesUrl": "/api/nubian/stash/files",
|
||||||
"rawUrl": "/api/nubian/stash/raw"
|
"rawUrl": "/api/nubian/stash/raw"
|
||||||
|
},
|
||||||
|
"api": {
|
||||||
|
"cairo": {
|
||||||
|
"verify": "/api/cairo/user/data"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"serverFields": {
|
"serverFields": {
|
||||||
"uploadField": "user-selected-file"
|
"uploadField": "user-selected-file"
|
||||||
},
|
}
|
||||||
"constants": { "jwtHeader": "authorization" }
|
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue