Force Rebuild frontend

This commit is contained in:
Frikky
2024-08-20 14:53:53 +02:00
parent c4f502eb63
commit 1a9f82a3e7
5 changed files with 319 additions and 76 deletions
@@ -19,17 +19,19 @@ const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, i
const handleSwitchChange = (event) => { const handleSwitchChange = (event) => {
if (folderDisabled) { if (folderDisabled) {
toast("enable the directory to enable individual rules"); toast.warn("Enable the directory to enable individual rules");
return; return;
} }
if (!isTenzirActive) { if (!isTenzirActive) {
toast("connect to the siem to enable/disable the rule"); toast.warn("Connect to the siem first to enable/disable the rule");
return; return;
} }
const newIsEnabled = event.target.checked; const newIsEnabled = event.target.checked;
toggleRule(file_id, !newIsEnabled, globalUrl, () => { toggleRule(file_id, !newIsEnabled, globalUrl, () => {
setIsEnabled(newIsEnabled); setIsEnabled(newIsEnabled);
}); })
}; };
const UpdateText = (text) => { const UpdateText = (text) => {
@@ -73,7 +75,6 @@ const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, i
color: "white", color: "white",
}} }}
> >
<h1> HELO</h1>
<Typography variant="h6">{ruleName}</Typography> <Typography variant="h6">{ruleName}</Typography>
<div style={{ display: 'flex', alignItems: 'center' }}> <div style={{ display: 'flex', alignItems: 'center' }}>
<IconButton onClick={() => openEditBar(file_id, setOpenCodeEditor, setFileData, globalUrl)}> <IconButton onClick={() => openEditBar(file_id, setOpenCodeEditor, setFileData, globalUrl)}>
@@ -82,7 +83,7 @@ const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, i
<Switch <Switch
checked={isEnabled && !folderDisabled} checked={isEnabled && !folderDisabled}
onChange={handleSwitchChange} onChange={handleSwitchChange}
disabled={!isTenzirActive} disabled={false}
/> />
</div> </div>
</div> </div>
@@ -107,7 +108,7 @@ const RuleCard = ({ ruleName, description, file_id, globalUrl, folderDisabled, i
const toggleRule = (fileId, isCurrentlyEnabled, globalUrl, callback) => { const toggleRule = (fileId, isCurrentlyEnabled, globalUrl, callback) => {
const action = isCurrentlyEnabled ? "disable" : "enable"; const action = isCurrentlyEnabled ? "disable" : "enable";
const url = `${globalUrl}/api/v1/files/detection/${fileId}/${action}_rule`; const url = `${globalUrl}/api/v1/detections/${fileId}/${action}_rule`;
fetch(url, { fetch(url, {
method: "PUT", method: "PUT",
+18 -10
View File
@@ -456,15 +456,19 @@ const Header = (props) => {
<LightbulbIcon style={{ marginRight: 5 }} /> Use Cases <LightbulbIcon style={{ marginRight: 5 }} /> Use Cases
</MenuItem> </MenuItem>
</Link> </Link>
<Link to={`/creators/${userdata.public_username}`} style={hrefStyle}>
<MenuItem {userdata?.public_username === undefined || userdata?.public_username === null || userdata?.public_username.length <= 0 ? null :
onClick={(event) => { <Link to={`/creators/${userdata.public_username}`} style={hrefStyle}>
handleClose(); <MenuItem
}} onClick={(event) => {
> handleClose();
<EmojiObjectsIcon style={{ marginRight: 5 }} /> Creator page }}
</MenuItem> >
</Link> <EmojiObjectsIcon style={{ marginRight: 5 }} /> Creator page
</MenuItem>
</Link>
}
<Divider style={{ marginTop: 10, marginBottom: 10, }} /> <Divider style={{ marginTop: 10, marginBottom: 10, }} />
<MenuItem <MenuItem
style={{ color: "white" }} style={{ color: "white" }}
@@ -1155,7 +1159,11 @@ const Header = (props) => {
userdata.app_execution_usage === undefined || userdata.app_execution_usage === undefined ||
userdata.app_execution_usage < 1000 ? null : ( userdata.app_execution_usage < 1000 ? null : (
<Tooltip <Tooltip
title={`Amount of App Runs used: ${userdata.app_execution_usage} / ${userdata.app_execution_limit}. When the limit is reached, you can still use Shuffle normally, but your Workflow triggers will stop workflows from starting. Reach out to support@shuffler.io to extend this limit.`} title={
<Typography variant="body1" style={{margin: 10, }}>
<b>App Runs used</b>: {userdata.app_execution_usage} / {userdata.app_execution_limit}. When the limit is reached, you can still use Shuffle normally, but your Workflow triggers will stop workflows from starting. Reach out to support@shuffler.io to extend this limit. Customer workflows are NOT stopped this way.
</Typography>
}
> >
<div <div
style={{ style={{
+17 -6
View File
@@ -4877,7 +4877,7 @@ If you're interested, please let me know a time that works for you, or set up a
<a <a
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
href="/docs/organizations#schedules" href="/docs/triggers#schedules"
style={{ textDecoration: "none", color: "#f85a3e" }} style={{ textDecoration: "none", color: "#f85a3e" }}
> >
Learn more Learn more
@@ -4994,9 +4994,20 @@ If you're interested, please let me know a time that works for you, or set up a
})} })}
</List> </List>
)} )}
<div style={{ marginTop: 20, marginBottom: 20 }}> <div style={{ marginTop: 20, marginBottom: 20 }}>
<h2 style={{ display: "inline" }}>WebHooks</h2> <h2 style={{ display: "inline" }}>Webhooks</h2>
<span style={{ marginLeft: 25 }}>
Webhooks used in Shuffle workflows.&nbsp;
<a
target="_blank"
rel="noopener noreferrer"
href="/docs/triggers#webhooks"
style={{ textDecoration: "none", color: "#f85a3e" }}
>
Learn more
</a>
</span>
</div> </div>
<Divider <Divider
@@ -5138,8 +5149,8 @@ If you're interested, please let me know a time that works for you, or set up a
</List> </List>
)} )}
{/* <div style={{ marginTop: 20, marginBottom: 20 }}> <div style={{ marginTop: 20, marginBottom: 20 }}>
<h2 style={{ display: "inline" }}>Tenzir Pipelines</h2> <h2 style={{ display: "inline" }}>Pipelines</h2>
<span style={{ marginLeft: 25 }}> <span style={{ marginLeft: 25 }}>
Controls a pipeline to run things.{" "} Controls a pipeline to run things.{" "}
<a <a
@@ -5241,7 +5252,7 @@ If you're interested, please let me know a time that works for you, or set up a
); );
})} })}
</List> </List>
)}*/} )}
</div> </div>
) : null; ) : null;
+52 -54
View File
@@ -334,6 +334,11 @@ const Apps = (props) => {
}, },
}); });
useEffect(() => {
console.log("APPVALID: ", appValidation)
redirectOpenApi()
}, [appValidation])
const getUserProfile = (username) => { const getUserProfile = (username) => {
if (serverside === true || !isCloud) { if (serverside === true || !isCloud) {
setCreatorProfile({}) setCreatorProfile({})
@@ -1535,27 +1540,34 @@ const Apps = (props) => {
const makeFancy = text?.includes("Generate") const makeFancy = text?.includes("Generate")
var parsedStyle = {
flex: 1,
padding: 15,
margin: 10,
paddingTop: 25,
backgroundColor: hover ? theme.palette.surfaceColor : "transparent",
cursor: hover ? "pointer" : "default",
textAlign: "center",
minHeight: 150,
maxHeight: 150,
borderRadius: theme.palette.borderRadius,
}
if (!makeFancy) {
parsedStyle.border = hover ? "1px solid #f85a3e" : "1px solid rgba(255,255,255,0.3)"
} else {
parsedStyle.border = "1px solid transparent"
parsedStyle.borderImage = "linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1"
parsedStyle.borderRadius = 0 // This doesn't work. Try to hover with a high one, and it's weird due to borderImage
}
return ( return (
<Paper <Paper
onMouseEnter={() => setHover(true)} onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)} onMouseLeave={() => setHover(false)}
onClick={func} onClick={func}
style={{ style={parsedStyle}
flex: 1,
padding: 15,
margin: 10,
paddingTop: 25,
backgroundColor: hover ? theme.palette.surfaceColor : "transparent",
border: hover ? "1px solid #f85a3e" : "1px solid rgba(255,255,255,0.3)",
cursor: hover ? "pointer" : "default",
textAlign: "center",
minHeight: 150,
maxHeight: 150,
borderRadius: theme.palette.borderRadius,
//borderImage: makeFancy ? "linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1" : null,
}}
> >
{icon} {icon}
<Typography> <Typography>
@@ -2568,7 +2580,8 @@ const Apps = (props) => {
} }
//fetch("http://localhost:8080/doc_to_openapi", { //fetch("http://localhost:8080/doc_to_openapi", {
fetch("https://doc-to-openapi-stbuwivzoq-nw.a.run.app/doc_to_openapi", { //fetch("https://doc-to-openapi-stbuwivzoq-nw.a.run.app/doc_to_openapi", {
fetch("https://doc-to-openapi-stbuwivzoq-nw.a.run.app/api/v1/doc_to_openapi", {
method: "POST", method: "POST",
headers: { headers: {
"Accept": "application/json", "Accept": "application/json",
@@ -2588,14 +2601,14 @@ const Apps = (props) => {
}) })
.then((responseJson) => { .then((responseJson) => {
// Check if openapi or swagger in string of the json // Check if openapi or swagger in string of the json
var parsedtext = responseJson
try { try {
const parsedtext = JSON.stringify(responseJson); parsedtext = JSON.stringify(responseJson);
if (parsedtext.indexOf("openapi") === -1 && parsedtext.indexOf("swagger") === -1) { if (parsedtext.indexOf("openapi") === -1 && parsedtext.indexOf("swagger") === -1) {
setValidation(false); setValidation(false)
setOpenApiError("Error in generation: "+parsedtext); setOpenApiError("Error in generation: "+parsedtext)
return
return;
} }
} catch (e) { } catch (e) {
setValidation(false); setValidation(false);
@@ -2604,7 +2617,7 @@ const Apps = (props) => {
} }
console.log("Validating response!"); console.log("Validating response!");
validateOpenApi(responseJson); validateOpenApi(parsedtext)
}) })
.catch((error) => { .catch((error) => {
setValidation(false); setValidation(false);
@@ -2716,8 +2729,16 @@ const Apps = (props) => {
}; };
const redirectOpenApi = () => { const redirectOpenApi = () => {
if (appValidation === undefined || appValidation === null || appValidation.length === 0) {
return
}
toast.success("Successfully validated OpenAPI. Redirecting to app creation. Remember to save the app to be able to use it.", {
// Disable autoclose
autoClose: 10000,
})
navigate(`/apps/new?id=${appValidation}`) navigate(`/apps/new?id=${appValidation}`)
}; }
const handleGithubValidation = (forceUpdate) => { const handleGithubValidation = (forceUpdate) => {
getSpecificApps(openApi, forceUpdate); getSpecificApps(openApi, forceUpdate);
@@ -2977,10 +2998,12 @@ const Apps = (props) => {
}} }}
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: surfaceColor, backgroundColor: theme.palette.platformColor,
borderRadius: theme.palette.borderRadius,
color: "white", color: "white",
minWidth: "800px", minWidth: "800px",
minHeight: "320px", minHeight: "320px",
padding: 50,
}, },
}} }}
> >
@@ -3019,7 +3042,7 @@ const Apps = (props) => {
validateDocumentationUrl(); validateDocumentationUrl();
}} }}
> >
Validate Generate
</Button> </Button>
), ),
}} }}
@@ -3034,22 +3057,6 @@ const Apps = (props) => {
placeholder="API Documentation URL" placeholder="API Documentation URL"
fullWidth fullWidth
/> />
<p>Or upload document with the content (coming soon)</p>
<input
hidden
type="file"
ref={upload}
multiple={false}
onChange={uploadFileDocumentation}
/>
<Button
variant="contained"
color="primary"
disabled
onClick={() => upload.current.click()}
>
Upload
</Button>
{errorText} {errorText}
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
@@ -3068,17 +3075,6 @@ const Apps = (props) => {
> >
Cancel Cancel
</Button> </Button>
<Button
variant="contained"
style={{ borderRadius: "0px" }}
disabled={appValidation.length === 0}
onClick={() => {
redirectOpenApi();
}}
color="primary"
>
Continue
</Button>
</DialogActions> </DialogActions>
</FormControl> </FormControl>
</Dialog> </Dialog>
@@ -3094,10 +3090,12 @@ const Apps = (props) => {
}} }}
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: surfaceColor, backgroundColor: theme.palette.platformColor,
borderRadius: theme.palette.borderRadius,
color: "white", color: "white",
minWidth: "800px", minWidth: "800px",
minHeight: "320px", minHeight: "320px",
padding: 50,
}, },
}} }}
> >
+225
View File
@@ -0,0 +1,225 @@
import React, { useState } from "react";
import {
Container,
Box,
TextField,
Switch,
Typography,
Button,
CircularProgress,
Paper,
} from "@mui/material";
import { toast } from "react-toastify";
import theme from '../theme.jsx';
import DetectionRuleCard from "../components/DetectionRuleCard.jsx";
const handleDirectoryChange = (folderDisabled, setFolderDisabled, globalUrl, isTenzirActive) => {
if (!isTenzirActive) {
toast.warn("Connect to siem first for global enable/disable to work");
return;
}
const action = folderDisabled ? "enable_folder" : "disable_folder";
const url = `${globalUrl}/api/v1/detections/${action}`;
fetch(url, {
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === true) {
if (action === "enable_folder") setFolderDisabled(false);
else setFolderDisabled(true);
} else {
//toast(`failed to disable rule`);
}
})
)
.catch((error) => {
console.log(`Error in ${action} the rule: `, error);
toast(`An error occurred while ${action} the rule`);
});
};
const Detection = (props) => {
const { globalUrl, ruleInfo, folderDisabled, setFolderDisabled, isTenzirActive, detectionInfo } = props;
const [searchQuery, setSearchQuery] = useState("");
const [loading, setLoading] = useState(false);
const handleConnectClick = () => {
if (isTenzirActive) {
return
}
if (detectionInfo.category === undefined || detectionInfo.category === null) {
toast.warn("Detection category not found. Please try again or contact support@shuffler.io if you think this is a bug.")
return
}
setLoading(true);
const url = `${globalUrl}/api/v1/detections/${detectionInfo?.category}/connect`;
fetch(url, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === true) {
setTimeout(() => {
setLoading(false);
window.location.reload();
}, 15000);
} else {
if (responseJson.reason !== undefined && responseJson.reason !== null) {
toast(responseJson.reason)
} else {
toast(`Failed to connect to ${detectionInfo?.category}`);
}
if (responseJson.action !== undefined && responseJson.actio !== null && responseJson.action.length > 0) {
//if (responseJson.action === "environment_create") {
// navigate("/admin?tab=environments")
//}
}
setLoading(false);
}
})
)
.catch((error) => {
setLoading(false);
console.log(`Error in connecting to ${detectionInfo?.category}: `, error);
toast(`An error occurred while connecting to ${detectionInfo?.category}`);
});
}
const filteredRules = ruleInfo === "default" ? [] : ruleInfo?.filter((rule) =>
rule.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
rule.description.toLowerCase().includes(searchQuery.toLowerCase())
)
return (
<Container>
<Paper
style={{
marginTop: 50,
width: "100%",
padding: 50,
backgroundColor: theme.palette.backgroundColor,
borderRadius: theme.palette.borderRadius,
}}
>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
mb: 2,
}}
>
<Typography variant="h6" component="div">
{detectionInfo?.name} ({filteredRules?.length})
</Typography>
<Button
variant="contained"
onClick={handleConnectClick}
disabled={loading} // Disable the button while loading
color={isTenzirActive ? "primary" : "secondary"}
style={{ }}
>
{loading ? <CircularProgress size={24} /> : isTenzirActive ? `Connected to ${detectionInfo?.category}` : `Connect to ${detectionInfo?.category}`}
</Button>
</Box>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
mb: 2,
}}
>
<Box
sx={{
display: "flex",
}}
>
<TextField
label="Search rules"
variant="outlined"
size="small"
sx={{ mr: 2 }}
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
{/* <Button
color="primary"
variant="contained"
onClick={() => uploadRef.current.click()}
>
<PublishIcon /> Upload sigma file
</Button>
<input
hidden
type="file"
multiple
ref={uploadRef}
onChange={(event) => {
uploadFiles(event.target.files);
}}
/> */}
</Box>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Typography variant="body2" sx={{ mr: 1 }}>
Global disable/enable
</Typography>
<Switch
checked={!folderDisabled}
onChange={() =>
handleDirectoryChange(folderDisabled, setFolderDisabled, globalUrl, isTenzirActive)
}
/>
</Box>
</Box>
<Box
sx={{
height: "500px",
width: "100%",
overflowY: "auto",
p: 1,
}}
>
{filteredRules?.length > 0 ?
filteredRules.map((rule, index) => {
console.log("RULE CARD: ", rule);
return (
<DetectionRuleCard
key={index}
ruleName={rule.file_name}
description={rule.description}
file_id={rule.file_id}
globalUrl={globalUrl}
folderDisabled={folderDisabled}
isTenzirActive={isTenzirActive}
{...rule}
/>
)
})
: null }
</Box>
</Paper>
</Container>
);
};
export default Detection;