#256: Added category dropdown to app editor
This commit is contained in:
+17
-13
@@ -541,9 +541,11 @@ class AppBase:
|
|||||||
print(action["parameters"])
|
print(action["parameters"])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
action["parameters"] = []
|
action["parameters"] = []
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
self.action = copy.deepcopy(action)
|
self.action = copy.deepcopy(action)
|
||||||
self.logger.info("ACTION RESULT (start): %s", action_result)
|
self.logger.info("Sending starting action result (EXECUTING)")
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -1473,10 +1475,10 @@ class AppBase:
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
print("Return value: %s" % value)
|
#print("Return value: %s" % value)
|
||||||
actionname = action["name"]
|
actionname = action["name"]
|
||||||
#print("Multicheck ", actualitem)
|
#print("Multicheck ", actualitem)
|
||||||
print("ITEM LENGTH: %d, Actual item: %s" % (len(actualitem), actualitem))
|
#print("ITEM LENGTH: %d, Actual item: %s" % (len(actualitem), actualitem))
|
||||||
if len(actualitem) > 0:
|
if len(actualitem) > 0:
|
||||||
multiexecution = True
|
multiexecution = True
|
||||||
|
|
||||||
@@ -1636,14 +1638,14 @@ class AppBase:
|
|||||||
|
|
||||||
# With this parameter ready, add it to... a greater list of parameters. Rofl
|
# With this parameter ready, add it to... a greater list of parameters. Rofl
|
||||||
print("LENGTH OF ARR: %d" % len(resultarray))
|
print("LENGTH OF ARR: %d" % len(resultarray))
|
||||||
print("RESULTARRAY: %s" % resultarray)
|
#print("RESULTARRAY: %s" % resultarray)
|
||||||
if resultarray not in multi_execution_lists:
|
if resultarray not in multi_execution_lists:
|
||||||
multi_execution_lists.append(resultarray)
|
multi_execution_lists.append(resultarray)
|
||||||
|
|
||||||
multi_parameters[parameter["name"]] = resultarray
|
multi_parameters[parameter["name"]] = resultarray
|
||||||
else:
|
else:
|
||||||
# Parses things like int(value)
|
# Parses things like int(value)
|
||||||
print("Normal parsing (not looping) with data %s" % value)
|
print("Normal parsing (not looping)")#with data %s" % value)
|
||||||
value = parse_wrapper_start(value)
|
value = parse_wrapper_start(value)
|
||||||
|
|
||||||
if parameter["id"] == "body_replacement":
|
if parameter["id"] == "body_replacement":
|
||||||
@@ -1663,7 +1665,7 @@ class AppBase:
|
|||||||
# print("PARAM: %s" % parameter)
|
# print("PARAM: %s" % parameter)
|
||||||
#if param.id == "body_replacement":
|
#if param.id == "body_replacement":
|
||||||
|
|
||||||
print("POST data value: %s" % value)
|
#print("POST data value: %s" % value)
|
||||||
params[parameter["name"]] = value
|
params[parameter["name"]] = value
|
||||||
multi_parameters[parameter["name"]] = value
|
multi_parameters[parameter["name"]] = value
|
||||||
|
|
||||||
@@ -1719,9 +1721,9 @@ class AppBase:
|
|||||||
#})
|
#})
|
||||||
|
|
||||||
#print("[INFO] APP_SDK DONE: Starting NORMAL execution of function")
|
#print("[INFO] APP_SDK DONE: Starting NORMAL execution of function")
|
||||||
#print("[INFO] Running with params (0): %s" % params)
|
print("[INFO] Running execition\n")
|
||||||
newres = await func(**params)
|
newres = await func(**params)
|
||||||
print("[INFO] Returned from execution:", newres)
|
print("\n[INFO] Returned from execution:", newres)
|
||||||
if isinstance(newres, tuple):
|
if isinstance(newres, tuple):
|
||||||
print("[INFO] Handling return as tuple")
|
print("[INFO] Handling return as tuple")
|
||||||
# Handles files.
|
# Handles files.
|
||||||
@@ -1940,16 +1942,16 @@ class AppBase:
|
|||||||
logger = logging.getLogger(f"{cls.__name__}")
|
logger = logging.getLogger(f"{cls.__name__}")
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
print("Started execution: %s!!" % cls)
|
#print("Started execution: %s!!" % cls)
|
||||||
print("Action: %s" % action)
|
#print("Action: %s" % action)
|
||||||
#if isinstance(cls, object):
|
#if isinstance(cls, object):
|
||||||
# self.action = cls
|
# self.action = cls
|
||||||
|
|
||||||
# Authorization for the app/function to control the workflow
|
|
||||||
# Function will crash if its wrong, which it probably should.
|
|
||||||
app = cls(redis=None, logger=logger, console_logger=logger)
|
app = cls(redis=None, logger=logger, console_logger=logger)
|
||||||
|
|
||||||
if isinstance(action, object):
|
if isinstance(action, str):
|
||||||
|
print("Normal execution. Action is a string.")
|
||||||
|
elif isinstance(action, object):
|
||||||
app.action = action
|
app.action = action
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -1967,5 +1969,7 @@ class AppBase:
|
|||||||
app.base_url = action["base_url"]
|
app.base_url = action["base_url"]
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
print("ACTION TYPE (unhandled): %s" % type(action))
|
||||||
|
|
||||||
await app.execute_action(app.action)
|
await app.execute_action(app.action)
|
||||||
|
|||||||
@@ -6615,7 +6615,7 @@ func healthCheckHandler(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
// Creates osfs from folderpath with a basepath as directory base
|
// Creates osfs from folderpath with a basepath as directory base
|
||||||
func createFs(basepath, pathname string) (billy.Filesystem, error) {
|
func createFs(basepath, pathname string) (billy.Filesystem, error) {
|
||||||
log.Printf("base: %s, pathname: %s", basepath, pathname)
|
log.Printf("[INFO] MemFS base: %s, pathname: %s", basepath, pathname)
|
||||||
|
|
||||||
fs := memfs.New()
|
fs := memfs.New()
|
||||||
err := filepath.Walk(pathname,
|
err := filepath.Walk(pathname,
|
||||||
@@ -6676,19 +6676,19 @@ func handleAppHotload(location string, forceUpdate bool) error {
|
|||||||
log.Printf("Failed memfs creation - probably bad path: %s", err)
|
log.Printf("Failed memfs creation - probably bad path: %s", err)
|
||||||
return errors.New(fmt.Sprintf("Failed to find directory %s", location))
|
return errors.New(fmt.Sprintf("Failed to find directory %s", location))
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Memfs creation from %s done", location)
|
log.Printf("[INFO] Memfs creation from %s done", location)
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, err := fs.ReadDir("")
|
dir, err := fs.ReadDir("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed reading folder: %s", err)
|
log.Printf("[WARNING] Failed reading folder: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//log.Printf("Reading app folder: %#v", dir)
|
//log.Printf("Reading app folder: %#v", dir)
|
||||||
_, _, err = iterateAppGithubFolders(fs, dir, "", "", forceUpdate)
|
_, _, err = iterateAppGithubFolders(fs, dir, "", "", forceUpdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Err: %s", err)
|
log.Printf("[WARNING] Githubfolders error: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -820,7 +820,7 @@ func handleGetWorkflowqueue(resp http.ResponseWriter, request *http.Request) {
|
|||||||
if len(executionRequests.Data) == 0 {
|
if len(executionRequests.Data) == 0 {
|
||||||
executionRequests.Data = []ExecutionRequest{}
|
executionRequests.Data = []ExecutionRequest{}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[INFO] Executionrequests: %d", len(executionRequests.Data))
|
log.Printf("[INFO] Executionrequests (%s): %d", id, len(executionRequests.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
newjson, err := json.Marshal(executionRequests)
|
newjson, err := json.Marshal(executionRequests)
|
||||||
@@ -3135,7 +3135,6 @@ func handleExecution(id string, workflow Workflow, request *http.Request) (Workf
|
|||||||
|
|
||||||
// This one doesn't really matter.
|
// This one doesn't really matter.
|
||||||
log.Printf("[INFO] Running POST execution with body of length %d", len(string(body)))
|
log.Printf("[INFO] Running POST execution with body of length %d", len(string(body)))
|
||||||
a
|
|
||||||
if body[0] == 34 && body[len(body)-1] == 34 {
|
if body[0] == 34 && body[len(body)-1] == 34 {
|
||||||
body = body[1 : len(body)-1]
|
body = body[1 : len(body)-1]
|
||||||
}
|
}
|
||||||
@@ -5958,7 +5957,7 @@ func handleAppHotloadRequest(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Starting app hotloading")
|
log.Printf("[INFO] Starting app hotloading")
|
||||||
|
|
||||||
// Just need to be logged in
|
// Just need to be logged in
|
||||||
// FIXME - should have some permissions?
|
// FIXME - should have some permissions?
|
||||||
@@ -5983,7 +5982,7 @@ func handleAppHotloadRequest(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Hotloading from %s", location)
|
log.Printf("[INFO] Hotloading from %s", location)
|
||||||
err = handleAppHotload(location, true)
|
err = handleAppHotload(location, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed app hotload: %s", err)
|
log.Printf("Failed app hotload: %s", err)
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ const AngularWorkflow = (props) => {
|
|||||||
const [workflow, setWorkflow] = React.useState({});
|
const [workflow, setWorkflow] = React.useState({});
|
||||||
const [userSettings, setUserSettings] = React.useState({});
|
const [userSettings, setUserSettings] = React.useState({});
|
||||||
const [subworkflow, setSubworkflow] = React.useState({});
|
const [subworkflow, setSubworkflow] = React.useState({});
|
||||||
|
const [subworkflowStartnode, setSubworkflowStartnode] = React.useState("");
|
||||||
const [leftViewOpen, setLeftViewOpen] = React.useState(true);
|
const [leftViewOpen, setLeftViewOpen] = React.useState(true);
|
||||||
const [leftBarSize, setLeftBarSize] = React.useState(350)
|
const [leftBarSize, setLeftBarSize] = React.useState(350)
|
||||||
const [executionText, setExecutionText] = React.useState("");
|
const [executionText, setExecutionText] = React.useState("");
|
||||||
@@ -783,8 +784,8 @@ const AngularWorkflow = (props) => {
|
|||||||
//alert.success("Successfully saved workflow")
|
//alert.success("Successfully saved workflow")
|
||||||
setSavingState(1)
|
setSavingState(1)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setSavingState(0)
|
setSavingState(0)
|
||||||
}, 3000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -830,9 +831,9 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (executionArgument.length > 0) {
|
if (executionArgument.length > 0) {
|
||||||
alert.success("Starting execution WITH an execution argument")
|
//alert.success("Starting execution WITH an execution argument")
|
||||||
} else {
|
} else {
|
||||||
alert.success("Starting execution")
|
//alert.success("Starting execution")
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {"execution_argument": executionArgument, "start": startNode}
|
const data = {"execution_argument": executionArgument, "start": startNode}
|
||||||
@@ -5154,6 +5155,7 @@ const AngularWorkflow = (props) => {
|
|||||||
setUpdate(Math.random())
|
setUpdate(Math.random())
|
||||||
workflow.triggers[selectedTriggerIndex].parameters[0].value = e.target.value.id
|
workflow.triggers[selectedTriggerIndex].parameters[0].value = e.target.value.id
|
||||||
setWorkflow(workflow)
|
setWorkflow(workflow)
|
||||||
|
setSubworkflowStartnode(e.target.value.start)
|
||||||
}}
|
}}
|
||||||
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
||||||
>
|
>
|
||||||
@@ -5170,9 +5172,9 @@ const AngularWorkflow = (props) => {
|
|||||||
})}
|
})}
|
||||||
</Select>
|
</Select>
|
||||||
}
|
}
|
||||||
{/*subworkflow === undefined || subworkflow === null || subworkflow.id === undefined ? null :
|
{/*subworkflow === undefined || subworkflow === null || subworkflow.id === undefined || subworkflow.actions === null || subworkflow.actions === undefined || subworkflow.actions.length === 0 ? null :
|
||||||
<Select
|
<Select
|
||||||
value={subworkflow}
|
value={subworkflowStartnode}
|
||||||
SelectDisplayProps={{
|
SelectDisplayProps={{
|
||||||
style: {
|
style: {
|
||||||
marginLeft: 10,
|
marginLeft: 10,
|
||||||
@@ -5181,21 +5183,24 @@ const AngularWorkflow = (props) => {
|
|||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSubworkflow(e.target.value)
|
console.log("Change startnode to" + e.target)
|
||||||
setUpdate(Math.random())
|
//setSubworkflow(e.target.value)
|
||||||
workflow.triggers[selectedTriggerIndex].parameters[0].value = e.target.value.id
|
//setUpdate(Math.random())
|
||||||
setWorkflow(workflow)
|
//workflow.triggers[selectedTriggerIndex].parameters[0].value = e.target.value.id
|
||||||
|
//const [subworkflowStartnode, setSubworkflowStartnode] = React.useState("");
|
||||||
|
//setWorkflow(workflow)
|
||||||
}}
|
}}
|
||||||
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
||||||
>
|
>
|
||||||
{workflows.map((data, index) => {
|
{subworkflow.actions.map((data, index) => {
|
||||||
|
console.log(data)
|
||||||
if (data.id === workflow.id) {
|
if (data.id === workflow.id) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem key={index} style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
<MenuItem key={index} style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||||
{data.name}
|
{data.index}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -444,6 +444,10 @@ const AppCreator = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.info["x-categories"] !== undefined && data.info["x-categories"].length > 0) {
|
if (data.info["x-categories"] !== undefined && data.info["x-categories"].length > 0) {
|
||||||
|
if (typeof(data.info["x-categories"]) == "array") {
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
setNewWorkflowCategories(data.info["x-categories"])
|
setNewWorkflowCategories(data.info["x-categories"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1991,31 +1995,20 @@ const AppCreator = (props) => {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
|
||||||
|
const categories = [
|
||||||
|
"Communication",
|
||||||
|
"Cases",
|
||||||
|
"EDR",
|
||||||
|
"Intel",
|
||||||
|
"SIEM",
|
||||||
|
"Network",
|
||||||
|
"Assets",
|
||||||
|
"Other",
|
||||||
|
]
|
||||||
const tagView =
|
const tagView =
|
||||||
<div style={{color: "white"}}>
|
<div style={{color: "white"}}>
|
||||||
<h2>Tags</h2>
|
{/*
|
||||||
<ChipInput
|
|
||||||
style={{marginTop: 10}}
|
|
||||||
InputProps={{
|
|
||||||
style:{
|
|
||||||
color: "white",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
placeholder="Tags"
|
|
||||||
color="primary"
|
|
||||||
fullWidth
|
|
||||||
value={newWorkflowTags}
|
|
||||||
onAdd={(chip) => {
|
|
||||||
newWorkflowTags.push(chip)
|
|
||||||
setNewWorkflowTags(newWorkflowTags)
|
|
||||||
setUpdate("added"+chip)
|
|
||||||
}}
|
|
||||||
onDelete={(chip, index) => {
|
|
||||||
newWorkflowTags.splice(index, 1)
|
|
||||||
setNewWorkflowTags(newWorkflowTags)
|
|
||||||
setUpdate("delete "+chip)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ChipInput
|
<ChipInput
|
||||||
style={{marginTop: 10}}
|
style={{marginTop: 10}}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -2038,6 +2031,51 @@ const AppCreator = (props) => {
|
|||||||
setUpdate("delete "+chip)
|
setUpdate("delete "+chip)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
*/}
|
||||||
|
<h4>Categories</h4>
|
||||||
|
<Select
|
||||||
|
fullWidth
|
||||||
|
SelectDisplayProps={{
|
||||||
|
style: {
|
||||||
|
marginLeft: 10,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onChange={(e) => {
|
||||||
|
setNewWorkflowCategories([e.target.value])
|
||||||
|
setUpdate("added "+e.target.value)
|
||||||
|
}}
|
||||||
|
value={newWorkflowCategories.length === 0 ? "Select a category" : newWorkflowCategories[0]}
|
||||||
|
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
||||||
|
>
|
||||||
|
{categories.map(data => (
|
||||||
|
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||||
|
{data}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
<h4>Tags</h4>
|
||||||
|
<ChipInput
|
||||||
|
style={{marginTop: 10}}
|
||||||
|
InputProps={{
|
||||||
|
style:{
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
placeholder="Tags"
|
||||||
|
color="primary"
|
||||||
|
fullWidth
|
||||||
|
value={newWorkflowTags}
|
||||||
|
onAdd={(chip) => {
|
||||||
|
newWorkflowTags.push(chip)
|
||||||
|
setNewWorkflowTags(newWorkflowTags)
|
||||||
|
setUpdate("added"+chip)
|
||||||
|
}}
|
||||||
|
onDelete={(chip, index) => {
|
||||||
|
newWorkflowTags.splice(index, 1)
|
||||||
|
setNewWorkflowTags(newWorkflowTags)
|
||||||
|
setUpdate("delete "+chip)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
const actionView =
|
const actionView =
|
||||||
|
|||||||
Reference in New Issue
Block a user