Added statistics to both backend and frontend + cloud sync

This commit is contained in:
Frikky
2023-10-17 02:40:32 +02:00
parent 0579f60b58
commit 595c217a7c
32 changed files with 4035 additions and 1753 deletions
+181 -121
View File
@@ -6,6 +6,7 @@ import { makeStyles, } from "@mui/styles";
import classNames from "classnames";
import theme from '../theme.jsx';
import { useNavigate, Link, useParams } from "react-router-dom";
import WorkflowTemplatePopup from "../components/WorkflowTemplatePopup.jsx";
// react plugin used to create charts
//import { Line, Bar } from "react-chartjs-2";
@@ -90,7 +91,7 @@ const useStyles = makeStyles({
},
});
const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows}) => {
const UsecaseListComponent = ({userdata, keys, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows}) => {
const [expandedIndex, setExpandedIndex] = useState(-1);
const [expandedItem, setExpandedItem] = useState(-1);
const [inputUsecase, setInputUsecase] = useState({});
@@ -103,17 +104,69 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
const [selectedWorkflows, setSelectedWorkflows] = useState([])
const [firstLoad, setFirstLoad] = useState(true)
const [apps, setApps] = useState([])
const classes = useStyles();
const classes = useStyles();
let navigate = useNavigate();
const [mitreTags, setMitreTags] = useState([]);
const loadApps = () => {
fetch(`${globalUrl}/api/v1/apps`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
return response.json();
})
.then((responseJson) => {
if (responseJson === null) {
console.log("null-response from server")
const pretend_apps = [{
"name": "TBD",
"app_name": "TBD",
"app_version": "TBD",
"description": "TBD",
"version": "TBD",
"large_image": "",
}]
setApps(pretend_apps)
return
}
if (responseJson.success === false) {
console.log("error loading apps: ", responseJson)
return
}
setApps(responseJson);
})
.catch((error) => {
console.log("App loading error: " + error.toString());
})
}
useEffect(() => {
loadApps()
}, [])
if (keys === undefined || keys === null || keys.length === 0) {
return null
}
const getUsecase = (name, index, subindex) => {
fetch(`${globalUrl}/api/v1/workflows/usecases/${escape(name.replaceAll(" ", "_"))}`, {
const parseUsecase = (parsedUsecase, subcase) => {
console.log("parseUsecase: ", parsedUsecase, subcase)
}
const getUsecase = (subcase, index, subindex) => {
console.log(subcase)
fetch(`${globalUrl}/api/v1/workflows/usecases/${escape(subcase.name.replaceAll(" ", "_"))}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
@@ -129,14 +182,26 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
return response.json();
})
.then((responseJson) => {
var parsedUsecase = responseJson
if (responseJson.success === false) {
setInputUsecase({
"name": name,
})
parsedUsecase = subcase
//img1={inputUsecase.srcimg}
//srcapp={inputUsecase.srcapp}
//img2={inputUsecase.dstimg}
//dstapp={inputUsecase.dstapp}
//title={inputUsecase.name}
parsedUsecase = parseUsecase(parsedUsecase, subcase)
} else {
setInputUsecase(responseJson)
parsedUsecase = responseJson
parsedUsecase = parseUsecase(parsedUsecase, responseJson)
}
// Look for the type of app and fill in img1, srcapp...
setInputUsecase(parsedUsecase)
setExpandedIndex(index)
setExpandedItem(subindex)
@@ -289,6 +354,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
if (selectedItem && subcase.matches.length > 0 && selectedWorkflows.length === 0 && firstLoad === true) {
setFirstLoad(false)
setSelectedWorkflows(subcase.matches)
}
}
@@ -316,10 +382,8 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
}
}
//const backgroundColor = selectedItem ? "inherit" : finished ? "inherit" : usecase.color
const finished = subcase.matches.length > 0
const backgroundColor = theme.palette.surfaceColor
//"inherit"
const itemBorder = `${selectedItem ? "3px" : expandedItem >= 0 ? "0px" : "1px"} solid ${usecase.color}`
const fixedName = subcase.name.toLowerCase().replace("_", " ")
@@ -330,14 +394,14 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
//setSelectedWorkflows([])
if (selectedItem) {
} else {
getUsecase(subcase.name, index, subindex)
getUsecase(subcase, index, subindex)
navigate(`/usecases?selected_object=${fixedName}`)
//const newitem = removeParam("selected_object", cursearch);
//navigate(curpath + newitem)
}
}}>
<Paper style={{padding: 25, minHeight: 75, cursor: !selectedItem ? "pointer" : "default", border: itemBorder, backgroundColor: backgroundColor,}} onClick={() => {
<Paper style={{padding: 25, minHeight: isCloud ? 75 : 122, cursor: !selectedItem ? "pointer" : "default", border: itemBorder, backgroundColor: backgroundColor,}} onClick={() => {
}}>
{!selectedItem ?
<div style={{textAlign: "left", position: "relative",}}>
@@ -649,12 +713,12 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
: null}
{workflows !== undefined && workflows !== null && workflows.length > 0 ?
<Autocomplete
multiple
<Autocomplete
multiple
id="workflow_matching"
options={workflows}
autoHighlight
value={selectedWorkflows}
value={selectedWorkflows}
classes={{ inputRoot: classes.inputRoot }}
ListboxProps={{
style: {
@@ -662,7 +726,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
color: "white",
},
}}
getOptionSelected={(option, value) => option.id === value.id}
getOptionSelected={(option, value) => option.id === value.id}
getOptionLabel={(option) => {
if (
@@ -685,120 +749,120 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
borderRadius: theme.palette.borderRadius,
}}
onChange={(event, newValue) => {
console.log("CLICK: ", newValue)
//handleWorkflowSelectionUpdate({ target: { value: newValue} })
//setSelectedWorkflows=
//var newvalue = []
//for (var key in newValue) {
// if (newValue[key].id !== undefined) {
// newvalue.push(newValue[key].id)
// }
//}
console.log("CLICK: ", newValue)
//handleWorkflowSelectionUpdate({ target: { value: newValue} })
//setSelectedWorkflows=
//var newvalue = []
//for (var key in newValue) {
// if (newValue[key].id !== undefined) {
// newvalue.push(newValue[key].id)
// }
//}
// Doing this way as you may want to remove some too
for (var key in workflows) {
if (!newValue.find(data => data.id === workflows[key].id)) {
// Check if it has the one in it
if (workflows[key]["usecase_ids"] !== undefined && workflows[key]["usecase_ids"] !== null && workflows[key]["usecase_ids"].includes(subcase.name)) {
const filtered = workflows[key]["usecase_ids"].filter(data => data !== subcase.name)
if (filtered !== undefined && filtered !== null) {
//console.log("Removing: ", workflows[key].name, workflows[key])
workflows[key]["usecase_ids"] = filtered
setWorkflow(workflows[key])
}
}
// Doing this way as you may want to remove some too
for (var key in workflows) {
if (!newValue.find(data => data.id === workflows[key].id)) {
// Check if it has the one in it
if (workflows[key]["usecase_ids"] !== undefined && workflows[key]["usecase_ids"] !== null && workflows[key]["usecase_ids"].includes(subcase.name)) {
const filtered = workflows[key]["usecase_ids"].filter(data => data !== subcase.name)
if (filtered !== undefined && filtered !== null) {
//console.log("Removing: ", workflows[key].name, workflows[key])
workflows[key]["usecase_ids"] = filtered
setWorkflow(workflows[key])
}
}
continue
}
continue
}
if (workflows[key]["usecase_ids"] === undefined || workflows[key]["usecase_ids"] === null) {
workflows[key]["usecase_ids"] = [subcase.name]
console.log("Setting: ", workflows[key].name)
setWorkflow(workflows[key])
if (workflows[key]["usecase_ids"] === undefined || workflows[key]["usecase_ids"] === null) {
workflows[key]["usecase_ids"] = [subcase.name]
console.log("Setting: ", workflows[key].name)
setWorkflow(workflows[key])
} else if (!workflows[key]["usecase_ids"].includes(subcase.name)) {
workflows[key]["usecase_ids"].push(subcase.name)
console.log("Adding: ", workflows[key].name)
setWorkflow(workflows[key])
} else if (!workflows[key]["usecase_ids"].includes(subcase.name)) {
workflows[key]["usecase_ids"].push(subcase.name)
console.log("Adding: ", workflows[key].name)
setWorkflow(workflows[key])
}
}
}
}
setWorkflows(workflows)
console.log("New: ", newValue)
setSelectedWorkflows(newValue)
setWorkflows(workflows)
console.log("New: ", newValue)
setSelectedWorkflows(newValue)
//setUpdate(Math.random())
}}
renderOption={(props, option) => {
//console.log("In options?: ", props, option)
renderOption={(props, data, state) => {
var newname = data.name
if (newname === undefined || newname === null) {
newname = "placeholder"
}
var newname = props.name
if (newname === undefined || newname === null) {
newname = "placeholder"
}
if (newname.length > 2) {
newname = newname.charAt(0).toUpperCase() + newname.substring(1)
}
return (
<li {...props}>
<Tooltip arrow placement="left" title={
<span style={{}}>
{props.image !== undefined && props.image !== null && props.image.length > 0 ?
<img src={props.image} alt={newname} style={{backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette.borderRadius, }} />
: null}
<Typography>
Choose {newname}
</Typography>
</span>
} placement="bottom">
<span>
<Checkbox
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
checkedIcon={<CheckBoxIcon fontSize="small" />}
style={{ marginRight: 8 }}
checked={option.selected}
/>
{newname}
</span>
</Tooltip>
</li>
)
}}
if (newname.length > 2) {
newname = newname.charAt(0).toUpperCase() + newname.substring(1)
}
return (
<li {...props}>
<Tooltip arrow placement="left" title={
<span style={{}}>
{data.image !== undefined && data.image !== null && data.image.length > 0 ?
<img src={data.image} alt={newname} style={{backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette.borderRadius, }} />
: null}
<Typography>
Choose {newname}
</Typography>
</span>
} placement="bottom">
<span>
<Checkbox
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
checkedIcon={<CheckBoxIcon fontSize="small" />}
style={{ marginRight: 8 }}
checked={selectedWorkflows.find(wf => wf.id === data.id) !== undefined}
/>
{newname}
</span>
</Tooltip>
</li>
)
}}
renderInput={(params) => {
return (
<TextField
style={{
backgroundColor: theme.palette.inputColor,
borderRadius: theme.palette.borderRadius,
}}
{...params}
label="Find your workflows"
variant="outlined"
<TextField
style={{
backgroundColor: theme.palette.inputColor,
borderRadius: theme.palette.borderRadius,
}}
{...params}
label="Find your workflows"
variant="outlined"
/>
);
}}
/>
: null}
: null}
<span style={{top: 30, position: "relative",}}>
<Typography variant="body1" style={{marginTop: 0,}} onClick={() => {}}>
Try it out
</Typography>
<WorkflowTemplatePopup
userdata={userdata}
globalUrl={globalUrl}
img1={inputUsecase.srcimg}
srcapp={inputUsecase.srcapp}
img2={inputUsecase.dstimg}
dstapp={inputUsecase.dstapp}
title={inputUsecase.name}
description={inputUsecase.description}
apps={apps}
/>
</span>
{/*
{/*subcase.matches.length > 0 ?
<Grid container style={{maxWidth: 325, marginTop: 10, }}>
{subcase.matches.map((workflow, workflowindex) => {
return (
<Grid key={workflowindex} item index={workflowindex} xs={12}>
<WorkflowPaper key={workflowindex} data={workflow} />
</Grid>
)
})}
</Grid>
:
<div>
<Typography variant="body1" color="textSecondary">
No workflow selected yet.
</Typography>
</div>
*/}
{subcase.extra_buttons !== undefined && subcase.extra_buttons !== null && subcase.extra_buttons.length > 0 ?
<div style={{marginTop: 25, }}>
@@ -852,15 +916,9 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
<Typography variant="body1" style={{marginTop: 15, cursor: "pointer",}} onClick={() => {}}>
See other Public Workflows for {} <OpenInNewIcon style={{marginTop: 5, marginLeft: 15, }}/>
</Typography>
{/*
<div>
<Typography variant="body1" color="textSecondary">
No workflows yet.
</Typography>
</div>
*/}
</a>
</div>
*/}
</div>
}
<div style={{
@@ -868,6 +926,8 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
width: 350,
borderRadius: theme.palette.borderRadius,
border: "1px solid rgba(255,255,255,0.3)",
padding: 5,
backgroundColor: theme.palette.backgroundColor,
}}>
<AppFramework
inputUsecase={inputUsecase}