import React, { useEffect} from 'react'; import { makeStyles } from '@material-ui/styles'; import {Link} from 'react-router-dom'; import Paper from '@material-ui/core/Paper'; import Card from '@material-ui/core/Card'; import Tooltip from '@material-ui/core/Tooltip'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import Typography from '@material-ui/core/Typography'; import Switch from '@material-ui/core/Switch'; import Select from '@material-ui/core/Select'; import MenuItem from '@material-ui/core/MenuItem'; import Divider from '@material-ui/core/Divider'; import TextField from '@material-ui/core/TextField'; import Button from '@material-ui/core/Button'; import Tabs from '@material-ui/core/Tabs'; import Tab from '@material-ui/core/Tab'; import Grid from '@material-ui/core/Grid'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemText from '@material-ui/core/ListItemText'; import ListItemAvatar from '@material-ui/core/ListItemAvatar'; import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; import IconButton from '@material-ui/core/IconButton'; import Avatar from '@material-ui/core/Avatar'; import Zoom from '@material-ui/core/Zoom'; import { useAlert } from "react-alert"; import { Dialog, DialogTitle, DialogActions, DialogContent } from '@material-ui/core'; import { useTheme } from '@material-ui/core/styles'; import HandlePayment from './HandlePayment' import OrgHeader from '../components/OrgHeader' import OpenInNewIcon from '@material-ui/icons/OpenInNew'; import CloudDownloadIcon from '@material-ui/icons/CloudDownload'; import DescriptionIcon from '@material-ui/icons/Description'; import PolymerIcon from '@material-ui/icons/Polymer'; import CheckCircleIcon from '@material-ui/icons/CheckCircle'; import CloseIcon from '@material-ui/icons/Close'; import AppsIcon from '@material-ui/icons/Apps'; import ImageIcon from '@material-ui/icons/Image'; import DeleteIcon from '@material-ui/icons/Delete'; import CachedIcon from '@material-ui/icons/Cached'; import AccessibilityNewIcon from '@material-ui/icons/AccessibilityNew'; import LockIcon from '@material-ui/icons/Lock'; import EcoIcon from '@material-ui/icons/Eco'; import ScheduleIcon from '@material-ui/icons/Schedule'; import CloudIcon from '@material-ui/icons/Cloud'; import BusinessIcon from '@material-ui/icons/Business'; const useStyles = makeStyles({ notchedOutline: { borderColor: "#f85a3e !important" }, }) const Admin = (props) => { const { globalUrl, userdata } = props; var upload = "" const theme = useTheme(); const classes = useStyles(); const [firstRequest, setFirstRequest] = React.useState(true); const [modalUser, setModalUser] = React.useState({}); const [modalOpen, setModalOpen] = React.useState(false); const [cloudSyncModalOpen, setCloudSyncModalOpen] = React.useState(false); const [cloudSyncApikey, setCloudSyncApikey] = React.useState(""); const [loading, setLoading] = React.useState(false); const [selectedOrganization, setSelectedOrganization] = React.useState({}); const [organizationFeatures, setOrganizationFeatures] = React.useState({}); const [loginInfo, setLoginInfo] = React.useState(""); const [curTab, setCurTab] = React.useState(0); const [users, setUsers] = React.useState([]); const [organizations, setOrganizations] = React.useState([]); const [orgSyncResponse, setOrgSyncResponse] = React.useState(""); const [userSettings, setUserSettings] = React.useState({}); const [environments, setEnvironments] = React.useState([]); const [authentication, setAuthentication] = React.useState([]); const [schedules, setSchedules] = React.useState([]) const [files, setFiles] = 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 [showArchived, setShowArchived] = React.useState(false) const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" const getApps = () => { fetch(globalUrl+"/api/v1/workflows/apps", { 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 response.json() }) .then((responseJson) => { console.log("apps: ", responseJson) //setApps(responseJson) //setFilteredApps(responseJson) //if (responseJson.length > 0) { // setSelectedApp(responseJson[0]) // if (responseJson[0].actions !== null && responseJson[0].actions.length > 0) { // setSelectedAction(responseJson[0].actions[0]) // } else { // setSelectedAction({}) // } //} }) .catch(error => { alert.error(error.toString()) }); } const categories = [ { "name": "Ticketing", "apps": [ "TheHive", "Service-Now", "SecureWorks", ], "categories": ["tickets", "ticket", "ticketing"] }, ] /* "SIEM", "Active Directory", "Firewalls", "Proxies web", "SIEM", "SOAR", "Mail", "EDR", "AV", "MDM/MAM", "DNS", "Ticketing platform", "TIP", "Communication", "DDOS protection", "VMS", ] */ 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 deleted authentication!") } }), ) .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 enableCloudSync = (apikey, organization, disableSync) => { setOrgSyncResponse("") const data = { apikey: apikey, organization: organization, disable: disableSync, } const url = globalUrl + '/api/v1/cloud/setup'; 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 => { setLoading(false) if (response.status === 200) { console.log("Cloud sync success?") } else { console.log("Cloud sync fail?") } return response.json() }) .then((responseJson) => { if (!responseJson.success && responseJson.reason !== undefined) { setOrgSyncResponse(responseJson.reason) alert.error("Failed to handle sync: "+responseJson.reason) } else if (!responseJson.success) { alert.error("Failed to handle sync.") } else { getOrgs() if (disableSync) { alert.success("Successfully disabled sync!") setOrgSyncResponse("Successfully disabled syncronization") } else { alert.success("Cloud Syncronization successfully set up!") setOrgSyncResponse("Successfully started syncronization. Cloud features you now have access to can be seen below.") } selectedOrganization.cloud_sync = !selectedOrganization.cloud_sync setSelectedOrganization(selectedOrganization) setCloudSyncApikey("") handleGetOrg(userdata.active_org.id) } }) .catch(error => { setLoading(false) alert.error("Err: " + error.toString()) }) } 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("Successfully password!") setSelectedUserModalOpen(false) } }), ) .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 handleGetOrg = (orgId) => { // Just use this one? var baseurl = globalUrl const url = baseurl + '/api/v1/orgs/'+orgId fetch(url, { method: 'GET', credentials: "include", headers: { 'Content-Type': 'application/json', }, }) .then(response => { if (response.status === 401) { } return response.json() }) .then(responseJson => { if (responseJson["success"] === false) { alert.error("Failed getting org: ", responseJson.readon) } else { setSelectedOrganization(responseJson) var lists = { "active": { "triggers": [], "features": [], "sync": [], }, "inactive": { "triggers": [], "features": [], "sync": [], }, } // FIXME: Set up features Object.keys(responseJson.sync_features).map(function(key, index) { //console.log(responseJson.sync_features[key]) }) //setOrgName(responseJson.name) //setOrgDescription(responseJson.description) setOrganizationFeatures(lists) } }) .catch(error => { console.log("Error getting org: ", error) alert.error("Error getting current organization") }); } const submitUser = (data) => { 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) }); } // Horrible frontend fix for environments const setDefaultEnvironment = (name) => { // FIXME - add some check here ROFL alert.info("Setting default env to " + name) var newEnv = [] for (var key in environments) { if (environments[key].Name == name) { if (environments[key].archived) { alert.error("Can't set archived to default") return } environments[key].default = true } else if (environments[key].default == true && environments[key].name !== name) { environments[key].default = false } 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) getEnvironments() } else { setLoginInfo("") setModalOpen(false) getEnvironments() } }), ) .catch(error => { console.log("Error in backend data: ", error) }) } const flushQueue = (name) => { // Just use this one? const url = globalUrl + '/api/v1/flush_queue'; fetch(url, { method: 'DELETE', credentials: "include", headers: { 'Content-Type': 'application/json', }, }) .then(response => response.json().then(responseJson => { if (responseJson["success"] === false) { alert.error(responseJson.reason) getEnvironments() } else { setLoginInfo("") setModalOpen(false) getEnvironments() } }), ) .catch(error => { console.log("Error when deleting: ", 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) { if (environments[key].default) { alert.error("Can't delete the default environment") return } if (environments[key].type === "cloud") { alert.error("Can't delete the cloud environments") return } environments[key].archived = true } 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) getEnvironments() } else { setLoginInfo("") setModalOpen(false) getEnvironments() } }), ) .catch(error => { console.log("Error when deleting: ", 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) getEnvironments() } else { setLoginInfo("") setModalOpen(false) getEnvironments() } }), ) .catch(error => { console.log("Error in userdata: ", error) }); } const getFiles = () => { fetch(globalUrl + "/api/v1/files", { 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) setFiles(responseJson) }) .catch(error => { alert.error(error.toString()) }); } const downloadFile = (file) => { fetch(globalUrl + "/api/v1/files/"+file.id+"/content", { 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.text() }) .then((respdata) => { if (respdata.length === 0) { alert.error("Failed getting file") return } var blob = new Blob( [ respdata ], { type: 'application/octet-stream' }) var url = URL.createObjectURL( blob ) var link = document.createElement( 'a' ) link.setAttribute( 'href', url ) link.setAttribute( 'download', `${file.filename}` ) var event = document.createEvent( 'MouseEvents' ) event.initMouseEvent( 'click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null) link.dispatchEvent( event ) //return response.json() }) .then((responseJson) => { //console.log(responseJson) //setSchedules(responseJson) }) .catch(error => { alert.error(error.toString()) }); } 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) => { console.log(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) => { setEnvironments(responseJson) }) .catch(error => { alert.error(error.toString()) }); } const getOrgs = () => { fetch(globalUrl + "/api/v1/orgs", { 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) => { setOrganizations(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) { window.location.pathname = "/workflows" return } return response.json() }) .then((responseJson) => { setUsers(responseJson) }) .catch(error => { alert.error(error.toString()) }); } const getSettings = () => { fetch(globalUrl+"/api/v1/getsettings", { method: 'GET', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, credentials: "include", }) .then((response) => { if (response.status !== 200) { console.log("Status not 200 when getting settings :O!") } return response.json() }) .then((responseJson) => { setUserSettings(responseJson) }) .catch(error => { console.log(error) }); } const setConfig = (event, newValue) => { if (newValue === 1) { getUsers() } else if (newValue === 2) { getAppAuthentication() } else if (newValue === 3) { getEnvironments() } else if (newValue === 4) { getSchedules() } else if (newValue === 5) { getFiles() } else if (newValue === 6) { getOrgs() } if (newValue === 6) { console.log("Should get apps for categories.") } const views = { 0: "organization", 1: "users", 2: "app_auth", 3: "environments", 4: "schedules", 5: "files", 6: "categories", } //var theURL = window.location.pathname //FIXME: Add url edits //var theURL = window.location //theURL.replace(`/${views[curTab]}`, `/${views[newValue]}`) //window.history.pushState({"html":response.html,"pageTitle":response.pageTitle},"", urlPath); //console.log(newpath) //window.location.pathame = newpath setModalUser({}) setCurTab(newValue) } if (firstRequest) { setFirstRequest(false) if (!isCloud) { getUsers() } else { getSettings() } const views = { "organization": 0, "users": 1, "app_auth": 2, "environments": 3, "schedules": 4, "files": 5, } if (props.match.params.key !== undefined) { const tmpitem = views[props.match.params.key] if (tmpitem !== undefined) { //setCurTab(tmpitem) setConfig("", tmpitem) } } } if (selectedOrganization.id === undefined && userdata !== undefined && userdata.active_org !== undefined) { //setSelectedOrganization(userdata.active_org) handleGetOrg(userdata.active_org.id) } 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 GridItem = (props) => { const [expanded, setExpanded] = React.useState(false) const primary = props.data.primary const secondary = props.data.secondary const primaryIcon = props.data.icon const secondaryIcon = props.data.active ? : return ( { setExpanded(!expanded) }}> {primaryIcon} {secondaryIcon} {expanded ?
Usage: {props.data.limit === 0 ? "Infinite" : {props.data.usage} / {props.data.limit}} Data sharing: {props.data.data_collection} Description: {secondary}
: null}
) } const itemColor = "black" var syncList = [ { "primary": "Workflows", "secondary": "", "active": true, "icon": , }, { "primary": "Apps", "secondary": "", "active": true, "icon": , }, { "primary": "Organization", "secondary": "", "active": true, "icon": , }, ] const cloudSyncModal = { setCloudSyncModalOpen(false) }} PaperProps={{ style: { backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: "800px", minHeight: "320px", }, }} > Enable cloud features What does cloud sync do?
{ setCloudSyncApikey(event.target.value) }} />
{orgSyncResponse.length > 0 ? Error: {orgSyncResponse} : null } {syncList.map((data, index) => { return ( ) })} * New triggers (userinput, hotmail realtime)
* Execute in the cloud rather than onprem
* Apps can be built in the cloud
* Easily share apps and workflows
* Access to powerful cloud search
const cancelSubscriptions = (subscription_id) => { console.log(selectedOrganization) const data = { "subscription_id": subscription_id, "action": "cancel", "org_id": selectedOrganization.id, } const url = globalUrl + `/api/v1/orgs/${selectedOrganization.id}`; 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(function(response) { if (response.status !== 200) { console.log("Error in response") } handleGetOrg(selectedOrganization.id) return response.json(); }).then(function(responseJson) { if (responseJson.success !== undefined && responseJson.success) { alert.success("Successfully stopped subscription!") } else { alert.error("Failed stopping subscription. Please contact us.") } }) .catch(function(error) { console.log("Error: ", error) alert.error("Failed stopping subscription. Please contact us.") }) } const organizationView = curTab === 0 && selectedOrganization.id !== undefined ?

