Further cloud syncs for MUlti Tenant distribution

This commit is contained in:
Frikky
2025-02-13 13:28:17 +01:00
parent b367b4cfb7
commit 1f2e0ed6a3
6 changed files with 96 additions and 246 deletions
+4 -1
View File
@@ -4122,7 +4122,10 @@ const AngularWorkflow = (defaultprops) => {
setCookie("session_token", sessionToken, { path: "/" });
window.location.href = "https://shuffler.io/workflows/3abdfb21-b40f-4e50-b855-ac0d62f83cbe";
}, 2000)
}
} else if (execFound !== null && response.status >= 300) {
toast.info("Failed to load the workflow, but you may still find a list of workflow runs if you have access.")
setExecutionModalOpen(true)
}
}
}
+32 -206
View File
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useContext, useRef } from "react";
import React, { useState, useEffect, useContext } from "react";
import theme from "../theme.jsx";
import ReactGA from "react-ga4";
@@ -223,7 +223,6 @@ const AppExplorer = (props) => {
result: baseResult,
});
const [executing, setExecuting] = useState(false);
const [activatedApps, setActivatedApps] = useState([]);
const [anchorEl, setAnchorEl] = React.useState(null);
const [creatorProfile, setCreatorProfile] = React.useState({});
const [selectedTab, setSelectedTab] = React.useState(0);
@@ -248,7 +247,6 @@ const AppExplorer = (props) => {
})
const isCloud = (window.location.host === "localhost:3002" || window.location.host === "shuffler.io") ? true : (process.env.IS_SSR === "true");
const isFirstRequestSentRef = useRef(false);
// FIXME: This is used, as useEffect() creates an issue with apps not loading at all
@@ -301,15 +299,13 @@ const AppExplorer = (props) => {
if (serverside) {
console.log("Not getting app because serverside.");
} else {
if (isCloud) {
if (params.appid.length === 32 || params.appid.length === 36) {
handleEditApp(params.appid);
runAlgoliaAppSearch(params.appid, false, true);
} else {
runAlgoliaAppSearch(params.appid);
//handleEditApp()
}
if (params.appid.length === 32 || params.appid.length === 36) {
handleEditApp(params.appid);
runAlgoliaAppSearch(params.appid, false, true);
} else {
runAlgoliaAppSearch(params.appid);
//handleEditApp()
}
}
//parseIncomingOpenapiData(YAML.parse(data))
@@ -348,86 +344,6 @@ const AppExplorer = (props) => {
loadOrganization(userdata.active_org.id)
}
const getApps = () => {
// Get apps from localstorage
var storageApps = []
try {
const appstorage = localStorage.getItem("apps")
storageApps = JSON.parse(appstorage)
if (storageApps === null || storageApps === undefined || storageApps.length === 0) {
storageApps = []
} else {
setActivatedApps(storageApps)
}
} catch (e) {
//console.log("Failed to get apps from localstorage: ", e)
}
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!");
//if (isCloud) {
// window.location.pathname = "/search";
//}
}
return response.json();
})
.then((responseJson) => {
var privateapps = [];
var valid = [];
var invalid = [];
for (var key in responseJson) {
const app = responseJson[key];
if (app.categories !== undefined && app.categories !== null && app?.categories.includes("Eradication")) {
app.categories = ["EDR"]
}
if (app.is_valid && !(!app.activated && app.generated)) {
privateapps.push(app);
} else if (
app.private_id !== undefined &&
app.private_id.length > 0
) {
valid.push(app);
} else {
invalid.push(app);
}
}
privateapps.push(...valid);
privateapps.push(...invalid);
setActivatedApps(privateapps);
if (params.appid.length === 32 || params.appid.length === 36) {
handleEditApp(params.appid, privateapps);
runAlgoliaAppSearch(params.appid, false, true, privateapps);
} else {
runAlgoliaAppSearch(params.appid,true, false, privateapps);
}
})
.catch((error) => {
toast(error.toString());
});
};
useEffect(() => {
if (activatedApps?.length === 0 && !isCloud) {
getApps();
}
}, [activatedApps]);
var activateButton = (
<Link to={`/apps/new?id=${appId}`} style={{ textDecoration: "none" }}>
<Button
@@ -869,101 +785,14 @@ const AppExplorer = (props) => {
});
};
const HandleActivateApp = (appid) => {
if (isFirstRequestSentRef.current) {
console.log("Skipping duplicate activation request for app:", appid);
return;
}
isFirstRequestSentRef.current = true;
toast.info("App is not activated. Activating it now. Please wait...");
const baseURL = globalUrl;
const url = `${baseURL}/api/v1/apps/${appid}/activate`;
fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => response.json())
.then((responseJson) => {
if (!responseJson.success) {
toast.error("Failed to activate app. Redirecting to https://shuffler.io. Please wait...");
setTimeout(() => {
window.location.replace(`https://shuffler.io/apps/${appid}`);
}, 2000);
return;
}
localStorage.removeItem("apps");
getApps();
})
.catch((error) => {
console.log("App activation error: ", error.toString());
toast.error("Failed to activate app. Redirecting to https://shuffler.io. Please wait...");
setTimeout(() => {
window.location.href = `https://shuffler.io/apps/${appid}`;
}, 2000);
});
};
const handleEditApp = (appid, privateapps) => {
const handleEditApp = (appid) => {
if (serverside === true) {
return;
}
var newAppId = appid
var appIdFound = false
if (!isCloud) {
// Ensure privateapps is always an array
privateapps = Array.isArray(privateapps) ? privateapps : [];
let found = privateapps.find(app => {
return app.id?.trim().toLowerCase() === appid
});
if (!found) {
found = privateapps.find(app => {
return app.published_id?.trim().toLowerCase() === appid;
});
}
if (found && found.id) {
newAppId = found.id;
appIdFound = true
} else {
if (!isFirstRequestSentRef.current) {
HandleActivateApp(appid);
return;
} else {
toast.info("App activated but can't load it for now. Loading app on https://shuffler.io. Please wait...");
setTimeout(() => {
window.location.href = `https://shuffler.io/apps/${appid}`;
}, 3000);
}
}
}
setAppId(appid)
setAppId(newAppId)
if (isFirstRequestSentRef.current && !isCloud && !appIdFound) {
return
}
fetch(`${globalUrl}/api/v1/apps/${newAppId}/config`, {
fetch(globalUrl + "/api/v1/apps/" + appid + "/config", {
method: "GET",
headers: {
"Content-Type": "application/json",
@@ -997,9 +826,9 @@ const AppExplorer = (props) => {
) {
toast("Failed to get the app")
setIsAppLoaded(true)
// setTimeout(() => {
// navigate("/search")
// }, 1000);
setTimeout(() => {
navigate("/search")
}, 1000);
return;
} else {
parseIncomingOpenapiData(responseJson);
@@ -1010,7 +839,6 @@ const AppExplorer = (props) => {
});
};
const parseIncomingAppdata = (data, openapiExists) => {
document.title = data.name + " App - OpenAPI and API";
@@ -1594,7 +1422,7 @@ const AppExplorer = (props) => {
});
};
const runAlgoliaAppSearch = (appname, isOriginal, triggerOnly, privatedapps) => {
const runAlgoliaAppSearch = (appname, isOriginal, triggerOnly) => {
const index = searchClient.initIndex("appsearch");
console.log("Running appsearch for: ", appname);
@@ -1609,7 +1437,7 @@ const AppExplorer = (props) => {
if (hits !== undefined && hits !== null && hits.length === 1) {
found = true
if (isOriginal !== false) {
handleEditApp(hits[0].objectID, privatedapps)
handleEditApp(hits[0].objectID)
} else {
setSecondaryApp(hits[0])
}
@@ -1644,7 +1472,7 @@ const AppExplorer = (props) => {
} else {
if (isOriginal !== false) {
found = true
handleEditApp(hit.objectID, privatedapps);
handleEditApp(hit.objectID);
} else {
console.log("Found second app: ", hit);
hit.name = hit.name.charAt(0).toUpperCase() + hit.name.slice(1);
@@ -1659,7 +1487,7 @@ const AppExplorer = (props) => {
if (!found) {
if (hits.length > 0) {
if (isOriginal !== false) {
handleEditApp(hits[0].objectID, privatedapps)
handleEditApp(hits[0].objectID)
} else {
setSecondaryApp(hits[0]);
}
@@ -1717,13 +1545,11 @@ const AppExplorer = (props) => {
setTriggers([])
//handleEditApp(params.appid)
if (isCloud) {
if (params.appid.length === 32 || params.appid.length === 36) {
handleEditApp(params.appid);
runAlgoliaAppSearch(params.appid, false, true);
} else {
runAlgoliaAppSearch(params.appid);
}
if (params.appid.length === 32 || params.appid.length === 36) {
handleEditApp(params.appid);
runAlgoliaAppSearch(params.appid, false, true);
} else {
runAlgoliaAppSearch(params.appid);
}
}
@@ -3216,7 +3042,9 @@ const AppExplorer = (props) => {
const getDownloadUrl = () => {
return `curl -X POST ${globalUrl}/api/v1/download_docker_image \\\n -H \"Authorization: Bearer ${userdata?.apikey}" \\\n -d '{"name": "frikky/shuffle:${app?.name.toLowerCase().replaceAll(' ', '_')}_${app.app_version}"}' \\\n -o image.zip; \\\n docker load -i image.zip`
const appEnding = app?.public === true ? app?.app_verison : app?.id
return `curl -L \ \\\n "${globalUrl}/api/v1/download_docker_image?image=frikky/shuffle:${app?.name.toLowerCase().replaceAll(' ', '_')}_${appEnding}" \\\n -H \"Authorization: Bearer ${userdata?.apikey}" \\\n -o image.zip; \\\n docker load -i image.zip`
}
const renderedActionOptions = deduplicateByName((
@@ -3406,9 +3234,11 @@ const AppExplorer = (props) => {
Use the App onprem
</Typography>
<Typography variant="body2" color="textSecondary" style={{marginTop: 5, }}>
Due to using docker containers with private containers, we had to use a custom registry. Use the command below to download the image to the server if it fails to run.
Due to using docker containers with privately uploaded containers, we had to use a custom registry. Use the command below to download the image to the server if it fails to run.
<b>&nbsp;PS: This does NOT work for ARM containers.</b>
It will authenticate and authorize you, before redirecting to a Signed URL on https://storage.googleapis.com
<b>&nbsp;Now also works for ARM containers!</b>
</Typography>
<div
@@ -4076,10 +3906,6 @@ const AppExplorer = (props) => {
</Dialog>
) : null;
console.log("App: ", app);
console.log("userdata is: ", userdata);
const landingpageDataBrowser = (
<div
style={{
@@ -4218,7 +4044,7 @@ const AppExplorer = (props) => {
{isMobile ? null : (
<Button
variant={(userdata.active_apps !== undefined && userdata.active_apps !== null && userdata.active_apps.includes(appId) || !isCloud) ? "outlined": "contained"}
variant={userdata.active_apps !== undefined && userdata.active_apps !== null && userdata.active_apps.includes(appId) ? "outlined": "contained"}
component="label"
color="primary"
onClick={() => {
@@ -4263,7 +4089,7 @@ const AppExplorer = (props) => {
}}
style={{ height: 40, marginTop: 5 }}
>
{((userdata.active_apps !== undefined && userdata.active_apps !== null && userdata.active_apps.includes(appId) )|| !isCloud ) ?
{userdata.active_apps !== undefined && userdata.active_apps !== null && userdata.active_apps.includes(appId) ?
"Deactivate App"
:
"Activate App"