Merge branch 'launch' of https://github.com/ayush0033/Shuffle into launch

This commit is contained in:
Gelot Ayush
2022-11-01 18:51:30 +05:30
31 changed files with 4194 additions and 763 deletions
+4 -3
View File
@@ -1,5 +1,6 @@
import React, { useState, useEffect, useLayoutEffect } from "react";
import ReactDOM from "react-dom"
import { useInterval } from "react-powerhooks";
import { makeStyles, useTheme } from "@material-ui/core/styles";
@@ -1400,7 +1401,6 @@ const AngularWorkflow = (defaultprops) => {
setVisited([])
setExecutionRequest({})
stop()
})
var curelements = cy.elements();
for (var i = 0; i < curelements.length; i++) {
@@ -1476,6 +1476,7 @@ const AngularWorkflow = (defaultprops) => {
setExecutionRequestStarted(false)
console.log("Execute workflow err: ", error.toString());
});
})
};
// This can be used to only show prioritzed ones later
@@ -13858,7 +13859,7 @@ const AngularWorkflow = (defaultprops) => {
<span style={{ color: "white" }}>Execution Variable</span>
</DialogTitle>
<DialogContent>
Execution Variables are TEMPORARY variables that you can ony be set
Execution Variables are TEMPORARY variables that you can only be set
and used during execution. Learn more{" "}
<a
rel="noopener noreferrer"
@@ -13955,7 +13956,7 @@ const AngularWorkflow = (defaultprops) => {
const variable = execution.execution_variables.find(
(data) => data.name === newVariableName
);
)
if (variable === undefined || variable.value === undefined) {
return null;
}
+16 -10
View File
@@ -34,8 +34,17 @@ import {
AttachFile as AttachFileIcon,
Apps as AppsIcon,
ErrorOutline as ErrorOutlineIcon,
AddAPhoto as AddAPhotoIcon,
AddAPhotoOutlined as AddAPhotoOutlinedIcon,
ZoomInOutlined as ZoomInOutlinedIcon,
ZoomOutOutlined as ZoomOutOutlinedIcon,
Loop as LoopIcon,
} from "@material-ui/icons";
import {
AddPhotoAlternate as AddPhotoAlternateIcon,
} from '@mui/icons-material';
import { v4 as uuidv4 } from "uuid";
import { Link, useParams } from "react-router-dom";
import YAML from "yaml";
@@ -44,12 +53,6 @@ import { useAlert } from "react-alert";
import words from "shellwords";
import AvatarEditor from "react-avatar-editor";
import AddAPhotoIcon from "@material-ui/icons/AddAPhoto";
import AddAPhotoOutlinedIcon from "@material-ui/icons/AddAPhotoOutlined";
import ZoomInOutlinedIcon from "@material-ui/icons/ZoomInOutlined";
import ZoomOutOutlinedIcon from "@material-ui/icons/ZoomOutOutlined";
import LoopIcon from "@material-ui/icons/Loop";
import AddPhotoAlternateIcon from "@material-ui/icons/AddPhotoAlternate";
const surfaceColor = "#27292D";
const inputColor = "#383B40";
@@ -344,14 +347,14 @@ const AppCreator = (defaultprops) => {
useEffect(() => {
if (window.location.pathname.includes("apps/edit")) {
setIsEditing(true);
handleEditApp();
handleEditApp(props.match.params.appid);
} else {
checkQuery();
}
}, []);
const handleEditApp = () => {
fetch(globalUrl + "/api/v1/apps/" + props.match.params.appid + "/config", {
const handleEditApp = (appid) => {
fetch(globalUrl + "/api/v1/apps/" + appid + "/config", {
method: "GET",
headers: {
"Content-Type": "application/json",
@@ -389,7 +392,10 @@ const AppCreator = (defaultprops) => {
setIsAppLoaded(true);
return;
}
//handleEditApp(urlParams.get("id"))
// THIS has to stay due to ID may not exist as normal app yet
fetch(globalUrl + "/api/v1/get_openapi/" + urlParams.get("id"), {
method: "GET",
headers: {
@@ -408,7 +414,7 @@ const AppCreator = (defaultprops) => {
.then((responseJson) => {
setIsAppLoaded(true);
if (!responseJson.success) {
alert.error("Failed to verify");
alert.error("Failed to get app config. Do you have access?");
} else {
parseIncomingOpenapiData(responseJson);
}
+28 -15
View File
@@ -39,6 +39,10 @@ import {
Delete as DeleteIcon,
} from "@material-ui/icons";
import {
ForkRight as ForkRightIcon,
} from '@mui/icons-material';
import { useTheme } from "@material-ui/core/styles";
import YAML from "yaml";
@@ -807,9 +811,11 @@ const Apps = (props) => {
</Tooltip>
) : null;
// FIXME: Add /apps/new?id=<PUBLIC> to allow for changes of the original
// Should always reference the original ID.
var editButton =
//if (selectedApp.name !== undefined && selectedApp.name !== null && selectedApp.name.includes("New")) {
//}
var editButton =
selectedApp.activated &&
selectedApp.private_id !== undefined &&
selectedApp.private_id.length > 0 &&
@@ -829,21 +835,19 @@ const Apps = (props) => {
) : null;
//var editNewButton = editButton === null ?
var editNewButton = selectedApp.generated && selectedApp.activated && props.userdata.id !== selectedApp.owner ?
isCloud ?
var editNewButton = selectedApp.generated && selectedApp.activated && props.userdata.id !== selectedApp.owner && isCloud ?
<Link to={activateUrl} style={{ textDecoration: "none" }}>
<Tooltip title={"Edit this public app to your liking"}>
<Tooltip title={"Fork and Edit this public app to your liking"}>
<Button
variant="contained"
component="label"
color="primary"
style={{ marginTop: 10, marginRight: 10 }}
>
<EditIcon />
<ForkRightIcon />
</Button>
</Tooltip>
</Link>
: null
: null
const activateButton =
@@ -879,8 +883,7 @@ const Apps = (props) => {
((selectedApp.private_id !== undefined &&
selectedApp.private_id.length > 0 &&
selectedApp.generated) ||
(selectedApp.downloaded !== undefined &&
selectedApp.downloaded == true) ||
(selectedApp.downloaded !== undefined && selectedApp.downloaded == true) ||
!selectedApp.generated) &&
activateButton === null ? (
<Tooltip title={"Delete app"}>
@@ -982,6 +985,10 @@ const Apps = (props) => {
const userRoles = ["you", isCloud ? "public" : "everyone"];
// 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 =
newAppname.length > 0 ? (
@@ -1086,14 +1093,20 @@ const Apps = (props) => {
) : null}
{activateButton}
{editNewButton}
{(editNewButton === null && userdata !== undefined && (userdata.admin === "true" || userdata.id === selectedApp.owner || selectedApp.owner === "" )) || !selectedApp.generated ? (
{ /* editNewButton === null && */ }
{canEditApp ? (
<div>
{editButton}
{downloadButton}
{deleteButton}
</div>
) : null}
) :
<div>
{editNewButton}
</div>
}
{selectedApp.tags !== undefined && selectedApp.tags !== null ? (
<div
style={{
@@ -1119,8 +1132,8 @@ const Apps = (props) => {
})}
</div>
) : null}
{props.userdata !== undefined &&
props.userdata.id === selectedApp.owner ? (
{canEditApp
? (
<div style={{ marginTop: 15 }}>
{/*<p><b>ID:</b> {selectedApp.id}</p>*/}
<b style={{ marginRight: 15 }}>Sharing </b>
@@ -1877,7 +1890,7 @@ const Apps = (props) => {
getApps();
}, 1000);
} else {
alert.error("Failed deleting app");
alert.error("Failed deleting app. Does it still exist?");
}
})
.catch((error) => {
+2 -2
View File
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { useInterval } from "react-powerhooks";
import DetectionFramework from "../components/DetectionFramework.jsx";
import AppFramework from "../components/AppFramework.jsx";
import { makeStyles, useTheme } from "@material-ui/core/styles";
// nodejs library that concatenates classes
import classNames from "classnames";
@@ -834,7 +834,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
borderRadius: theme.palette.borderRadius,
border: "1px solid rgba(255,255,255,0.3)",
}}>
<DetectionFramework
<AppFramework
inputUsecase={inputUsecase}
frameworkData={frameworkData}
selectedOption={"Draw"}
-1
View File
@@ -1,6 +1,5 @@
import React, { useState, useEffect } from "react";
import { useInterval } from "react-powerhooks";
import DetectionFramework from "../components/DetectionFramework.jsx";
import { makeStyles, useTheme } from "@material-ui/core/styles";
// nodejs library that concatenates classes
import classNames from "classnames";
+2 -2
View File
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import ReactDOM from "react-dom"
import DetectionFramework from "../components/DetectionFramework.jsx";
import AppFramework from "../components/AppFramework.jsx";
import { useAlert } from "react-alert";
import { Link, useParams } from "react-router-dom";
import theme from '../theme';
@@ -69,7 +69,7 @@ const Framework = (props) => {
</Link>
</div>
{frameworkLoaded === true && isLoaded ?
<DetectionFramework
<AppFramework
frameworkData={frameworkData}
selectedOption={"Draw"}
showOptions={false}
+298 -35
View File
@@ -1,20 +1,45 @@
import React, { useState, useEffect } from 'react';
import WelcomeForm from "../components/WelcomeForm.jsx";
import DetectionFramework from "../components/DetectionFramework.jsx";
import ReactGA from 'react-ga';
import WelcomeForm2 from "../components/WelcomeForm2.jsx";
import Stepper from "@material-ui/core/Stepper";
import Step from "@material-ui/core/Step";
import StepLabel from "@material-ui/core/StepLabel";
import AppFramework from "../components/AppFramework.jsx";
import {
Grid,
Container,
Fade,
Typography,
Paper,
Button,
Card,
CardContent,
CardActionArea,
} from '@mui/material';
import theme from '../theme';
import { useNavigate } from "react-router-dom";
import { useNavigate, Link } from "react-router-dom";
// Should be different if logged in :|
const Welcome = (props) => {
const { globalUrl, surfaceColor, newColor, mini, inputColor, userdata, isLoggedIn, isLoaded } = props;
const [skipped, setSkipped] = React.useState(new Set());
const [inputUsecase, setInputUsecase] = useState({});
const [frameworkData, setFrameworkData] = useState(undefined);
const [discoveryWrapper, setDiscoveryWrapper] = useState(undefined);
const [activeStep, setActiveStep] = React.useState(0);
const [apps, setApps] = React.useState([]);
const [defaultSearch, setDefaultSearch] = React.useState("")
const [selectionOpen, setSelectionOpen] = React.useState(false)
const [showWelcome, setShowWelcome] = React.useState(false)
const isCloud =
window.location.host === "localhost:3002" ||
window.location.host === "shuffler.io";
const [steps, setSteps] = useState([
"Help us get to know you",
"Find your Apps",
"Discover Usecases",
])
let navigate = useNavigate();
@@ -51,46 +76,284 @@ const Welcome = (props) => {
})
}
const getApps = () => {
fetch(globalUrl + "/api/v1/apps", {
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 response.json();
})
.then((responseJson) => {
setApps(responseJson);
})
.catch((error) => {
console.log("App loading error: "+error.toString());
});
}
const usecaseButtons = [{
"name": "Phishing",
"usecase": "Email management",
"color": "#C51152",
}, {
"name": "Enrichment",
"usecase": "2. Enrich",
"color": "#F4C20D",
}, {
"name": "Detection",
"usecase": "3. Detect",
"color": "#3CBA54",
}, {
"name": "Response",
"usecase": "4. Respond",
"color": "#4885ED",
}]
const handleSetSearch = (input, orgupdate) => {
console.log("INPUT & ORGUPDATE: ", input, orgupdate, defaultSearch)
if (input !== defaultSearch) {
setDefaultSearch(input)
setSelectionOpen(false)
setTimeout(function(){
setSelectionOpen(true)
}, 150);
//if (userdata !== undefined && userdata.active_org !== undefined && userdata.active_org.id !== undefined) {
// sendOrgUpdate("", "", userdata.active_org.id, orgupdate)
//}
} else {
setDefaultSearch("")
setSelectionOpen(false)
}
}
useEffect(() => {
getFramework()
}, []);
getApps()
if (
window.location.search !== undefined &&
window.location.search !== null
) {
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
const foundTab = params["tab"];
if (foundTab !== null && foundTab !== undefined && !isNaN(foundTab)) {
console.log("FOUND TAB: ", foundTab)
setShowWelcome(true)
if (foundTab === 3 || foundTab === "3") {
console.log("SET SEARCH!!")
handleSetSearch(usecaseButtons[0].name, usecaseButtons[0].usecase)
}
setActiveStep(foundTab-1)
} else {
navigate(`/welcome?tab=1`)
}
}
}, [])
const isStepSkipped = step => {
return skipped.has(step)
}
const paperObject = {
flex: 1,
padding: 0,
textAlign: "center",
maxWidth: 300,
minWidth: 300,
backgroundColor: theme.palette.surfaceColor,
color: "white",
}
const actionObject = {
padding: "50px 35px 50px 35px",
}
const imageStyle = {
width: 150,
height: 150,
margin: "auto",
marginTop: 30,
}
return (
<Grid container spacing={2} style={{ padding: 70, maxWidth: 1366, minWidth: 1366, margin: "auto", }}>
<Grid item xs={6}>
<div>
<WelcomeForm
userdata={userdata}
globalUrl={globalUrl}
discoveryWrapper={discoveryWrapper}
setDiscoveryWrapper={setDiscoveryWrapper}
/>
<div style={{width: 1000, margin: "auto", backgroundColor: theme.palette.platformColor, paddingBottom: 150, minHeight: 1500,}}>
{/*
<div style={{position: "fixed", bottom: 110, right: 110, display: "flex", }}>
<img src="/images/Arrow.png" style={{width: 250, height: "100%",}} />
</div>
*/}
{showWelcome === true ?
<div>
<div style={{minWidth: 500, maxWidth: 500, margin: "auto",}}>
<Stepper
activeStep={activeStep}
color="primary"
style={{
backgroundColor: theme.palette.platformColor,
borderRadius: theme.palette.borderRadius,
padding: 12,
border: "1px solid rgba(255,255,255,0.3)",
maxWidth: 500,
color: "white",
}}
>
{steps.map((label, index) => {
const stepProps = {}
const labelProps = {}
//if (isStepOptional(index)) {
// labelProps.optional = "optional"
//}
if (isStepSkipped(index)) {
stepProps.completed = false;
}
return (
<Step key={label} {...stepProps} style={{maxWidth: 160, color: "white", }}>
<StepLabel {...labelProps} style={{marginLeft: 10, color: "white",}}>
{label}
</StepLabel>
</Step>
)
})}
</Stepper>
</div>
</Grid>
{frameworkData === undefined || window.location.href.includes("tab=3") ? null :
<div style={{marginTop: 25}}>
<Typography variant="h6" style={{textAlign: "center", marginBottom: 25, }}>
App Framework
</Typography>
<Fade>
<DetectionFramework
inputUsecase={inputUsecase}
frameworkData={frameworkData}
selectedOption={"Draw"}
showOptions={false}
isLoaded={true}
isLoggedIn={true}
<Grid container spacing={2} style={{ padding: 0, maxWidth: 1000, minWidth: 1000, margin: "auto", }}>
<Grid item xs={window.location.href.includes("tab=2") ? 6 : 12}>
<div>
{/*
<WelcomeForm
userdata={userdata}
globalUrl={globalUrl}
size={0.8}
color={theme.palette.platformColor}
discoveryWrapper={discoveryWrapper}
setDiscoveryWrapper={setDiscoveryWrapper}
/>
</Fade>
/>
*/}
<WelcomeForm2
userdata={userdata}
globalUrl={globalUrl}
discoveryWrapper={discoveryWrapper}
setDiscoveryWrapper={setDiscoveryWrapper}
appFramework={frameworkData}
getFramework={getFramework}
steps={steps}
skipped={skipped}
setSkipped={setSkipped}
activeStep={activeStep}
setActiveStep={setActiveStep}
getApps={getApps}
apps={apps}
handleSetSearch={handleSetSearch}
usecaseButtons={usecaseButtons}
defaultSearch={defaultSearch}
setDefaultSearch={setDefaultSearch}
selectionOpen={selectionOpen}
setSelectionOpen={setSelectionOpen}
/>
</div>
</Grid>
{frameworkData === undefined || window.location.href.includes("tab=1") || window.location.href.includes("tab=3") ? null :
<div style={{marginTop: 25, }}>
<Typography variant="h6" style={{textAlign: "center", marginBottom: 25, }}>
App Framework
</Typography>
<Fade>
<AppFramework
inputUsecase={inputUsecase}
frameworkData={frameworkData}
setFrameworkData={setFrameworkData}
selectedOption={"Draw"}
showOptions={false}
isLoaded={true}
isLoggedIn={true}
globalUrl={globalUrl}
size={0.78}
color={theme.palette.platformColor}
discoveryWrapper={discoveryWrapper}
setDiscoveryWrapper={setDiscoveryWrapper}
apps={apps}
/>
</Fade>
</div>
}
</Grid>
</div>
:
<Fade in={true}>
<div style={{maxWidth: 700, margin: "auto", marginTop: 50, }}>
<Typography variant="h4" style={{color: "white", textAlign: "center"}}>
Welcome to Shuffle
</Typography>
<Typography variant="body1" style={{textAlign: "center", marginBottom: 50, }}>
Who do you identify with the most?
</Typography>
<div style={{display: "flex", marginTop: 70, width: 700, margin: "auto",}}>
<Card style={paperObject} onClick={() => {
if (isCloud) {
ReactGA.event({
category: "welcome",
action: "click_welcome_continue",
label: "",
})
}
setShowWelcome(true)
}}>
<CardActionArea style={actionObject}>
<Typography variant="h4" style={{color: "#49A928"}}>
New to Shuffle
</Typography>
<img src="/images/welcome_cog.png" style={imageStyle} />
<Typography variant="body1" style={{marginTop: 30, color: "rgba(255,255,255,0.8)"}}>
Follow our short introduction and learn some tips and tricks
</Typography>
</CardActionArea>
</Card>
<div style={{marginLeft: 25, marginRight: 25, }}>
<Typography style={{marginTop: 200, }}>
OR
</Typography>
</div>
<Card style={paperObject} onClick={() => {
if (isCloud) {
ReactGA.event({
category: "welcome",
action: "click_getting_started",
label: "",
})
}
navigate("/getting-started?message=Skipped intro")
}}>
<CardActionArea style={actionObject}>
<Typography variant="h4" style={{color: "#f86a3e"}}>
Experienced
</Typography>
<img src="/images/social/shuffle_logo_round.png" style={imageStyle} />
<Typography variant="body1" style={{marginTop: 30, color: "rgba(255,255,255,0.8)"}}>
You know Shuffle well. Head to the product right away!
</Typography>
</CardActionArea>
</Card>
</div>
</div>
}
</Grid>
)
</Fade>
}
</div>
)
}
export default Welcome;
+7 -2
View File
@@ -1274,8 +1274,12 @@ const Workflows = (props) => {
for (var subkey in data.actions[key].parameters) {
const param = data.actions[key].parameters[subkey];
// Removed October 10th, 2022 as key usually isn't
// containing anything secret, but rather necessary configurations.
// param.name.includes("key") ||
//
if (
param.name.includes("key") ||
param.name.includes("user") ||
param.name.includes("pass") ||
param.name.includes("api") ||
@@ -1322,8 +1326,9 @@ const Workflows = (props) => {
) {
for (key in data.workflow_variables) {
const param = data.workflow_variables[key];
//param.name.includes("key") ||
if (
param.name.includes("key") ||
param.name.includes("user") ||
param.name.includes("pass") ||
param.name.includes("api") ||