From c1c34ff72a92c97840ceddc176037f09fa991f35 Mon Sep 17 00:00:00 2001 From: Frikky Date: Tue, 19 Sep 2023 14:37:41 +0200 Subject: [PATCH] Loads of frontend fixes related to React & MUI --- frontend/src/components/AppGrid.jsx | 30 +- frontend/src/components/CreatorGrid.jsx | 22 +- frontend/src/components/DocsGrid.jsx | 24 +- frontend/src/components/Header.jsx | 2 +- frontend/src/components/Oauth2Auth.jsx | 25 +- frontend/src/components/ParsedAction.jsx | 217 +- frontend/src/components/Searchfield.jsx | 10 +- frontend/src/components/ShuffleCodeEditor.jsx | 3 + frontend/src/components/WorkflowGrid.jsx | 6 + frontend/src/defaultCytoscapeStyle.jsx | 25 +- frontend/src/theme.jsx | 17 +- frontend/src/views/Admin.jsx | 9 +- frontend/src/views/AngularWorkflow.jsx | 2000 ++++++++++++----- frontend/src/views/AppCreator.jsx | 222 +- frontend/src/views/Docs.jsx | 46 +- frontend/src/views/RunWorkflow.jsx | 135 +- frontend/src/views/Workflows.jsx | 139 +- 17 files changed, 1961 insertions(+), 971 deletions(-) diff --git a/frontend/src/components/AppGrid.jsx b/frontend/src/components/AppGrid.jsx index 57369deb..2d0e9d3d 100644 --- a/frontend/src/components/AppGrid.jsx +++ b/frontend/src/components/AppGrid.jsx @@ -3,6 +3,7 @@ import React, {useEffect, useState} from 'react'; import theme from '../theme.jsx'; import ReactGA from 'react-ga4'; import {Link} from 'react-router-dom'; +import { removeQuery } from '../components/ScrollToTop.jsx'; import { Search as SearchIcon, @@ -89,21 +90,24 @@ const AppGrid = props => { } const SearchBox = ({currentRefinement, refine, isSearchStalled} ) => { - useEffect(() => { - if (window !== undefined && window.location !== undefined && window.location.search !== undefined && window.location.search !== null) { - const urlSearchParams = new URLSearchParams(window.location.search) - const params = Object.fromEntries(urlSearchParams.entries()) - const foundQuery = params["q"] - if (foundQuery !== null && foundQuery !== undefined) { - console.log("Got query: ", foundQuery) - refine(foundQuery) - } + var defaultSearch = "" + //useEffect(() => { + if (window !== undefined && window.location !== undefined && window.location.search !== undefined && window.location.search !== null) { + const urlSearchParams = new URLSearchParams(window.location.search) + const params = Object.fromEntries(urlSearchParams.entries()) + const foundQuery = params["q"] + if (foundQuery !== null && foundQuery !== undefined) { + console.log("Got query: ", foundQuery) + refine(foundQuery) + defaultSearch = foundQuery } - }, []) + } + //}, []) return (
{ autoComplete='off' type="search" color="primary" - defaultValue={currentRefinement} placeholder="Find Apps..." id="shuffle_search_field" onChange={(event) => { + // Remove "q" from URL + removeQuery("q") + refine(event.currentTarget.value) }} limit={5} @@ -151,8 +157,6 @@ const AppGrid = props => { // setInnerHits(hits) //} - console.log("In appgrid") - return ( {hits.map((data, index) => { diff --git a/frontend/src/components/CreatorGrid.jsx b/frontend/src/components/CreatorGrid.jsx index 712a2197..56b80786 100644 --- a/frontend/src/components/CreatorGrid.jsx +++ b/frontend/src/components/CreatorGrid.jsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react'; import ReactGA from 'react-ga4'; import {Link} from 'react-router-dom'; import theme from '../theme.jsx'; +import { removeQuery } from '../components/ScrollToTop.jsx'; import { SkipNext as SkipNextIcon, @@ -97,20 +98,21 @@ const CreatorGrid = props => { // value={currentRefinement} const SearchBox = ({currentRefinement, refine, isSearchStalled} ) => { - useEffect(() => { - if (window !== undefined && window.location !== undefined && window.location.search !== undefined && window.location.search !== null) { - const urlSearchParams = new URLSearchParams(window.location.search) - const params = Object.fromEntries(urlSearchParams.entries()) - const foundQuery = params["q"] - if (foundQuery !== null && foundQuery !== undefined) { - refine(foundQuery) - } + var defaultSearch = "" + if (window !== undefined && window.location !== undefined && window.location.search !== undefined && window.location.search !== null) { + const urlSearchParams = new URLSearchParams(window.location.search) + const params = Object.fromEntries(urlSearchParams.entries()) + const foundQuery = params["q"] + if (foundQuery !== null && foundQuery !== undefined) { + refine(foundQuery) + defaultSearch = foundQuery } - }, []) + } return ( { autoComplete='off' type="search" color="primary" - value={currentRefinement} placeholder="Find Creators..." id="shuffle_search_field" onChange={(event) => { + removeQuery("q") refine(event.currentTarget.value) }} /> diff --git a/frontend/src/components/DocsGrid.jsx b/frontend/src/components/DocsGrid.jsx index 947a2d76..06469251 100644 --- a/frontend/src/components/DocsGrid.jsx +++ b/frontend/src/components/DocsGrid.jsx @@ -3,6 +3,7 @@ import React, {useEffect, useState} from 'react'; import theme from '../theme.jsx'; import ReactGA from 'react-ga4'; import {Link} from 'react-router-dom'; +import { removeQuery } from '../components/ScrollToTop.jsx'; import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon, Close as CloseIcon, Folder as FolderIcon, LibraryBooks as LibraryBooksIcon } from '@mui/icons-material'; import aa from 'search-insights' @@ -84,21 +85,22 @@ const DocsGrid = props => { } const SearchBox = ({currentRefinement, refine, isSearchStalled} ) => { - useEffect(() => { - if (window !== undefined && window.location !== undefined && window.location.search !== undefined && window.location.search !== null) { - const urlSearchParams = new URLSearchParams(window.location.search) - const params = Object.fromEntries(urlSearchParams.entries()) - const foundQuery = params["q"] - if (foundQuery !== null && foundQuery !== undefined) { - console.log("Got query: ", foundQuery) - refine(foundQuery) - } + var defaultSearch = "" + if (window !== undefined && window.location !== undefined && window.location.search !== undefined && window.location.search !== null) { + const urlSearchParams = new URLSearchParams(window.location.search) + const params = Object.fromEntries(urlSearchParams.entries()) + const foundQuery = params["q"] + if (foundQuery !== null && foundQuery !== undefined) { + console.log("Got query: ", foundQuery) + refine(foundQuery) + defaultSearch = foundQuery } - }, []) + } return ( { autoComplete='off' type="search" color="primary" - defaultValue={currentRefinement} placeholder="Search our Documentation..." id="shuffle_search_field" onChange={(event) => { + removeQuery("q") refine(event.currentTarget.value) }} limit={5} diff --git a/frontend/src/components/Header.jsx b/frontend/src/components/Header.jsx index 6a680b5e..44024d8c 100644 --- a/frontend/src/components/Header.jsx +++ b/frontend/src/components/Header.jsx @@ -521,7 +521,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho } // Handle top bar or something - const defaultTop = 7 + const defaultTop = 0 const loginTextBrowser = !isLoggedIn ?
diff --git a/frontend/src/components/Oauth2Auth.jsx b/frontend/src/components/Oauth2Auth.jsx index 46f03017..204af1c6 100755 --- a/frontend/src/components/Oauth2Auth.jsx +++ b/frontend/src/components/Oauth2Auth.jsx @@ -218,7 +218,7 @@ const AuthenticationOauth2 = (props) => { "31cb4c84-658e-43d5-ae84-22c9142e967a", "", "https://graph.microsoft.com", - ["ChannelMessage.Edit", "ChannelMessage.Read.All", "ChannelMessage.Send", "Chat.Create", "Chat.ReadWrite", "Chat.Read", "offline_access"], + ["ChannelMessage.Edit", "ChannelMessage.Read.All", "ChannelMessage.Send", "Chat.Create", "Chat.ReadWrite", "Chat.Read", "offline_access", "Team.ReadBasic.All"], admin_consent, ) } else if (selectedApp.name.toLowerCase().includes("todoist")) { @@ -607,7 +607,7 @@ const AuthenticationOauth2 = (props) => {
- Authentication for {selectedApp.name} + Authenticate {selectedApp.name.replaceAll("_", " ")}
@@ -674,11 +674,6 @@ const AuthenticationOauth2 = (props) => { style={{backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}} InputProps={{ style:{ - color: "white", - marginLeft: "5px", - maxWidth: "95%", - height: 50, - fontSize: "1em", }, }} fullWidth @@ -763,11 +758,6 @@ const AuthenticationOauth2 = (props) => { }} InputProps={{ style: { - color: "white", - marginLeft: "5px", - maxWidth: "95%", - height: 50, - fontSize: "1em", }, }} fullWidth @@ -804,11 +794,6 @@ const AuthenticationOauth2 = (props) => { }} InputProps={{ style: { - color: "white", - marginLeft: "5px", - maxWidth: "95%", - fontSize: "1em", - height: "50px", }, }} fullWidth @@ -827,11 +812,6 @@ const AuthenticationOauth2 = (props) => { }} InputProps={{ style: { - color: "white", - marginLeft: "5px", - maxWidth: "95%", - fontSize: "1em", - height: "50px", }, }} fullWidth @@ -848,6 +828,7 @@ const AuthenticationOauth2 = (props) => { Scopes { return (
-
-

- {selectedTrigger.app_name}: {selectedTrigger.status} -

- - What are email triggers? - -
+

+ {selectedTrigger.app_name}: {selectedTrigger.status} +

+ + What are email triggers? + { return (
-
-

- {selectedTrigger.app_name} -

- - What are subflows? - -
+

+ {selectedTrigger.app_name} +

+ + What are subflows? + { { return (
- +

Comment

+ + What are comments? + { // Special SCHEDULE handler var trigger_header_auth = "" if (Object.getOwnPropertyNames(selectedTrigger).length > 0 && workflow.triggers[selectedTriggerIndex] !== undefined ) { - if (selectedTrigger.trigger_type === "SCHEDULE" && workflow.triggers[selectedTriggerIndex].parameters === undefined || workflow.triggers[selectedTriggerIndex].parameters === null || workflow.triggers[selectedTriggerIndex].parameters.length === 0) { + if (selectedTrigger.trigger_type === "SCHEDULE" && workflow.triggers[selectedTriggerIndex].parameters === undefined || workflow.triggers[selectedTriggerIndex].parameters === null) { console.log("Autofixing schedule") workflow.triggers[selectedTriggerIndex].parameters = []; @@ -10701,19 +11539,17 @@ const AngularWorkflow = (defaultprops) => { const WebhookSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "WEBHOOK" ? null :
-
-

- {selectedTrigger.app_name}: {selectedTrigger.status} -

- - What are webhooks? - -
+

+ {selectedTrigger.app_name}: {selectedTrigger.status} +

+ + What are webhooks? + { return (
-
-

- {selectedTrigger.app_name} -

- - What is the user input trigger? - -
+

+ {selectedTrigger.app_name} +

+ + What is the user input trigger? + { const ScheduleSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined && selectedTrigger.trigger_type !== "SCHEDULE" ? null :
-
-

- {selectedTrigger.app_name}: {selectedTrigger.status} -

- - What are schedules? - -
+

+ {selectedTrigger.app_name}: {selectedTrigger.status} +

+ + What are schedules? + { workflow.triggers[selectedTriggerIndex].status === "running" } defaultValue={ - workflow.triggers[selectedTriggerIndex].parameters[0].value + workflow.triggers[selectedTriggerIndex].parameters === undefined ? "" : workflow.triggers[selectedTriggerIndex].parameters[0].value } color="primary" placeholder="defaultValue" @@ -12037,7 +12869,7 @@ const AngularWorkflow = (defaultprops) => { multiline color="primary" defaultValue={ - workflow.triggers[selectedTriggerIndex] !== undefined && workflow.triggers[selectedTriggerIndex].parameters.length > 1 ? + workflow.triggers[selectedTriggerIndex] !== undefined && workflow.triggers[selectedTriggerIndex].parameters !== undefined && workflow.triggers[selectedTriggerIndex].parameters !== null && workflow.triggers[selectedTriggerIndex].parameters.length > 1 ? workflow.triggers[selectedTriggerIndex].parameters[1].value : "" } @@ -12384,6 +13216,66 @@ const AngularWorkflow = (defaultprops) => { } }; + const BottomAvatars = () => { + const connectedUsers = [{ + "user": "Anonymous", + "user_id": "user_id", + "color": "blue", + }, { + "user": "frikky", + "user_id": "user_id", + "color": "red", + }] + + + if (connectedUsers === undefined || connectedUsers === null || connectedUsers.length < 2) { + return null + } + + const avatarStyle = { + position: "fixed", + display: "flex", + right: isMobile ? 20 : 20, + top: isMobile ? appBarSize-100 : undefined, + bottom: isMobile ? undefined : 0, + left: isMobile ? undefined : leftBarSize, + minWidth: cytoscapeViewWidths, + maxWidth: cytoscapeViewWidths, + marginLeft: 20, + marginBottom: 20, + zIndex: 50, + } + + const HandleAvatar = (props) => { + const {user} = props + console.log("Clicked avatar: ", user) + + const userTitle = user.user[0].toUpperCase() + return ( + + + {userTitle} + + + ) + } + + return ( +
+ {connectedUsers.map((user) => { + return ( + + ) + })} +
+ ) + } + const BottomCytoscapeBar = () => { if (workflow.id === undefined || workflow.id === null || (!workflow.public && apps.length === 0)) { return null; @@ -12681,7 +13573,7 @@ const AngularWorkflow = (defaultprops) => { disabled={workflow.public} color="primary" style={{ height: 50, marginLeft: 10 }} - variant={allRevisions === undefined || allRevisions === null || allRevisions.length === 0 ? "outlined" : "contained"} + variant={"outlined"} onClick={() => { setShowWorkflowRevisions(true) setSelectedRevision(workflow) @@ -13131,8 +14023,8 @@ const AngularWorkflow = (defaultprops) => { getSettings(); getFiles() - // For loading datastore - // listOrgCache(workflow.org_id) + // For loading datastore + // listOrgCache(workflow.org_id) setUpdate(Math.random()); }} @@ -13202,15 +14094,15 @@ const AngularWorkflow = (defaultprops) => { const executionPaperStyle = { minWidth: "95%", maxWidth: "95%", - marginTop: "5px", + marginTop: 5, color: "white", marginBottom: 10, padding: 5, backgroundColor: theme.palette.surfaceColor, cursor: "pointer", display: "flex", - minHeight: 50, - maxHeight: 50, + minHeight: 45, + maxHeight: 45, }; const parsedExecutionArgument = () => { @@ -13305,11 +14197,7 @@ const AngularWorkflow = (defaultprops) => { const defaultImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACOCAMAAADkWgEmAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAWlBMVEX4Wj69TDgmKCvkVTwlJyskJiokJikkJSkjJSn4Ykf+6+f5h3L////8xLr5alH/9fT7nYz4Wz/919H5cVn/+vr8qpv4XUL94d35e2X//v38t6v4YUbkVDy8SzcVIzHLAAAAAWJLR0QMgbNRYwAAAAlwSFlzAAARsAAAEbAByCf1VAAAAAd0SU1FB+QGGgsvBZ/GkmwAAAFKSURBVHja7dlrTgMxDEXhFgpTiukL2vLc/zbZQH5N7MmReu4KPmlGN4m9WgGzfhgtaOZxM1rQztNoQDvPowHtTKMB7WxHA2TJkiVLlixIZMmSRYgsWbIIkSVLFiGyZMkiRNZirBcma/eKZEW87ZGsOBxPRFbE+R3Jio/LlciKuH0iWfH1/UNkRSR3RRYruSvyWKldkcjK7IpUVl5X5LLSuiKbldQV6aycrihgZXRFCau/K2pY3V1RxersijJWX1cUsnq6opLV0RW1rNldUc2a2RXlrHldsQBrTlfcLwv5EZm/PLIgkHXKPHyQRzXzYoO8BjIvzcgnBvJBxny+Ih/7zNEIcpDEHLshh5TIkS5zAI5cFzCXK8hVFHNxh1xzQpfC0BV6XWTJkkWILFmyCJElSxYhsmTJIkSWLFmEyJIlixBZsmQB8stk/U3/Yb49pVcDMg4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDYtMjZUMTE6NDc6MDUrMDI6MDD8QCPmAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTA2LTI2VDExOjQ3OjA1KzAyOjAwjR2bWgAAAABJRU5ErkJggg=="; const size = 40; - if ( - execution.execution_source === undefined || - execution.execution_source === null || - execution.execution_source.length === 0 - ) { + if (execution.execution_source === undefined || execution.execution_source === null || execution.execution_source.length === 0) { return ( default { width: lastExecution === data.execution_id ? 4 : 2, backgroundColor: statusColor, marginRight: 5, + maxHeight: 40, }} />
{ marginRight: 20, width: imgsize, height: imgsize, - border: `2px solid ${statusColor}`, - borderRadius: - executionData.start === data.action.id ? 25 : 5, + borderRadius: executionData.start === data.action.id ? 25 : 5, }} /> ); @@ -14271,18 +15158,14 @@ const AngularWorkflow = (defaultprops) => { cy !== undefined ) { const nodedata = cy.getElementById(data.action.id).data(); - if ( - nodedata !== undefined && - nodedata !== null && - nodedata.fillstyle === "linear-gradient" - ) { + if (nodedata !== undefined && nodedata !== null && nodedata.fillstyle === "linear-gradient") { var imgStyle = { marginRight: 20, width: imgsize, height: imgsize, border: `2px solid ${statusColor}`, borderRadius: - executionData.start === data.action.id ? 25 : 5, + executionData.start === data.action.id ? 25 : 5, background: `linear-gradient(to right, ${nodedata.fillGradient})`, }; @@ -14293,7 +15176,22 @@ const AngularWorkflow = (defaultprops) => { style={imgStyle} /> ); - } + } else { + console.log("Node not found: ", nodedata) + actionimg = ( + {data.action.app_name} + ) + } } if (validate.valid && typeof validate.result === "string") { @@ -14580,7 +15478,7 @@ const AngularWorkflow = (defaultprops) => { const showVariable = data.value.length < 60 // Check if it's valid JSON - const checked = validateJson(data.value.trim()) + const checked = validateJson(data.value.trim()) return (
@@ -14806,6 +15704,7 @@ const AngularWorkflow = (defaultprops) => { +
{curapp === null ? null : ( @@ -14832,7 +15731,7 @@ const AngularWorkflow = (defaultprops) => { cursor: "move", }} > - {selectedResult.action.label} + {selectedResult.action.label.replaceAll("_", " ")}
{selectedResult.action.name}
@@ -15054,6 +15953,7 @@ const AngularWorkflow = (defaultprops) => { {showWorkflowRevisions ? null : + {/**/} @@ -15953,17 +16853,26 @@ const AngularWorkflow = (defaultprops) => { )} ) : ( - + + {selectedApp.documentation} + )}
@@ -16072,6 +16981,7 @@ const AngularWorkflow = (defaultprops) => { "action_name": item.action_name, "label": item.label, "example": exampledata, + "example_response": exampledata, }) } } @@ -16094,7 +17004,7 @@ const AngularWorkflow = (defaultprops) => { conversationData.parameters = inputAction.parameters if (!value.includes(inputAction.label)) { - conversationData.query = inputAction.label.replace("_", " ", -1) + conversationData.query = inputAction.label.replaceAll("_", " ") } } diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx index 9b7646bd..334b23a4 100755 --- a/frontend/src/views/AppCreator.jsx +++ b/frontend/src/views/AppCreator.jsx @@ -196,8 +196,9 @@ const parseCurl = (s) => { case "data": if (out.method === "GET" || out.method === "HEAD") out.method = "POST"; - out.header["Content-Type"] = - out.header["Content-Type"] || "application/x-www-form-urlencoded"; + + out.header["Content-Type"] = out.header["Content-Type"] || "application/x-www-form-urlencoded"; + out.body = out.body ? out.body + "&" + arg : arg; state = ""; break; @@ -223,52 +224,52 @@ const parseCurl = (s) => { // Basically CRUD for each category + special export const appCategories = [ - { - "name": "Communication", - "color": "#FFC107", - "icon": "communication", - "action_labels": ["List Messages", "Send Message", "Get Message", "Search messages"], - }, { - "name": "SIEM", - "color": "#FFC107", - "icon": "siem", - "action_labels": ["Search", "List Alerts", "Close Alert", "Create detection", "Add to lookup list",], - }, { - "name": "Eradication", - "color": "#FFC107", - "icon": "eradication", - "action_labels": ["List Alerts", "Close Alert", "Create detection", "Block hash", "Search Hosts", "Isolate host", "Unisolate host"], - }, { - "name": "Cases", - "color": "#FFC107", - "icon": "cases", - "action_labels": ["List tickets", "Get ticket", "Create ticket", "Close ticket", "Add comment", "Update ticket",], - }, { - "name": "Assets", - "color": "#FFC107", - "icon": "assets", - "action_labels": ["List Assets", "Get Asset", "Search Assets", "Search Users", "Search endpoints", "Search vulnerabilities"], - }, { - "name": "Intel", - "color": "#FFC107", - "icon": "intel", - "action_labels": ["Get IOC", "Search IOC", "Create IOC", "Update IOC", "Delete IOC",], - }, { - "name": "IAM", - "color": "#FFC107", - "icon": "iam", - "action_labels": ["Reset Password", "Enable user", "Disable user", "Get Identity", "Get Asset", "Search Identity", ], - }, { - "name": "Network", - "color": "#FFC107", - "icon": "network", - "action_labels": ["Get Rules", "Allow IP", "Block IP",], - }, { - "name": "Other", - "color": "#FFC107", - "icon": "other", - "action_labels": ["Update Info", "Get Info", "Get Status", "Get Version", "Get Health", "Get Config", "Get Configs", "Get Configs by type", "Get Configs by name", "Run script"], - }, + { + "name": "Communication", + "color": "#FFC107", + "icon": "communication", + "action_labels": ["List Messages", "Send Message", "Get Message", "Search messages", "List Attachments", "Get Attachment", "Get Contact"], + }, { + "name": "SIEM", + "color": "#FFC107", + "icon": "siem", + "action_labels": ["Search", "List Alerts", "Close Alert", "Get Alert", "Create detection", "Add to lookup list",], + }, { + "name": "Eradication", + "color": "#FFC107", + "icon": "eradication", + "action_labels": ["List Alerts", "Close Alert", "Get Alert", "Create detection", "Block hash", "Search Hosts", "Isolate host", "Unisolate host"], + }, { + "name": "Cases", + "color": "#FFC107", + "icon": "cases", + "action_labels": ["List tickets", "Get ticket", "Create ticket", "Close ticket", "Add comment", "Update ticket", "Search tickets"], + }, { + "name": "Assets", + "color": "#FFC107", + "icon": "assets", + "action_labels": ["List Assets", "Get Asset", "Search Assets", "Search Users", "Search endpoints", "Search vulnerabilities"], + }, { + "name": "Intel", + "color": "#FFC107", + "icon": "intel", + "action_labels": ["Get IOC", "Search IOC", "Create IOC", "Update IOC", "Delete IOC",], + }, { + "name": "IAM", + "color": "#FFC107", + "icon": "iam", + "action_labels": ["Reset Password", "Enable user", "Disable user", "Get Identity", "Get Asset", "Search Identity", ], + }, { + "name": "Network", + "color": "#FFC107", + "icon": "network", + "action_labels": ["Get Rules", "Allow IP", "Block IP",], + }, { + "name": "Other", + "color": "#FFC107", + "icon": "other", + "action_labels": ["Update Info", "Get Info", "Get Status", "Get Version", "Get Health", "Get Config", "Get Configs", "Get Configs by type", "Get Configs by name", "Run script"], + }, ] export const base64_decode = (str) => { @@ -570,11 +571,11 @@ const AppCreator = (defaultprops) => { if (data.openapi === null) { toast("Failed to load OpenAPI for app. Please contact support if this persists.") - setIsAppLoaded(true); + setIsAppLoaded(true); return } - console.log("Decoded: ", parsedDecoded) + //console.log("Decoded: ", parsedDecoded) const parsedapp = data.openapi === undefined || data.openapi === null ? data @@ -719,9 +720,9 @@ const AppCreator = (defaultprops) => { var newActions = []; var wordlist = {}; var all_categories = []; - var parentUrl = "" + var parentUrl = "" - console.log("Paths: ", data.paths) + console.log("Paths: ", data.paths) if (data.paths !== null && data.paths !== undefined) { for (let [path, pathvalue] of Object.entries(data.paths)) { @@ -751,45 +752,44 @@ const AppCreator = (defaultprops) => { tmpname = methodvalue.operationId; } - if (tmpname !== undefined && tmpname !== null) { - tmpname = tmpname.replaceAll(".", " "); - } + if (tmpname !== undefined && tmpname !== null) { + tmpname = tmpname.replaceAll(".", " "); + } - if ((tmpname === undefined || tmpname === null) && methodvalue.description !== undefined && methodvalue.description !== null && methodvalue.description.length > 0) { - tmpname = methodvalue.description.replaceAll(".", " ").replaceAll("_", " ") - } + if ((tmpname === undefined || tmpname === null) && methodvalue.description !== undefined && methodvalue.description !== null && methodvalue.description.length > 0) { + tmpname = methodvalue.description.replaceAll(".", " ").replaceAll("_", " ") + } - var newaction = { - name: tmpname, - description: methodvalue.description, - url: path, - file_field: "", - method: method.toUpperCase(), - headers: "", - queries: [], - paths: [], - body: "", - errors: [], - example_response: "", - action_label: "No Label", - required_bodyfields: [], - }; + var newaction = { + name: tmpname, + description: methodvalue.description, + url: path, + file_field: "", + method: method.toUpperCase(), + headers: "", + queries: [], + paths: [], + body: "", + errors: [], + example_response: "", + action_label: "No Label", + required_bodyfields: [], + }; - if (methodvalue["x-label"] !== undefined && methodvalue["x-label"] !== null) { - // FIX: Map labels only if they're actually in the category list - newaction.action_label = methodvalue["x-label"] - } + if (methodvalue["x-label"] !== undefined && methodvalue["x-label"] !== null) { + // FIX: Map labels only if they're actually in the category list + newaction.action_label = methodvalue["x-label"] + } - if (methodvalue["x-required-fields"] !== undefined && methodvalue["x-required-fields"] !== null) { - newaction.required_bodyfields = methodvalue["x-required-fields"] - } + if (methodvalue["x-required-fields"] !== undefined && methodvalue["x-required-fields"] !== null) { + newaction.required_bodyfields = methodvalue["x-required-fields"] + } - if (newaction.url !== undefined && newaction.url !== null && newaction.url.includes("_shuffle_replace_")) { - const regex = /_shuffle_replace_\d/i; - //console.log("NEW: ", - newaction.url = newaction.url.replaceAll(new RegExp(regex, 'g'), "") - console.log("Replaced: ", newaction.url) - } + if (newaction.url !== undefined && newaction.url !== null && newaction.url.includes("_shuffle_replace_")) { + const regex = /_shuffle_replace_\d/i; + //console.log("NEW: ", + newaction.url = newaction.url.replaceAll(new RegExp(regex, 'g'), "") + } // Finding category if (path.includes("/")) { @@ -1110,19 +1110,11 @@ const AppCreator = (defaultprops) => { undefined ) { if ( - methodvalue.responses.default.content["text/plain"][ - "schema" - ] !== undefined - ) { - if ( - methodvalue.responses.default.content["text/plain"][ - "schema" - ]["example"] !== undefined - ) { - newaction.example_response = - methodvalue.responses.default.content["text/plain"][ - "schema" - ]["example"] + methodvalue.responses.default.content["text/plain"]["schema"] !== undefined) { + if (methodvalue.responses.default.content["text/plain"]["schema"]["example"] !== undefined) { + newaction.example_response = methodvalue.responses.default.content["text/plain"]["schema"]["example"] + + } @@ -1560,12 +1552,12 @@ const AppCreator = (defaultprops) => { if (securitySchemes !== undefined) { - console.log("SECURITY: ", securitySchemes) - var newauth = []; - try { - var optionset = false + //console.log("SECURITY: ", securitySchemes) + var newauth = []; + try { + var optionset = false for (const [key, value] of Object.entries(securitySchemes)) { - console.log("AUTH: ", key, value); + //console.log("AUTH: ", key, value); if (key === "jwt") { setAuthenticationOption("JWT"); @@ -1776,12 +1768,12 @@ const AppCreator = (defaultprops) => { if (!found) { newActions2.push(action) } else { - console.log("NOT skipping duplicate action: ", action.url, ". Should merge contents") + //console.log("NOT skipping duplicate action: ", action.url, ". Should merge contents") newActions2.push(action) } } - console.log("Actions: ", newActions.length, " Actions2: ", newActions2.length) + //console.log("Actions: ", newActions.length, " Actions2: ", newActions2.length) newActions = newActions2 if (newActions.length > increaseAmount - 1) { setActionAmount(increaseAmount); @@ -3880,7 +3872,7 @@ const AppCreator = (defaultprops) => { const datasplit = parsedurlsplit[1].split("&") for (var key in datasplit) { - console.log("Data: ", datasplit[key]) + //console.log("Data: ", datasplit[key]) var actualkey = datasplit[key] var example = "" if (datasplit[key].includes("=")) { @@ -4143,7 +4135,7 @@ const AppCreator = (defaultprops) => { overflowX: "hidden", }} onClick={() => { - console.log("Data: ", data) + //console.log("Data: ", data) if (hasFile) { //setActionField("headers", "") //console.log("It has a file: ", data["file_field"]) @@ -4321,9 +4313,9 @@ const AppCreator = (defaultprops) => { } const LoopActions = (props) => { - const { filteredActions } = props; + const { filteredActions } = props; - console.log("Actions: ", filteredActions) + //console.log("Actions: ", filteredActions) if (filteredActions === null || filteredActions === undefined || filteredActions.length === 0) { return null } @@ -4745,7 +4737,7 @@ const AppCreator = (defaultprops) => { } const handleSubmitCheck = () => { - console.log("NEW AUTH: ", authenticationOption); + //console.log("NEW AUTH: ", authenticationOption); if (authenticationOption.label.length === 0) { authenticationOption.label = `Auth for ${selectedApp.name}`; //toast("Label can't be empty") @@ -4968,10 +4960,10 @@ const AppCreator = (defaultprops) => { {projectCategories.map((tag, index) => { const newname = tag.charAt(0).toUpperCase() + tag.slice(1); - //var regex = /_shuffle_replace_\d/i; - ////console.log("NEW: ", - //newname = newname.replaceAll(regex, "") - //console.log("Replaced: ", newname) + //var regex = /_shuffle_replace_\d/i; + ////console.log("NEW: ", + //newname = newname.replaceAll(regex, "") + //console.log("Replaced: ", newname) return ( { } function CodeHandler(props) { + console.log("PROPS: ", props) + + const propvalue = props.value !== undefined && props.value !== null ? props.value : props.children !== undefined && props.children !== null && props.children.length > 0 ? props.children[0] : "" + return ( -
-        {props.value}
-      
+ {propvalue} +
); } @@ -436,7 +445,7 @@ const Docs = (defaultprops) => { href={selectedMeta.link} style={{ textDecoration: "none", color: "#f85a3e" }} > - @@ -638,7 +647,7 @@ const Docs = (defaultprops) => { Why Shuffle? - Security first. We incentivize trying before buying, and give you the full set of tools you need to automate your operations. What's more is we also help you find usecases that fit your your unique needs. Accessibility is key, and we intend to help every SOC globally use and share their usecases. + Security first. We incentivize trying before buying, and give you the full set of tools you need to automate your operations. What's more is we also help you find usecases that fit your unique needs. Accessibility is key, and we intend to help every SOC globally use and share their usecases. Get help @@ -878,16 +887,25 @@ const Docs = (defaultprops) => { :
+ > + {data} +
} { marginBottom: 150, } - const params = useParams(); - var props = JSON.parse(JSON.stringify(defaultprops)) - props.match = {} - props.match.params = params + const params = useParams(); + var props = JSON.parse(JSON.stringify(defaultprops)) + props.match = {} + props.match.params = params const defaultTitle = "Run Workflow" if (document != undefined && document.title != defaultTitle) { @@ -126,12 +126,14 @@ const RunWorkflow = (defaultprops) => { } const executionMargin = 20 - const defaultReturn = + const defaultReturn = null + /*
No results yet
+ */ if (executionData.results === undefined || executionData.results === null) { return defaultReturn @@ -271,7 +273,7 @@ const RunWorkflow = (defaultprops) => { width: 30, }} onClick={() => { - navigate(`?execution_highlight=${parsed_url}`) + //navigate(`?execution_highlight=${parsed_url}`) }} > @@ -314,10 +316,16 @@ const RunWorkflow = (defaultprops) => { ) } - const onSubmit = (execution_id, authorization, answer) => { + const onSubmit = (event, execution_id, authorization, answer) => { + if (event !== null) { + event.preventDefault() + } + + console.log("In submit!") + stop() - setMessage("") - setExecutionLoading(true) + setMessage("") + setExecutionLoading(true) setExecutionData({}) setExecutionInfo("") @@ -327,13 +335,13 @@ const RunWorkflow = (defaultprops) => { var url = `${globalUrl}/api/v1/workflows/${props.match.params.key}/execute` var fetchBody = { + headers: { + 'Content-Type': 'application/json; charset=utf-8', + }, mode: 'cors', credentials: 'include', crossDomain: true, withCredentials: true, - headers: { - 'Content-Type': 'application/json; charset=utf-8', - }, } if (answer !== undefined && execution_id !== undefined && authorization !== undefined) { @@ -345,8 +353,10 @@ const RunWorkflow = (defaultprops) => { fetchBody.body = JSON.stringify(data) } + console.log("Pre request: ", url, fetchBody) fetch(url, fetchBody) .then((response) => { + console.log("Got answer 1") if (response.status !== 200 && response.status !== 201) { if (answer !== undefined && execution_id !== undefined && authorization !== undefined) { @@ -362,9 +372,11 @@ const RunWorkflow = (defaultprops) => { } } + console.log("Got answer 2") return response.json(); }) .then(responseJson => { + console.log("Got answer 3") setExecutionLoading(false) if (responseJson["success"] === false) { console.log("Failed sending execution request") @@ -379,6 +391,7 @@ const RunWorkflow = (defaultprops) => { start(); } } + console.log("Got answer 4") }) .catch(error => { //setExecutionInfo("Error in workflow startup: " + error) @@ -387,14 +400,14 @@ const RunWorkflow = (defaultprops) => { } const getWorkflow = (workflow_id) => { - fetch(globalUrl + "/api/v1/workflows/" + workflow_id, { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) + fetch(globalUrl + "/api/v1/workflows/" + workflow_id, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) .then((response) => { if (response.status !== 200) { console.log("Status not 200 for workflows :O!"); @@ -441,35 +454,35 @@ const RunWorkflow = (defaultprops) => { return } - console.log("Got response: ", responseJson) + //console.log("Got response: ", responseJson) - ReactDOM.unstable_batchedUpdates(() => { - if (JSON.stringify(responseJson) !== JSON.stringify(executionData)) { - // FIXME: If another is selected, don't edit.. - // Doesn't work because this is some async garbage - if (executionData.execution_id === undefined || (responseJson.execution_id === executionData.execution_id && responseJson.results !== undefined && responseJson.results !== null)) { - if (executionData.status !== responseJson.status || executionData.result !== responseJson.result || (executionData.results !== undefined && responseJson.results !== null && executionData.results.length !== responseJson.results.length)) { - console.log("Updating data!") - setExecutionData(responseJson) + ReactDOM.unstable_batchedUpdates(() => { + if (JSON.stringify(responseJson) !== JSON.stringify(executionData)) { + // FIXME: If another is selected, don't edit.. + // Doesn't work because this is some async garbage + if (executionData.execution_id === undefined || (responseJson.execution_id === executionData.execution_id && responseJson.results !== undefined && responseJson.results !== null)) { + if (executionData.status !== responseJson.status || executionData.result !== responseJson.result || (executionData.results !== undefined && responseJson.results !== null && executionData.results.length !== responseJson.results.length)) { + //console.log("Updating data!") + setExecutionData(responseJson) - for (var key in responseJson.results) { - if (responseJson.results[key].status === "WAITING") { - console.log("Found: ", responseJson.results[key]) - - const validate = validateJson(responseJson.results[key].result) - console.log("Validate: ", validate) - if (validate.valid && typeof validate.result === "string") { - validate.result = JSON.parse(validate.result) - } + for (var key in responseJson.results) { + if (responseJson.results[key].status === "WAITING") { + console.log("Found: ", responseJson.results[key]) + + const validate = validateJson(responseJson.results[key].result) + console.log("Validate: ", validate) + if (validate.valid && typeof validate.result === "string") { + validate.result = JSON.parse(validate.result) + } - console.log("Newresult: ", validate.result) - if (validate.result["information"] !== undefined && validate.result["information"] !== null) { - setWorkflowQuestion(validate.result["information"]) - } - - break - } + console.log("Newresult: ", validate.result) + if (validate.result["information"] !== undefined && validate.result["information"] !== null) { + setWorkflowQuestion(validate.result["information"]) } + + break + } + } } else { console.log("NOT updating executiondata state."); } @@ -518,9 +531,9 @@ const RunWorkflow = (defaultprops) => { if (responseJson.sync_features === undefined || responseJson.sync_features === null) { } - if (document != undefined && document.title != defaultTitle) { - document.title = responseJson.name + " - " + defaultTitle - } + if (document != undefined && document.title != defaultTitle) { + document.title = responseJson.name + " - " + defaultTitle + } setSelectedOrganization(responseJson) } }) @@ -530,6 +543,11 @@ const RunWorkflow = (defaultprops) => { }; const fetchUpdates = (execution_id, authorization, getorg) => { + if (execution_id === undefined || execution_id === null || execution_id === "") { + stop() + return + } + const innerRequest = { "execution_id": execution_id, "authorization": authorization @@ -594,7 +612,7 @@ const RunWorkflow = (defaultprops) => { const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)" const buttonStyle = {borderRadius: 25, height: 50, fontSize: 18, backgroundImage: handleValidateForm(executionArgument) || executionLoading ? buttonBackground : "grey", color: "white"} - console.log("execdata: ", executionData) + //console.log("execdata: ", executionData) const disabledButtons = message.length > 0 || executionData.status === "FINISHED" || executionData.status === "ABORTED" const organization = selectedOrganization !== undefined && selectedOrganization !== null ? selectedOrganization.name : "Unknown" @@ -603,7 +621,7 @@ const RunWorkflow = (defaultprops) => { const image = selectedOrganization !== undefined && selectedOrganization !== null && selectedOrganization.image !== undefined && selectedOrganization.image !== null && selectedOrganization.image !== "" ? selectedOrganization.image : theme.palette.defaultImage - console.log("IMG: ", image, "ORG: ", selectedOrganization) + //console.log("IMG: ", image, "ORG: ", selectedOrganization) if (!disabledButtons && answer !== undefined && answer !== null && organization !== "Unknown" && buttonClicked.length === 0) { console.log("Finding button!") @@ -627,7 +645,7 @@ const RunWorkflow = (defaultprops) => { const basedata =
- {onSubmit()}} style={{margin: "15px 15px 15px 15px"}}> + {onSubmit(e)}} style={{margin: "15px 15px 15px 15px"}}> {workflow.name} { {answer !== undefined && answer !== null ? null : - Execution Argument + Runtime Argument
{ {executionRunning ? - - Status: {executionData.status} - + + {executionData.status !== undefined && executionData.status !== null && executionData.status !== "" ? + + Status: {executionData.status} + + : null} : @@ -723,7 +744,7 @@ const RunWorkflow = (defaultprops) => { }
@@ -3485,11 +3492,11 @@ const Workflows = (props) => { /> : null} -
+
{view === "grid" ? ( - + {/**/} - + {/**/} {filteredWorkflows.map((data, index) => {