Added usecase editing & app framework handling in any place

This commit is contained in:
frikky
2022-03-08 12:45:45 +01:00
parent f88636579f
commit 923e9e5be2
9 changed files with 926 additions and 442 deletions
+91 -19
View File
@@ -4,7 +4,7 @@ import { securityFramework } from "./LandingpageUsecases.jsx";
import CytoscapeComponent from 'react-cytoscapejs';
import frameworkStyle from '../frameworkStyle.jsx';
import WorkflowSearch from './Workflowsearch.jsx';
import uuid from "uuid";
import { v4 as uuidv4 } from "uuid";
import theme from '../theme';
import { useAlert } from "react-alert";
@@ -518,7 +518,7 @@ export const usecases = {
}
const Framework = (props) => {
const {globalUrl, isLoaded, showOptions, selectedOption, rolling, frameworkData, size } = props;
const {globalUrl, isLoaded, showOptions, selectedOption, rolling, frameworkData, size, inputUsecase, isLoggedIn, } = props;
const [cy, setCy] = React.useState()
const [edgesStarted, setEdgesStarted] = React.useState(false)
const [graphDone, setGraphDone] = React.useState(false)
@@ -532,6 +532,50 @@ const Framework = (props) => {
const alert = useAlert()
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) {
alert.error("Failed updating: " + responseJson.reason)
} else {
alert.error("Failed to update framework for your org.")
}
} else {
alert.info("Updated usecase.")
}
})
.catch((error) => {
alert.error(error.toString());
//setFrameworkLoaded(true)
})
}
const setFrameworkItem = (data) => {
fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", {
method: "POST",
@@ -586,17 +630,18 @@ const Framework = (props) => {
const foundelement = cy.getElementById(discoveryData.id)
if (foundelement !== undefined && foundelement !== null) {
foundelement.data("large_image", newSelectedApp.image_url)
foundelement.data("text_margin_y", "60px")
foundelement.data("margin_x", "0px")
foundelement.data("margin_y", "50px")
foundelement.data("width", "85px")
foundelement.data("height", "85px")
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`)
}
setFrameworkItem(submitValue)
}, [newSelectedApp])
const isCloud =
window.location.host === "localhost:3002" ||
window.location.host === "shuffler.io";
@@ -649,7 +694,6 @@ const Framework = (props) => {
const [usecaseType, setUsecaseType] = React.useState(0)
const [selectedUsecase, setSelectedUsecase] = React.useState(selectedOption !== undefined ? selectedOption : "Phishing")
const elements = []
const surfaceColor = "#27292D"
@@ -680,12 +724,15 @@ const Framework = (props) => {
setSelectedUsecase(value)
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 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()
}
}
}
@@ -719,7 +766,6 @@ const Framework = (props) => {
if (cy !== undefined && cyDone && !animationStarted) {
const foundelement = cy.getElementById("CASES")
console.log("FOUND: ", foundelement)
if (foundelement !== undefined && foundelement !== null) {
setAnimationStarted(true)
@@ -819,6 +865,7 @@ const Framework = (props) => {
)
}
const onNodeSelect = (event) => {
const data = event.target.data();
console.log("Node: ", data)
@@ -841,7 +888,7 @@ const Framework = (props) => {
const onEdgeSelect = (event) => {
console.log(event)
if (event.target.data("human") === undefined) {
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()
@@ -854,9 +901,6 @@ const Framework = (props) => {
}
if (graphDone && cyDone === false) {
//const [cyDone, setCyDone] = React.useState(false)
console.log("IN CYDONe")
cy.fit(null, 200);
cy.on("select", "edge", (e) => onEdgeSelect(e));
cy.on("add", "edge", (e) => onEdgeAdded(e));
@@ -878,9 +922,9 @@ const Framework = (props) => {
const baselocationX = 285*scale
const baselocationY = 50*scale
const shiftmodifier = 3*scale
const svgSize = `${40*scale}px`
console.log("Framework: ", parsedFrameworkData)
const fontSize = `${12*scale}px`
const defaultSize = `${85*scale}px`
@@ -1217,6 +1261,27 @@ const Framework = (props) => {
}
changeUsecase(selectedUsecase, usecaseType)
if (inputUsecase !== undefined && inputUsecase !== null) {
console.log("Got usecase: ", inputUsecase)
for (var key in inputUsecase.process) {
if (inputUsecase.process[key].source === "" || inputUsecase.process[key].target === "") {
continue
}
console.log("Edge: ", inputUsecase.process[key])
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) {
@@ -1571,6 +1636,13 @@ const Framework = (props) => {
setCy(incy)
}}
/>
{isCloud && inputUsecase !== undefined && inputUsecase !== null && isLoggedIn === true && Object.keys(inputUsecase).length > 0 ?
<Button color="secondary" variant={"outlined"} style={{position: "absolute", bottom: -10, right: 0,}} onClick={() => {
setUsecaseItem(inputUsecase)
}}>
Save
</Button>
: null}
</div>
)
}
+5 -30
View File
@@ -165,6 +165,8 @@ const ParsedAction = (props) => {
actionDelayChange,
getParents,
isCloud,
lastSaved,
setLastSaved,
} = props;
//const theme = useTheme();
@@ -1487,6 +1489,9 @@ const ParsedAction = (props) => {
}
onBlur={(event) => {
baseHelperText = calculateHelpertext(event.target.value)
if (setLastSaved !== undefined) {
setLastSaved(false)
}
}}
/>
);
@@ -2201,35 +2206,6 @@ const ParsedAction = (props) => {
return null;
};
const expansionModal = (
<Dialog
disableEnforceFocus={false}
hideBackdrop={true}
open={expansionModalOpen}
onClose={() => {
setExpansionModalOpen(false);
}}
PaperProps={{
style: {
backgroundColor: theme.palette.surfaceColor,
color: "white",
minWidth: 600,
padding: 50,
pointerEvents: "auto",
maxHeight: 550,
overflowY: "auto",
overflowX: "hidden",
zIndex: 10012,
}
}}
>
<DialogTitle>
<span style={{ color: "white" }}>Workflow Variable</span>
</DialogTitle>
<DialogContent>Hello</DialogContent>
</Dialog>
);
//const CustomPopper = function (props) {
// const classes = useStyles()
// return <Popper {...props} className={classes.root} placement="bottom" />
@@ -2239,7 +2215,6 @@ const ParsedAction = (props) => {
return (
<div style={appApiViewStyle} id="parsed_action_view">
{expansionModal}
{hideExtraTypes === true ? null : (
<span>
<div style={{ display: "flex", minHeight: 40, marginBottom: 30 }}>
+116 -111
View File
@@ -12,6 +12,7 @@ import {
import Checkbox from '@mui/material/Checkbox';
import { orange } from '@mui/material/colors';
import { isMobile } from "react-device-detect"
import {
FullscreenExit as FullscreenExitIcon,
@@ -86,7 +87,7 @@ const CodeEditor = (props) => {
var popup = false
for(var ch=0; ch<code_line.length; ch++){
if(code_line[ch] == '$'){
if(code_line[ch] === '$'){
dollar_occurences.push(ch)
}
}
@@ -118,7 +119,7 @@ const CodeEditor = (props) => {
for(var occ = 0; occ<variable_ranges.length; occ++){
for(var occ1 = 0; occ1<variable_ranges[occ].length; occ1++){
// console.log(variable_ranges[occ][occ1])
if(loc == variable_ranges[occ][occ1]){
if(loc === variable_ranges[occ][occ1]){
popup = true
setCurrentLocation([line, dollar_occurences[occ]])
console.log("Current Location : "+dollar_occurences[occ])
@@ -172,7 +173,7 @@ const CodeEditor = (props) => {
// console.log()
// for (var j = 0; j < actionlist.length; j++) {
// if(found[i].slice(1,).toLowerCase() == actionlist[j].autocomplete.toLowerCase()){
// if(found[i].slice(1,).toLowerCase() === actionlist[j].autocomplete.toLowerCase()){
// input = input.replace(found[i], JSON.stringify(actionlist[j].example));
// console.log(input)
// console.log(actionlist[j].example)
@@ -182,7 +183,7 @@ const CodeEditor = (props) => {
var dollar_occurence = []
for(var ch=0; ch<current_code_line.length; ch++){
if(current_code_line[ch] == '$'){
if(current_code_line[ch] === '$'){
dollar_occurence.push(ch)
}
}
@@ -200,11 +201,11 @@ const CodeEditor = (props) => {
for (var occ = 0; occ<variable_occurence.length; occ++){
// value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: #8b8e26; border-radius: 4px; color: white"})
var correctVariable = actionlist.find(action => action.autocomplete.toLowerCase() === variable_occurence[occ].slice(1,).toLowerCase())
if(correctVariable == undefined) {
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: red; border-radius: 4px; color: white"})
if(correctVariable === undefined) {
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: #f86a3e; padding-top: 2px; padding-bottom: 2px; color: white"})
}
else{
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: #8b8e26; border-radius: 4px; color: white"})
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: #8b8e26; padding-top: 2px; padding-bottom: 2px; color: white"})
}
// console.log(correctVariables)
}
@@ -237,7 +238,13 @@ const CodeEditor = (props) => {
// console.log(currentLocation)
var code_lines = localcodedata.split('\n')
code_lines[currentLine] = code_lines[currentLine].slice(0,currentLocation[1]) + "$" + swapVariable + code_lines[currentLine].slice(currentLocation[1]+currentVariable.length,)
var parsedVariable = currentVariable
if (currentVariable === undefined || currentVariable === null) {
console.log("Location: ", currentLocation)
parsedVariable= "$"
}
code_lines[currentLine] = code_lines[currentLine].slice(0,currentLocation[1]) + "$" + swapVariable + code_lines[currentLine].slice(currentLocation[1]+parsedVariable.length,)
// console.log(code_lines)
var updatedCode = code_lines.join('\n')
// console.log(updatedCode)
@@ -255,7 +262,7 @@ const CodeEditor = (props) => {
// console.log(found[i]);
for (var j = 0; j < actionlist.length; j++) {
if(found[i].slice(1,).toLowerCase() == actionlist[j].autocomplete.toLowerCase()){
if(found[i].slice(1,).toLowerCase() === actionlist[j].autocomplete.toLowerCase()){
input = input.replace(found[i], JSON.stringify(actionlist[j].example));
// console.log(input)
// console.log(actionlist[j].example)
@@ -293,8 +300,8 @@ const CodeEditor = (props) => {
style: {
backgroundColor: theme.palette.surfaceColor,
color: "white",
minWidth: 600,
padding: 25,
minWidth: isMobile ? "100%" : 600,
padding: isMobile ? "25px 10px 25px 10px" : 25,
border: theme.palette.defaultBorder,
zIndex: 10012,
},
@@ -318,7 +325,7 @@ const CodeEditor = (props) => {
</DialogTitle>
<IconButton
style={{
marginLeft: 400,
marginLeft: isMobile ? "80%" : 400,
height: 50,
width: 50,
}}
@@ -393,7 +400,7 @@ const CodeEditor = (props) => {
style={{
margin: 10,
padding: 10,
width: 250,
width: isMobile ? "100%" : 250,
// textOverflow: 'ellipsis'
}}
>
@@ -478,10 +485,10 @@ const CodeEditor = (props) => {
Dark Theme
<Checkbox
onClick={() => {
if (codeTheme == "gruvbox-dark") {
if (codeTheme === "gruvbox-dark") {
setcodeTheme("duotone-light")
}
if (codeTheme == "duotone-light"){
if (codeTheme === "duotone-light"){
setcodeTheme("gruvbox-dark")
}
}}
@@ -500,68 +507,70 @@ const CodeEditor = (props) => {
</div>
<div>
<DialogTitle
style={{
paddingTop: 30,
paddingLeft: 10,
}}
>
<span
{isMobile ? null :
<DialogTitle
style={{
color: "white"
paddingTop: 30,
paddingLeft: 10,
}}
>
Output
</span>
</DialogTitle>
{validation === true ?
<ReactJson
src={expOutput}
theme={theme.palette.jsonTheme}
style={{
borderRadius: 5,
border: `2px solid ${theme.palette.inputColor}`,
padding: 10,
maxHeight: 250,
minheight: 250,
overflow: "auto",
}}
collapsed={false}
enableClipboard={(copy) => {
//handleReactJsonClipboard(copy);
}}
displayDataTypes={false}
onSelect={(select) => {
//HandleJsonCopy(validate.result, select, "exec");
}}
name={"JSON autocompletion"}
/>
:
<p
id='expOutput'
style={{
whiteSpace: "pre-wrap",
color: "#f85a3e",
fontFamily: "monospace",
backgroundColor: "#282828",
padding: 20,
marginTop: -2,
border: `2px solid ${theme.palette.inputColor}`,
borderRadius: theme.palette.borderRadius,
maxHeight: 250,
overflow: "auto",
}}
>
{expOutput}
</p>
<span
style={{
color: "white"
}}
>
Output
</span>
</DialogTitle>
}
{isMobile ? null :
validation === true ?
<ReactJson
src={expOutput}
theme={theme.palette.jsonTheme}
style={{
borderRadius: 5,
border: `2px solid ${theme.palette.inputColor}`,
padding: 10,
maxHeight: 250,
minheight: 250,
overflow: "auto",
}}
collapsed={false}
enableClipboard={(copy) => {
//handleReactJsonClipboard(copy);
}}
displayDataTypes={false}
onSelect={(select) => {
//HandleJsonCopy(validate.result, select, "exec");
}}
name={"JSON autocompletion"}
/>
:
<p
id='expOutput'
style={{
whiteSpace: "pre-wrap",
color: "#f85a3e",
fontFamily: "monospace",
backgroundColor: "#282828",
padding: 20,
marginTop: -2,
border: `2px solid ${theme.palette.inputColor}`,
borderRadius: theme.palette.borderRadius,
maxHeight: 250,
overflow: "auto",
}}
>
{expOutput}
</p>
}
<p
style={{
color: "white",
fontFamily: "monospace",
padding: 20,
paddingLeft: 10,
marginTop: -15,
margin: 20,
marginTop: 30,
}}
>
JSON Validation: {validation ? "Correct" : "Incorrect"}
@@ -573,48 +582,44 @@ const CodeEditor = (props) => {
display: 'flex',
}}
>
<div>
<button
style={{
color: "white",
background: "#383b49",
border: "none",
height: 35,
width: 290,
marginLeft: 5,
marginTop: 20,
cursor: "pointer"
}}
onClick={() => {
setExpansionModalOpen(false)
}}
>
Cancel
</button>
</div>
<div>
<button
style={{
color: "white",
background: "#f85a3e",
border: "none",
height: 35,
width: 290,
marginLeft: 10,
marginTop: 20,
cursor: "pointer"
}}
onClick={(event) => {
// console.log(codedata)
// console.log(fieldCount)
changeActionParameterCodeMirror(event, fieldCount, localcodedata)
setExpansionModalOpen(false)
setcodedata(localcodedata)
}}
>
Done
</button>
</div>
<button
style={{
color: "white",
background: "#383b49",
border: "none",
height: 35,
flex: 1,
marginLeft: 5,
marginTop: 20,
cursor: "pointer"
}}
onClick={() => {
setExpansionModalOpen(false)
}}
>
Cancel
</button>
<button
style={{
color: "white",
background: "#f85a3e",
border: "none",
height: 35,
flex: 1,
marginLeft: 10,
marginTop: 20,
cursor: "pointer"
}}
onClick={(event) => {
// console.log(codedata)
// console.log(fieldCount)
changeActionParameterCodeMirror(event, fieldCount, localcodedata)
setExpansionModalOpen(false)
setcodedata(localcodedata)
}}
>
Done
</button>
</div>
</Dialog>)
}