From 7d4c48b45c9ee77d0db0a3e1594aadfbd28b5243 Mon Sep 17 00:00:00 2001 From: Miles <14067660+milesflo@users.noreply.github.com> Date: Tue, 21 Jul 2020 22:47:01 -0700 Subject: [PATCH] Housekeeping. Refer to PR for specifics --- frontend/package-lock.json | 20 +- frontend/src/Admin.js | 1039 ----------------- frontend/src/App.js | 169 --- frontend/src/App.jsx | 168 +++ frontend/src/Flows.js | 25 - frontend/src/Hookpost.js | 25 - frontend/src/Schedulespost.js | 25 - frontend/src/{ => __test__}/appdata.js | 0 .../src/{ => __test__}/environmentdata.js | 0 frontend/src/{ => __test__}/scheduledata.js | 0 frontend/src/{ => __test__}/webhookdata.js | 0 frontend/src/{ => __test__}/workflowdata.js | 0 frontend/src/{ => components}/AlertPopup.js | 0 .../src/{ => components}/AlertTemplate.js | 0 frontend/src/{ => components}/FooterNew.js | 0 frontend/src/{ => components}/Header.js | 0 frontend/src/{ => components}/LoginPopup.js | 0 .../src/{ => components}/SettingsPopup.js | 0 frontend/src/{About.js => views/About.jsx} | 12 +- frontend/src/views/Admin.jsx | 1039 +++++++++++++++++ .../{AdminSetup.js => views/AdminSetup.jsx} | 0 .../AngularWorkflow.jsx} | 9 +- .../{AppCreator.js => views/AppCreator.jsx} | 0 frontend/src/{Apps.js => views/Apps.jsx} | 2 +- .../src/{Contact.js => views/Contact.jsx} | 196 ++-- .../src/{Dashboard.js => views/Dashboard.jsx} | 2 +- frontend/src/{Docs.js => views/Docs.jsx} | 0 .../EditSchedule.jsx} | 3 - .../{EditWebhook.js => views/EditWebhook.jsx} | 4 +- .../EditWorkflow.jsx} | 0 .../ForgotPassword.jsx} | 0 .../ForgotPasswordLink.jsx} | 0 .../{Landingpage.js => views/Landingpage.jsx} | 0 .../LandingpageLoggedin.jsx} | 0 .../LandingpageNew.jsx} | 0 .../src/{LoginPage.js => views/LoginPage.jsx} | 190 +-- frontend/src/{Oauth2.js => views/Oauth2.jsx} | 0 frontend/src/{Post.js => views/Post.jsx} | 0 .../PrivacyPolicy.jsx} | 0 .../RegisterLink.jsx} | 0 .../RegisterPage.jsx} | 0 .../src/{Schedules.js => views/Schedules.jsx} | 0 .../SettingsPage.jsx} | 0 .../src/{Webhooks.js => views/Webhooks.jsx} | 4 +- .../src/{Workflows.js => views/Workflows.jsx} | 2 +- 45 files changed, 1428 insertions(+), 1506 deletions(-) delete mode 100644 frontend/src/Admin.js delete mode 100644 frontend/src/App.js create mode 100644 frontend/src/App.jsx delete mode 100644 frontend/src/Flows.js delete mode 100644 frontend/src/Hookpost.js delete mode 100644 frontend/src/Schedulespost.js rename frontend/src/{ => __test__}/appdata.js (100%) rename frontend/src/{ => __test__}/environmentdata.js (100%) rename frontend/src/{ => __test__}/scheduledata.js (100%) rename frontend/src/{ => __test__}/webhookdata.js (100%) rename frontend/src/{ => __test__}/workflowdata.js (100%) rename frontend/src/{ => components}/AlertPopup.js (100%) rename frontend/src/{ => components}/AlertTemplate.js (100%) rename frontend/src/{ => components}/FooterNew.js (100%) rename frontend/src/{ => components}/Header.js (100%) rename frontend/src/{ => components}/LoginPopup.js (100%) rename frontend/src/{ => components}/SettingsPopup.js (100%) rename frontend/src/{About.js => views/About.jsx} (85%) create mode 100644 frontend/src/views/Admin.jsx rename frontend/src/{AdminSetup.js => views/AdminSetup.jsx} (100%) rename frontend/src/{AngularWorkflow.js => views/AngularWorkflow.jsx} (99%) rename frontend/src/{AppCreator.js => views/AppCreator.jsx} (100%) rename frontend/src/{Apps.js => views/Apps.jsx} (99%) rename frontend/src/{Contact.js => views/Contact.jsx} (54%) rename frontend/src/{Dashboard.js => views/Dashboard.jsx} (99%) rename frontend/src/{Docs.js => views/Docs.jsx} (100%) rename frontend/src/{EditSchedule.js => views/EditSchedule.jsx} (99%) rename frontend/src/{EditWebhook.js => views/EditWebhook.jsx} (98%) rename frontend/src/{EditWorkflow.js => views/EditWorkflow.jsx} (100%) rename frontend/src/{ForgotPassword.js => views/ForgotPassword.jsx} (100%) rename frontend/src/{ForgotPasswordLink.js => views/ForgotPasswordLink.jsx} (100%) rename frontend/src/{Landingpage.js => views/Landingpage.jsx} (100%) rename frontend/src/{LandingpageLoggedin.js => views/LandingpageLoggedin.jsx} (100%) rename frontend/src/{LandingpageNew.js => views/LandingpageNew.jsx} (100%) rename frontend/src/{LoginPage.js => views/LoginPage.jsx} (56%) rename frontend/src/{Oauth2.js => views/Oauth2.jsx} (100%) rename frontend/src/{Post.js => views/Post.jsx} (100%) rename frontend/src/{PrivacyPolicy.js => views/PrivacyPolicy.jsx} (100%) rename frontend/src/{RegisterLink.js => views/RegisterLink.jsx} (100%) rename frontend/src/{RegisterPage.js => views/RegisterPage.jsx} (100%) rename frontend/src/{Schedules.js => views/Schedules.jsx} (100%) rename frontend/src/{SettingsPage.js => views/SettingsPage.jsx} (100%) rename frontend/src/{Webhooks.js => views/Webhooks.jsx} (98%) rename frontend/src/{Workflows.js => views/Workflows.jsx} (99%) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 276ecded..7af54656 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,6 +1,6 @@ { "name": "shuffler", - "version": "0.3.0", + "version": "0.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3733,9 +3733,9 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { - "version": "14.0.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", - "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==" + "version": "14.0.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.24.tgz", + "integrity": "sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA==" }, "@types/object-assign": { "version": "4.0.30", @@ -3748,9 +3748,9 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "@types/prop-types": { - "version": "15.7.1", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", - "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==" + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/q": { "version": "1.5.4", @@ -3758,9 +3758,9 @@ "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" }, "@types/react": { - "version": "16.8.20", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.20.tgz", - "integrity": "sha512-ZLmI+ubSJpfUIlQuULDDrdyuFQORBuGOvNnMue8HeA0GVrAJbWtZQhcBvnBPNRBI/GrfSfrKPFhthzC2SLEtLQ==", + "version": "16.9.43", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.43.tgz", + "integrity": "sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg==", "requires": { "@types/prop-types": "*", "csstype": "^2.2.0" diff --git a/frontend/src/Admin.js b/frontend/src/Admin.js deleted file mode 100644 index e60d14e0..00000000 --- a/frontend/src/Admin.js +++ /dev/null @@ -1,1039 +0,0 @@ -import React, { useEffect} from 'react'; - -import {Link} from 'react-router-dom'; -import Paper from '@material-ui/core/Paper'; -import Select from '@material-ui/core/Select'; -import MenuItem from '@material-ui/core/MenuItem'; -import List from '@material-ui/core/List'; -import Divider from '@material-ui/core/Divider'; -import TextField from '@material-ui/core/TextField'; -import ListItem from '@material-ui/core/ListItem'; -import Button from '@material-ui/core/Button'; -import Tabs from '@material-ui/core/Tabs'; -import Tab from '@material-ui/core/Tab'; -import ListItemText from '@material-ui/core/ListItemText'; -import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; - -import { useAlert } from "react-alert"; - -import Dialog from '@material-ui/core/Dialog'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; - -import CachedIcon from '@material-ui/icons/Cached'; - -const surfaceColor = "#27292D" -const inputColor = "#383B40" -const Admin = (props) => { - const { globalUrl, } = props; - const [firstRequest, setFirstRequest] = React.useState(true); - const [modalUser, setModalUser] = React.useState({}); - const [modalOpen, setModalOpen] = React.useState(false); - const [loginInfo, setLoginInfo] = React.useState(""); - const [curTab, setCurTab] = React.useState(0); - const [users, setUsers] = React.useState([]); - const [environments, setEnvironments] = React.useState([]); - const [authentication, setAuthentication] = React.useState([]); - const [schedules, setSchedules] = React.useState([]) - const [selectedUser, setSelectedUser] = React.useState({}) - const [newPassword, setNewPassword] = React.useState(""); - const [selectedUserModalOpen, setSelectedUserModalOpen] = React.useState(false) - const [selectedAuthentication, setSelectedAuthentication] = React.useState({}) - const [selectedAuthenticationModalOpen, setSelectedAuthenticationModalOpen] = React.useState(false) - - const alert = useAlert() - - const deleteAuthentication = (data) => { - alert.info("Deleting auth "+data.label) - - // Just use this one? - const url = globalUrl+'/api/v1/apps/authentication/'+data.id - console.log("URL: ", url) - fetch(url, { - method: 'DELETE', - credentials: "include", - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(response => - response.json().then(responseJson => { - console.log("RESP: ", responseJson) - if (responseJson["success"] === false) { - alert.error("Failed stopping schedule") - } else { - getAppAuthentication() - alert.success("Successfully stopped schedule!") - } - }), - ) - .catch(error => { - console.log("Error in userdata: ", error) - }); - } - - const deleteSchedule = (data) => { - // FIXME - add some check here ROFL - console.log("INPUT: ", data) - - // Just use this one? - const url = globalUrl+'/api/v1/workflows/'+data["workflow_id"]+"/schedule/"+data.id - console.log("URL: ", url) - fetch(url, { - method: 'DELETE', - credentials: "include", - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(response => - response.json().then(responseJson => { - console.log("RESP: ", responseJson) - if (responseJson["success"] === false) { - alert.error("Failed stopping schedule") - } else { - getSchedules() - alert.success("Successfully stopped schedule!") - } - }), - ) - .catch(error => { - console.log("Error in userdata: ", error) - }); - } - - const onPasswordChange = () => { - const data = {"username": selectedUser.username, "newpassword": newPassword} - const url = globalUrl+'/api/v1/users/passwordchange'; - fetch(url, { - mode: 'cors', - method: 'POST', - body: JSON.stringify(data), - credentials: 'include', - crossDomain: true, - withCredentials: true, - headers: { - 'Content-Type': 'application/json; charset=utf-8', - }, - }) - .then(response => - response.json().then(responseJson => { - if (responseJson["success"] === false) { - alert.error("Failed setting new password") - } else { - alert.success("Changed password!") - } - }), - ) - .catch(error => { - alert.error("Err: "+error.toString()) - }); - } - - const deleteUser = (data) => { - // Just use this one? - const url = globalUrl+'/api/v1/users/'+data.id - fetch(url, { - method: 'DELETE', - credentials: "include", - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(response => { - if (response.status === 200) { - getUsers() - } - - return response.json() - }) - .then((responseJson) => { - if (!responseJson.success && responseJson.reason !== undefined) { - alert.error("Failed to deactivate user: "+responseJson.reason) - } else { - alert.success("Deactivated user "+data.id) - } - }) - - .catch(error => { - console.log("Error in userdata: ", error) - }); - } - - const submitUser = (data) => { - // FIXME - add some check here ROFL - console.log("INPUT: ", data) - - // Just use this one? - var data = {"username": data.Username, "password": data.Password} - var baseurl = globalUrl - const url = baseurl+'/api/v1/users/register'; - fetch(url, { - method: 'POST', - credentials: "include", - body: JSON.stringify(data), - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(response => - response.json().then(responseJson => { - if (responseJson["success"] === false) { - setLoginInfo("Error in input: "+responseJson.reason) - } else { - setLoginInfo("") - setModalOpen(false) - getUsers() - } - }), - ) - .catch(error => { - console.log("Error in userdata: ", error) - }); - } - - const deleteEnvironment = (name) => { - // FIXME - add some check here ROFL - alert.info("Deleting environment "+name) - var newEnv = [] - for (var key in environments) { - if (environments[key].Name == name) { - continue - } - - newEnv.push(environments[key]) - } - - // Just use this one? - const url = globalUrl+'/api/v1/setenvironments'; - fetch(url, { - method: 'PUT', - credentials: "include", - body: JSON.stringify(newEnv), - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(response => - response.json().then(responseJson => { - if (responseJson["success"] === false) { - alert.error(responseJson.reason) - } else { - setLoginInfo("") - setModalOpen(false) - getEnvironments() - } - }), - ) - //.catch(error => { - // console.log("Error in userdata: ", error) - //}); - } - - const submitEnvironment = (data) => { - // FIXME - add some check here ROFL - environments.push({"name": data.environment, "type": "onprem"}) - - // Just use this one? - var baseurl = globalUrl - const url = baseurl+'/api/v1/setenvironments'; - fetch(url, { - method: 'PUT', - credentials: "include", - body: JSON.stringify(environments), - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(response => - response.json().then(responseJson => { - if (responseJson["success"] === false) { - setLoginInfo("Error in input: "+responseJson.reason) - } else { - setLoginInfo("") - setModalOpen(false) - getEnvironments() - } - }), - ) - .catch(error => { - console.log("Error in userdata: ", error) - }); - } - - const getSchedules = () => { - fetch(globalUrl+"/api/v1/workflows/schedules", { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for apps :O!") - return - } - - return response.json() - }) - .then((responseJson) => { - setSchedules(responseJson) - }) - .catch(error => { - alert.error(error.toString()) - }); - } - - const getAppAuthentication = () => { - fetch(globalUrl+"/api/v1/apps/authentication", { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for apps :O!") - return - } - - return response.json() - }) - .then((responseJson) => { - if (responseJson.success) { - console.log(responseJson.data) - setAuthentication(responseJson.data) - } else { - alert.error("Failed getting authentications") - } - }) - .catch(error => { - alert.error(error.toString()) - }); - } - - const getEnvironments = () => { - fetch(globalUrl+"/api/v1/getenvironments", { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for apps :O!") - return - } - - return response.json() - }) - .then((responseJson) => { - console.log(responseJson) - setEnvironments(responseJson) - }) - .catch(error => { - alert.error(error.toString()) - }); - } - - const getUsers = () => { - fetch(globalUrl+"/api/v1/getusers", { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for apps :O!") - return - } - - return response.json() - }) - .then((responseJson) => { - console.log(responseJson) - setUsers(responseJson) - }) - .catch(error => { - alert.error(error.toString()) - }); - } - - if (firstRequest) { - setFirstRequest(false) - getUsers() - } - - const paperStyle = { - maxWidth: 1250, - margin: "auto", - color: "white", - backgroundColor: surfaceColor, - marginBottom: 10, - padding: 20, - } - - const changeModalData = (field, value) => { - modalUser[field] = value - } - - const setUser = (userId, field, value) => { - const data = {"user_id": userId} - data[field] = value - console.log("DATA: ", data) - - fetch(globalUrl+"/api/v1/users/updateuser", { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - body: JSON.stringify(data), - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for WORKFLOW EXECUTION :O!") - } else { - getUsers() - } - - return response.json() - }) - .then((responseJson) => { - if (!responseJson.success && responseJson.reason !== undefined) { - alert.error("Failed setting user: "+responseJson.reason) - } else { - alert.success("Set the user field "+field+" to "+value) - } - }) - .catch(error => { - console.log(error) - }); - } - - - - const generateApikey = (userId) => { - const data = {"user_id": userId} - - fetch(globalUrl+"/api/v1/generateapikey", { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - body: JSON.stringify(data), - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for WORKFLOW EXECUTION :O!") - } else { - getUsers() - } - - return response.json() - }) - .then((responseJson) => { - console.log("RESP: ", responseJson) - if (!responseJson.success && responseJson.reason !== undefined) { - alert.error("Failed getting new: "+responseJson.reason) - } else { - alert.success("Got new API key") - } - }) - .catch(error => { - console.log(error) - }); - } - - const editAuthenticationModal = - {setSelectedAuthenticationModalOpen(false)}} - PaperProps={{ - style: { - backgroundColor: surfaceColor, - color: "white", - minWidth: "800px", - minHeight: "320px", - }, - }} - > - Edit authentication - -
- setNewPassword(e.target.value)} - /> - -
- - - -
-
- - const editUserModal = - {setSelectedUserModalOpen(false)}} - PaperProps={{ - style: { - backgroundColor: surfaceColor, - color: "white", - minWidth: "800px", - minHeight: "320px", - }, - }} - > - Edit user - -
- setNewPassword(e.target.value)} - /> - -
- - - -
-
- - const modalView = - {setModalOpen(false)}} - PaperProps={{ - style: { - backgroundColor: surfaceColor, - color: "white", - minWidth: "800px", - minHeight: "320px", - }, - }} - > - - {curTab === 0 ? "Add user" : "Add environment"} - - - {curTab === 0 ? -
- Username - changeModalData("Username", event.target.value)} - /> - Password - changeModalData("Password", event.target.value)} - /> -
- : curTab === 2 ? -
- Environment Name - changeModalData("environment", event.target.value)} - /> -
- : null } - {loginInfo} -
- - - - -
- - const usersView = curTab === 0 ? -
-
-

