From f4ebe2d0461e858acbefd10cde5533eb7314a09f Mon Sep 17 00:00:00 2001 From: Frikky Date: Thu, 19 Oct 2023 12:37:04 +0200 Subject: [PATCH] More polishing in the onboarding and usecase generation process --- backend/go-app/main.go | 10 +- frontend/src/components/AppSelection.jsx | 569 ++++++++++++++++++ .../src/components/WorkflowTemplatePopup.jsx | 4 +- 3 files changed, 579 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/AppSelection.jsx diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 63448dc4..ba444b10 100755 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -4147,8 +4147,8 @@ func runInitEs(ctx context.Context) { if err != nil && len(workflowapps) == 0 { log.Printf("[WARNING] Failed getting apps (runInit): %s", err) - } else if err == nil { - log.Printf("[DEBUG] Downloading default apps") + } else if err == nil && len(workflowapps) < 10 { + log.Printf("[DEBUG] Downloading default apps as %d were found", len(workflowapps)) fs := memfs.New() storer := memory.NewStorage() @@ -4204,6 +4204,8 @@ func runInitEs(ctx context.Context) { if len(location) != 0 { handleAppHotload(ctx, location, false) } + } else { + log.Printf("[DEBUG] Skipping download of default apps as %d were found", len(workflowapps)) } log.Printf("[INFO] Downloading OpenAPI data for search - EXTRA APPS") @@ -4219,7 +4221,7 @@ func runInitEs(ctx context.Context) { _, err = git.Clone(storer, fs, cloneOptions) if err != nil { log.Printf("[WARNING] Failed loading repo %s into memory: %s", apis, err) - } else { + } else if err == nil && len(workflowapps) < 10 { log.Printf("[INFO] Finished git clone. Looking for updates to the repo.") dir, err := fs.ReadDir("") if err != nil { @@ -4228,6 +4230,8 @@ func runInitEs(ctx context.Context) { iterateOpenApiGithub(fs, dir, "", "") log.Printf("[INFO] Finished downloading extra API samples") + } else { + log.Printf("[INFO] Skipping download of extra API samples as %d were found", len(workflowapps)) } log.Printf("[INFO] Finished INIT (ES)") diff --git a/frontend/src/components/AppSelection.jsx b/frontend/src/components/AppSelection.jsx new file mode 100644 index 00000000..bea2cc54 --- /dev/null +++ b/frontend/src/components/AppSelection.jsx @@ -0,0 +1,569 @@ +import React, { useState, useEffect, useRef } from "react"; +import theme from '../theme.jsx'; +import ReactGA from 'react-ga4'; +import { useNavigate, Link } from 'react-router-dom'; + +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' +import DeleteIcon from '@mui/icons-material/Delete'; +import ShowChartIcon from '@mui/icons-material/ShowChart'; +import ExploreIcon from '@mui/icons-material/Explore'; +import LightbulbIcon from "@mui/icons-material/Lightbulb"; +import NewReleasesIcon from "@mui/icons-material/NewReleases"; +import ExtensionIcon from "@mui/icons-material/Extension"; +import EmailIcon from "@mui/icons-material/Email"; +import FingerprintIcon from '@mui/icons-material/Fingerprint'; +import AppSearch from "../components/Appsearch.jsx"; +import { toast } from 'react-toastify'; +import { + Zoom, + Grid, + Paper, + TextField, + Collapse, + IconButton, + Avatar, + ButtonBase, + InputAdornment, + Typography, + Button, + Tooltip, + List, + ListItem, + ListItemAvatar, + ListItemText, +} from '@mui/material'; + +const AppSelection = props => { + const { + userdata, + globalUrl, + appFramework, + setActiveStep, + defaultSearch, + setDefaultSearch, + checkLogin, + } = props; + const [discoveryData, setDiscoveryData] = React.useState({}) + const [selectionOpen, setSelectionOpen] = React.useState(false) + const [newSelectedApp, setNewSelectedApp] = React.useState({}) + const [finishedApps, setFinishedApps] = React.useState([]) + const [moreButton, setMoreButton] = useState(false); + const [mouseHoverIndex, setMouseHoverIndex] = useState(-1) + const ref = useRef() + let navigate = useNavigate(); + const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; + + const setFrameworkItem = (data) => { + console.log("Setting framework item: ", data, isCloud) + // if (!isCloud) { + // activateApp(data.id) + // } + + fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", { + 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 framework!"); + } + + if (checkLogin !== undefined) { + checkLogin() + } + + return response.json(); + }) + .then((responseJson) => { + if (responseJson.success === false) { + if (responseJson.reason !== undefined) { + toast("Failed updating: " + responseJson.reason) + } else { + toast("Failed to update framework for your org.") + + } + } + + //setFrameworkLoaded(true) + //setFrameworkData(responseJson) + }) + .catch((error) => { + if (checkLogin !== undefined) { + checkLogin() + } + + toast(error.toString()); + //setFrameworkLoaded(true) + }) + } + + const onNodeSelect = (label) => { + // if (setDiscoveryWrapper !== undefined) { + // setDiscoveryWrapper({ id: label }); + // } + + if (isCloud) { + ReactGA.event({ + category: "welcome", + action: `click_${label}`, + label: "", + }); + } + setDiscoveryData(label) + setSelectionOpen(true) + setNewSelectedApp({}) + + setDefaultSearch(label.charAt(0).toUpperCase() + (label.substring(1)).toLowerCase()) + }; + + useEffect(() => { + if (newSelectedApp.objectID === undefined || newSelectedApp.objectID === undefined || newSelectedApp.objectID.length === 0) { + return + } + const submitNewApp = { + description: newSelectedApp.description, + id: newSelectedApp.objectID, + large_image: newSelectedApp.image_url, + name: newSelectedApp.name, + type: discoveryData + } + if (discoveryData === "CASES") { + appFramework.cases = submitNewApp + } + else if (discoveryData === "SIEM") { + appFramework.siem = submitNewApp + } + else if (discoveryData === "ERADICATION") { + appFramework.eradication = submitNewApp + } + else if (discoveryData === "INTEL") { + appFramework.intel = submitNewApp + } + else if (discoveryData === "EMAIL") { + appFramework.email = submitNewApp + } + else if (discoveryData === "NETWORK") { + appFramework.network = submitNewApp + } + else if (discoveryData === "ASSETS") { + appFramework.assets = submitNewApp + } + else if (discoveryData === "IAM") { + appFramework.iam = submitNewApp + } + setFrameworkItem(submitNewApp); + + setSelectionOpen(false); + console.log("Selected app changed (effect)"); + + }, [newSelectedApp]); + + const sizing = 510; + const buttonWidth = 450; + const buttonMargin = 10; + const bottomButtonStyle = { + borderRadius: 200, + marginTop: moreButton ? 44 : "", + height: 51, + width: 464, + fontSize: 16, + // background: "linear-gradient(89.83deg, #FF8444 0.13%, #F2643B 99.84%)", + background: "linear-gradient(90deg, #F86744 0%, #F34475 100%)", + padding: "16px 24px", + // top: 20, + // margin: "auto", + itemAlign: "center", + // marginLeft: "65px", + }; + const buttonStyle = { + flex: 1, + width: 224, + padding: 25, + margin: buttonMargin, + color: "var(--White-text, #F1F1F1)", + fontWeight: 400, + fontSize: 17, + background: "rgba(33, 33, 33, 1)", + textTransform: 'capitalize', + border: mouseHoverIndex ? "1px solid rgba(33, 33, 33, 1)" : "1px solid #f85a3e", + borderRadius: 8, + marginRight: 8, + }; + + return ( + +
+ {selectionOpen ? ( +
+
+
+ {discoveryData} +
+
+ + { + setSelectionOpen(false) + }} + > + + + + + { + e.preventDefault(); + setSelectionOpen(false) + setDefaultSearch("") + const submitDeletedApp = { + "description": "", + "id": "remove", + "name": "", + "type": discoveryData + } + setFrameworkItem(submitDeletedApp) + setNewSelectedApp({}) + setTimeout(() => { + setDiscoveryData({}) + setFrameworkItem(submitDeletedApp) + setNewSelectedApp({}) + }, 1000) + }} + > + + + +
+
+
+ +
+ ) : null} + + Find your apps + + + Select the apps you work with and we will connect the for you. + + + {/*Find your integrations!*/} +
{ + setMouseHoverIndex() + }} onMouseOut={() => { + setMouseHoverIndex(-1) + }} + > + +
+
+ + +
+
+ + +
+ {moreButton ? ( +
{ + setMouseHoverIndex() + }} onMouseOut={() => { + setMouseHoverIndex(-1) + }} + > + + + +
+ ) + : +
+ +
} + + {/* + What do you want to automate first ? + + { onNodeSelect("Email") }} />} + label="Email" + labelPlacement="Email" + /> + { onNodeSelect("SIEM") }} />} + label="SIEM" + labelPlacement="SIEM" + /> + { onNodeSelect("EDR") }} />} + label="EDR" + labelPlacement="EDR" + /> + + */} +
+
+
+ +
+ + ) +} + +export default AppSelection; diff --git a/frontend/src/components/WorkflowTemplatePopup.jsx b/frontend/src/components/WorkflowTemplatePopup.jsx index f74c79af..a0d7842f 100644 --- a/frontend/src/components/WorkflowTemplatePopup.jsx +++ b/frontend/src/components/WorkflowTemplatePopup.jsx @@ -387,6 +387,8 @@ const WorkflowTemplatePopup = (props) => { //setIsActive(!isActive) if (errorMessage !== "") { toast("Already failed to generate a workflow for this usecase. Please try again later or contact support@shuffler.io.") + + setModalOpen(true) } else if (isActive) { toast("Workflow already generated. Please try another workflow template!") @@ -418,7 +420,7 @@ const WorkflowTemplatePopup = (props) => { - +