Organization overview

On this page you can configure individual parts of your organization. Learn more
{selectedOrganization.id === undefined ?
:
{selectedOrganization.name.length > 0 ? : null} Cloud syncronization What does cloud sync do? Cloud syncronization is a way of getting more out of Shuffle. Shuffle will ALWAYS make every option open source, but features relying on other users can't be done without a collaborative approach. {isCloud ?
Currently syncronizing: {selectedOrganization.cloud_sync_active === true ? "True" : "False"} {selectedOrganization.cloud_sync_active ? Syncronization interval: {selectedOrganization.sync_config.interval === 0 ? "60" : selectedOrganization.sync_config.interval} : null } Your Apikey
:
{ setCloudSyncApikey(event.target.value) }} />
{orgSyncResponse.length > 0 ? Message from Shuffle: {orgSyncResponse} : null }
} Cloud sync features {Object.keys(selectedOrganization.sync_features).map(function(key, index) { if (key === "schedule") { return null } const item = selectedOrganization.sync_features[key] const newkey = key.replace("_", " ") const griditem = { "primary": newkey, "secondary": item.description === undefined || item.description === null || item.description.length === 0 ? "Not defined yet" : item.description, "limit": item.limit, "usage": 0, "data_collection": "None", "active": item.active, "icon": , } return ( ) })} {isCloud && selectedOrganization.subscriptions !== null && selectedOrganization.subscriptions.length > 0 ?
Your subscription{selectedOrganization.subscriptions.length > 1 ? "s" : ""} {selectedOrganization.subscriptions.reverse().map((sub, index) => { return ( Type: {sub.level}
Recurrence: {sub.recurrence}
{sub.active ?
Started: {new Date(sub.startdate*1000).toISOString()}
:
Cancelled: {new Date(sub.cancellationdate*1000).toISOString()}
Status: Deactivated
} ) })}
: null }
}
: null const modalView = { setModalOpen(false) }} PaperProps={{ style: { backgroundColor: theme.palette.surfaceColor, color: "white", minWidth: "800px", minHeight: "320px", }, }} > {curTab === 1 ? "Add user" : "Add environment"} {curTab === 1 ?
Username changeModalData("Username", event.target.value)} /> Password changeModalData("Password", event.target.value)} />
: curTab === 3 ?
Environment Name changeModalData("environment", event.target.value)} />
: null} {loginInfo}
const usersView = curTab === 1 ?