User management

- Add, edit, block or change passwords -
-
- - - - - - - - - - - {users === undefined ? null : users.map(data => { - return ( - - - - { - console.log("VALUE: ", e.target.value) - setUser(data.id, "role", e.target.value) - }} - style={{backgroundColor: surfaceColor, color: "white", height: "50px"}} - > - - Admin - - - User - - - style={{minWidth: 150, maxWidth: 150}} - /> - - - - - - ) - })} - -
- : null - - const schedulesView = curTab === 3 ? -
-
-

Schedules

- Schedules used in Workflows. Makes locating and control easier. -
- - - - - - - - {schedules === undefined || schedules === null ? null : schedules.map(schedule => { - return ( - - - - - - - - ) - })} - -
- : null - - const authenticationView = curTab === 1 ? -
-
-

App Authentication

- Control the authentication options for individual apps. Actions can be destructive! -
- - - - - - - - - - - - {authentication === undefined ? null : authentication.map(data => { - return ( - - - style={{minWidth: 150, maxWidth: 150}} - /> - - - - - { - return data.key - }).join(", ")} - style={{minWidth: 200, maxWidth: 200, overflow: "hidden"}} - /> - - - - - ) - })} - -
- : null - - const environmentView = curTab === 2 ? -
-
-

Environments

