Made a few smaller fixes for priority/onboarding system to be better used by those who configure nothing
This commit is contained in:
@@ -37,6 +37,137 @@ 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") {
|
||||
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: "EDR :default",
|
||||
large_image: parsedDatatypeImages["EDR & AV"],
|
||||
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 = {
|
||||
"SIEM": encodeURI(`data:image/svg+xml;utf-8,<svg fill="rgb(248,90,62)" width="${svgSize}" height="${svgSize}" viewBox="0 0 ${svgSize} ${svgSize}" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M6.93767 0C8.71083 0 10.4114 0.704386 11.6652 1.9582C12.919 3.21202 13.6234 4.91255 13.6234 6.68571C13.6234 8.34171 13.0165 9.864 12.0188 11.0366L12.2965 11.3143H13.1091L18.252 16.4571L16.7091 18L11.5662 12.8571V12.0446L11.2885 11.7669C10.116 12.7646 8.59367 13.3714 6.93767 13.3714C5.16451 13.3714 3.46397 12.667 2.21015 11.4132C0.956339 10.1594 0.251953 8.45888 0.251953 6.68571C0.251953 4.91255 0.956339 3.21202 2.21015 1.9582C3.46397 0.704386 5.16451 0 6.93767 0ZM6.93767 2.05714C4.36624 2.05714 2.3091 4.11429 2.3091 6.68571C2.3091 9.25714 4.36624 11.3143 6.93767 11.3143C9.5091 11.3143 11.5662 9.25714 11.5662 6.68571C11.5662 4.11429 9.5091 2.05714 6.93767 2.05714Z" /></svg>`),
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'react-alice-carousel/lib/alice-carousel.css';
|
||||
import TrendingFlatIcon from '@mui/icons-material/TrendingFlat';
|
||||
import theme from '../theme.jsx';
|
||||
import CheckBoxSharpIcon from '@mui/icons-material/CheckBoxSharp';
|
||||
import { findSpecificApp } from "../components/AppFramework.jsx"
|
||||
import {
|
||||
Checkbox,
|
||||
Button,
|
||||
@@ -39,7 +40,7 @@ import { useNavigate, Link } from "react-router-dom";
|
||||
import WorkflowTemplatePopup from "../components/WorkflowTemplatePopup.jsx";
|
||||
|
||||
const ExploreWorkflow = (props) => {
|
||||
const { userdata, globalUrl } = props
|
||||
const { userdata, globalUrl, appFramework } = props
|
||||
const [activeUsecases, setActiveUsecases] = useState(0);
|
||||
const [modalOpen, setModalOpen] = React.useState(false);
|
||||
const [suggestedUsecases, setSuggestedUsecases] = useState([])
|
||||
@@ -105,9 +106,66 @@ const ExploreWorkflow = (props) => {
|
||||
continue
|
||||
}
|
||||
|
||||
const descsplit = userdata.priorities[i].description.split("&")
|
||||
if (descsplit.length === 5) {
|
||||
console.log("descsplit: ", descsplit)
|
||||
if (descsplit[1] === "") {
|
||||
const item = findSpecificApp(appFramework, descsplit[0])
|
||||
console.log("item: ", item)
|
||||
if (item !== null) {
|
||||
descsplit[1] = item.large_image
|
||||
}
|
||||
}
|
||||
|
||||
if (descsplit[3] === "") {
|
||||
const item = findSpecificApp(appFramework, descsplit[2])
|
||||
console.log("item: ", item)
|
||||
if (item !== null) {
|
||||
descsplit[3] = item.large_image
|
||||
}
|
||||
}
|
||||
|
||||
console.log("descsplit: ", descsplit)
|
||||
userdata.priorities[i].description = descsplit.join("&")
|
||||
}
|
||||
|
||||
tmpUsecases.push(userdata.priorities[i])
|
||||
}
|
||||
|
||||
console.log("USECASES: ", tmpUsecases)
|
||||
if (tmpUsecases.length === 0) {
|
||||
console.log("Add some random ones, as everything is done")
|
||||
|
||||
const comms = findSpecificApp(appFramework, "communication")
|
||||
const cases = findSpecificApp(appFramework, "cases")
|
||||
const edr = findSpecificApp(appFramework, "edr")
|
||||
const siem = findSpecificApp(appFramework, "siem")
|
||||
|
||||
tmpUsecases = [{
|
||||
"name": "Suggested Usecase: Email management",
|
||||
"description": comms.name+"&"+comms.large_image+"&"+cases.name+"&"+cases.large_image,
|
||||
"type": "usecase",
|
||||
"url": "/usecases?selected_object=Email management",
|
||||
"severity": 0,
|
||||
"active": false,
|
||||
},{
|
||||
"name": "Suggested Usecase: EDR to ticket",
|
||||
"description": edr.name+"&"+edr.large_image+"&"+cases.name+"&"+cases.large_image,
|
||||
"type": "usecase",
|
||||
"url": "/usecases?selected_object=EDR to ticket",
|
||||
"severity": 0,
|
||||
"active": false,
|
||||
},{
|
||||
"name": "Suggested Usecase: SIEM to ticket",
|
||||
"description": siem.name+"&"+siem.large_image+"&"+cases.name+"&"+cases.large_image,
|
||||
"type": "usecase",
|
||||
"url": "/usecases?selected_object=SIEM to ticket",
|
||||
"severity": 0,
|
||||
"active": false,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
setSuggestedUsecases(tmpUsecases)
|
||||
setUsecasesSet(true)
|
||||
loadApps()
|
||||
|
||||
@@ -4,6 +4,7 @@ import { toast } from 'react-toastify';
|
||||
import ReactGA from 'react-ga4';
|
||||
import theme from "../theme.jsx";
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import { findSpecificApp } from "../components/AppFramework.jsx"
|
||||
import {
|
||||
Paper,
|
||||
Typography,
|
||||
@@ -21,50 +22,82 @@ import {
|
||||
//import { useAlert
|
||||
|
||||
const Priority = (props) => {
|
||||
const { globalUrl, userdata, serverside, priority, checkLogin, setAdminTab, setCurTab, } = props;
|
||||
const { globalUrl, userdata, serverside, priority, checkLogin, setAdminTab, setCurTab, appFramework, } = props;
|
||||
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
let navigate = useNavigate();
|
||||
|
||||
var realigned = false
|
||||
let newdescription = priority.description
|
||||
const descsplit = priority.description.split("&")
|
||||
if (appFramework !== undefined && descsplit.length === 5 && priority.description.includes(":default")) {
|
||||
console.log("descsplit: ", descsplit)
|
||||
if (descsplit[1] === "") {
|
||||
const item = findSpecificApp(appFramework, descsplit[0])
|
||||
console.log("item: ", item)
|
||||
if (item !== null) {
|
||||
descsplit[1] = item.large_image
|
||||
descsplit[0] = descsplit[0].split(":")[0]
|
||||
}
|
||||
|
||||
realigned = true
|
||||
}
|
||||
|
||||
if (descsplit[3] === "") {
|
||||
const item = findSpecificApp(appFramework, descsplit[2])
|
||||
console.log("item: ", item)
|
||||
if (item !== null) {
|
||||
descsplit[3] = item.large_image
|
||||
descsplit[2] = descsplit[2].split(":")[0]
|
||||
}
|
||||
|
||||
realigned = true
|
||||
}
|
||||
|
||||
newdescription = descsplit.join("&")
|
||||
}
|
||||
|
||||
const changeRecommendation = (recommendation, action) => {
|
||||
const data = {
|
||||
action: action,
|
||||
name: recommendation.name,
|
||||
};
|
||||
const data = {
|
||||
action: action,
|
||||
name: recommendation.name,
|
||||
};
|
||||
|
||||
fetch(`${globalUrl}/api/v1/recommendations/modify`, {
|
||||
mode: "cors",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
credentials: "include",
|
||||
crossDomain: true,
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
} else {
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success === true) {
|
||||
if (checkLogin !== undefined) {
|
||||
checkLogin()
|
||||
}
|
||||
} else {
|
||||
if (responseJson.success === false && responseJson.reason !== undefined) {
|
||||
toast("Failed change recommendation: ", responseJson.reason)
|
||||
} else {
|
||||
toast("Failed change recommendation");
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
toast("Failed dismissing alert. Please contact support@shuffler.io if this persists.");
|
||||
});
|
||||
fetch(`${globalUrl}/api/v1/recommendations/modify`, {
|
||||
mode: "cors",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
credentials: "include",
|
||||
crossDomain: true,
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
} else {
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success === true) {
|
||||
if (checkLogin !== undefined) {
|
||||
checkLogin()
|
||||
}
|
||||
} else {
|
||||
if (responseJson.success === false && responseJson.reason !== undefined) {
|
||||
toast("Failed change recommendation: ", responseJson.reason)
|
||||
} else {
|
||||
toast("Failed change recommendation");
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
toast("Failed dismissing alert. Please contact support@shuffler.io if this persists.");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -79,17 +112,17 @@ const Priority = (props) => {
|
||||
</span>
|
||||
{priority.type === "usecase" && priority.description.includes("&") ?
|
||||
<span style={{display: "flex", marginTop: 10, }}>
|
||||
<img src={priority.description.split("&")[1]} alt={priority.name} style={{height: 30, width: 30, marginRight: 5, borderRadius: theme.palette.borderRadius, marginRight: 10, }} />
|
||||
<img src={newdescription.split("&")[1]} alt={priority.name} style={{height: realigned ? 30 : "auto", width: realigned ? 30 : 40, marginRight: realigned ? -10 : 10, borderRadius: theme.palette.borderRadius, marginTop: realigned ? 5 : 0 }} />
|
||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 3, }}>
|
||||
{priority.description.split("&")[0]}
|
||||
{newdescription.split("&")[0]}
|
||||
</Typography>
|
||||
|
||||
{priority.description.split("&").length > 3 ?
|
||||
{newdescription.split("&").length > 3 ?
|
||||
<span style={{display: "flex", }}>
|
||||
<ArrowForwardIcon style={{marginLeft: 15, marginRight: 15, }}/>
|
||||
<img src={priority.description.split("&")[3]} alt={priority.name+"2"} style={{height: 30, width: 30, borderRadius: theme.palette.borderRadius, marginRight: 10, }} />
|
||||
<img src={newdescription.split("&")[3]} alt={priority.name+"2"} style={{height: realigned ? 30 : "auto", width: realigned ? 30 : 40, marginRight: realigned ? -10 : 10, borderRadius: theme.palette.borderRadius, marginTop: realigned ? 5 : 0 }} />
|
||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 3}}>
|
||||
{priority.description.split("&")[2]}
|
||||
{newdescription.split("&")[2]}
|
||||
</Typography>
|
||||
</span>
|
||||
: null}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import ReactGA from "react-ga4";
|
||||
import Checkbox from "@mui/material/Checkbox";
|
||||
|
||||
@@ -13,8 +13,6 @@ import LightbulbIcon from "@mui/icons-material/Lightbulb";
|
||||
import TrendingFlatIcon from "@mui/icons-material/TrendingFlat";
|
||||
import theme from "../theme.jsx";
|
||||
import CheckBoxSharpIcon from "@mui/icons-material/CheckBoxSharp";
|
||||
import AppSearch from "../components/Appsearch.jsx";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import {
|
||||
Button,
|
||||
Collapse,
|
||||
@@ -47,6 +45,7 @@ import AuthenticationItem from "../components/AuthenticationItem.jsx";
|
||||
import WorkflowPaper from "../components/WorkflowPaper.jsx";
|
||||
import UsecaseSearch from "../components/UsecaseSearch.jsx";
|
||||
import ExploreWorkflow from "../components/ExploreWorkflow.jsx";
|
||||
import AppSelection from "../components/AppSelection.jsx";
|
||||
|
||||
const responsive = {
|
||||
0: { items: 1 },
|
||||
@@ -79,9 +78,10 @@ const WelcomeForm = (props) => {
|
||||
setDefaultSearch,
|
||||
selectionOpen,
|
||||
setSelectionOpen,
|
||||
checkLogin,
|
||||
} = props;
|
||||
const [isActive, setIsActive] = useState(0);
|
||||
|
||||
const [moreButton, setMoreButton] = useState(false);
|
||||
const ref = useRef()
|
||||
const [usecaseItems, setUsecaseItems] = useState([
|
||||
{
|
||||
search: "Phishing",
|
||||
@@ -101,91 +101,72 @@ const WelcomeForm = (props) => {
|
||||
},
|
||||
]);
|
||||
/*
|
||||
<div style={{minWidth: "95%", maxWidth: "95%", marginLeft: 5, marginRight: 5, }}>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={"Phishing"}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
,
|
||||
<div style={{minWidth: "95%", maxWidth: "95%", marginLeft: 5, marginRight: 5, }}>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={"Enrichment"}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
,
|
||||
<div style={{minWidth: "95%", maxWidth: "95%", marginLeft: 5, marginRight: 5, }}>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={"Enrichment"}
|
||||
usecaseSearch={"SIEM alert enrichment"}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
,
|
||||
<div style={{minWidth: "95%", maxWidth: "95%", marginLeft: 5, marginRight: 5, }}>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={"Build your own"}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
])
|
||||
*/
|
||||
<div style={{minWidth: "95%", maxWidth: "95%", marginLeft: 5, marginRight: 5, }}>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={"Phishing"}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
,
|
||||
<div style={{minWidth: "95%", maxWidth: "95%", marginLeft: 5, marginRight: 5, }}>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={"Enrichment"}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
,
|
||||
<div style={{minWidth: "95%", maxWidth: "95%", marginLeft: 5, marginRight: 5, }}>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={"Enrichment"}
|
||||
usecaseSearch={"SIEM alert enrichment"}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
,
|
||||
<div style={{minWidth: "95%", maxWidth: "95%", marginLeft: 5, marginRight: 5, }}>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={"Build your own"}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
])
|
||||
*/
|
||||
const [name, setName] = React.useState("")
|
||||
const [orgName, setOrgName] = React.useState("")
|
||||
const [role, setRole] = React.useState("")
|
||||
const [orgType, setOrgType] = React.useState("")
|
||||
const [finishedApps, setFinishedApps] = React.useState([])
|
||||
const [authentication, setAuthentication] = React.useState([]);
|
||||
|
||||
const [discoveryData, setDiscoveryData] = React.useState({})
|
||||
const [name, setName] = React.useState("")
|
||||
const [orgName, setOrgName] = React.useState("")
|
||||
const [role, setRole] = React.useState("")
|
||||
const [orgType, setOrgType] = React.useState("")
|
||||
const [finishedApps, setFinishedApps] = React.useState([])
|
||||
const [authentication, setAuthentication] = React.useState([]);
|
||||
const [newSelectedApp, setNewSelectedApp] = React.useState({})
|
||||
const [thumbIndex, setThumbIndex] = useState(0);
|
||||
const [thumbAnimation, setThumbAnimation] = useState(false);
|
||||
const [clickdiff, setclickdiff] = useState(0);
|
||||
const [thumbIndex, setThumbIndex] = useState(0);
|
||||
const [thumbAnimation, setThumbAnimation] = useState(false);
|
||||
const [clickdiff, setclickdiff] = useState(0);
|
||||
const [mouseHoverIndex, setMouseHoverIndex] = useState(-1)
|
||||
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
|
||||
//const alert = useAlert();
|
||||
let navigate = useNavigate();
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
//const alert = useAlert();
|
||||
let navigate = useNavigate();
|
||||
|
||||
const iconStyles = {
|
||||
color: "rgba(255, 255, 255, 1)",
|
||||
};
|
||||
|
||||
const onNodeSelect = (label) => {
|
||||
if (setDiscoveryWrapper !== undefined) {
|
||||
setDiscoveryWrapper({ id: label });
|
||||
}
|
||||
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "welcome",
|
||||
action: `click_${label}`,
|
||||
label: "",
|
||||
});
|
||||
}
|
||||
|
||||
setSelectionOpen(true);
|
||||
setDefaultSearch(label);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (userdata.id === undefined) {
|
||||
return;
|
||||
@@ -407,6 +388,7 @@ const WelcomeForm = (props) => {
|
||||
console.log("Should send basic information about org (fetch)");
|
||||
setclickdiff(240);
|
||||
navigate(`/welcome?tab=2`);
|
||||
setActiveStep(1);
|
||||
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
@@ -440,6 +422,7 @@ const WelcomeForm = (props) => {
|
||||
//handleSetSearch("Enrichment", "2. Enrich")
|
||||
handleSetSearch(usecaseButtons[0].name, usecaseButtons[0].usecase);
|
||||
getApps();
|
||||
setActiveStep(2);
|
||||
|
||||
// Make sure it's up to date
|
||||
if (getFramework !== undefined) {
|
||||
@@ -493,16 +476,13 @@ const WelcomeForm = (props) => {
|
||||
setActiveStep(0);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Selected app changed (effect)");
|
||||
}, [newSelectedApp]);
|
||||
|
||||
//const buttonWidth = 145
|
||||
const buttonWidth = 450;
|
||||
const buttonMargin = 10;
|
||||
const sizing = 475;
|
||||
const sizing = 510;
|
||||
const bottomButtonStyle = {
|
||||
borderRadius: 200,
|
||||
marginTop: moreButton ? 44 : "",
|
||||
height: 51,
|
||||
width: 464,
|
||||
fontSize: 16,
|
||||
@@ -510,24 +490,11 @@ const WelcomeForm = (props) => {
|
||||
background: "linear-gradient(90deg, #F86744 0%, #F34475 100%)",
|
||||
padding: "16px 24px",
|
||||
// top: 20,
|
||||
margin: "auto",
|
||||
// margin: "auto",
|
||||
itemAlign: "center",
|
||||
// marginLeft: "65px",
|
||||
};
|
||||
|
||||
const buttonStyle = {
|
||||
flex: 1,
|
||||
width: 224,
|
||||
padding: 25,
|
||||
margin: buttonMargin,
|
||||
color : "var(--White-text, #F1F1F1)",
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
background: "rgba(33, 33, 33, 1)",
|
||||
borderColor: "rgba(33, 33, 33, 1)",
|
||||
borderRadius: 8,
|
||||
};
|
||||
|
||||
const slideNext = () => {
|
||||
if (!thumbAnimation && thumbIndex < usecaseItems.length - 1) {
|
||||
//handleSetSearch(usecaseButtons[0].name, usecaseButtons[0].usecase)
|
||||
@@ -557,30 +524,30 @@ const WelcomeForm = (props) => {
|
||||
appFramework === undefined || appFramework === null
|
||||
? []
|
||||
: usecaseItems.map((item, index) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
minWidth: "95%",
|
||||
maxWidth: "95%",
|
||||
marginLeft: 5,
|
||||
marginRight: 5,
|
||||
}}
|
||||
>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={item.search}
|
||||
usecaseSearch={item.usecase_search}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
autotry={item.autotry}
|
||||
sourceapp={item.sourceapp}
|
||||
destinationapp={item.destinationapp}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
minWidth: "95%",
|
||||
maxWidth: "95%",
|
||||
marginLeft: 5,
|
||||
marginRight: 5,
|
||||
}}
|
||||
>
|
||||
<UsecaseSearch
|
||||
globalUrl={globalUrl}
|
||||
defaultSearch={item.search}
|
||||
usecaseSearch={item.usecase_search}
|
||||
appFramework={appFramework}
|
||||
apps={apps}
|
||||
getFramework={getFramework}
|
||||
userdata={userdata}
|
||||
autotry={item.autotry}
|
||||
sourceapp={item.sourceapp}
|
||||
destinationapp={item.destinationapp}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const getStepContent = (step) => {
|
||||
switch (step) {
|
||||
@@ -694,288 +661,42 @@ const WelcomeForm = (props) => {
|
||||
</Collapse>
|
||||
);
|
||||
case 1:
|
||||
return (
|
||||
<AppSelection
|
||||
globalUrl={globalUrl}
|
||||
userdata={userdata}
|
||||
appFramework={appFramework}
|
||||
setActiveStep={setActiveStep}
|
||||
defaultSearch={defaultSearch}
|
||||
setDefaultSearch={setDefaultSearch}
|
||||
selectionOpen={selectionOpen}
|
||||
setSelectionOpen={setSelectionOpen}
|
||||
checkLogin={checkLogin}
|
||||
/>
|
||||
)
|
||||
case 2:
|
||||
return (
|
||||
<Collapse in={true}>
|
||||
<div
|
||||
style={{
|
||||
minHeight: sizing,
|
||||
maxHeight: sizing,
|
||||
marginTop: 20,
|
||||
width: 500,
|
||||
}}
|
||||
>
|
||||
{selectionOpen ? (
|
||||
<div
|
||||
style={{
|
||||
width: 319,
|
||||
height: 395,
|
||||
flexShrink: 0,
|
||||
marginLeft:70,
|
||||
marginTop: 68,
|
||||
position:"absolute",
|
||||
zIndex:100,
|
||||
borderRadius: 6,
|
||||
border: "1px solid var(--Container-Stroke, #494949)",
|
||||
background: "var(--Container, #212121)",
|
||||
boxShadow: "8px 8px 32px 24px rgba(0, 0, 0, 0.16)",
|
||||
}}
|
||||
>
|
||||
<div style={{display: "flex", textAlign:"center"}}>
|
||||
<Typography style={{padding:16}}> {defaultSearch} </Typography>
|
||||
<Button
|
||||
style={{
|
||||
flex: 1,
|
||||
width: 224,
|
||||
paddingLeft: 172,
|
||||
fontSize: 16,
|
||||
background: "rgba(33, 33, 33, 1)",
|
||||
borderColor: "rgba(33, 33, 33, 1)",
|
||||
borderRadius: 8,
|
||||
}}
|
||||
onClick={() => {
|
||||
setSelectionOpen(false)
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M1 1L10.5 10.5"
|
||||
stroke="#9E9E9E"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M10.5 1L1 10.5"
|
||||
stroke="#9E9E9E"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</svg>
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
style={{ width: "100%", border: "1px #494949 solid" }}
|
||||
/>
|
||||
<AppSearch
|
||||
defaultSearch={defaultSearch}
|
||||
newSelectedApp={newSelectedApp}
|
||||
setNewSelectedApp={setNewSelectedApp}
|
||||
<div style={{ marginTop: 0, maxWidth: 700, minWidth: 700, margin: "auto", minHeight: sizing, maxHeight: sizing, }}>
|
||||
|
||||
<div style={{ marginTop: 0, }}>
|
||||
<div className="thumbs" style={{ display: "flex" }}>
|
||||
<div style={{ minWidth: 554, maxWidth: 554, borderRadius: theme.palette.borderRadius, }}>
|
||||
<ExploreWorkflow
|
||||
globalUrl={globalUrl}
|
||||
userdata={userdata}
|
||||
// cy={cy}
|
||||
appFramework={appFramework}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
{/* <Typography variant="body1" style={{marginLeft: 8, marginTop: 50, marginRight: 30, marginBottom: 0, }} color="textSecondary">
|
||||
Apps for each category are shown based on your activity and can be changed by clicking their icon. We will help you connect them later.
|
||||
</Typography> */}
|
||||
{/* <div style={{display:"flex"}}>
|
||||
<ArrowBackIosNewIcon style={{color: "#9E9E9E", width: "16px",}} onClick={() => {
|
||||
navigate("/welcome")
|
||||
}}/>
|
||||
<Typography variant="h8" style={{color: "#9E9E9E",textAlign: "center", marginLeft: 5}} onClick={() => {
|
||||
navigate("/welcome")
|
||||
}}>
|
||||
Back
|
||||
</Typography>
|
||||
</div> */}
|
||||
<Typography
|
||||
variant="h4"
|
||||
style={{
|
||||
marginLeft: 8,
|
||||
marginTop: 40,
|
||||
marginRight: 30,
|
||||
marginBottom: 0,
|
||||
}}
|
||||
color="rgba(241, 241, 241, 1)"
|
||||
>
|
||||
Find your apps
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{
|
||||
marginLeft: 8,
|
||||
marginTop: 10,
|
||||
marginRight: 30,
|
||||
marginBottom: 40,
|
||||
}}
|
||||
color="rgba(158, 158, 158, 1)"
|
||||
>
|
||||
Select the apps you work with and we will connect the for you.
|
||||
</Typography>
|
||||
{/*The app framework helps us access and authenticate the most important APIs for you. */}
|
||||
|
||||
{/*
|
||||
<Grid item xs={10}>
|
||||
<FormControl fullWidth={true}>
|
||||
<InputLabel style={{ color: "#B9B9BA" }}>What is your development experience?</InputLabel>
|
||||
<Select
|
||||
required
|
||||
>
|
||||
<MenuItem value={10}>Beginner</MenuItem>
|
||||
<MenuItem value={20}>Intermediate</MenuItem>
|
||||
<MenuItem value={30}>Automation Ninja</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
*/}
|
||||
<Grid item xs={11} style={{}}>
|
||||
{/*<FormLabel style={{ color: "#B9B9BA" }}>Find your integrations!</FormLabel>*/}
|
||||
<div style={{ display: "flex", width: 464 }}>
|
||||
<Button
|
||||
disabled={finishedApps.includes("CASES")}
|
||||
variant={
|
||||
defaultSearch === "CASES" ? "contained" : "outlined"
|
||||
}
|
||||
color="secondary"
|
||||
style={{
|
||||
flex: 1,
|
||||
width: "100%",
|
||||
padding: 25,
|
||||
margin: buttonMargin,
|
||||
fontSize: 16,
|
||||
color : "var(--White-text, #F1F1F1)",
|
||||
fontWeight: 400,
|
||||
background: "rgba(33, 33, 33, 1)",
|
||||
borderColor: finishedApps.includes("CASES")
|
||||
? "inherit"
|
||||
: "rgba(33, 33, 33, 1)",
|
||||
borderRadius: 8,
|
||||
}}
|
||||
startIcon = {<LightbulbIcon/>}
|
||||
onClick={(event) => {
|
||||
onNodeSelect("CASES");
|
||||
}}
|
||||
>
|
||||
Case Management
|
||||
</Button>
|
||||
</div>
|
||||
<div style={{ display: "flex", width: 464 }}>
|
||||
<Button
|
||||
disabled={finishedApps.includes("SIEM")}
|
||||
variant={
|
||||
defaultSearch === "SIEM" ? "contained" : "outlined"
|
||||
}
|
||||
style={buttonStyle}
|
||||
startIcon={<SearchIcon />}
|
||||
color="secondary"
|
||||
onClick={(event) => {
|
||||
onNodeSelect("SIEM");
|
||||
}}
|
||||
>
|
||||
SIEM
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
finishedApps.includes("EDR & AV") ||
|
||||
finishedApps.includes("ERADICATION")
|
||||
}
|
||||
variant={
|
||||
defaultSearch === "Eradication" ? "contained" : "outlined"
|
||||
}
|
||||
style={buttonStyle}
|
||||
startIcon={<NewReleasesIcon />}
|
||||
color="secondary"
|
||||
onClick={(event) => {
|
||||
onNodeSelect("ERADICATION");
|
||||
}}
|
||||
>
|
||||
Endpoint
|
||||
</Button>
|
||||
</div>
|
||||
<div style={{ display: "flex", width: 464 }}>
|
||||
<Button
|
||||
disabled={finishedApps.includes("INTEL")}
|
||||
variant={
|
||||
defaultSearch === "INTEL" ? "contained" : "outlined"
|
||||
}
|
||||
style={buttonStyle}
|
||||
startIcon={<ExtensionIcon />}
|
||||
color="secondary"
|
||||
onClick={(event) => {
|
||||
onNodeSelect("INTEL");
|
||||
}}
|
||||
>
|
||||
Intel
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
finishedApps.includes("COMMS") ||
|
||||
finishedApps.includes("EMAIL")
|
||||
}
|
||||
variant={
|
||||
defaultSearch === "EMAIL" ? "contained" : "outlined"
|
||||
}
|
||||
style={buttonStyle}
|
||||
startIcon={<EmailIcon />}
|
||||
color="secondary"
|
||||
onClick={(event) => {
|
||||
onNodeSelect("EMAIL");
|
||||
}}
|
||||
>
|
||||
Email
|
||||
</Button>
|
||||
</div>
|
||||
{/* <FormControl>
|
||||
<FormLabel style={{ color: "#B9B9BA" }}>What do you want to automate first ?</FormLabel>
|
||||
<FormGroup>
|
||||
<FormControlLabel
|
||||
value="Email"
|
||||
control={<Checkbox style={{ color: "#F85A3E" }} onChange={(event) => { onNodeSelect("Email") }} />}
|
||||
label="Email"
|
||||
labelPlacement="Email"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="SIEM"
|
||||
control={<Checkbox style={{ color: "#F85A3E" }} onChange={(event) => { onNodeSelect("SIEM") }} />}
|
||||
label="SIEM"
|
||||
labelPlacement="SIEM"
|
||||
/>
|
||||
<FormControlLabel
|
||||
value="EDR"
|
||||
control={<Checkbox style={{ color: "#F85A3E" }} onChange={(event) => { onNodeSelect("EDR") }} />}
|
||||
label="EDR"
|
||||
labelPlacement="EDR"
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormControl> */}
|
||||
</Grid>
|
||||
</div>
|
||||
<div style={{ flexDirection: "row", }}>
|
||||
<Button variant="contained" type="submit" fullWidth style={bottomButtonStyle} onClick={() => {
|
||||
navigate("/welcome?tab=3")
|
||||
setActiveStep(2)
|
||||
}}>
|
||||
Continue
|
||||
</Button>
|
||||
</div>
|
||||
</Collapse>
|
||||
|
||||
)
|
||||
case 2:
|
||||
return (
|
||||
<Collapse in={true}>
|
||||
<div style={{marginTop: 0, maxWidth: 700, minWidth: 700, margin: "auto", minHeight: sizing, maxHeight: sizing, }}>
|
||||
|
||||
<div style={{marginTop: 0, }}>
|
||||
<div className="thumbs" style={{display: "flex"}}>
|
||||
<div style={{minWidth: 554, maxWidth: 554, borderRadius: theme.palette.borderRadius, }}>
|
||||
<ExploreWorkflow
|
||||
globalUrl={globalUrl}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Collapse>
|
||||
)
|
||||
default:
|
||||
return "unknown step"
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Collapse>
|
||||
)
|
||||
default:
|
||||
return "unknown step"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const extraHeight = isCloud ? -7 : 0;
|
||||
@@ -1081,7 +802,7 @@ const WelcomeForm = (props) => {
|
||||
</div>
|
||||
}*/}
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
|
||||
|
||||
import { toast } from "react-toastify"
|
||||
import theme from '../theme.jsx';
|
||||
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||
import {
|
||||
Button,
|
||||
Typography,
|
||||
@@ -33,8 +34,11 @@ const WorkflowTemplatePopup = (props) => {
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
const [workflowLoading, setWorkflowLoading] = useState(false);
|
||||
const [workflow, setWorkflow] = useState({});
|
||||
|
||||
const [appAuthentication, setAppAuthentication] = React.useState(undefined);
|
||||
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
let navigate = useNavigate();
|
||||
|
||||
const imagestyleWrapper = {
|
||||
height: 40,
|
||||
width: 40,
|
||||
@@ -48,7 +52,7 @@ const WorkflowTemplatePopup = (props) => {
|
||||
height: 40,
|
||||
width: 40,
|
||||
borderRadius: 40,
|
||||
border: "1px solid red",
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
overflow: "hidden",
|
||||
display: "flex",
|
||||
}
|
||||
@@ -63,8 +67,10 @@ const WorkflowTemplatePopup = (props) => {
|
||||
|
||||
const imagestyleDefault = {
|
||||
display: "block",
|
||||
marginLeft: 9,
|
||||
marginTop: 10,
|
||||
marginLeft: 11,
|
||||
marginTop: 11,
|
||||
height: 35,
|
||||
width: "auto",
|
||||
}
|
||||
|
||||
if (title === undefined || title === null || title === "") {
|
||||
@@ -102,6 +108,22 @@ const WorkflowTemplatePopup = (props) => {
|
||||
}
|
||||
|
||||
const loadAppAuth = () => {
|
||||
if (userdata === undefined || userdata === null) {
|
||||
setErrorMessage("You need to be logged in to try usecases. Redirecting in 5 seconds...")
|
||||
// Send the user to the login screen after 3 seconds
|
||||
setTimeout(() => {
|
||||
// Make it cancel if the state modalOpen changes
|
||||
if (modalOpen === false) {
|
||||
return
|
||||
}
|
||||
|
||||
navigate("/login?view=" + window.location.pathname + window.location.search)
|
||||
}, 4500)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
fetch(`${globalUrl}/api/v1/apps/authentication`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
@@ -168,7 +190,8 @@ const WorkflowTemplatePopup = (props) => {
|
||||
},
|
||||
}
|
||||
|
||||
fetch(globalUrl + "/api/v1/workflows/merge", {
|
||||
//fetch(globalUrl + "/api/v1/workflows/merge", {
|
||||
fetch("https://shuffler.io/api/v1/workflows/merge", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -226,8 +249,6 @@ const WorkflowTemplatePopup = (props) => {
|
||||
return true
|
||||
}
|
||||
|
||||
console.log("APPCONFIG: ", appconfig)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -309,6 +330,9 @@ const WorkflowTemplatePopup = (props) => {
|
||||
<Button
|
||||
style={{marginTop: 50, }}
|
||||
variant={isFinished() ? "contained" : "outlined"}
|
||||
onClick={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
>
|
||||
Done
|
||||
</Button>
|
||||
@@ -330,7 +354,7 @@ const WorkflowTemplatePopup = (props) => {
|
||||
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", maxWidth: 470, minWidth: 470, height: 78, borderRadius: 8 }}>
|
||||
<div style={{ display: "flex", maxWidth: isCloud ? 470 : 450, minWidth: isCloud ? 470 : 450, height: 78, borderRadius: 8 }}>
|
||||
<ModalView />
|
||||
<div
|
||||
// variant={isActive === 1 ? "contained" : "outlined"}
|
||||
@@ -362,7 +386,7 @@ const WorkflowTemplatePopup = (props) => {
|
||||
|
||||
//setIsActive(!isActive)
|
||||
if (errorMessage !== "") {
|
||||
toast("Already failed to generate workflow for these apps. Please try again later or contact support@shuffler.io.")
|
||||
toast("Already failed to generate a workflow for this usecase. Please try again later or contact support@shuffler.io.")
|
||||
} else if (isActive) {
|
||||
toast("Workflow already generated. Please try another workflow template!")
|
||||
|
||||
@@ -393,7 +417,9 @@ const WorkflowTemplatePopup = (props) => {
|
||||
<Tooltip title={dstapp.replaceAll(":default", "").replaceAll("_", " ").replaceAll(" API", "")} placement="top">
|
||||
<span style={{display: "flex", }}>
|
||||
<TrendingFlatIcon style={{ marginTop: 7, }} />
|
||||
<img src={img2} style={srcapp !== undefined && srcapp.includes(":default") ? imagestyleDefault : imagestyleWrapper} />
|
||||
<span style={dstapp !== undefined && dstapp.includes(":default") ? imagestyleWrapperDefault : imagestyleWrapper}>
|
||||
<img src={img2} style={srcapp !== undefined && srcapp.includes(":default") ? imagestyleDefault : imagestyle} />
|
||||
</span>
|
||||
</span>
|
||||
</Tooltip>
|
||||
:
|
||||
|
||||
Reference in New Issue
Block a user