Added file category listing with new app options to work with detections in the future
This commit is contained in:
@@ -1,15 +1,14 @@
|
|||||||
# This can be done in the dockerpush workflow itself
|
# This can be done in the dockerpush workflow itself
|
||||||
|
# Done manually for now since GHCR isn't being pushed to easily with the current Github action CI. Nightly = Latest IF we run hotfixes on latest
|
||||||
|
|
||||||
docker pull frikky/shuffle-backend:nightly
|
docker pull frikky/shuffle-backend:nightly
|
||||||
docker pull frikky/shuffle-frontend:nightly
|
docker pull frikky/shuffle-frontend:nightly
|
||||||
|
|
||||||
#docker tag frikky/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:nightly
|
docker tag frikky/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:latest
|
||||||
#docker tag frikky/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:nightly
|
docker tag frikky/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:latest
|
||||||
#
|
|
||||||
#docker push ghcr.io/frikky/shuffle-backend:nightly
|
|
||||||
#docker push ghcr.io/frikky/shuffle-frontend:nightly
|
|
||||||
|
|
||||||
docker tag frikky/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:nightly
|
|
||||||
docker tag frikky/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:nightly
|
|
||||||
|
|
||||||
docker push ghcr.io/frikky/shuffle-backend:nightly
|
docker push ghcr.io/frikky/shuffle-backend:nightly
|
||||||
docker push ghcr.io/frikky/shuffle-frontend:nightly
|
docker push ghcr.io/frikky/shuffle-frontend:nightly
|
||||||
|
|
||||||
|
docker push ghcr.io/frikky/shuffle-backend:latest
|
||||||
|
docker push ghcr.io/frikky/shuffle-frontend:latest
|
||||||
|
|||||||
@@ -1022,6 +1022,33 @@ class AppBase:
|
|||||||
self.logger.info("\nLOOP: %s\nRESULTS: %s" % (loop_wrapper, results))
|
self.logger.info("\nLOOP: %s\nRESULTS: %s" % (loop_wrapper, results))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
# Downloads all files from a namespace
|
||||||
|
# Currently only working on local version of Shuffle
|
||||||
|
def get_file_category_ids(self, category):
|
||||||
|
org_id = self.full_execution["workflow"]["execution_org"]["id"]
|
||||||
|
|
||||||
|
get_path = "/api/v1/files/namespaces/%s?execution_id=%s&ids=true" % (category, self.full_execution["execution_id"])
|
||||||
|
headers = {
|
||||||
|
"Authorization": "Bearer %s" % self.authorization
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = requests.get("%s%s" % (self.url, get_path), headers=headers)
|
||||||
|
return ret.json()
|
||||||
|
#if ret1.status_code != 200:
|
||||||
|
# return {
|
||||||
|
# "success": False,
|
||||||
|
# "reason": "Status code is %d from backend for category %s" % category,
|
||||||
|
# "list": [],
|
||||||
|
# }
|
||||||
|
|
||||||
|
#return {
|
||||||
|
# "success": True,
|
||||||
|
# "ids": ret1.json(),
|
||||||
|
#}
|
||||||
|
|
||||||
|
def get_file_namespace_ids(self, namespace):
|
||||||
|
return get_file_category_ids(self, namespace)
|
||||||
|
|
||||||
# Downloads all files from a namespace
|
# Downloads all files from a namespace
|
||||||
# Currently only working on local version of Shuffle
|
# Currently only working on local version of Shuffle
|
||||||
def get_file_namespace(self, namespace):
|
def get_file_namespace(self, namespace):
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ const openApiFieldDesc = "Generated by OpenAPI body example";
|
|||||||
const ParsedAction = (props) => {
|
const ParsedAction = (props) => {
|
||||||
const {
|
const {
|
||||||
workflow,
|
workflow,
|
||||||
|
files,
|
||||||
setWorkflow,
|
setWorkflow,
|
||||||
setAction,
|
setAction,
|
||||||
setSelectedAction,
|
setSelectedAction,
|
||||||
@@ -1300,6 +1301,7 @@ const ParsedAction = (props) => {
|
|||||||
data.value = data.example;
|
data.value = data.example;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (data.value.length === 0) {
|
if (data.value.length === 0) {
|
||||||
if (data.name.toLowerCase() === "headers") {
|
if (data.name.toLowerCase() === "headers") {
|
||||||
console.log("Should show headers field instead with + and -!")
|
console.log("Should show headers field instead with + and -!")
|
||||||
@@ -1878,6 +1880,14 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
// Basic helpertext
|
// Basic helpertext
|
||||||
|
|
||||||
|
if (data.name.toLowerCase() === "file_category") {
|
||||||
|
//selectedActionParameters[count].options.length > 0
|
||||||
|
console.log("FileS: ", files)
|
||||||
|
if (files.namespaces !== undefined && files.namespaces !== null && files.namespaces.length > 0) {
|
||||||
|
data.options = files.namespaces
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//const keywords = ["len", "lower", "upper", "trim", "split", "length", "number", "parse", "join"]
|
//const keywords = ["len", "lower", "upper", "trim", "split", "length", "number", "parse", "join"]
|
||||||
if (
|
if (
|
||||||
selectedActionParameters[count].schema !== undefined &&
|
selectedActionParameters[count].schema !== undefined &&
|
||||||
@@ -1942,16 +1952,22 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
} else if (
|
} else if (
|
||||||
selectedActionParameters[count].options !== undefined &&
|
(data.options !== undefined &&
|
||||||
|
data.options !== null &&
|
||||||
|
data.options.length > 0)
|
||||||
|
||
|
||||||
|
(selectedActionParameters[count].options !== undefined &&
|
||||||
selectedActionParameters[count].options !== null &&
|
selectedActionParameters[count].options !== null &&
|
||||||
selectedActionParameters[count].options.length > 0
|
selectedActionParameters[count].options.length > 0)
|
||||||
) {
|
) {
|
||||||
|
const parsedoptions = data.options !== undefined ? data.options : selectedActionParameters[count].options
|
||||||
|
|
||||||
if (selectedActionParameters[count].value === "") {
|
if (selectedActionParameters[count].value === "") {
|
||||||
// && selectedActionParameters[count].required) {
|
// && selectedActionParameters[count].required) {
|
||||||
// Rofl, dirty workaround :)
|
// Rofl, dirty workaround :)
|
||||||
const e = {
|
const e = {
|
||||||
target: {
|
target: {
|
||||||
value: selectedActionParameters[count].options[0],
|
value: parsedoptions.options[0],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1982,7 +1998,7 @@ const ParsedAction = (props) => {
|
|||||||
borderRadius: theme.palette.borderRadius,
|
borderRadius: theme.palette.borderRadius,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedActionParameters[count].options.map(
|
{parsedoptions.map(
|
||||||
(data, index) => {
|
(data, index) => {
|
||||||
const split_data = data.split("||");
|
const split_data = data.split("||");
|
||||||
var viewed_data = data;
|
var viewed_data = data;
|
||||||
@@ -2014,6 +2030,7 @@ const ParsedAction = (props) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Shows nested list of nodes > their JSON lists
|
// Shows nested list of nodes > their JSON lists
|
||||||
const ActionlistWrapper = (props) => {
|
const ActionlistWrapper = (props) => {
|
||||||
const handleMenuClose = () => {
|
const handleMenuClose = () => {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import { useNavigate, Link, useParams } from "react-router-dom";
|
|||||||
|
|
||||||
const liquidFilters = [
|
const liquidFilters = [
|
||||||
{"name": "Size", "value": "size", "example": ""},
|
{"name": "Size", "value": "size", "example": ""},
|
||||||
{"name": "Date", "value": `date: "%Y%M%d"`, "example": `{{ "now" | date: "%s" }}`},
|
{"name": "Date", "value": `date: "%Y%m%d"`, "example": `{{ "now" | date: "%s" }}`},
|
||||||
{"name": "Escape String", "value": `{{ \"\"\"'string with weird'" quotes\"\"\" | escape_string }}`, "example": ``},
|
{"name": "Escape String", "value": `{{ \"\"\"'string with weird'" quotes\"\"\" | escape_string }}`, "example": ``},
|
||||||
{"name": "Flatten", "value": `flatten`, "example": `{{ [1, [1, 2], [2, 3, 4]] | flatten }}`},
|
{"name": "Flatten", "value": `flatten`, "example": `{{ [1, [1, 2], [2, 3, 4]] | flatten }}`},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -513,7 +513,7 @@ const WelcomeForm = (props) => {
|
|||||||
}}>
|
}}>
|
||||||
Phishing
|
Phishing
|
||||||
</Button>
|
</Button>
|
||||||
<Button disabled={true} variant={defaultSearch === "Detection" ? "contained" : "outlined"} startIcon={<NewReleasesIcon />} style={newButtonStyle} onClick={() => {
|
<Button variant={defaultSearch === "Detection" ? "contained" : "outlined"} startIcon={<NewReleasesIcon />} style={newButtonStyle} onClick={() => {
|
||||||
setDefaultSearch("Detection")
|
setDefaultSearch("Detection")
|
||||||
setSelectionOpen(false)
|
setSelectionOpen(false)
|
||||||
|
|
||||||
@@ -525,7 +525,7 @@ const WelcomeForm = (props) => {
|
|||||||
}}>
|
}}>
|
||||||
Detection
|
Detection
|
||||||
</Button>
|
</Button>
|
||||||
<Button disabled={true} variant={defaultSearch === "Response" ? "contained" : "outlined"} startIcon={<NewReleasesIcon />} style={newButtonStyle} onClick={() => {
|
<Button variant={defaultSearch === "Response" ? "contained" : "outlined"} startIcon={<NewReleasesIcon />} style={newButtonStyle} onClick={() => {
|
||||||
setDefaultSearch("Response")
|
setDefaultSearch("Response")
|
||||||
setSelectionOpen(false)
|
setSelectionOpen(false)
|
||||||
|
|
||||||
|
|||||||
@@ -746,7 +746,7 @@ const Admin = (props) => {
|
|||||||
|
|
||||||
if (orgId.length === 0) {
|
if (orgId.length === 0) {
|
||||||
alert.error(
|
alert.error(
|
||||||
"Organization ID not defined. Please contact us on https://shuffler.io if this persists logout."
|
"Organization ID not defined (get deals). Please contact us on https://shuffler.io if this persists logout."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2693,6 +2693,22 @@ const Admin = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
|
{/*
|
||||||
|
<Tooltip
|
||||||
|
title={"Go to Organization document"}
|
||||||
|
style={{}}
|
||||||
|
aria-label={"Organization doc"}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
style={{ top: -10, right: 50, position: "absolute" }}
|
||||||
|
onClick={() => {
|
||||||
|
console.log("Should go to icon")
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FileCopyIcon style={{ color: "rgba(255,255,255,0.8)" }} />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
*/}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={"Copy Organization ID"}
|
title={"Copy Organization ID"}
|
||||||
style={{}}
|
style={{}}
|
||||||
|
|||||||
@@ -264,6 +264,11 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const [leftViewOpen, setLeftViewOpen] = React.useState(isMobile ? false : true);
|
const [leftViewOpen, setLeftViewOpen] = React.useState(isMobile ? false : true);
|
||||||
const [leftBarSize, setLeftBarSize] = React.useState(isMobile ? 0 : 350);
|
const [leftBarSize, setLeftBarSize] = React.useState(isMobile ? 0 : 350);
|
||||||
const [creatorProfile, setCreatorProfile] = React.useState({});
|
const [creatorProfile, setCreatorProfile] = React.useState({});
|
||||||
|
const [files, setFiles] = React.useState({
|
||||||
|
"namespaces": [
|
||||||
|
"default",
|
||||||
|
]
|
||||||
|
});
|
||||||
const [appGroup, setAppGroup] = React.useState([]);
|
const [appGroup, setAppGroup] = React.useState([]);
|
||||||
const [triggerGroup, setTriggerGroup] = React.useState([]);
|
const [triggerGroup, setTriggerGroup] = React.useState([]);
|
||||||
const [executionText, setExecutionText] = React.useState("");
|
const [executionText, setExecutionText] = React.useState("");
|
||||||
@@ -1677,6 +1682,43 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getFiles = () => {
|
||||||
|
fetch(globalUrl + "/api/v1/files", {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.log("Status not 200 for apps :O!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((responseJson) => {
|
||||||
|
if (responseJson.files !== undefined && responseJson.files !== null) {
|
||||||
|
setFiles(responseJson);
|
||||||
|
} else {
|
||||||
|
setFiles({"namespaces": []});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("NAMESPACES: ", responseJson.namespaces);
|
||||||
|
if (
|
||||||
|
responseJson.namespaces !== undefined &&
|
||||||
|
responseJson.namespaces !== null
|
||||||
|
) {
|
||||||
|
//setFileNamespaces(responseJson.namespaces);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
alert.error(error.toString());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getWorkflow = (workflow_id, sourcenode) => {
|
const getWorkflow = (workflow_id, sourcenode) => {
|
||||||
fetch(globalUrl + "/api/v1/workflows/" + workflow_id, {
|
fetch(globalUrl + "/api/v1/workflows/" + workflow_id, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -1745,8 +1787,14 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setTriggerGroup(appsFound)
|
setTriggerGroup(appsFound)
|
||||||
}
|
} else {
|
||||||
|
getAppAuthentication();
|
||||||
|
getEnvironments();
|
||||||
|
getWorkflowExecution(props.match.params.key, "");
|
||||||
|
getAvailableWorkflows(-1);
|
||||||
|
getSettings();
|
||||||
|
getFiles()
|
||||||
|
}
|
||||||
|
|
||||||
// Appends SUBFLOWS. Does NOT run during normal grabbing of workflows.
|
// Appends SUBFLOWS. Does NOT run during normal grabbing of workflows.
|
||||||
if (sourcenode.id !== undefined) {
|
if (sourcenode.id !== undefined) {
|
||||||
@@ -4598,11 +4646,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setFirstrequest(false);
|
setFirstrequest(false);
|
||||||
getWorkflow(props.match.params.key, {});
|
getWorkflow(props.match.params.key, {});
|
||||||
getApps();
|
getApps();
|
||||||
getAppAuthentication();
|
|
||||||
getEnvironments();
|
|
||||||
getWorkflowExecution(props.match.params.key, "");
|
|
||||||
getAvailableWorkflows(-1);
|
|
||||||
getSettings();
|
|
||||||
|
|
||||||
const cursearch =
|
const cursearch =
|
||||||
typeof window === "undefined" || window.location === undefined
|
typeof window === "undefined" || window.location === undefined
|
||||||
@@ -5327,7 +5370,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
description: "O365 email trigger",
|
description: "O365 email trigger",
|
||||||
trigger_type: "EMAIL",
|
trigger_type: "EMAIL",
|
||||||
errors: null,
|
errors: null,
|
||||||
is_valid: cloudSyncEnabled || isCloud ? true : false,
|
is_valid: isCloud ? true : false,
|
||||||
label: "Email",
|
label: "Email",
|
||||||
environment: "cloud",
|
environment: "cloud",
|
||||||
large_image:
|
large_image:
|
||||||
@@ -5341,7 +5384,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
description: "Gmail email trigger",
|
description: "Gmail email trigger",
|
||||||
trigger_type: "EMAIL",
|
trigger_type: "EMAIL",
|
||||||
errors: null,
|
errors: null,
|
||||||
is_valid: cloudSyncEnabled || isCloud ? true : false,
|
is_valid: isCloud ? true : false,
|
||||||
label: "Email",
|
label: "Email",
|
||||||
environment: "cloud",
|
environment: "cloud",
|
||||||
large_image:
|
large_image:
|
||||||
@@ -11177,6 +11220,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
defaultReturn = <ParsedAction
|
defaultReturn = <ParsedAction
|
||||||
id="rightside_subactions"
|
id="rightside_subactions"
|
||||||
|
files={files}
|
||||||
setShowVideo={setShowVideo}
|
setShowVideo={setShowVideo}
|
||||||
isCloud={isCloud}
|
isCloud={isCloud}
|
||||||
getParents={getParents}
|
getParents={getParents}
|
||||||
|
|||||||
Reference in New Issue
Block a user