- Decides what Orborus environment to execute an action in a workflow in. -
- - - - - - - - - - {environments === undefined ? null : environments.map(environment => { - return ( - - - - - - - - ) - })} - -
- : null - - // primary={environment.Registered ? "true" : "false"} - - const setConfig = (event, newValue) => { - if (newValue === 1) { - getAppAuthentication() - } else if (newValue === 2) { - getEnvironments() - } else if (newValue === 3) { - getSchedules() - } - - setModalUser({}) - setCurTab(newValue) - } - - const data = -
- - - - - - - - -
- {authenticationView} - {usersView} - {environmentView} - {schedulesView} -
-
-
- - return ( -
- {modalView} - {editUserModal} - {editAuthenticationModal} - {data} -
- ) -} - -export default Admin diff --git a/frontend/src/App.js b/frontend/src/App.js deleted file mode 100644 index c162b774..00000000 --- a/frontend/src/App.js +++ /dev/null @@ -1,169 +0,0 @@ -import React, {useState, useEffect} from 'react'; - -import {Route} from 'react-router'; -import {BrowserRouter} from 'react-router-dom'; -import { CookiesProvider } from 'react-cookie'; -import { useCookies } from 'react-cookie'; - -import EditSchedule from "./EditSchedule"; -import Schedules from "./Schedules"; -import Webhooks from "./Webhooks"; -import Workflows from "./Workflows"; -import EditWebhook from "./EditWebhook"; -import AngularWorkflow from "./AngularWorkflow"; -import ForgotPassword from "./ForgotPassword"; -import ForgotPasswordLink from "./ForgotPasswordLink"; - -import Header from './Header'; -import Apps from './Apps'; -import AppCreator from './AppCreator'; -import Contact from './Contact'; -import Oauth2 from './Oauth2'; -import About from "./About"; -import Post from "./Post"; -import Dashboard from "./Dashboard"; -import AdminSetup from "./AdminSetup"; -import Admin from "./Admin"; -import Docs from "./Docs"; -import RegisterLink from "./RegisterLink"; -import LandingPage from "./Landingpage"; -import LandingPageNew from "./LandingpageNew"; -import LoginPage from "./LoginPage"; -import SettingsPage from "./SettingsPage"; - -import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider'; -import { createMuiTheme } from '@material-ui/core/styles'; - -import AlertTemplate from "react-alert-template-basic"; -import { positions, Provider } from "react-alert"; - -// Production - backend proxy forwarding in nginx -var globalUrl = window.location.origin - -// CORS used for testing purposes. Should only happen with specific port and http -if (window.location.protocol == "http:" && window.location.port === "3000") { - globalUrl = "http://localhost:5001" -} - -const surfaceColor = "#27292D" -const inputColor = "#383B40" - -const theme = createMuiTheme({ - palette: { - primary: { - main: "#f85a3e" - }, - secondary: { - main: '#e8eaf6', - }, - }, - typography: { - useNextVariants: true - }, - overrides: { - MuiMenu: { - list: { - backgroundColor: inputColor, - }, - }, - }, -}); - - -// FIXME - set client side cookies -const App = (message, props) => { - const [userdata, setUserData] = useState({}); - //const [homePage, ] = useState(true); - const [cookies, setCookie, removeCookie] = useCookies([]); - const [isLoggedIn, setIsLoggedIn] = useState(false); - const [dataset, setDataset] = useState(false); - const [isLoaded, setIsLoaded] = useState(false); - - useEffect(() => { - if (dataset === false) { - checkLogin() - setDataset(true) - }}) - - if (isLoaded && !isLoggedIn && (!window.location.pathname.startsWith("/login") && (!window.location.pathname.startsWith("/docs") && (!window.location.pathname.startsWith("/adminsetup"))))) { - window.location = "/login" - } - - const checkLogin = () => { - var baseurl = globalUrl - fetch(baseurl+"/api/v1/users/getinfo", { - credentials: "include", - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(response => response.json()) - .then(responseJson => { - if (responseJson.success === true) { - setUserData(responseJson) - setIsLoggedIn(true) - - // Updating cookie every request - for (var key in responseJson["cookies"]) { - setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, {path: "/"}) - } - } - setIsLoaded(true) - }) - .catch(error => { - setIsLoaded(true) - }); - } - - // Dumb for content load (per now), but good for making the site not suddenly reload parts (ajax thingies) - - const options = { - timeout: 5000, - position: positions.BOTTOM_CENTER - }; - - const includedData = window.location.pathname === "/home" || window.location.pathname === "/features" ? -
- } /> -
: -
-
- } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - {window.location.pathname = "/docs/about"}} /> - {window.location.pathname = "/login"}} /> -
- - //
- // backgroundColor: "#213243", - // This is a mess hahahah - return ( - - - - - {includedData} - - - - - ); -}; - -export default App; - diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx new file mode 100644 index 00000000..2c23c389 --- /dev/null +++ b/frontend/src/App.jsx @@ -0,0 +1,168 @@ +import React, { useState, useEffect } from 'react'; + +import { Route } from 'react-router'; +import { BrowserRouter } from 'react-router-dom'; +import { CookiesProvider } from 'react-cookie'; +import { useCookies } from 'react-cookie'; + +import EditSchedule from "./views/EditSchedule"; +import Schedules from "./views/Schedules"; +import Webhooks from "./views/Webhooks"; +import Workflows from "./views/Workflows"; +import EditWebhook from "./views/EditWebhook"; +import AngularWorkflow from "./views/AngularWorkflow"; +// import ForgotPassword from "./views/ForgotPassword"; +// import ForgotPasswordLink from "./components/ForgotPasswordLink"; + +import Header from './components/Header'; +import Apps from './views/Apps'; +import AppCreator from './views/AppCreator'; +import Contact from './views/Contact'; +import Oauth2 from './views/Oauth2'; +// import About from "./views/About"; +// import Post from "./views/Post"; +import Dashboard from "./views/Dashboard"; +import AdminSetup from "./views/AdminSetup"; +import Admin from "./views/Admin"; +import Docs from "./views/Docs"; +// import RegisterLink from "./views/RegisterLink"; +// import LandingPage from "./views/Landingpage"; +import LandingPageNew from "./views/LandingpageNew"; +import LoginPage from "./views/LoginPage"; +import SettingsPage from "./views/SettingsPage"; + +import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles'; + +import AlertTemplate from "react-alert-template-basic"; +import { positions, Provider } from "react-alert"; + +// Production - backend proxy forwarding in nginx +var globalUrl = window.location.origin + +// CORS used for testing purposes. Should only happen with specific port and http +if (window.location.protocol == "http:" && window.location.port === "3000") { + globalUrl = "http://localhost:5001" +} + +const theme = createMuiTheme({ + palette: { + primary: { + main: "#f85a3e" + }, + secondary: { + main: '#e8eaf6', + }, + surfaceColor: "#27292d", + inputColor: "#383B40" + }, + typography: { + useNextVariants: true + }, + overrides: { + MuiMenu: { + list: { + backgroundColor: "#383B40", + }, + }, + }, +}); + + +// FIXME - set client side cookies +const App = (message, props) => { + const [userdata, setUserData] = useState({}); + //const [homePage, ] = useState(true); + const [cookies, setCookie, removeCookie] = useCookies([]); + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [dataset, setDataset] = useState(false); + const [isLoaded, setIsLoaded] = useState(false); + + useEffect(() => { + if (dataset === false) { + checkLogin() + setDataset(true) + } + }) + + if (isLoaded && !isLoggedIn && (!window.location.pathname.startsWith("/login") && (!window.location.pathname.startsWith("/docs") && (!window.location.pathname.startsWith("/adminsetup"))))) { + window.location = "/login" + } + + const checkLogin = () => { + var baseurl = globalUrl + fetch(baseurl + "/api/v1/users/getinfo", { + credentials: "include", + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => response.json()) + .then(responseJson => { + if (responseJson.success === true) { + setUserData(responseJson) + setIsLoggedIn(true) + + // Updating cookie every request + for (var key in responseJson["cookies"]) { + setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, { path: "/" }) + } + } + setIsLoaded(true) + }) + .catch(error => { + setIsLoaded(true) + }); + } + + // Dumb for content load (per now), but good for making the site not suddenly reload parts (ajax thingies) + + const options = { + timeout: 5000, + position: positions.BOTTOM_CENTER + }; + + const includedData = window.location.pathname === "/home" || window.location.pathname === "/features" ? +
+ } /> +
: +
+
+ } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + { window.location.pathname = "/docs/about" }} /> + { window.location.pathname = "/login" }} /> +
+ + //
+ // backgroundColor: "#213243", + // This is a mess hahahah + return ( + + + + + {includedData} + + + + + ); +}; + +export default App; + diff --git a/frontend/src/Flows.js b/frontend/src/Flows.js deleted file mode 100644 index aa1a35a3..00000000 --- a/frontend/src/Flows.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; - -const Flows = () => { - return ( -
-

