import React, { useState, useEffect } from 'react'; import theme from '../theme.jsx'; import CytoscapeComponent from 'react-cytoscapejs'; import frameworkStyle from '../frameworkStyle.jsx'; import { v4 as uuidv4 } from "uuid"; import AppSearch from '../components/Appsearch.jsx'; import PaperComponent from "../components/PaperComponent.jsx" import { usecaseTypes } from "../components/UsecaseSearch.jsx" import SuggestedWorkflows from "../components/SuggestedWorkflows.jsx" import { securityFramework} from "../components/LandingpageUsecases.jsx"; import { Paper, Typography, Divider, IconButton, Badge, CircularProgress, Tooltip, Dialog, Chip, Avatar, Button, } from "@mui/material"; import { Close as CloseIcon, Delete as DeleteIcon, } from "@mui/icons-material"; import edgehandles from "cytoscape-edgehandles"; import cytoscape from "cytoscape"; import { toast } from 'react-toastify'; cytoscape.use(edgehandles) export const findSpecificApp = (framework, inputcategory) => { // Get the frameworkinfo for the org and fill in if (framework === undefined || framework === null) { //console.log("findSpecificApp: framework is null") return null } if (inputcategory === undefined || inputcategory === null) { //console.log("findSpecificApp: category is null") return null } const category = inputcategory.toLowerCase().split(":")[0].trim() //console.log("findSpecificApp: ", category, framework) if (category === "edr" || category === "eradication" || category === "edr & av") { if (framework["EDR & AV"] !== undefined && framework["EDR & AV"].name !== undefined) { return framework["EDR & AV"] } return { name: "EDR :default", large_image: parsedDatatypeImages()["EDR & AV"], count: 0, description: "", id: "", } } else if (category === "communication" || category === "comms") { if (framework["Comms"] !== undefined && framework["Comms"].name !== undefined) { return framework["Comms"] } return { name: "COMMS :default", large_image: parsedDatatypeImages()["COMMS"], count: 0, description: "", id: "", } } else if (category === "email") { if (framework["Email"] !== undefined && framework["Email"].name !== undefined) { return framework["Email"] } return { name: "COMMS :default", large_image: parsedDatatypeImages()["COMMS"], count: 0, description: "", id: "", } } else if (category === "assets") { if (framework["Assets"] !== undefined && framework["Assets"].name !== undefined) { return framework["Assets"] } return { name: "ASSETS :default", large_image: parsedDatatypeImages()["ASSETS"], count: 0, description: "", id: "", } } else if (category === "cases") { if (framework["Cases"] !== undefined && framework["Cases"].name !== undefined) { return framework["Cases"] } return { name: "CASES :default", large_image: parsedDatatypeImages()["CASES"], count: 0, description: "", id: "", } } else if (category === "iam") { if (framework["IAM"] !== undefined && framework["IAM"].name !== undefined) { return framework["IAM"] } return { name: "IAM :default", large_image: parsedDatatypeImages()["IAM"], count: 0, description: "", id: "", } } else if (category === "network") { if (framework["Network"] !== undefined && framework["Network"].name !== undefined) { return framework["Network"] } return { name: "Network :default", large_image: parsedDatatypeImages()["NETWORK"], count: 0, description: "", id: "", } } else if (category === "intel") { if (framework["Intel"] !== undefined && framework["Intel"].name !== undefined) { return framework["Intel"] } return { name: "INTEL :default", large_image: parsedDatatypeImages()["INTEL"], count: 0, description: "", id: "", } } else if (category === "siem") { if (framework["SIEM"] !== undefined && framework["SIEM"].name !== undefined) { return framework["SIEM"] } return { name: "SIEM :default", large_image: parsedDatatypeImages()["SIEM"], count: 0, description: "", id: "", } } else { console.log("findSpecificApp: unknown category: ", category) } return null } const svgSize = "40px" export const parsedDatatypeImages = () => { const isWorkflow = window.location.pathname.includes("/workflows/") const svgSize = isWorkflow ? "24px" : "40px" const colorfill = isWorkflow ? "rgb(240,240,240)" : "rgb(248,90,62)" return { "SIEM": encodeURI(`data:image/svg+xml;utf-8,`), "CASES": encodeURI(`data:image/svg+xml;utf-8,`), "EDR & AV": encodeURI(`data:image/svg+xml;utf-8,`), "INTEL": encodeURI(`data:image/svg+xml;utf-8,`), "COMMS": encodeURI(`data:image/svg+xml;utf-8,`), "NETWORK": encodeURI(`data:image/svg+xml;utf-8,`), "INTEL": encodeURI(`data:image/svg+xml;utf-8,`), "ASSETS": encodeURI(`data:image/svg+xml;utf-8,`), "IAM": encodeURI(`data:image/svg+xml;utf-8,`), } } export const usecases = { "None": { "manual": [], "automated": [], }, "Phishing": { "manual": [], "automated": [ { "source": "BOTTOM_LEFT", "target": "COMMS", "description": "Email received", "human": false, }, { "source": "COMMS", "target": "SHUFFLE", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "human": false, }, { "source": "INTEL", "target": "SHUFFLE", "human": false, }, { "source": "ASSETS", "target": "SHUFFLE", "human": false, }, { "source": "SIEM", "target": "SHUFFLE", "human": false, }, { "source": "SHUFFLE", "target": "INTEL", "human": false, }, { "source": "SHUFFLE", "target": "COMMS", "human": false, }, { "source": "CASES", "target": "EDR & AV", "human": true, }, ]}, "Exploits": { "manual": [], "automated": [ { "source": "TOP_LEFT", "target": "NETWORK", "description": "Exploit", "human": false, }, { "source": "NETWORK", "target": "SIEM", "description": "WAF alert", "human": false, }, { "source": "SIEM", "target": "SHUFFLE", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "human": false, }, { "source": "SHUFFLE", "target": "COMMS", "human": false, }, { "source": "INTEL", "target": "SHUFFLE", "human": false, }, { "source": "ASSETS", "target": "SHUFFLE", "human": false, }, { "source": "IAM", "target": "SHUFFLE", "human": false, }, { "source": "CASES", "target": "EDR & AV", "human": true, }, ] }, "SIEM alerts": { "manual": [], "automated": [ { "source": "TOP_LEFT", "target": "SIEM", "description": "Syslog", "human": false, }, { "source": "SIEM", "target": "SHUFFLE", "description": "Alerts", "human": false, }, { "source": "SHUFFLE", "target": "INTEL", "description": "Enrich", "human": false, }, { "source": "INTEL", "target": "SHUFFLE", "human": false, }, { "source": "IAM", "target": "SHUFFLE", "human": false, "description": "enrich", }, { "source": "SHUFFLE", "target": "IAM", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "human": false, }, { "source": "SHUFFLE", "target": "COMMS", "human": false, }, { "source": "SHUFFLE", "target": "EDR & AV", "human": false, }, { "source": "SHUFFLE", "target": "EDR & AV", "human": true, }, ] }, "New Detections": { "manual": [], "automated": [ { "source": "TOP_LEFT", "target": "SIEM", "description": "Hypothesis", "human": true, }, { "source": "SIEM", "target": "SIEM", "description": "Create rule", "human": true, }, { "source": "SIEM", "target": "NETWORK", "description": "Create rule", "human": true, }, { "source": "NETWORK", "target": "EDR & AV", "description": "Create rule", "human": true, }, { "source": "SIEM", "target": "SHUFFLE", "description": "Send alert", "human": false, }, { "source": "NETWORK", "target": "SHUFFLE", "description": "Send alert", "human": false, }, { "source": "EDR & AV", "target": "SHUFFLE", "description": "Send alert", "human": false, }, { "source": "INTEL", "target": "SHUFFLE", "description": "Enrich IOCs", "human": false, }, { "source": "ASSETS", "target": "SHUFFLE", "description": "Enrich hostnames etc.", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "description": "Create enriched alert", "human": false, }, ] }, "Vulnerabilities": { "manual": [], "automated": [ { "source": "TOP_RIGHT", "target": "ASSETS", "description": "New vuln", "human": false, }, { "source": "ASSETS", "target": "SHUFFLE", "description": "Get vuln", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "description": "Raise ticket", "human": false, }, { "source": "SHUFFLE", "target": "COMMS", "description": "Notify owner", "human": false, }, { "source": "COMMS", "target": "SHUFFLE", "description": "", "human": true, }, { "source": "SHUFFLE", "target": "ASSETS", "description": "Auto-patch", "human": false, }, ] }, "Approvals": { "manual": [], "automated": [ { "source": "TOP_LEFT", "target": "CASES", "description": "New inquiry", "human": false, }, { "source": "CASES", "target": "SHUFFLE", "description": "Get tickets", "human": false, }, { "source": "SHUFFLE", "target": "COMMS", "description": "Ask for approval", "human": false, }, { "source": "COMMS", "target": "SHUFFLE", "human": true, }, { "source": "SHUFFLE", "target": "ASSETS", "description": "Add to user", "human": false, }, { "source": "SHUFFLE", "target": "IAM", "description": "Approve access", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "human": false, }, ] }, "Enrichment": { "manual": [], "automated": [ { "source": "TOP_LEFT", "target": "CASES", "description": "Case updated", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "description": "Get and enrich ticket", "human": false, }, { "source": "IAM", "target": "SHUFFLE", "description": "Get access rights", "human": false, }, { "source": "ASSETS", "target": "SHUFFLE", "description": "Get relevant assets", "human": false, }, { "source": "INTEL", "target": "SHUFFLE", "description": "Get relevant IPs", "human": false, }, { "source": "COMMS", "target": "SHUFFLE", "description": "Find relevant mails & chats", "human": false, }, { "source": "EDR & AV", "target": "SHUFFLE", "description": "Find incidents for host", "human": false, }, { "source": "SIEM", "target": "SHUFFLE", "description": "Find info about hostname and user", "human": false, }, { "source": "SHUFFLE", "target": "SHUFFLE", "description": "Format info", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "description": "", "human": false, }, ] }, "Ransomware": { "manual": [], "automated": [ { "source": "BOTTOM_LEFT", "target": "EDR & AV", "description": "EDR & AV alert", "human": false, }, { "source": "EDR & AV", "target": "SHUFFLE", "description": "", "human": false, }, { "source": "SHUFFLE", "target": "EDR & AV", "human": false, "description": "isolate", }, { "source": "SHUFFLE", "target": "IAM", "human": false, "description": "Block access", }, { "source": "SHUFFLE", "target": "COMMS", "description": "Notify oncall and affected user", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "description": "Create enriched alert", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "human": false, }, { "source": "CASES", "target": "EDR & AV", "description": "Validate alert", "human": true, }, ] }, "Draw": { } } const AppFramework = (props) => { const { globalUrl, isLoaded, showOptions, selectedOption, rolling, frameworkData, setFrameworkData, size, inputUsecase, isLoggedIn, color, discoveryWrapper, setDiscoveryWrapper, userdata, apps, inputUsecases, setInputUsecases } = props; const [cy, setCy] = React.useState() const [edgesStarted, setEdgesStarted] = React.useState(false) const [graphDone, setGraphDone] = React.useState(false) const [cyDone, setCyDone] = React.useState(false) const [discoveryData, setDiscoveryData] = React.useState({}) const [selectionOpen, setSelectionOpen] = React.useState(true) const [frameworkSuggestions, setFrameworkSuggestions] = React.useState([]) const [newSelectedApp, setNewSelectedApp] = React.useState({}) const [defaultSearch, setDefaultSearch] = React.useState("") const [animationStarted, setAnimationStarted] = React.useState(false) const [paperTitle, setPaperTitle] = React.useState("") const [changedApp, setChangedApp] = React.useState("") const [usecaseType, setUsecaseType] = React.useState(0) const [selectedUsecase, setSelectedUsecase] = React.useState(selectedOption !== undefined ? selectedOption : "Phishing") const [injectedApps, setInjectedApps] = React.useState([]) const scale = size === undefined ? 1 : size > 5 ? 3 : size //const alert = useAlert() const handleLoadNextSuggestion = (frameworkData) => { //console.log("Should check for next apps to load from App suggestion model") //fetch(globalUrl + "/api/v1/workflows/usecases", { //credentials: "include", //cors: "no-cors", const max_suggestions = 5 const max_per_category = 2 const priorities = { "edr": 1, "siem": 2, "cases": 3, "intel": 4, "comms": 5, } // Based on apps recommended from repo https://github.com/Shuffle/app-recommender //fetch("http://localhost:8080/app_recommendations", { fetch("https://europe-west2-shuffler.cloudfunctions.net/app_recommendations", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify(frameworkData), }) .then((response) => { //if (response.status !== 200) { // console.log("Status not 200 for framework!"); //} return response.json(); }) .then((responseJson) => { // Loop the response dict var suggestions = [] var suggestion_cnt = 0 var category_count = {} for (const [key, value] of Object.entries(responseJson)) { if (suggestion_cnt >= max_suggestions) { break } if (category_count[key] === undefined) { category_count[key] = 1 } else { category_count[key] += 1 } if (category_count[key] > max_per_category) { continue } //console.log("Found: " + key + " with value of len: " + value.length) //suggestion_cnt += value.slice(0,1).length suggestions.push(value.slice(0,1)) } setInjectedApps(suggestions) }) .catch((error) => { console.log("Recommendation error: ", error); }) } const showRecommendations = (changed, frameworkData) => { //console.log("Inside recommendation loader") setChangedApp(changed) handleLoadNextSuggestion(frameworkData) // Alternative changed // This is for secondary values like email = comms var alternativeChanged = changed if (changed == "COMMS") { alternativeChanged = "email" } // FIX: // 0. Get workflows loaded in from usecasesearch // 1. Search through workflow templates for matching app types // 2. Validate if template is already in use~ (workflows with same tools) // 3. Generate the workflow(s) - PS: Fix new workflow templates // 4. Moving on! // How can we load templates? UsecaseSearch? var showusecases = [] //const foundusecase = usecaseTypes.find(data => data.name.toLowerCase() === defaultSearch.toLowerCase()) for (var key in usecaseTypes) { for (var subkey in usecaseTypes[key].value) { const usecase = usecaseTypes[key].value[subkey] if (usecase.active === false) { continue } var potential = false var matches = [] for (var itemtype in usecase.items) { var apptype = usecase.items[itemtype].app_type.toLowerCase() if (apptype.toLowerCase() === "email" || apptype.toLowerCase() === "comms" || apptype === "communication") { apptype = "Comms" } //console.log("OLD: ", changed, "USECASE: ", apptype) //console.log("APptype, changed, framework: ", apptype.toLowerCase(), alternativeChanged.toLowerCase(), changed.toLowerCase(), frameworkData) if (changed.toLowerCase() === apptype.toLowerCase() || changed.toLowerCase().includes(apptype.toLowerCase()) || alternativeChanged.toLowerCase() === apptype.toLowerCase() || alternativeChanged.toLowerCase().includes(apptype.toLowerCase())) { potential = true //console.log("Potential: !", apptype) if (frameworkData[apptype] !== undefined && frameworkData[apptype].name !== undefined && frameworkData[apptype].name !== null && frameworkData[apptype].name.length > 0) { usecase.items[itemtype].app = frameworkData[apptype] } matches.push(usecase.items[itemtype]) } else { // Check if the type is done in frameworkData if (frameworkData[apptype] !== undefined) { //console.log("NOT UNDEFINED: ", frameworkData[apptype]) if (frameworkData[apptype].name !== undefined && frameworkData[apptype].name !== null && frameworkData[apptype].name.length > 0) { //console.log("FOUND: ", frameworkData[apptype]) usecase.items[itemtype].app = frameworkData[apptype] //console.log("Real app!") matches.push(usecase.items[itemtype]) } //if (frameworkData[apptype] !== undefined) { } else { console.log("UNDEFINED APP (bad name?): ", apptype) } } } // Adds to list if it's all matching and unhandled if (potential) { // Check finished usecases. if (inputUsecases !== undefined && setInputUsecases !== undefined && usecase.usecase_references !== undefined && usecase.usecase_references.length > 0) { var foundUsecase = false for (var usecaseKey in inputUsecases) { const usecaseCategory = inputUsecases[usecaseKey] for (var subUsecaseKey in usecaseCategory.list) { const loopUsecase = usecaseCategory.list[subUsecaseKey] if (loopUsecase.matches === undefined || loopUsecase.matches === null || loopUsecase.matches.length === 0) { //console.log("No matches - continuing") continue } if (usecase.usecase_references.includes(loopUsecase.name)) { foundUsecase = true break } } if (foundUsecase) { break } } if (!foundUsecase) { console.log("Usecase NOT found!") } else { console.log("FOUND usecase existing in ", usecase.usecase_references) continue } } else { //console.log("No usecase to try to match it to (usecase.usecase_references in UsecaseSearch)") } //console.log("Usecase: ", usecase) if (matches.length === usecase.items.length) { usecase.color = "#c51152" usecase.type = usecaseTypes[key].name showusecases.push(usecase) } } } } // FIXME: Check if a usecase has already been handled //console.log("") //console.log("GOT USECASES: ", showusecases) // FIXME: Just showing one usecase at a time for now if (showusecases.length > 0) { setFrameworkSuggestions(showusecases.slice(0,1)) } } useEffect(() => { //console.log("DISCWRAP CHANG: ", discoveryWrapper) if (discoveryWrapper === undefined || discoveryWrapper.id === "SHUFFLE" || discoveryWrapper.id === undefined || cy === undefined) { setDiscoveryData({}) if (cy !== undefined) { cy.nodes().unselect() } return } // Find the node and click it? //setTimeout(() => { const nodes = cy.nodes().jsons() for (var key in nodes) { const node = nodes[key] var newSearchName = discoveryWrapper.id.valueOf() if (newSearchName === "EMAIL") { newSearchName = "COMMS" } if (newSearchName === "ERADICATION" || newSearchName === "ENDPOINT") { newSearchName = "EDR & AV" } if (node.data.id === newSearchName) { const tmpnode = cy.getElementById(node.data.id) if (tmpnode !== undefined) { tmpnode.select() } setDefaultSearch(discoveryWrapper.id) setPaperTitle(discoveryWrapper.id) } } //}, 50,) //setDiscoveryData(discoveryWrapper) }, [discoveryWrapper]) const setUsecaseItem = (inputUsecase) => { var parsedUsecase = inputUsecase const edges = cy.edges().jsons() parsedUsecase.process = [] for (var key in edges) { const edge = edges[key] console.log("Edge: ", edge) parsedUsecase.process.push(edge.data) } fetch(globalUrl + "/api/v1/workflows/usecases", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify(parsedUsecase), credentials: "include", }) .then((response) => { if (response.status !== 200) { console.log("Status not 200 for framework!"); } 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.") } } else { toast("Updated usecase.") } }) .catch((error) => { toast(error.toString()); }) } const activateApp = (appid) => { fetch(globalUrl+"/api/v1/apps/"+appid+"/activate", { method: 'GET', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, credentials: "include", }) .then((response) => { if (response.status !== 200 || response.status !== 202) { console.log("Failed to activate") } return response.json() }) .then((responseJson) => { if (responseJson.success === false) { var msgString = "Failed to activate the app" if (responseJson.reason !== undefined) { msgString += ": " + responseJson.reason } toast(msgString) } else { //toast("App activated for your organization! Refresh the page to use the app.") } }) .catch(error => { //toast(error.toString()) console.log("Activate app error: ", error.toString()) }); } const setFrameworkItem = (data) => { 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!"); } return response.json(); }) .then((responseJson) => { if (responseJson.success === false) { if (responseJson.reason !== undefined) { toast("Failed getting appframework: " + responseJson.reason) } else { toast("Failed to update framework for your org.") } } else { if (data.id === "remove") { frameworkData[data.type] = {} frameworkData[data.type.toLowerCase()] = {} } else { frameworkData[data.type] = data frameworkData[data.type.toLowerCase()] = data } setDiscoveryData({}) if (setFrameworkData !== undefined) { setFrameworkData(frameworkData) } } }) .catch((error) => { toast(error.toString()); //setFrameworkLoaded(true) }) } useEffect(() => { if (!window.location.pathname.includes("usecases")) { handleLoadNextSuggestion(frameworkData) } }, []) useEffect(() => { //console.log("New selected app: ", newSelectedApp, discoveryData) if (newSelectedApp.objectID === undefined || newSelectedApp.objectID === undefined || newSelectedApp.objectID.length === 0) { return } //if (paperTitle.length > 0) { // console.log("No papertitle (parent button)") // cy.elements().unselect() // return //} if (discoveryData.id === undefined) { console.log("No discoverydata (parent button)") cy.elements().unselect() return } const submitValue = { "type": discoveryData.id, "name": newSelectedApp.name, "id": newSelectedApp.objectID, "large_image": newSelectedApp.image_url, "description": newSelectedApp.description === undefined ? "" : newSelectedApp.description, } const foundelement = cy.getElementById(discoveryData.id) if (foundelement !== undefined && foundelement !== null) { foundelement.data("large_image", newSelectedApp.image_url) foundelement.data("margin_x", "0px") foundelement.data("margin_y", "0px") foundelement.data("text_margin_y", `${60*scale}px`) foundelement.data("width", `${85*scale}px`) foundelement.data("height", `${85*scale}px`) } if (setFrameworkData !== undefined) { // Find discoveryData.id var keys = [] for (const [key, value] of Object.entries(frameworkData)) { if (key.toLowerCase() === discoveryData.id.toLowerCase()) { keys.push(key) } } if (keys.length === 0) { console.log("Failed to find: ", discoveryData.id, " IN ", frameworkData) } else { for (var key in keys) { frameworkData[keys[key]] = submitValue } setFrameworkData(frameworkData) if (discoveryData.large_image !== undefined && discoveryData.large_image !== null && discoveryData.large_image.includes("storage.googleapis.com")) { showRecommendations(discoveryData.id, frameworkData) } else { console.log("Skipping recommendations during unselect") } } } setFrameworkItem(submitValue) cy.elements().unselect() }, [newSelectedApp]) const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const imgSize = 50; var parsedFrameworkData = frameworkData === undefined ? {} : frameworkData // Awful mapping to make sure all access is always there if (frameworkData !== undefined) { if (frameworkData.cases !== undefined) { if (frameworkData.cases.large_image === undefined && frameworkData.cases.large_image === null || frameworkData.cases.large_image === "") { frameworkData.cases = {} } parsedFrameworkData.Cases = frameworkData.cases } else { parsedFrameworkData.Cases = {} } if (frameworkData.siem !== undefined) { if (frameworkData.siem.large_image === undefined && frameworkData.siem.large_image === null || frameworkData.siem.large_image === "") { frameworkData.siem = {} } parsedFrameworkData.SIEM = frameworkData.siem } else { parsedFrameworkData.SIEM = {} } if (frameworkData.assets !== undefined) { if (frameworkData.assets.large_image === undefined && frameworkData.assets.large_image === null || frameworkData.assets.large_image === "") { frameworkData.assets = {} } parsedFrameworkData.Assets = frameworkData.assets } else { parsedFrameworkData.Assets = {} } if (frameworkData.intel !== undefined) { if (frameworkData.intel.large_image === undefined && frameworkData.intel.large_image === null || frameworkData.intel.large_image === "") { frameworkData.intel = {} } parsedFrameworkData.Intel = frameworkData.intel } else { parsedFrameworkData.Intel= {} } if (frameworkData.communication !== undefined) { if (frameworkData.communication.large_image === undefined && frameworkData.communication.large_image === null || frameworkData.communication.large_image === "") { frameworkData.communication = {} } parsedFrameworkData.Comms = frameworkData.communication } else { parsedFrameworkData.Comms = {} } if (frameworkData.network !== undefined) { if (frameworkData.network.large_image === undefined && frameworkData.network.large_image === null || frameworkData.network.large_image === "") { frameworkData.network = {} } parsedFrameworkData.Network = frameworkData.network } else { parsedFrameworkData.Network = {} } if (frameworkData.iam !== undefined) { if (frameworkData.iam.large_image === undefined && frameworkData.iam.large_image === null || frameworkData.iam.large_image === "") { frameworkData.iam = {} } parsedFrameworkData.IAM = frameworkData.iam } else { parsedFrameworkData.IAM = {} } if (frameworkData.edr !== undefined) { if (frameworkData.edr.large_image === undefined && frameworkData.edr.large_image === null || frameworkData.edr.large_image === "") { frameworkData.edr = {} } parsedFrameworkData["EDR & AV"] = frameworkData.edr } else { parsedFrameworkData["EDR & AV"] = {} } } else { //console.log("No frameworkdata for org! Setting default") parsedFrameworkData["Cases"] = {} parsedFrameworkData["SIEM"] = {} parsedFrameworkData["Assets"] = {} parsedFrameworkData["IAM"] = {} parsedFrameworkData["Intel"] = {} parsedFrameworkData["Comms"] = {} parsedFrameworkData["Network"] = {} parsedFrameworkData["EDR & AV"] = {} } //console.log("Framework - update? ", parsedFrameworkData) // 0 = automated, 1 = manual const elements = [] const surfaceColor = "#27292D" const changeUsecase = (value, type) => { //console.log("Value: ", value) if (value === "Draw" && !edgesStarted) { setEdgesStarted(true) cy.edgehandles({ handleNodes: (el) => { if (el.isNode() && !el.data("isButton") && !el.data("isDescriptor") && el.data("type") !== "COMMENT") { return true } return false }, preview: true, toggleOffOnLeave: true, loopAllowed: function (node) { return false; }, }) } setSelectedUsecase(value) const edges = cy.edges() if (edges !== undefined) { const allEdges = edges.jsons() for (var key in allEdges) { const newedge = allEdges[key] const foundelement = cy.getElementById(newedge.data.id) if (foundelement !== undefined && foundelement !== null) { foundelement.remove() } } } var found = false var parsedType = type === 1 ? "manual" : "automated" if (usecases === undefined || usecases === null) { return } const newedges = usecases[value][parsedType] for (var key in newedges) { newedges[key].label = parseInt(key)+1 if (newedges[key].description !== undefined && newedges[key].description !== null && newedges[key].description.length > 0) { newedges[key].label = (parseInt(key)+1)+" "+newedges[key].description } cy.add({ group: "edges", data: newedges[key], }) } setGraphDone(true) } const animationDuration = 150; const nodeAddDuration = 2500; if (cy !== undefined && cyDone && !animationStarted) { const foundelement = cy.getElementById("CASES") if (foundelement !== undefined && foundelement !== null) { setAnimationStarted(true) var parsedStyle = { "ghost": "yes", "border-color": "#f86a3e", "border-width": "10px", "border-opacity": ".7", } var parsedStyle2 = { "ghost": "yes", "border-width": "7px", } /* // Animation for (var i = 0; i < 10; i++) { foundelement.animate( { style: parsedStyle, }, { duration: nodeAddDuration, } ).delay(1000) foundelement.animate( { style: parsedStyle2, }, { duration: nodeAddDuration, } ) } */ } } const onNodeAdded = (event) => { //if (event.target.data("animate") === true) { //} } const onNodeHover = (event) => { const nodedata = event.target.data(); const cytoscapeElement = document.getElementById("cytoscape_view") if (cytoscapeElement !== undefined && cytoscapeElement !== null) { cytoscapeElement.style.cursor = "pointer" } var parsedStyle = { "border-width": "7px", "border-opacity": ".7", } //if (nodedata.type !== "COMMENT") { // parsedStyle.color = "white"; //} if (event.target !== undefined && event.target !== null) { event.target.animate( { style: parsedStyle, }, { duration: animationDuration, } ); } } const onNodeHoverOut = (event) => { const nodedata = event.target.data(); //console.log("Node OUT: ", nodedata) const cytoscapeElement = document.getElementById("cytoscape_view") if (cytoscapeElement !== undefined && cytoscapeElement !== null) { cytoscapeElement.style.cursor = "default" } var parsedStyle = { "border-width": "3px", //"cursor": "default", } event.target.animate( { style: parsedStyle, }, { duration: animationDuration, } ) } const onNodeUnselect = (event) => { var data = event.target.data(); console.log("UNSELECT: ", data) var parsedStyle = { "border-width": "10px", "border-opacity": ".7", "border-color": "#7fe57f", } // Some error here? if (event.target !== undefined && event.target !== null) { event.target.animate( { style: parsedStyle, }, { duration: animationDuration, } ) setTimeout(() => { event.target.animate( { style: { "border-width": "3px", }, }, { duration: animationDuration, } ) }, 2500) } //setDiscoveryData({}) if (setDiscoveryWrapper !== undefined) { setDiscoveryWrapper({}) } setSelectionOpen(false) setDefaultSearch("") setPaperTitle("") //setDiscoveryData({}) } const onNodeSelect = (event) => { var data = event.target.data(); if (data.id === "SHUFFLE") { event.target.unselect() return } if (data.label === "EDR & AV") { data.label = "ERADICATION" } setDiscoveryData(data) setSelectionOpen(true) setNewSelectedApp({}) setDefaultSearch(data.label.charAt(0).toUpperCase()+(data.label.substring(1)).toLowerCase()) } const onEdgeAdded = (event) => { //event.target.data("human", false) } const onEdgeSelect = (event) => { console.log(event) if (event.target.data("human") === undefined || event.target.data("human") === false) { event.target.data("human", true) } else if (event.target.data("human") === true) { event.target.remove() return //event.target.data("human", false) } console.log("Edge selected!", event.target.data()) event.target.unselect() } if (graphDone && cyDone === false) { cy.fit(null, 200); cy.on("select", "edge", (e) => onEdgeSelect(e)); cy.on("add", "edge", (e) => onEdgeAdded(e)); cy.on("select", "node", (e) => { onNodeSelect(e) }) cy.on("unselect", "node", (e) => { onNodeUnselect(e) }) cy.on("mouseover", "node", (e) => {onNodeHover(e)}) cy.on("mouseout", "node", (e) => onNodeHoverOut(e)); cy.on("add", "node", (e) => onNodeAdded(e)); setCyDone(true) } if (cy !== undefined && cy.elements().length === 0 && parsedFrameworkData !== undefined) { //'background-image': 'data(small_image)', const shiftradius = 115*scale const baselocationX = 285*scale const baselocationY = 50*scale const shiftmodifier = 3*scale //const svgSize = `${40*scale}px` //const svgSize = `${40}px` const foundMiddleImage = userdata !== undefined && userdata !== null && userdata.active_org !== undefined && userdata.active_org.image !== undefined && userdata.active_org.image !== null && userdata.active_org.image !== "" ? userdata.active_org.image : '/images/Shuffle_logo.png' const siemcheck = parsedFrameworkData.SIEM.large_image === undefined || (parsedFrameworkData.SIEM.name !== undefined && parsedFrameworkData.SIEM.name !== null && parsedFrameworkData.SIEM.name.includes(":default")) const iamcheck = parsedFrameworkData.IAM.large_image === undefined || (parsedFrameworkData.IAM.name !== undefined && parsedFrameworkData.IAM.name !== null && parsedFrameworkData.IAM.name.includes(":default")) const casescheck = parsedFrameworkData.Cases.large_image === undefined || (parsedFrameworkData.Cases.name !== undefined && parsedFrameworkData.Cases.name !== null && parsedFrameworkData.Cases.name.includes(":default")) const assetscheck = parsedFrameworkData.Assets.large_image === undefined || (parsedFrameworkData.Assets.name !== undefined && parsedFrameworkData.Assets.name !== null && parsedFrameworkData.Assets.name.includes(":default")) const intelcheck = parsedFrameworkData.Intel.large_image === undefined || (parsedFrameworkData.Intel.name !== undefined && parsedFrameworkData.Intel.name !== null && parsedFrameworkData.Intel.name.includes(":default")) const commscheck = parsedFrameworkData.Comms.large_image === undefined || (parsedFrameworkData.Comms.name !== undefined && parsedFrameworkData.Comms.name !== null && parsedFrameworkData.Comms.name.includes(":default")) const edrcheck = parsedFrameworkData["EDR & AV"].large_image === undefined || (parsedFrameworkData["EDR & AV"].name !== undefined && parsedFrameworkData["EDR & AV"].name !== null && parsedFrameworkData["EDR & AV"].name.includes(":default")) const networkcheck = parsedFrameworkData.Network.large_image === undefined || (parsedFrameworkData.Network.name !== undefined && parsedFrameworkData.Network.name !== null && parsedFrameworkData.Network.name.includes(":default")) const fontSize = `${12*scale}px` const defaultSize = `${85*scale}px` const iconSize = `${45*scale}px` const textMarginDefault = `${14*scale}px` const textMarginImage = `${60*scale}px` const nodes = [ { group: "nodes", data: { boxwidth: defaultSize, boxheight: defaultSize, font_size: fontSize, is_valid: true, isValid: true, errors: [], name: parsedFrameworkData.Cases.name === undefined ? "" : parsedFrameworkData.Cases.name, description: parsedFrameworkData.Cases.description === undefined ? "" : parsedFrameworkData.Cases.description, app_id: parsedFrameworkData.Cases.id === undefined ? "" : parsedFrameworkData.Cases.id, text_margin_y: casescheck ? textMarginDefault : textMarginImage, margin_x: casescheck ? `${32*scale}px` : "0px", margin_y: casescheck ? `${19*scale}px` : `0px`, width: casescheck ? iconSize : defaultSize, height: casescheck ? iconSize : defaultSize, large_image: parsedFrameworkData.Cases.large_image === undefined ? parsedDatatypeImages()["CASES"] : parsedFrameworkData.Cases.large_image, label: securityFramework[0].text.toUpperCase(), id: securityFramework[0].text.toUpperCase(), animate: true, }, renderedPosition: { x: baselocationX, y: baselocationY, } }, { group: "nodes", data: { font_size: fontSize, boxwidth: defaultSize, boxheight: defaultSize, is_valid: true, isValid: true, errors: [], name: parsedFrameworkData.IAM.name === undefined ? "" : parsedFrameworkData.IAM.name, description: parsedFrameworkData.IAM.description === undefined ? "" : parsedFrameworkData.IAM.description, app_id: parsedFrameworkData.IAM.id === undefined ? "" : parsedFrameworkData.IAM.id, text_margin_y: iamcheck ? textMarginDefault : textMarginImage, margin_x: iamcheck ? `${32*scale}px` : "0px", margin_y: iamcheck ? `${19*scale}px` : `0px`, width: iamcheck ? iconSize : defaultSize, height: iamcheck ? iconSize : defaultSize, large_image: parsedFrameworkData.IAM.large_image === undefined ? parsedDatatypeImages()["IAM"] : parsedFrameworkData.IAM.large_image, label: securityFramework[3].text.toUpperCase(), id: securityFramework[3].text.toUpperCase(), animate: false, }, renderedPosition: { x: baselocationX+shiftradius+(shiftradius/shiftmodifier), y: baselocationY+shiftradius-(shiftradius/shiftmodifier), } }, { group: "nodes", data: { font_size: fontSize, boxwidth: defaultSize, boxheight: defaultSize, is_valid: true, isValid: true, errors: [], name: parsedFrameworkData.Assets.name === undefined ? "" : parsedFrameworkData.Assets.name, description: parsedFrameworkData.Assets.description === undefined ? "" : parsedFrameworkData.Assets.description, app_id: parsedFrameworkData.Assets.id === undefined ? "" : parsedFrameworkData.Assets.id, text_margin_y: assetscheck ? textMarginDefault : textMarginImage, margin_x: assetscheck ? `${32*scale}px` : "0px", margin_y: assetscheck ? `${19*scale}px` : `0px`, width: assetscheck ? iconSize : defaultSize, height: assetscheck ? iconSize : defaultSize, large_image: parsedFrameworkData.Assets.large_image === undefined ? parsedDatatypeImages()["ASSETS"] : parsedFrameworkData.Assets.large_image, label: securityFramework[2].text.toUpperCase(), id: securityFramework[2].text.toUpperCase(), animate: false, }, renderedPosition: { x: baselocationX+shiftradius*2, y: baselocationY+shiftradius*2, } }, { group: "nodes", data: { font_size: fontSize, boxwidth: defaultSize, boxheight: defaultSize, is_valid: true, isValid: true, errors: [], name: parsedFrameworkData.Intel.name === undefined ? "" : parsedFrameworkData.Intel.name, description: parsedFrameworkData.Intel.description === undefined ? "" : parsedFrameworkData.Intel.description, app_id: parsedFrameworkData.Intel.id === undefined ? "" : parsedFrameworkData.Intel.id, text_margin_y: intelcheck ? textMarginDefault : textMarginImage, margin_x: intelcheck ? `${32*scale}px` : "0px", margin_y: intelcheck ? `${19*scale}px` : `0px`, width: intelcheck ? iconSize : defaultSize, height: intelcheck ? iconSize : defaultSize, large_image: parsedFrameworkData.Intel.large_image === undefined ? parsedDatatypeImages()["INTEL"] : parsedFrameworkData.Intel.large_image, label: securityFramework[4].text.toUpperCase(), id: securityFramework[4].text.toUpperCase(), animate: false, }, renderedPosition: { x: baselocationX+shiftradius+(shiftradius/shiftmodifier), y: baselocationY+shiftradius*3+(shiftradius/shiftmodifier), } }, { group: "nodes", data: { font_size: fontSize, boxwidth: defaultSize, boxheight: defaultSize, is_valid: true, isValid: true, errors: [], name: parsedFrameworkData.Comms.name === undefined ? "" : parsedFrameworkData.Comms.name, description: parsedFrameworkData.Comms.description === undefined ? "" : parsedFrameworkData.Comms.description, app_id: parsedFrameworkData.Comms.id === undefined ? "" : parsedFrameworkData.Comms.id, text_margin_y: commscheck ? textMarginDefault : textMarginImage, margin_x: commscheck ? `${32*scale}px` : "0px", margin_y: commscheck ? `${19*scale}px` : `0px`, width: commscheck ? iconSize : defaultSize, height: commscheck ? iconSize : defaultSize, large_image: parsedFrameworkData.Comms.large_image === undefined ? parsedDatatypeImages()["COMMS"] : parsedFrameworkData.Comms.large_image, label: securityFramework[5].text.toUpperCase(), id: securityFramework[5].text.toUpperCase(), animate: false, }, renderedPosition: { x: baselocationX, y: baselocationY+shiftradius*4, } }, { group: "nodes", data: { font_size: fontSize, boxwidth: defaultSize, boxheight: defaultSize, is_valid: true, isValid: true, errors: [], name: parsedFrameworkData["EDR & AV"].name === undefined ? "" : parsedFrameworkData["EDR & AV"].name, description: parsedFrameworkData["EDR & AV"].description === undefined ? "" : parsedFrameworkData["EDR & AV"].description, app_id: parsedFrameworkData["EDR & AV"].id === undefined ? "" : parsedFrameworkData["EDR & AV"].id, text_margin_y: edrcheck ? textMarginDefault : textMarginImage, margin_x: edrcheck ? `${32*scale}px` : "0px", margin_y: edrcheck ? `${19*scale}px` : `0px`, width: edrcheck ? iconSize : defaultSize, height: edrcheck ? iconSize : defaultSize, large_image: parsedFrameworkData["EDR & AV"].large_image === undefined ? parsedDatatypeImages()["EDR & AV"] : parsedFrameworkData["EDR & AV"].large_image, label: securityFramework[7].text.toUpperCase(), id: securityFramework[7].text.toUpperCase(), animate: false, }, renderedPosition: { x: baselocationX-shiftradius-(shiftradius/shiftmodifier), y: baselocationY+shiftradius*3+(shiftradius/shiftmodifier), } }, { group: "nodes", data: { font_size: fontSize, boxwidth: defaultSize, boxheight: defaultSize, is_valid: true, isValid: true, errors: [], name: parsedFrameworkData.Network.name === undefined ? "" : parsedFrameworkData.Network.name, description: parsedFrameworkData.Network.description === undefined ? "" : parsedFrameworkData.Network.description, app_id: parsedFrameworkData.Network.id === undefined ? "" : parsedFrameworkData.Network.id, text_margin_y: networkcheck ? textMarginDefault : textMarginImage, margin_x: networkcheck ? `${32*scale}px` : "0px", margin_y: networkcheck ? `${19*scale}px` : `0px`, width: networkcheck ? iconSize : defaultSize, height: networkcheck ? iconSize : defaultSize, large_image: parsedFrameworkData.Network.large_image === undefined ? parsedDatatypeImages()["NETWORK"] : parsedFrameworkData.Network.large_image, label: securityFramework[6].text.toUpperCase(), id: securityFramework[6].text.toUpperCase(), animate: false, }, renderedPosition: { x: baselocationX-shiftradius*2, y: baselocationY+shiftradius*2, } }, { group: "nodes", data: { font_size: fontSize, boxwidth: defaultSize, boxheight: defaultSize, is_valid: true, isValid: true, errors: [], name: parsedFrameworkData.SIEM.name === undefined ? "" : parsedFrameworkData.SIEM.name, description: parsedFrameworkData.SIEM.description === undefined ? "" : parsedFrameworkData.SIEM.description, app_id: parsedFrameworkData.SIEM.id === undefined ? "" : parsedFrameworkData.SIEM.id, text_margin_y: siemcheck ? textMarginDefault : textMarginImage, margin_x: siemcheck ? `${32*scale}px` : "0px", margin_y: siemcheck ? `${19*scale}px` : `0px`, width: siemcheck ? iconSize : defaultSize, height: siemcheck ? iconSize : defaultSize, large_image: parsedFrameworkData.SIEM.large_image === undefined ? parsedDatatypeImages()["SIEM"] : parsedFrameworkData.SIEM.large_image, label: securityFramework[1].text.toUpperCase(), id: securityFramework[1].text.toUpperCase(), animate: false, }, renderedPosition: { x: baselocationX-shiftradius-(shiftradius/shiftmodifier), y: baselocationY+shiftradius-(shiftradius/shiftmodifier), } }, ] // Middlenode nodes.push({ group: "nodes", data: { font_size: fontSize, width: defaultSize, height: defaultSize, id: "SHUFFLE", is_valid: true, isValid: true, errors: [], middle_node: true, large_image: foundMiddleImage, }, renderedPosition: { x: baselocationX, y: baselocationY+shiftradius*2, } }) // Extra nodes nodes.push({ group: "nodes", data: { is_valid: true, isValid: true, errors: [], large_image: encodeURI(`data:image/svg+xml;utf-8, , `), id: "TOP_LEFT", invisible: true, }, renderedPosition: { x: baselocationX-shiftradius*2.5, y: baselocationY-50, } }) nodes.push({ group: "nodes", data: { is_valid: true, isValid: true, errors: [], large_image: encodeURI(`data:image/svg+xml;utf-8, , `), id: "BOTTOM_LEFT", invisible: true, }, renderedPosition: { x: baselocationX-shiftradius*2.5-10, y: baselocationY+shiftradius*4-10, } }) nodes.push({ group: "nodes", data: { is_valid: true, isValid: true, errors: [], large_image: encodeURI(`data:image/svg+xml;utf-8, , `), id: "BOTTOM_RIGHT", invisible: true, }, renderedPosition: { x: baselocationX+shiftradius*2+50, y: baselocationY+shiftradius*4+50, } }) nodes.push({ group: "nodes", data: { is_valid: true, isValid: true, errors: [], large_image: encodeURI(`data:image/svg+xml;utf-8, , `), id: "TOP_RIGHT", invisible: true, }, renderedPosition: { x: baselocationX+shiftradius*2, y: baselocationY-150, } }) //console.log("NODES: " , nodes) for (var key in nodes) { cy.add(nodes[key]).lock() } changeUsecase(selectedUsecase, usecaseType) if (inputUsecase !== undefined && inputUsecase !== null) { for (var key in inputUsecase.process) { if (inputUsecase.process[key].source === "" || inputUsecase.process[key].target === "") { continue } inputUsecase.process[key].label = parseInt(key)+1 inputUsecase.process[key].id = uuidv4(); cy.add({ group: "edges", data: inputUsecase.process[key], }) } //changeUsecase(inputUsecase, 0) //setSelectedUsecase(value) } } if (selectedOption !== undefined && selectedUsecase !== selectedOption) { setSelectedUsecase(selectedOption) changeUsecase(selectedOption, usecaseType) } const UsecaseHandler = (props) => { const { data, index, diff } = props const leftImage = data.left_image !== undefined ? parsedDatatypeImages()[data.left_image.toUpperCase()] : undefined const rightImage = data.right_image !== undefined ? parsedDatatypeImages()[data.right_image.toUpperCase()] : undefined if (leftImage === undefined) { console.log("LEFT MISSING: ", leftImage) } if (rightImage === undefined) { console.log("Right MISSING: ", rightImage) } const parsedRightImage = const parsedRightText =
{data.right_text}
const parsedLeftImage = const parsedLeftText =
{data.left_text}
var svgIcon = if (data.direction === "right") { svgIcon = } else if (data.direction === "left") { svgIcon = } //{"usecase_directional_arrow_"+index} // const handleHover = () => { //console.log("Hover IN: ", data.automated) const allEdges = cy.edges().jsons() for (var key in allEdges) { const newedge = allEdges[key] const foundelement = cy.getElementById(newedge.data.id) if (foundelement !== undefined && foundelement !== null) { foundelement.remove() } } //const newedges = usecases[value][parsedType] for (var key in data.automated) { data.automated[key].label = parseInt(key)+1 if (data.automated[key].description !== undefined && data.automated[key].description !== null && data.automated[key].description.length > 0) { data.automated[key].label = (parseInt(key)+1)+" "+data.automated[key].description } cy.add({ group: "edges", data: data.automated[key], }) } } const handleHoverOut = () => { //console.log("Hover out: ", data.automated) //const allEdges = cy.edges().jsons() //for (var key in allEdges) { // const newedge = allEdges[key] // const foundelement = cy.getElementById(newedge.data.id) // if (foundelement !== undefined && foundelement !== null) { // foundelement.remove() // } //} } const bgColor = color === undefined || color === null || color.length === 0 ? theme.palette.surfaceColor : color console.log("BGCOLOR: ", bgColor) return ( {data.name}
{parsedLeftImage} {parsedLeftText}
{svgIcon}
{parsedRightImage} {parsedRightText}
) } const selectedUsecases = [ { "name": "Sync tickets", "description": "Do cool shit weeeee - this just ensure they are syncing", "left_text": "Cases", "right_text": "Cases", "left_image": "Cases", "right_image": "Cases", "direction": "both", "manual": [], "automated": [ { "source": "CASES", "target": "SHUFFLE", "description": "Get cases", "human": false, }, { "source": "SHUFFLE", "target": "CASES", "description": "Update cases", "human": false, }, ] }, { "name": "Forward alerts with enrichment", "description": "Do cool shit weeeee - this just ensure they are syncing", "left_text": "EDR & AV", "right_text": "Cases", "left_image": "EDR & AV", "right_image": "Cases", "direction": "right", "manual": [], "automated": [ { "source": "BOTTOM_LEFT", "target": "COMMS", "description": "Email received", "human": false, }, ] } ] const getNodeName = (category) => { if (category === "email") { category = "COMMS" } else if (category === "edr") { category = "EDR & AV" } return category.toUpperCase() } //autounselectify={true} var usecasediff = -100 const bgColor = color === undefined || color === null || color.length === 0 ? theme.palette.surfaceColor : color return (
{/*
*/} {/*injectedApps.map((apps, appindex) => { var categoryTop = 100 var categoryLeft = 100 const category = apps[0].category if (category === "edr") { categoryTop = 355 categoryLeft = 50 } else if (category === "siem") { categoryTop = 95 categoryLeft = 50 } else if (category === "cases") { categoryTop = 65 categoryLeft = 175 } else if (category === "intel") { categoryTop = 355 categoryLeft = 315 } else if (category === "comms") { categoryTop = 415 categoryLeft = 175 } else if (category === "iam") { categoryTop = 95 categoryLeft = 315 } else { return null } const scale = 0.9 const offsetTop = -70 const offsetLeft = 0 return (
{apps.map((app, appIndex) => { return ( } key={app.id} label={""} variant="contained" style={{}} onClick={() => { console.log("Add app to framework and remove category: ", app) app.objectID = app.id app.type = app.category app.large_image = app.image_url const nodename = getNodeName(app.category) const foundelement = cy.getElementById(nodename) console.log("FOUND: ", foundelement) if (foundelement !== undefined && foundelement !== null) { foundelement.data("large_image", app.image_url) foundelement.data("margin_x", "0px") foundelement.data("margin_y", "0px") foundelement.data("text_margin_y", `${60*scale}px`) foundelement.data("width", `${85*scale}px`) foundelement.data("height", `${85*scale}px`) } if (setFrameworkData !== undefined) { // Find discoveryData.id var keys = [] for (const [key, value] of Object.entries(frameworkData)) { if (key.toLowerCase() === app.category.toLowerCase()) { keys.push(key) } } if (keys.length === 0) { console.log("Failed to find: ", app.category, " IN ", frameworkData) } else { console.log("In else for keys: ", frameworkData, keys) for (var key in keys) { frameworkData[keys[key]] = app } setFrameworkData(frameworkData) showRecommendations(app.category, frameworkData) } } setFrameworkItem(app) }} /> ) })}
) })*/} {showOptions === false ? null :
{Object.keys(usecases).map((data, index) => { return( ) })}
} {/* Object.getOwnPropertyNames(discoveryData).length > 0 ?
Use-cases {selectedUsecases.map((data, index) => { usecasediff += 175 return ( ) })}
: null*/} { Object.getOwnPropertyNames(discoveryData).length > 0 ? {paperTitle.length > 0 ? {paperTitle.replace("_", " ", -1)} : null} { //cy.elements().unselectify(); cy.elements().unselect() e.preventDefault(); setDiscoveryData({}) setDefaultSearch("") setPaperTitle("") }} > { e.preventDefault(); setDiscoveryData({ "id": discoveryData.id, "label": discoveryData.label, "name": "" }) setNewSelectedApp({ "animate": false, "app_id": "", "boxheight": "66.3px", "boxwidth": "66.3px", "description": "", "errors": [], "font_size": "9.36px", "height": "66.3px", "id": "", "isValid": true, "is_valid": true, "label": "SIEM", "large_image": "asd", "margin_x": "0px", "margin_y": "0px", "name": "", "text_margin_y": "46.800000000000004px", "width": "66.3px", "objectID": "remove", }) setSelectionOpen(true) setDefaultSearch("") //handleLoadNextSuggestion(frameworkData) setInjectedApps([]) const foundelement = cy.getElementById(discoveryData.id) if (foundelement !== undefined && foundelement !== null) { //console.log("element: ", foundelement) //console.log("DISC: ", discoveryData) foundelement.data("large_image", parsedDatatypeImages()[discoveryData.id.toUpperCase()]) foundelement.data("text_margin_y", "14px") foundelement.data("margin_x", "32px") foundelement.data("margin_y", "19x") foundelement.data("width", "45px") foundelement.data("height", "45px") } setTimeout(() => { setDiscoveryData({}) setNewSelectedApp({}) }, 1000) }} >
{discoveryData.name !== undefined && discoveryData.name !== null && discoveryData.name.length > 0 ?
{discoveryData.id} 0 ? newSelectedApp.image_url : discoveryData.large_image} style={{height: 40, width: 40, margin: "auto",}}/>
: {discoveryData.id} } {discoveryData.name !== undefined && discoveryData.name !== null && discoveryData.name.length > 0 ? discoveryData.name : newSelectedApp.name !== undefined && newSelectedApp.name !== null && newSelectedApp.name.length > 0 ? newSelectedApp.name : `Find your ${discoveryData.label} app!` }
{discoveryData !== undefined && discoveryData.name !== undefined && discoveryData.name !== null && discoveryData.name.length > 0 ? {discoveryData.description} {/*isCloud && defaultSearch !== undefined && defaultSearch.length > 0 ? {< newSelectedApp={newSelectedApp} setNewSelectedApp={setNewSelectedApp} defaultSearch={defaultSearch} />} : null */} : selectionOpen ? Search to find your app : }
{selectionOpen ? : null}
: null } { // FIXME: There's something specific loading when // you do the first hover of a node. Why is this different? //console.log("CY: ", incy) setCy(incy) }} /> {isCloud && inputUsecase !== undefined && inputUsecase !== null && isLoggedIn === true && Object.keys(inputUsecase).length > 0 ? : null}
) } export default AppFramework;