Fixed some frontend things for release and orborus is now better by default

This commit is contained in:
Frikky
2023-10-18 14:58:36 +02:00
parent 595c217a7c
commit 614e39da70
11 changed files with 378 additions and 199 deletions
+4 -3
View File
@@ -228,15 +228,16 @@ const parseCurl = (s) => {
// Basically CRUD for each category + special
export const appCategories = [
{
"name": "Communication",
"name": "Communication",
"color": "#FFC107",
"icon": "communication",
"action_labels": ["List Messages", "Send Message", "Get Message", "Search messages", "List Attachments", "Get Attachment", "Get Contact"],
}, {
},
{
"name": "SIEM",
"color": "#FFC107",
"icon": "siem",
"action_labels": ["Search", "List Alerts", "Close Alert", "Get Alert", "Create detection", "Add to lookup list",],
"action_labels": ["Search", "List Alerts", "Close Alert", "Get Alert", "Create detection", "Add to lookup list", "Isolate endpoint",],
}, {
"name": "Eradication",
"color": "#FFC107",
+76 -9
View File
@@ -287,6 +287,7 @@ const Apps = (props) => {
const [selectedAction, setSelectedAction] = React.useState({});
const [searchBackend, setSearchBackend] = React.useState(false);
const [searchableApps, setSearchableApps] = React.useState([]);
const [publishModalOpen, setPublishModalOpen] = React.useState(false);
const [openApi, setOpenApi] = React.useState("");
const [openApiData, setOpenApiData] = React.useState("");
@@ -441,6 +442,7 @@ const Apps = (props) => {
if (privateapps.length > 0) {
if (selectedApp.id === undefined || selectedApp.id === null) {
setSelectedApp(privateapps[0]);
setSharingConfiguration(privateapps[0].sharing === true ? "public" : "you")
}
if (
@@ -646,6 +648,7 @@ const Apps = (props) => {
if (selectedApp.id !== data.id) {
data.name = newAppname;
setSelectedApp(data);
setSharingConfiguration(data.sharing === true ? "public" : "you")
if (
data.actions !== undefined &&
@@ -658,7 +661,7 @@ const Apps = (props) => {
}
if (data.sharing) {
setSharingConfiguration(isCloud ? "public" : "everyone");
setSharingConfiguration("public");
}
}
}}
@@ -999,11 +1002,11 @@ const Apps = (props) => {
);
};
const userRoles = ["you", isCloud ? "public" : "everyone"];
const userRoles = ["you", "public"];
// Admin in org or creator of app
// FIXME: Missing check for if same creator account
const canEditApp = userdata !== undefined && (userdata.admin === "true" || userdata.id === selectedApp.owner || selectedApp.owner === "" || (userdata.admin === "true" && userdata.active_org.id === selectedApp.reference_org)) || !selectedApp.generated
// Admin in org or creator of app
// FIXME: Missing check for if same creator account
const canEditApp = userdata !== undefined && (userdata.admin === "true" || userdata.id === selectedApp.owner || selectedApp.owner === "" || (userdata.admin === "true" && userdata.active_org.id === selectedApp.reference_org)) || !selectedApp.generated
//fetch(globalUrl+"/api/v1/get_openapi/"+urlParams.get("id"),
var baseInfo =
@@ -1054,6 +1057,7 @@ const Apps = (props) => {
console.log("New version: ", newversion);
selectedApp.app_version = selectedApp.app_version;
setSelectedApp(selectedApp);
setSharingConfiguration(selectedApp.sharing === true ? "public" : "you")
if (newversion !== undefined && newversion !== null) {
getApp(newversion.id, true);
@@ -1156,17 +1160,22 @@ const Apps = (props) => {
<Select
value={sharingConfiguration}
onChange={(event) => {
toast("Changing sharing to " + event.target.value);
setSharingConfiguration(event.target.value);
if (event.target.value === "you") {
toast("Changing sharing to " + event.target.value);
updateAppField(selectedApp.id, "sharing", false);
} else if (
event.target.value === "everyone" ||
event.target.value === "public"
) {
updateAppField(selectedApp.id, "sharing", true);
if (!isCloud) {
setPublishModalOpen(true)
} else {
updateAppField(selectedApp.id, "sharing", true);
}
} else {
console.log(
"Can't handle value for sharing: ",
@@ -2247,6 +2256,7 @@ const Apps = (props) => {
setSelectedAction({});
}
setSelectedApp(responseJson);
setSharingConfiguration(responseJson.sharing === true ? "public" : "you")
}
})
.catch((error) => {
@@ -2282,6 +2292,7 @@ const Apps = (props) => {
const data = {};
data[fieldname] = fieldvalue;
console.log("DATA: ", data);
fetch(globalUrl + "/api/v1/apps/" + app_id, {
@@ -2305,8 +2316,8 @@ const Apps = (props) => {
if (responseJson.reason !== undefined && responseJson.reason !== null) {
toast("Error: "+responseJson.reason);
} else {
toast("Error updating app configuration");
}
toast("Error updating app configuration. Are you the owner of this app?");
}
}
})
.catch((error) => {
@@ -2507,6 +2518,61 @@ const Apps = (props) => {
setLoadAppsModalOpen(false);
};
const publishModal = publishModalOpen ? (
<Dialog
open={publishModalOpen}
onClose={() => {
setPublishModalOpen(false);
}}
PaperProps={{
style: {
backgroundColor: theme.palette.surfaceColor,
color: "white",
minWidth: 500,
padding: 50,
},
}}
>
<DialogTitle style={{ marginBottom: 0 }}>
<div style={{ textAlign: "center", color: "rgba(255,255,255,0.9)" }}>
Are you sure you want to PUBLISH this app?
</div>
</DialogTitle>
<DialogContent
style={{ color: "rgba(255,255,255,0.65)", textAlign: "center" }}
>
<div>
<Typography variant="body1" style={{ marginBottom: 20 }}>
Before publishing, make sure to sanitize the App for anything you don't want public.
</Typography>
<Typography variant="body1" style={{ marginBottom: 20 }}>
The published App is yours, and you can always change your public Apps after they are released.
</Typography>
</div>
<Button
variant="contained"
style={{}}
onClick={() => {
updateAppField(selectedApp.id, "sharing", true);
setPublishModalOpen(false);
}}
color="primary"
>
Yes
</Button>
<Button
style={{}}
onClick={() => {
setPublishModalOpen(false);
}}
color="primary"
>
No
</Button>
</DialogContent>
</Dialog>
) : null;
const deleteModal = deleteModalOpen ? (
<Dialog
open={deleteModalOpen}
@@ -2937,6 +3003,7 @@ const Apps = (props) => {
<div>
{appView}
{modalView}
{publishModal}
{generateAppView}
{appsModalLoad}
{deleteModal}
+217 -57
View File
@@ -12,6 +12,7 @@ import WorkflowTemplatePopup from "../components/WorkflowTemplatePopup.jsx";
//import { Line, Bar } from "react-chartjs-2";
//import { useAlert
import { ToastContainer, toast } from "react-toastify"
import { parsedDatatypeImages } from "../components/AppFramework.jsx"
import {
Autocomplete,
@@ -159,12 +160,165 @@ const UsecaseListComponent = ({userdata, keys, isCloud, globalUrl, frameworkData
return null
}
const parseUsecase = (parsedUsecase, subcase) => {
console.log("parseUsecase: ", parsedUsecase, subcase)
const findSpecificApp = (framework, inputcategory) => {
// Get the frameworkinfo for the org and fill in
//
if (framework === undefined || framework === null) {
console.log("findSpecificApp: frameworkData is null")
return null
}
if (inputcategory === undefined || inputcategory === null) {
console.log("findSpecificApp: category is null")
return null
}
const category = inputcategory.toLowerCase()
console.log("findSpecificApp: ", category, frameworkData)
if (category === "edr" || category === "eradication" || category === "edr & av") {
if (frameworkData["EDR & AV"] !== undefined && frameworkData["EDR & AV"].name !== undefined) {
return frameworkData["EDR & AV"]
}
return {
name: "EDR :default",
large_image: parsedDatatypeImages["EDR & AV"],
count: 0,
description: "",
id: "",
}
} else if (category === "communication") {
if (frameworkData["Comms"] !== undefined && frameworkData["Comms"].name !== undefined) {
return frameworkData["Comms"]
}
return {
name: "COMMS :default",
large_image: parsedDatatypeImages["COMMS"],
count: 0,
description: "",
id: "",
}
} else if (category === "email") {
if (frameworkData["Email"] !== undefined && frameworkData["Email"].name !== undefined) {
return frameworkData["Email"]
}
return {
name: "COMMS :default",
large_image: parsedDatatypeImages["COMMS"],
count: 0,
description: "",
id: "",
}
} else if (category === "assets") {
if (frameworkData["Assets"] !== undefined && frameworkData["Assets"].name !== undefined) {
return frameworkData["Assets"]
}
return {
name: "ASSETS :default",
large_image: parsedDatatypeImages["ASSETS"],
count: 0,
description: "",
id: "",
}
} else if (category === "cases") {
if (frameworkData["Cases"] !== undefined && frameworkData["Cases"].name !== undefined) {
return frameworkData["Cases"]
}
return {
name: "CASES :default",
large_image: parsedDatatypeImages["CASES"],
count: 0,
description: "",
id: "",
}
} else if (category === "iam") {
if (frameworkData["IAM"] !== undefined && frameworkData["IAM"].name !== undefined) {
return frameworkData["IAM"]
}
return {
name: "EDR :default",
large_image: parsedDatatypeImages["EDR & AV"],
count: 0,
description: "",
id: "",
}
} else if (category === "network") {
if (frameworkData["Network"] !== undefined && frameworkData["Network"].name !== undefined) {
return frameworkData["Network"]
}
return {
name: "Network :default",
large_image: parsedDatatypeImages["NETWORK"],
count: 0,
description: "",
id: "",
}
} else if (category === "intel") {
if (frameworkData["Intel"] !== undefined && frameworkData["Intel"].name !== undefined) {
return frameworkData["Intel"]
}
return {
name: "INTEL :default",
large_image: parsedDatatypeImages["INTEL"],
count: 0,
description: "",
id: "",
}
} else if (category === "siem") {
if (frameworkData["SIEM"] !== undefined && frameworkData["SIEM"].name !== undefined) {
return frameworkData["SIEM"]
}
return {
name: "SIEM :default",
large_image: parsedDatatypeImages["SIEM"],
count: 0,
description: "",
id: "",
}
} else {
console.log("findSpecificApp: unknown category: ", category)
}
return null
}
const parseUsecase = (subcase) => {
console.log("parseUsecase: ", subcase)
const srcdata = findSpecificApp(frameworkData, subcase.type)
const dstdata = findSpecificApp(frameworkData, subcase.last)
console.log("srcdata: ", srcdata)
console.log("dstdata: ", dstdata)
if (srcdata !== undefined && srcdata !== null) {
subcase.srcimg = srcdata.large_image
subcase.srcapp = srcdata.name
}
if (dstdata !== undefined && dstdata !== null) {
subcase.dstimg = dstdata.large_image
subcase.dstapp = dstdata.name
}
return subcase
}
const getUsecase = (subcase, index, subindex) => {
console.log(subcase)
subcase = parseUsecase(subcase)
// Timeout 50ms to delay it slightly
setTimeout(() => {
setInputUsecase(subcase)
}, 50)
fetch(`${globalUrl}/api/v1/workflows/usecases/${escape(subcase.name.replaceAll(" ", "_"))}`, {
method: "GET",
@@ -174,62 +328,68 @@ const UsecaseListComponent = ({userdata, keys, isCloud, globalUrl, frameworkData
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for framework!");
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for framework!");
}
return response.json();
})
.then((responseJson) => {
console.log("In responseJson for usecase: ", responseJson)
var parsedUsecase = responseJson
if (responseJson.success === false) {
//img1={inputUsecase.srcimg}
//srcapp={inputUsecase.srcapp}
//img2={inputUsecase.dstimg}
//dstapp={inputUsecase.dstapp}
//title={inputUsecase.name}
parsedUsecase = subcase
} else {
parsedUsecase = responseJson
parsedUsecase.srcimg = subcase.srcimg
parsedUsecase.srcapp = subcase.srcapp
parsedUsecase.dstimg = subcase.dstimg
parsedUsecase.dstapp = subcase.dstapp
//parsedUsecase = parseUsecase(responseJson)
}
// Look for the type of app and fill in img1, srcapp...
console.log("USECASE: ", parsedUsecase)
setInputUsecase(parsedUsecase)
setExpandedIndex(index)
setExpandedItem(subindex)
setTimeout(() => {
//console.log("Scroll!")
const found = document.getElementById("selected_box");
if (found !== undefined && found !== null) {
//console.log("FOUND!!")
found.scrollTo({
top: 100,
behavior: "smooth",
})
}
return response.json();
})
.then((responseJson) => {
var parsedUsecase = responseJson
if (responseJson.success === false) {
parsedUsecase = subcase
//img1={inputUsecase.srcimg}
//srcapp={inputUsecase.srcapp}
//img2={inputUsecase.dstimg}
//dstapp={inputUsecase.dstapp}
//title={inputUsecase.name}
parsedUsecase = parseUsecase(parsedUsecase, subcase)
} else {
parsedUsecase = responseJson
parsedUsecase = parseUsecase(parsedUsecase, responseJson)
}
// Look for the type of app and fill in img1, srcapp...
setInputUsecase(parsedUsecase)
setExpandedIndex(index)
setExpandedItem(subindex)
setTimeout(() => {
//console.log("Scroll!")
const found = document.getElementById("selected_box");
if (found !== undefined && found !== null) {
//console.log("FOUND!!")
found.scrollTo({
top: 100,
behavior: "smooth",
})
}
setFirstLoad(true)
setSelectedWorkflows([])
}, 100);
})
.catch((error) => {
//toast(error.toString());
setInputUsecase({})
setExpandedIndex(index)
setExpandedItem(subindex)
setFirstLoad(true)
setSelectedWorkflows([])
})
}
}, 100);
})
.catch((error) => {
//toast(error.toString());
setInputUsecase({})
setExpandedIndex(index)
setExpandedItem(subindex)
setFirstLoad(true)
setSelectedWorkflows([])
})
}
const setUsecaseItem = (inputUsecase) => {
var parsedUsecase = inputUsecase
@@ -290,7 +450,7 @@ const UsecaseListComponent = ({userdata, keys, isCloud, globalUrl, frameworkData
//toast(error.toString());
//setFrameworkLoaded(true)
})
}
}
const setWorkflow = (workflowdata) => {
const new_url = `${globalUrl}/api/v1/workflows/${workflowdata.id}`
@@ -845,7 +1005,7 @@ const UsecaseListComponent = ({userdata, keys, isCloud, globalUrl, frameworkData
: null}
<span style={{top: 30, position: "relative",}}>
<Typography variant="body1" style={{marginTop: 0,}} onClick={() => {}}>
Try it out
Try this Usecase
</Typography>
<WorkflowTemplatePopup
userdata={userdata}
+2 -2
View File
@@ -3419,8 +3419,8 @@ const Workflows = (props) => {
>
<img
style={{
height: imgSize,
width: imgSize,
height: imgSize+4,
width: imgSize+4,
position: "absolute",
top: -2,
left: -2,