Flows

- -

- Built to suit any organization -

- -

- WAT -

- -

-

- -

- -
- ) -} - -export default Flows; diff --git a/frontend/src/Hookpost.js b/frontend/src/Hookpost.js deleted file mode 100644 index 566a26d4..00000000 --- a/frontend/src/Hookpost.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; - -const Hooks = () => { - return ( -
-

Hooks

- -

- Built to suit any organization -

- -

- WAT -

- -

-

- -

- -
- ) -} - -export default Hooks; diff --git a/frontend/src/Schedulespost.js b/frontend/src/Schedulespost.js deleted file mode 100644 index 102144e7..00000000 --- a/frontend/src/Schedulespost.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; - -const Schedules = () => { - return ( -
-

Schedules

- -

- Built to suit any organization -

- -

- WAT -

- -

-

- -

- -
- ) -} - -export default Schedules; diff --git a/frontend/src/appdata.js b/frontend/src/__test__/appdata.js similarity index 100% rename from frontend/src/appdata.js rename to frontend/src/__test__/appdata.js diff --git a/frontend/src/environmentdata.js b/frontend/src/__test__/environmentdata.js similarity index 100% rename from frontend/src/environmentdata.js rename to frontend/src/__test__/environmentdata.js diff --git a/frontend/src/scheduledata.js b/frontend/src/__test__/scheduledata.js similarity index 100% rename from frontend/src/scheduledata.js rename to frontend/src/__test__/scheduledata.js diff --git a/frontend/src/webhookdata.js b/frontend/src/__test__/webhookdata.js similarity index 100% rename from frontend/src/webhookdata.js rename to frontend/src/__test__/webhookdata.js diff --git a/frontend/src/workflowdata.js b/frontend/src/__test__/workflowdata.js similarity index 100% rename from frontend/src/workflowdata.js rename to frontend/src/__test__/workflowdata.js diff --git a/frontend/src/AlertPopup.js b/frontend/src/components/AlertPopup.js similarity index 100% rename from frontend/src/AlertPopup.js rename to frontend/src/components/AlertPopup.js diff --git a/frontend/src/AlertTemplate.js b/frontend/src/components/AlertTemplate.js similarity index 100% rename from frontend/src/AlertTemplate.js rename to frontend/src/components/AlertTemplate.js diff --git a/frontend/src/FooterNew.js b/frontend/src/components/FooterNew.js similarity index 100% rename from frontend/src/FooterNew.js rename to frontend/src/components/FooterNew.js diff --git a/frontend/src/Header.js b/frontend/src/components/Header.js similarity index 100% rename from frontend/src/Header.js rename to frontend/src/components/Header.js diff --git a/frontend/src/LoginPopup.js b/frontend/src/components/LoginPopup.js similarity index 100% rename from frontend/src/LoginPopup.js rename to frontend/src/components/LoginPopup.js diff --git a/frontend/src/SettingsPopup.js b/frontend/src/components/SettingsPopup.js similarity index 100% rename from frontend/src/SettingsPopup.js rename to frontend/src/components/SettingsPopup.js diff --git a/frontend/src/About.js b/frontend/src/views/About.jsx similarity index 85% rename from frontend/src/About.js rename to frontend/src/views/About.jsx index 913eff3d..9c4044f9 100644 --- a/frontend/src/About.js +++ b/frontend/src/views/About.jsx @@ -1,7 +1,7 @@ import React from 'react'; const hrefStyle = { - color: "#f85a3e", + color: "#f85a3e", textDecoration: "none" } @@ -12,17 +12,17 @@ const About = () => {

About

- Endao was started as a project in late 2018 as a free service to analyze APK (and soon IPA) files for vulnerabilities. The project was started after I, + Endao was started as a project in late 2018 as a free service to analyze APK (and soon IPA) files for vulnerabilities. The project was started after I, @frikkylikeme , found multiple vulnerabilities in IoT devices based purely on their apps. As I wanted to learn more about these kind of vulnerabilities, I looked for solutions that work for my purpose, but didn't find any good, free and easy to use service - hence this site was born.

- My personal goal has and will always be to make the internet safer. As the IoT sphere grows, I want to be able to add ways of finding possible vulnerabilities fast to this website. This will hopefully include blogposts when I get around to it, as well as actual implementations. The vulnerability discovery field is in no way new, but I'll try my best to add whatever I can to it. As a disclaimer, I'm an "Ops" person, and I had never done frontend before creating this site. This is as much of a learning project within web development as it is in vulnerability discovery. + My personal goal has and will always be to make the internet safer. As the IoT sphere grows, I want to be able to add ways of finding possible vulnerabilities fast to this website. This will hopefully include blogposts when I get around to it, as well as actual implementations. The vulnerability discovery field is in no way new, but I'll try my best to add whatever I can to it. As a disclaimer, I'm an "Ops" person, and I had never done frontend before creating this site. This is as much of a learning project within web development as it is in vulnerability discovery.

- This site currently uses the following projects + This site currently uses the following projects

  • SUPER Android Analyzer
  • @@ -34,8 +34,8 @@ const About = () => {

    Hopefully it is of use to some people :)

    Thanks

    -

    - Thanks to Andy for the initial frontend help :) +

    + Thanks to Andy for the initial frontend help :)

    Regards

    diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx new file mode 100644 index 00000000..112c29f8 --- /dev/null +++ b/frontend/src/views/Admin.jsx @@ -0,0 +1,1039 @@ +import React, { useEffect } from 'react'; + +import { Link } from 'react-router-dom'; +import Paper from '@material-ui/core/Paper'; +import Select from '@material-ui/core/Select'; +import MenuItem from '@material-ui/core/MenuItem'; +import List from '@material-ui/core/List'; +import Divider from '@material-ui/core/Divider'; +import TextField from '@material-ui/core/TextField'; +import ListItem from '@material-ui/core/ListItem'; +import Button from '@material-ui/core/Button'; +import Tabs from '@material-ui/core/Tabs'; +import Tab from '@material-ui/core/Tab'; +import ListItemText from '@material-ui/core/ListItemText'; +import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; + +import { useAlert } from "react-alert"; + +import { Dialog, DialogTitle, DialogActions, DialogContent } from '@material-ui/core'; +import { useTheme } from '@material-ui/core/styles'; + + +import CachedIcon from '@material-ui/icons/Cached'; + +const Admin = (props) => { + const { globalUrl } = props; + + const theme = useTheme(); + + const [firstRequest, setFirstRequest] = React.useState(true); + const [modalUser, setModalUser] = React.useState({}); + const [modalOpen, setModalOpen] = React.useState(false); + const [loginInfo, setLoginInfo] = React.useState(""); + const [curTab, setCurTab] = React.useState(0); + const [users, setUsers] = React.useState([]); + const [environments, setEnvironments] = React.useState([]); + const [authentication, setAuthentication] = React.useState([]); + const [schedules, setSchedules] = React.useState([]) + const [selectedUser, setSelectedUser] = React.useState({}) + const [newPassword, setNewPassword] = React.useState(""); + const [selectedUserModalOpen, setSelectedUserModalOpen] = React.useState(false) + const [selectedAuthentication, setSelectedAuthentication] = React.useState({}) + const [selectedAuthenticationModalOpen, setSelectedAuthenticationModalOpen] = React.useState(false) + + const alert = useAlert() + + const deleteAuthentication = (data) => { + alert.info("Deleting auth " + data.label) + + // Just use this one? + const url = globalUrl + '/api/v1/apps/authentication/' + data.id + console.log("URL: ", url) + fetch(url, { + method: 'DELETE', + credentials: "include", + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => + response.json().then(responseJson => { + console.log("RESP: ", responseJson) + if (responseJson["success"] === false) { + alert.error("Failed stopping schedule") + } else { + getAppAuthentication() + alert.success("Successfully stopped schedule!") + } + }), + ) + .catch(error => { + console.log("Error in userdata: ", error) + }); + } + + const deleteSchedule = (data) => { + // FIXME - add some check here ROFL + console.log("INPUT: ", data) + + // Just use this one? + const url = globalUrl + '/api/v1/workflows/' + data["workflow_id"] + "/schedule/" + data.id + console.log("URL: ", url) + fetch(url, { + method: 'DELETE', + credentials: "include", + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => + response.json().then(responseJson => { + console.log("RESP: ", responseJson) + if (responseJson["success"] === false) { + alert.error("Failed stopping schedule") + } else { + getSchedules() + alert.success("Successfully stopped schedule!") + } + }), + ) + .catch(error => { + console.log("Error in userdata: ", error) + }); + } + + const onPasswordChange = () => { + const data = { "username": selectedUser.username, "newpassword": newPassword } + const url = globalUrl + '/api/v1/users/passwordchange'; + fetch(url, { + mode: 'cors', + method: 'POST', + body: JSON.stringify(data), + credentials: 'include', + crossDomain: true, + withCredentials: true, + headers: { + 'Content-Type': 'application/json; charset=utf-8', + }, + }) + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + alert.error("Failed setting new password") + } else { + alert.success("Changed password!") + } + }), + ) + .catch(error => { + alert.error("Err: " + error.toString()) + }); + } + + const deleteUser = (data) => { + // Just use this one? + const url = globalUrl + '/api/v1/users/' + data.id + fetch(url, { + method: 'DELETE', + credentials: "include", + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => { + if (response.status === 200) { + getUsers() + } + + return response.json() + }) + .then((responseJson) => { + if (!responseJson.success && responseJson.reason !== undefined) { + alert.error("Failed to deactivate user: " + responseJson.reason) + } else { + alert.success("Deactivated user " + data.id) + } + }) + + .catch(error => { + console.log("Error in userdata: ", error) + }); + } + + const submitUser = (data) => { + // FIXME - add some check here ROFL + console.log("INPUT: ", data) + + // Just use this one? + var data = { "username": data.Username, "password": data.Password } + var baseurl = globalUrl + const url = baseurl + '/api/v1/users/register'; + fetch(url, { + method: 'POST', + credentials: "include", + body: JSON.stringify(data), + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + setLoginInfo("Error in input: " + responseJson.reason) + } else { + setLoginInfo("") + setModalOpen(false) + getUsers() + } + }), + ) + .catch(error => { + console.log("Error in userdata: ", error) + }); + } + + const deleteEnvironment = (name) => { + // FIXME - add some check here ROFL + alert.info("Deleting environment " + name) + var newEnv = [] + for (var key in environments) { + if (environments[key].Name == name) { + continue + } + + newEnv.push(environments[key]) + } + + // Just use this one? + const url = globalUrl + '/api/v1/setenvironments'; + fetch(url, { + method: 'PUT', + credentials: "include", + body: JSON.stringify(newEnv), + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + alert.error(responseJson.reason) + } else { + setLoginInfo("") + setModalOpen(false) + getEnvironments() + } + }), + ) + //.catch(error => { + // console.log("Error in userdata: ", error) + //}); + } + + const submitEnvironment = (data) => { + // FIXME - add some check here ROFL + environments.push({ "name": data.environment, "type": "onprem" }) + + // Just use this one? + var baseurl = globalUrl + const url = baseurl + '/api/v1/setenvironments'; + fetch(url, { + method: 'PUT', + credentials: "include", + body: JSON.stringify(environments), + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + setLoginInfo("Error in input: " + responseJson.reason) + } else { + setLoginInfo("") + setModalOpen(false) + getEnvironments() + } + }), + ) + .catch(error => { + console.log("Error in userdata: ", error) + }); + } + + const getSchedules = () => { + fetch(globalUrl + "/api/v1/workflows/schedules", { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for apps :O!") + return + } + + return response.json() + }) + .then((responseJson) => { + setSchedules(responseJson) + }) + .catch(error => { + alert.error(error.toString()) + }); + } + + const getAppAuthentication = () => { + fetch(globalUrl + "/api/v1/apps/authentication", { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for apps :O!") + return + } + + return response.json() + }) + .then((responseJson) => { + if (responseJson.success) { + console.log(responseJson.data) + setAuthentication(responseJson.data) + } else { + alert.error("Failed getting authentications") + } + }) + .catch(error => { + alert.error(error.toString()) + }); + } + + const getEnvironments = () => { + fetch(globalUrl + "/api/v1/getenvironments", { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for apps :O!") + return + } + + return response.json() + }) + .then((responseJson) => { + console.log(responseJson) + setEnvironments(responseJson) + }) + .catch(error => { + alert.error(error.toString()) + }); + } + + const getUsers = () => { + fetch(globalUrl + "/api/v1/getusers", { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for apps :O!") + return + } + + return response.json() + }) + .then((responseJson) => { + console.log(responseJson) + setUsers(responseJson) + }) + .catch(error => { + alert.error(error.toString()) + }); + } + + if (firstRequest) { + setFirstRequest(false) + getUsers() + } + + const paperStyle = { + maxWidth: 1250, + margin: "auto", + color: "white", + backgroundColor: theme.palette.surfaceColor, + marginBottom: 10, + padding: 20, + } + + const changeModalData = (field, value) => { + modalUser[field] = value + } + + const setUser = (userId, field, value) => { + const data = { "user_id": userId } + data[field] = value + console.log("DATA: ", data) + + fetch(globalUrl + "/api/v1/users/updateuser", { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify(data), + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for WORKFLOW EXECUTION :O!") + } else { + getUsers() + } + + return response.json() + }) + .then((responseJson) => { + if (!responseJson.success && responseJson.reason !== undefined) { + alert.error("Failed setting user: " + responseJson.reason) + } else { + alert.success("Set the user field " + field + " to " + value) + } + }) + .catch(error => { + console.log(error) + }); + } + + + + const generateApikey = (userId) => { + const data = { "user_id": userId } + + fetch(globalUrl + "/api/v1/generateapikey", { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify(data), + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for WORKFLOW EXECUTION :O!") + } else { + getUsers() + } + + return response.json() + }) + .then((responseJson) => { + console.log("RESP: ", responseJson) + if (!responseJson.success && responseJson.reason !== undefined) { + alert.error("Failed getting new: " + responseJson.reason) + } else { + alert.success("Got new API key") + } + }) + .catch(error => { + console.log(error) + }); + } + + const editAuthenticationModal = + { setSelectedAuthenticationModalOpen(false) }} + PaperProps={{ + style: { + backgroundColor: theme.palette.surfaceColor, + color: "white", + minWidth: "800px", + minHeight: "320px", + }, + }} + > + Edit authentication + +
    + setNewPassword(e.target.value)} + /> + +
    + + + +
    +
    + + const editUserModal = + { setSelectedUserModalOpen(false) }} + PaperProps={{ + style: { + backgroundColor: theme.palette.surfaceColor, + color: "white", + minWidth: "800px", + minHeight: "320px", + }, + }} + > + Edit user + +
    + setNewPassword(e.target.value)} + /> + +
    + + + +
    +
    + + const modalView = + { setModalOpen(false) }} + PaperProps={{ + style: { + backgroundColor: theme.palette.surfaceColor, + color: "white", + minWidth: "800px", + minHeight: "320px", + }, + }} + > + + {curTab === 0 ? "Add user" : "Add environment"} + + + {curTab === 0 ? +
    + Username + changeModalData("Username", event.target.value)} + /> + Password + changeModalData("Password", event.target.value)} + /> +
    + : curTab === 2 ? +
    + Environment Name + changeModalData("environment", event.target.value)} + /> +
    + : null} + {loginInfo} +
    + + + + +
    + + const usersView = curTab === 0 ? +
    +
    +

    User management

    + Add, edit, block or change passwords +
    +
    + + + + + + + + + + + {users === undefined ? null : users.map(data => { + return ( + + + + { + console.log("VALUE: ", e.target.value) + setUser(data.id, "role", e.target.value) + }} + style={{ backgroundColor: theme.palette.surfaceColor, color: "white", height: "50px" }} + > + + Admin + + + User + + } + style = {{ minWidth: 150, maxWidth: 150}} + /> + + + + + + ) + })} + +
    + : null + +const schedulesView = curTab === 3 ? +
    +
    +

    Schedules

    + Schedules used in Workflows. Makes locating and control easier. +
    + + + + + + + + {schedules === undefined || schedules === null ? null : schedules.map(schedule => { + return ( + + + + + + + + ) + })} + +
    + : null + +const authenticationView = curTab === 1 ? +
    +
    +

    App Authentication

    + Control the authentication options for individual apps. Actions can be destructive! +
    + + + + + + + + + + + + {authentication === undefined ? null : authentication.map(data => { + return ( + + } + style={{ minWidth: 150, maxWidth: 150 }} + /> + + + + + { + return data.key + }).join(", ")} + style={{ minWidth: 200, maxWidth: 200, overflow: "hidden" }} + /> + + + + + ) + })} + +
    + : null + +const environmentView = curTab === 2 ? +
    +
    +

    Environments

    + Decides what Orborus environment to execute an action in a workflow in. +
    + + + + + + + + + + {environments === undefined ? null : environments.map(environment => { + return ( + + + + + + + + ) + })} + +
    + : null + +// primary={environment.Registered ? "true" : "false"} + +const setConfig = (event, newValue) => { + if (newValue === 1) { + getAppAuthentication() + } else if (newValue === 2) { + getEnvironments() + } else if (newValue === 3) { + getSchedules() + } + + setModalUser({}) + setCurTab(newValue) +} + +const data = +
    + + + + + + + + +
    + {authenticationView} + {usersView} + {environmentView} + {schedulesView} +
    +
    +
    + +return ( +
    + {modalView} + {editUserModal} + {editAuthenticationModal} + {data} +
    +) +} + +export default Admin; diff --git a/frontend/src/AdminSetup.js b/frontend/src/views/AdminSetup.jsx similarity index 100% rename from frontend/src/AdminSetup.js rename to frontend/src/views/AdminSetup.jsx diff --git a/frontend/src/AngularWorkflow.js b/frontend/src/views/AngularWorkflow.jsx similarity index 99% rename from frontend/src/AngularWorkflow.js rename to frontend/src/views/AngularWorkflow.jsx index 31f792c4..db31586e 100644 --- a/frontend/src/AngularWorkflow.js +++ b/frontend/src/views/AngularWorkflow.jsx @@ -68,8 +68,7 @@ import CytoscapeComponent from 'react-cytoscapejs'; import undoRedo from 'cytoscape-undo-redo'; import Draggable from 'react-draggable'; -import environmentdata from './environmentdata'; -import cytoscapestyle from './defaultCytoscapeStyle'; +import cytoscapestyle from '../defaultCytoscapeStyle'; import cxtmenu from 'cytoscape-cxtmenu'; import { w3cwebsocket as W3CWebSocket } from "websocket"; @@ -4774,7 +4773,7 @@ const AngularWorkflow = (props) => { Exit on Error
    + label={
    Exit on Error
    } control={ { workflow.configuration.exit_on_error = !workflow.configuration.exit_on_error @@ -4786,7 +4785,7 @@ const AngularWorkflow = (props) => { /> Start from top
+ label={
Start from top
} control={ { workflow.configuration.start_from_top = !workflow.configuration.start_from_top @@ -5114,7 +5113,7 @@ const AngularWorkflow = (props) => {

Executing Workflow

Show failed / skipped actions
+ label={
Show failed / skipped actions
} control={ {setShowSkippedActions(!showSkippedActions)}} /> } diff --git a/frontend/src/AppCreator.js b/frontend/src/views/AppCreator.jsx similarity index 100% rename from frontend/src/AppCreator.js rename to frontend/src/views/AppCreator.jsx diff --git a/frontend/src/Apps.js b/frontend/src/views/Apps.jsx similarity index 99% rename from frontend/src/Apps.js rename to frontend/src/views/Apps.jsx index 0d1d7263..0f7daa29 100644 --- a/frontend/src/Apps.js +++ b/frontend/src/views/Apps.jsx @@ -654,7 +654,7 @@ const Apps = (props) => { {isLoading ? : null} Search OpenAPI
+ label={
Search OpenAPI
} control={ { handleSearchChange("") setSearchBackend(!searchBackend)} diff --git a/frontend/src/Contact.js b/frontend/src/views/Contact.jsx similarity index 54% rename from frontend/src/Contact.js rename to frontend/src/views/Contact.jsx index 97cf84e6..5a34382c 100644 --- a/frontend/src/Contact.js +++ b/frontend/src/views/Contact.jsx @@ -1,11 +1,13 @@ -import React, {useState} from 'react'; -import {BrowserView, MobileView} from "react-device-detect"; +import React, { useState } from 'react'; +import { BrowserView, MobileView } from "react-device-detect"; import Paper from '@material-ui/core/Paper'; import Button from '@material-ui/core/Button'; import TextField from '@material-ui/core/TextField'; +import { useTheme } from '@material-ui/core/styles'; + const bodyDivStyle = { margin: "auto", textAlign: "center", @@ -13,11 +15,11 @@ const bodyDivStyle = { } - - // Should be different if logged in :| const Contact = (props) => { - const { globalUrl, isLoaded, surfaceColor, inputColor } = props; + const { globalUrl, isLoaded } = props; + + const theme = useTheme(); const boxStyle = { flex: "1", @@ -27,24 +29,24 @@ const Contact = (props) => { paddingRight: "30px", paddingBottom: "30px", paddingTop: "30px", - backgroundColor: surfaceColor, - display: "flex", + backgroundColor: theme.palette.surfaceColor, + display: "flex", flexDirection: "column" } - + const bodyTextStyle = { - color: "#ffffff", + color: "#ffffff", } - const [firstname, setFirstname] = useState(""); - const [lastname, setLastname] = useState(""); - const [title, setTitle] = useState(""); - const [companyname, setCompanyname] = useState(""); - const [email, setEmail] = useState(""); - const [phone, setPhone] = useState(""); - const [message, setMessage] = useState(""); + const [firstname, setFirstname] = useState(""); + const [lastname, setLastname] = useState(""); + const [title, setTitle] = useState(""); + const [companyname, setCompanyname] = useState(""); + const [email, setEmail] = useState(""); + const [phone, setPhone] = useState(""); + const [message, setMessage] = useState(""); - const [formMessage, setFormMessage] = useState(""); + const [formMessage, setFormMessage] = useState(""); const submitContact = () => { const data = { @@ -58,43 +60,43 @@ const Contact = (props) => { } console.log(data) - fetch(globalUrl+"/api/v1/contact", { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - }) - .then(response => response.json()) - .then(response => { - if (response.success === true) { - setFormMessage(response.message) - } else { - setFormMessage("Something went wrong. Please contact frikky@shuffler.io.") - } - console.log(response) - }) - .catch(error => { - console.log(error) - }); + fetch(globalUrl + "/api/v1/contact", { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }) + .then(response => response.json()) + .then(response => { + if (response.success === true) { + setFormMessage(response.message) + } else { + setFormMessage("Something went wrong. Please contact frikky@shuffler.io.") + } + console.log(response) + }) + .catch(error => { + console.log(error) + }); } // Random names for type & autoComplete. Didn't research :^) - const landingpageDataBrowser = + const landingpageDataBrowser =
-

Contact us

+

Contact us

Lets talk!

-
+

Contact Details

-
+
{ fullWidth={true} placeholder="First Name" type="firstname" - id="standard-required" + id="standard-required" autoComplete="firstname" margin="normal" variant="outlined" - onChange={e => setFirstname(e.target.value)} + onChange={e => setFirstname(e.target.value)} /> { fullWidth={true} placeholder="Last Name" type="lastname" - id="standard" + id="standard" autoComplete="lastname" margin="normal" variant="outlined" - onChange={e => setLastname(e.target.value)} + onChange={e => setLastname(e.target.value)} />
-
+
{ fullWidth={true} placeholder="Job Title" type="jobtitle" - id="standard-required" + id="standard-required" autoComplete="jobtitle" margin="normal" variant="outlined" - onChange={e => setTitle(e.target.value)} + onChange={e => setTitle(e.target.value)} /> { fullWidth={true} type="companyname" placeholder="Company Name" - id="standard-required" + id="standard-required" autoComplete="companyname" margin="normal" variant="outlined" - onChange={e => setCompanyname(e.target.value)} + onChange={e => setCompanyname(e.target.value)} />
-
+
{ fullWidth={true} placeholder="Email" type="email" - id="standard-required" + id="standard-required" autoComplete="email" margin="normal" variant="outlined" - onChange={e => setEmail(e.target.value)} + onChange={e => setEmail(e.target.value)} /> { fullWidth={true} type="phone" placeholder="Phone number" - id="standard-required" + id="standard-required" autoComplete="phone" margin="normal" variant="outlined" - onChange={e => setPhone(e.target.value)} + onChange={e => setPhone(e.target.value)} />
-
+

Message

-
+
setMessage(e.target.value)} + onChange={e => setMessage(e.target.value)} />

{formMessage}

- const landingpageDataMobile = -
-
-

Contact us

+ const landingpageDataMobile = +
+
+

Contact us

Lets talk!

-
+

Contact Details

-
+
{ fullWidth={true} placeholder="Name" type="firstname" - id="standard-required" + id="standard-required" autoComplete="firstname" margin="normal" variant="outlined" - onChange={e => setFirstname(e.target.value)} + onChange={e => setFirstname(e.target.value)} />
-
+
{ fullWidth={true} placeholder="Email" type="email" - id="standard-required" + id="standard-required" autoComplete="email" margin="normal" variant="outlined" - onChange={e => setEmail(e.target.value)} + onChange={e => setEmail(e.target.value)} />
-
+

Message

-
+
{ id="filled-multiline-static" margin="normal" variant="outlined" - onChange={e => setMessage(e.target.value)} + onChange={e => setMessage(e.target.value)} />

{formMessage}

@@ -321,7 +323,7 @@ const Contact = (props) => {
- const loadedCheck = isLoaded ? + const loadedCheck = isLoaded ?
{landingpageDataBrowser}
@@ -334,7 +336,7 @@ const Contact = (props) => {
- return( + return (
{loadedCheck}
diff --git a/frontend/src/Dashboard.js b/frontend/src/views/Dashboard.jsx similarity index 99% rename from frontend/src/Dashboard.js rename to frontend/src/views/Dashboard.jsx index f450e99e..3ffb560e 100644 --- a/frontend/src/Dashboard.js +++ b/frontend/src/views/Dashboard.jsx @@ -35,7 +35,7 @@ import { chartExample2, chartExample3, chartExample4 -} from "./charts.js"; +} from "../charts.js"; // This is the start of a dashboard that can be used. // What data do we fill in here? Idk diff --git a/frontend/src/Docs.js b/frontend/src/views/Docs.jsx similarity index 100% rename from frontend/src/Docs.js rename to frontend/src/views/Docs.jsx diff --git a/frontend/src/EditSchedule.js b/frontend/src/views/EditSchedule.jsx similarity index 99% rename from frontend/src/EditSchedule.js rename to frontend/src/views/EditSchedule.jsx index 0c588172..c47453e8 100644 --- a/frontend/src/EditSchedule.js +++ b/frontend/src/views/EditSchedule.jsx @@ -34,9 +34,6 @@ import DeleteIcon from '@material-ui/icons/Delete'; import Downshift from 'downshift'; import deburr from 'lodash/deburr'; -//import appdata from './appdata'; - - const EditSchedule = (props) => { const { globalUrl } = props; diff --git a/frontend/src/EditWebhook.js b/frontend/src/views/EditWebhook.jsx similarity index 98% rename from frontend/src/EditWebhook.js rename to frontend/src/views/EditWebhook.jsx index 6653cb5a..ba42a58b 100644 --- a/frontend/src/EditWebhook.js +++ b/frontend/src/views/EditWebhook.jsx @@ -6,8 +6,8 @@ import Divider from '@material-ui/core/Divider'; import Select from '@material-ui/core/Select'; import MenuItem from '@material-ui/core/MenuItem'; -import WebhookImage from './assets/img/webhook.png'; -import KafkaImage from './assets/img/kafka.png'; +import WebhookImage from '../assets/img/webhook.png'; +import KafkaImage from '../assets/img/kafka.png'; import EditWorkflow from "./EditWorkflow"; diff --git a/frontend/src/EditWorkflow.js b/frontend/src/views/EditWorkflow.jsx similarity index 100% rename from frontend/src/EditWorkflow.js rename to frontend/src/views/EditWorkflow.jsx diff --git a/frontend/src/ForgotPassword.js b/frontend/src/views/ForgotPassword.jsx similarity index 100% rename from frontend/src/ForgotPassword.js rename to frontend/src/views/ForgotPassword.jsx diff --git a/frontend/src/ForgotPasswordLink.js b/frontend/src/views/ForgotPasswordLink.jsx similarity index 100% rename from frontend/src/ForgotPasswordLink.js rename to frontend/src/views/ForgotPasswordLink.jsx diff --git a/frontend/src/Landingpage.js b/frontend/src/views/Landingpage.jsx similarity index 100% rename from frontend/src/Landingpage.js rename to frontend/src/views/Landingpage.jsx diff --git a/frontend/src/LandingpageLoggedin.js b/frontend/src/views/LandingpageLoggedin.jsx similarity index 100% rename from frontend/src/LandingpageLoggedin.js rename to frontend/src/views/LandingpageLoggedin.jsx diff --git a/frontend/src/LandingpageNew.js b/frontend/src/views/LandingpageNew.jsx similarity index 100% rename from frontend/src/LandingpageNew.js rename to frontend/src/views/LandingpageNew.jsx diff --git a/frontend/src/LoginPage.js b/frontend/src/views/LoginPage.jsx similarity index 56% rename from frontend/src/LoginPage.js rename to frontend/src/views/LoginPage.jsx index 49e22f55..31ccc384 100644 --- a/frontend/src/LoginPage.js +++ b/frontend/src/views/LoginPage.jsx @@ -1,13 +1,15 @@ /* eslint-disable react/no-multi-comp */ -import React, {useState} from 'react'; +import React, { useState } from 'react'; import { makeStyles } from '@material-ui/styles'; import TextField from '@material-ui/core/TextField'; import Button from '@material-ui/core/Button'; import Paper from '@material-ui/core/Paper'; +import { useTheme } from '@material-ui/core/styles'; + const hrefStyle = { - color: "white", + color: "white", textDecoration: "none" } @@ -17,16 +19,6 @@ const bodyDivStyle = { width: "500px", } -const surfaceColor = "#27292D" -const inputColor = "#383B40" - -const boxStyle = { - paddingLeft: "30px", - paddingRight: "30px", - paddingBottom: "30px", - paddingTop: "30px", - backgroundColor: surfaceColor, -} const useStyles = makeStyles({ notchedOutline: { @@ -35,12 +27,14 @@ const useStyles = makeStyles({ }); const LoginDialog = props => { - const { globalUrl, isLoaded, isLoggedIn, setIsLoggedIn, setCookie, register } = props; + const theme = useTheme(); + + const { globalUrl, isLoaded, isLoggedIn, setIsLoggedIn, setCookie, register } = props; const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [firstRequest, setFirstRequest] = useState(true); - // Used to swap from login to register. True = login, false = register + // Used to swap from login to register. True = login, false = register const classes = useStyles(); // Error messages etc @@ -51,32 +45,32 @@ const LoginDialog = props => { } if (isLoggedIn === true) { - window.location.pathname = "/workflows" + window.location.pathname = "/workflows" } const checkAdmin = () => { - const url = globalUrl+'/api/v1/checkusers'; + const url = globalUrl + '/api/v1/checkusers'; fetch(url, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, }) - .then(response => - response.json().then(responseJson => { - if (responseJson["success"] === false) { - setLoginInfo(responseJson["reason"]) - } else { - if (responseJson.reason === "stay") { - window.location.pathname = "/adminsetup" + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + setLoginInfo(responseJson["reason"]) + } else { + if (responseJson.reason === "stay") { + window.location.pathname = "/adminsetup" + } } - } - }), - ) - .catch(error => { - setLoginInfo("Error in userdata: ", error) - }) + }), + ) + .catch(error => { + setLoginInfo("Error in userdata: ", error) + }) } if (firstRequest) { @@ -89,41 +83,41 @@ const LoginDialog = props => { // FIXME - add some check here ROFL // Just use this one? - var data = {"username": username, "password": password} + var data = { "username": username, "password": password } var baseurl = globalUrl if (register) { - var url = baseurl+'/api/v1/users/login'; + var url = baseurl + '/api/v1/users/login'; fetch(url, { mode: 'cors', - method: 'POST', - body: JSON.stringify(data), - credentials: 'include', - crossDomain: true, - withCredentials: true, - headers: { - 'Content-Type': 'application/json; charset=utf-8', - }, + method: 'POST', + body: JSON.stringify(data), + credentials: 'include', + crossDomain: true, + withCredentials: true, + headers: { + 'Content-Type': 'application/json; charset=utf-8', + }, }) - .then(response => - response.json().then(responseJson => { - if (responseJson["success"] === false) { - setLoginInfo(responseJson["reason"]) - } else { - setLoginInfo("Successful login, rerouting") - for (var key in responseJson["cookies"]) { - setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, {path: "/"}) - } + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + setLoginInfo(responseJson["reason"]) + } else { + setLoginInfo("Successful login, rerouting") + for (var key in responseJson["cookies"]) { + setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, { path: "/" }) + } - setIsLoggedIn(true) - window.location.pathname = "/workflows" - } - }), - ) - .catch(error => { - setLoginInfo("Error in userdata: " + error) - }); + setIsLoggedIn(true) + window.location.pathname = "/workflows" + } + }), + ) + .catch(error => { + setLoginInfo("Error in userdata: " + error) + }); } else { - url = baseurl+'/api/v1/users/register'; + url = baseurl + '/api/v1/users/register'; fetch(url, { method: 'POST', body: JSON.stringify(data), @@ -131,27 +125,27 @@ const LoginDialog = props => { 'Content-Type': 'application/json', }, }) - .then(response => - response.json().then(responseJson => { - if (responseJson["success"] === false) { - setLoginInfo(responseJson["reason"]) - } else { - setLoginInfo("Successful register :)") - } - }), - ) - .catch(error => { - setLoginInfo("Error in userdata: ", error) - }); + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + setLoginInfo(responseJson["reason"]) + } else { + setLoginInfo("Successful register :)") + } + }), + ) + .catch(error => { + setLoginInfo("Error in userdata: ", error) + }); } } const onChangeUser = (e) => { - setUsername(e.target.value) + setUsername(e.target.value) } const onChangePass = (e) => { - setPassword(e.target.value) + setPassword(e.target.value) } //const onClickRegister = () => { @@ -167,25 +161,31 @@ const LoginDialog = props => { //var loginChange = register ? (

Want to register? Click here.

) : (

Go back to login? Click here.

); var formtitle = register ?
Login
:
Register
- // {formtitle} - - const basedata = + // {formtitle} + + const basedata =
- -
+ +

{formtitle}

Username
{ id="emailfield" margin="normal" variant="outlined" - onChange={onChangeUser} + onChange={onChangeUser} />
- Password + Password
{ placeholder="**********" margin="normal" variant="outlined" - onChange={onChangePass} + onChange={onChangePass} />
-
- - +
+ +
-
+
{loginInfo}
- const loadedCheck = isLoaded ? + const loadedCheck = isLoaded ?
- {basedata} + {basedata}
:
diff --git a/frontend/src/Oauth2.js b/frontend/src/views/Oauth2.jsx similarity index 100% rename from frontend/src/Oauth2.js rename to frontend/src/views/Oauth2.jsx diff --git a/frontend/src/Post.js b/frontend/src/views/Post.jsx similarity index 100% rename from frontend/src/Post.js rename to frontend/src/views/Post.jsx diff --git a/frontend/src/PrivacyPolicy.js b/frontend/src/views/PrivacyPolicy.jsx similarity index 100% rename from frontend/src/PrivacyPolicy.js rename to frontend/src/views/PrivacyPolicy.jsx diff --git a/frontend/src/RegisterLink.js b/frontend/src/views/RegisterLink.jsx similarity index 100% rename from frontend/src/RegisterLink.js rename to frontend/src/views/RegisterLink.jsx diff --git a/frontend/src/RegisterPage.js b/frontend/src/views/RegisterPage.jsx similarity index 100% rename from frontend/src/RegisterPage.js rename to frontend/src/views/RegisterPage.jsx diff --git a/frontend/src/Schedules.js b/frontend/src/views/Schedules.jsx similarity index 100% rename from frontend/src/Schedules.js rename to frontend/src/views/Schedules.jsx diff --git a/frontend/src/SettingsPage.js b/frontend/src/views/SettingsPage.jsx similarity index 100% rename from frontend/src/SettingsPage.js rename to frontend/src/views/SettingsPage.jsx diff --git a/frontend/src/Webhooks.js b/frontend/src/views/Webhooks.jsx similarity index 98% rename from frontend/src/Webhooks.js rename to frontend/src/views/Webhooks.jsx index 33596163..ac30a313 100644 --- a/frontend/src/Webhooks.js +++ b/frontend/src/views/Webhooks.jsx @@ -15,8 +15,8 @@ import DialogTitle from '@material-ui/core/DialogTitle'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; -import WebhookImage from './assets/img/webhook.png'; -import KafkaImage from './assets/img/kafka.png'; +import WebhookImage from '../assets/img/webhook.png'; +import KafkaImage from '../assets/img/kafka.png'; const Webhooks = (props) => { const { globalUrl, isLoaded } = props; diff --git a/frontend/src/Workflows.js b/frontend/src/views/Workflows.jsx similarity index 99% rename from frontend/src/Workflows.js rename to frontend/src/views/Workflows.jsx index 407e6186..7e448b90 100644 --- a/frontend/src/Workflows.js +++ b/frontend/src/views/Workflows.jsx @@ -988,7 +988,7 @@ const Workflows = (props) => {
Collapse results
+ label={
Collapse results
} control={ {setCollapseJson(!collapseJson)}} />} />