User management

Add, edit, block or change passwords. Learn more
{users === undefined ? null : users.map((data, index) => { var bgColor = "#27292d" if (index % 2 === 0) { bgColor = "#1f2023" } 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 filesView = curTab === 5 ?

Files

Files from Workflows. Learn more
{files === undefined || files === null ? null : files.map((file, index) => { var bgColor = "#27292d" if (index % 2 === 0) { bgColor = "#1f2023" } return ( style={{minWidth: 100, maxWidth: 100, overflow: "hidden"}} /> { downloadFile(file) }}> style={{minWidth: 75, maxWidth: 75, overflow: "hidden"}} /> {/* */} ) })}
: null const schedulesView = curTab === 4 ?

Schedules

Schedules used in Workflows. Makes locating and control easier. Learn more
{schedules === undefined || schedules === null ? null : schedules.map((schedule, index) => { var bgColor = "#27292d" if (index % 2 === 0) { bgColor = "#1f2023" } return ( {schedule.seconds} seconds} /> {schedule.workflow_id}} /> ) })}
: null const appCategoryView = curTab === 7 ?

Categories

Categories are the categories supported by Shuffle, which are mapped to apps and workflows
{categories.map(data => { if (data.apps.length === 0) { return null } return ( ) })}
: null const authenticationView = curTab === 2 ?

App Authentication

Control the authentication options for individual apps. Actions can be destructive!Learn more
{authentication === undefined ? null : authentication.map((data, index) => { var bgColor = "#27292d" if (index % 2 === 0) { bgColor = "#1f2023" } return ( style={{minWidth: 150, maxWidth: 150}} /> { return data.key }).join(", ")} style={{minWidth: 200, maxWidth: 200, overflow: "hidden"}} /> ) })}
: null const environmentView = curTab === 3 ?

Environments

Decides what Orborus environment to execute an action in a workflow in.Learn more
{setShowArchived(!showArchived)}} /> Show archived {environments === undefined || environments === null ? null : environments.map((environment, index)=> { if (!showArchived && environment.archived) { return null } if (environment.archived === undefined) { getEnvironments() return null } //var bgColor = "#27292d" //if (index % 2 === 0) { // bgColor = "#1f2023" //} return ( {environment.default ? null : } {/**/} ) })}
: null const organizationsTab = curTab === 7 ?

Organizations

Global admin: control organizations
{organizations !== undefined && organizations !== null && organizations.length > 0 ? {organizations.map((data, index) => { const isSelected = props.userdata.active_org.id === undefined ? "False" : props.userdata.active_org.id === data.id ? "True" : "False" return ( { setCloudSyncModalOpen(true) setSelectedOrganization(data) console.log("INVERT CLOUD SYNC") }} /> style={{minWidth: 150, maxWidth: 150}} /> ) })} : null}
: null const hybridTab = curTab === 6 ?

Hybrid

{console.log("INVERT")}} /> style={{minWidth: 150, maxWidth: 150}} />
: null // primary={environment.Registered ? "true" : "false"} const iconStyle = {marginRight: 10} const data =
Organization/> {isCloud ? null : Users />} {isCloud ? null : App Authentication/>} {isCloud ? null : Environments/>} {isCloud ? null : Schedules />} {isCloud ? null : Files />} {window.location.protocol == "http:" && window.location.port === "3000" ? Hybrid/> : null} {window.location.protocol == "http:" && window.location.port === "3000" ? Organizations/> : null} {window.location.protocol === "http:" && window.location.port === "3000" ? Categories/> : null}
{organizationView} {authenticationView} {appCategoryView} {usersView} {environmentView} {schedulesView} {filesView} {hybridTab} {organizationsTab}
return (
{modalView} {cloudSyncModal} {editUserModal} {editAuthenticationModal} {data}
) } export default Admin