diff --git a/frontend/src/components/OrgHeaderexpanded.jsx b/frontend/src/components/OrgHeaderexpanded.jsx
index 7729057d..350b456c 100644
--- a/frontend/src/components/OrgHeaderexpanded.jsx
+++ b/frontend/src/components/OrgHeaderexpanded.jsx
@@ -5,6 +5,7 @@ import theme from '../theme.jsx';
import { toast } from "react-toastify"
import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';
+import AuthenticationData from "./AuthenticationWindow";
import {
FormControl,
@@ -173,10 +174,32 @@ const OrgHeaderexpanded = (props) => {
const [webhookInputValue, setWebhookInputValue] = React.useState("");
const [authOptions, setAuthOptions] = React.useState([]);
const [selectedAuth, setSelectedAuth] = React.useState('');
+ // const [selectedAppAuth, setSelectedAppAuth] = React.useState({}); // for getting selected app auth parameters
+ const [authenticationModal, setAuthenticationModal] = React.useState(false);
- // for jira modal
- const [jiraIssueType, setJiraIssueType] = React.useState("");
- const [jiraProjectKey, setJiraProjectKey] = React.useState("");
+ const [notificationAppDetails, setNotificationAppDetails] = React.useState([]);
+
+ // const [tempResult, setTempResult] = React.useState([])
+
+ // useEffect(() => {
+ // if (authOptions.length < 1) {
+ // {getAppConfig(selectedAppDetails.id)}
+ // }
+ // }, [authOptions.length]); // not using this now
+
+ useEffect(() => {
+ if (notificationAppList.length > 0) {
+ (async () => {
+ const nameList = notificationAppList.map(item => item.name);
+ await prepareNotificationAppList(nameList);
+ })();
+ }
+ }, [notificationAppList]);
+
+
+ // for jira & email modal
+ const [textFieldValue, setTextFieldValue] = React.useState("");
+ const [textFieldOneValue, setTextFieldOneValue] = React.useState("");
const getAvailableWorkflows = (trigger_index) => {
fetch(globalUrl + "/api/v1/workflows", {
@@ -315,6 +338,146 @@ const OrgHeaderexpanded = (props) => {
);
+ const getAppIDs = async (appList) => {
+ fetch(globalUrl + "/api/v1/apps", {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ credentials: "include",
+ }).then((response) => {
+ if (response.status !== 200) {
+ toast("Failed getting app ids: ", response.reason);
+ console.log("Status not 200 for app ids :O!");
+ return;
+ }
+ return response.json();
+ }).then((responseJson) => {
+ if (responseJson !== undefined) {
+ // console.log("App ids: ", responseJson)
+ // console.log("App list: ", appList)
+ const filteredApps = responseJson.filter(app => appList.includes(app.name));
+ const appDetails = filteredApps.map(app => ({ name: app.name, id: app.id }));
+ return appDetails
+ // console.log("App IDs: ", appDetails)
+ }
+ }).catch((error) => {
+ console.log("Error getting app ids: " + error);
+ })
+}
+
+ // getting comms & cases app from app framework
+ var notificationAppList = [];
+ if (selectedOrganization.security_framework.cases && selectedOrganization.security_framework.cases.name.length > 0) {
+ notificationAppList = notificationAppList.concat(selectedOrganization.security_framework.cases);
+ }
+ if (selectedOrganization.security_framework.communication && selectedOrganization.security_framework.communication.name.length > 0) {
+ notificationAppList = notificationAppList.concat(selectedOrganization.security_framework.communication);
+ }
+
+ const mergeAuthData = (result, responseJson) => {
+ const updatedResult = result.map(item => {
+ const matches = responseJson.filter(authItem => authItem.app.name === item.name);
+ return {
+ ...item,
+ authentication_data: matches.length > 0 ? matches : null
+ };
+ });
+ return updatedResult;
+ };
+
+ const prepareNotificationAppList = async (appList) => {
+ // getting App ID,Authentication fields and saved auths for each app
+ var result = []
+ if (appList.length > 0) {
+ fetch(globalUrl + "/api/v1/apps", {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ credentials: "include",
+ }).then((response) => {
+ if (response.status !== 200) {
+ toast("Failed getting app ids: ", response.reason);
+ console.log("Status not 200 for app ids :O!");
+ return;
+ }
+ return response.json();
+ }).then((responseJson) => {
+ if (responseJson !== undefined) {
+ const filteredApps = responseJson.filter(app => appList.includes(app.name));
+ const appDetails = filteredApps.map(app => ({ name: app.name, id: app.id })); //mapped apps with IDs as sometime Ids were not correct in security framework
+ // console.log("appDetails: ", appDetails)
+ // result = appDetails
+
+ fetch(globalUrl + "/api/v1/apps/authentication", {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ credentials: "include",
+ })
+ .then((response) => {
+ if (response.status !== 200) {
+ toast(`Failed getting auth for : `, response.reason);
+ console.log("Status not 200 for app auth :O!");
+ return;
+ }
+ return response.json();
+ }).then(async (responseJson) => {
+ if (!responseJson.success) {
+ console.log("Could not get app auth")
+ return;
+ }
+ // console.log("responseJson of auth: ", responseJson.data)
+ result = await mergeAuthData(appDetails, responseJson.data)
+ console.log("merged auth data: ", result)
+ // console.log("result", result)
+ result.map(item => {
+ fetch(globalUrl + `/api/v1/apps/${item.id}/config`, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ credentials: "include",
+ }).then((response) => {
+ if (response.status !== 200) {
+ toast(`Failed getting config for ${item.id}: `, response.reason);
+ console.log("Status not 200 for app config :O!");
+ return;
+ }
+ return response.json();
+ }).then((responseJson) => {
+ if (!responseJson.success) {
+ console.log("Could not get app config")
+ return;
+ }
+ var decodedString = JSON.parse(atob(responseJson.app));
+ // console.log("dcodedString: ",decodedString)
+ item.auth_config = decodedString.authentication
+ item.large_image = decodedString.large_image
+ setNotificationAppDetails(result)
+ console.log("notificationAppDetails: ", notificationAppDetails)
+ // setSelectedAppAuth(decodedString.authentication)
+ }).catch((error) => {
+ console.log("Error getting app config: " + error);
+ toast("Error getting app config: " + error);
+ })
+ })
+ // get auth config for each app as it is required to render the modal when auth is not available
+ })
+ }
+ }).catch((error) => {
+ console.log("Error getting app ids: " + error);
+ })
+ }
+ }
+
+
const executeTestWorkflow = async (workflowid) => {
const data = { "execution_argument": '{"title":"THIS IS TEST ALERT","description":"TEST ALERT FROM SHUFFLE","reference_url": "shuffler.io"}' }
fetch(globalUrl + `/api/v1/workflows/${workflowid}/execute`, {
@@ -342,7 +505,7 @@ const OrgHeaderexpanded = (props) => {
const generateNotificationWorkflow = async (appname,appImage,appAuthId,projectId,issuetype) => {
//currently only supports JIRA figure out a way to support more apps
var workflowName = `[GENARATED] ${appname} notification workflow`
- var workflowDescription = "Generated by Shuffle for sending error notifications."
+ var workflowDescription = "Generated by Shuffle for sending info/error notifications."
var data = {
"name": workflowName,
"description": workflowDescription,
@@ -467,6 +630,121 @@ const generateNotificationWorkflow = async (appname,appImage,appAuthId,projectId
})
}
+const generateEmailNotificationWorkflow = async (appname,appImage,shuffleAPIKey,recepients) => {
+ //currently only supports figure out a way to support more apps
+ var workflowName = `[GENARATED] ${appname} notification workflow`
+ var workflowDescription = "Generated by Shuffle for sending info/error notifications."
+ var data = {
+ "name": workflowName,
+ "description": workflowDescription,
+ }
+
+ fetch(globalUrl + "/api/v1/workflows", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ body: JSON.stringify(data),
+ credentials: "include",
+ })
+ .then((response) => {
+ if (response.status !== 200) {
+ toast("Failed setting notification workflow: ", response.reason);
+ console.log("Status not 200 for workflows :O!");
+ return;
+ }
+ return response.json();
+ }).then((responseJson)=>{
+ if (responseJson !== undefined) {
+ console.log("Notification workflow created successfully")
+ var workflow_id = responseJson.id
+ if (appname.toLowerCase() === "email"){
+ console.log("updating workflow for email")
+ var workflowBody = {
+ "name": workflowName,
+ "Description": workflowDescription,
+ "id": workflow_id,
+ "actions": [
+ {
+ "app_name": "email",
+ "name": "send_email_shuffle",
+ "large_image":appImage,
+ "isStartNode": true,
+ "label": "send_email_shuffle",
+ "app_version": "1.3.0",
+ "parameters": [
+ {
+ "name": "apikey",
+ "value": shuffleAPIKey
+ },
+ {
+ "name": "recipients",
+ "value": recepients
+ },
+ {
+ "name": "subject",
+ "value": "$exec.title"
+ },
+ {
+ "name":"body",
+ "value":"$exec.description"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ fetch(globalUrl + `/api/v1/workflows/${workflow_id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ body: JSON.stringify(workflowBody),
+ credentials: "include",
+ })
+ .then((response) => {
+ if (response.status !== 200) {
+ toast("Failed setting notification workflow: ", response.reason);
+ console.log("Status not 200 for workflows :O!");
+ return;
+ }
+ return response.json();
+ }).then((responseJson)=>{
+ if (responseJson !== undefined) {
+ handleEditOrg(
+ orgName,
+ orgDescription,
+ selectedOrganization.id,
+ selectedOrganization.image,
+ {
+ app_download_repo: appDownloadUrl,
+ app_download_branch: appDownloadBranch,
+ workflow_download_repo: workflowDownloadUrl,
+ workflow_download_branch: workflowDownloadBranch,
+ notification_workflow: workflow_id,
+ documentation_reference: documentationReference,
+ },
+ {
+ sso_entrypoint: ssoEntrypoint,
+ sso_certificate: ssoCertificate,
+ client_id: openidClientId,
+ client_secret: openidClientSecret,
+ openid_authorization: openidAuthorization,
+ openid_token: openidToken,
+ }
+ )
+ console.log("Notification workflow updated successfully")
+ toast("Notification workflow updated successfully")
+ }
+ })
+ }
+ }).catch((error) => {
+ console.log("Error setting workflows: " + error);
+ })
+}
+
const getAppAuth = async (appName) => {
fetch(globalUrl + "/api/v1/apps/authentication", {
method: "GET",
@@ -497,6 +775,35 @@ const getAppAuth = async (appName) => {
})
}
+const getAppConfig = async (appId) => {
+ fetch(globalUrl + `/api/v1/apps/${appId}/config`, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ credentials: "include",
+ }).then((response) => {
+ if (response.status !== 200) {
+ toast(`Failed getting config for ${appId}: `, response.reason);
+ console.log("Status not 200 for app config :O!");
+ return;
+ }
+ return response.json();
+ }).then((responseJson) => {
+ if (!responseJson.success) {
+ console.log("Could not get app config")
+ return;
+ }
+ var decodedString = JSON.parse(atob(responseJson.app));
+ console.log("dcodedString: ",decodedString)
+ return decodedString.authentication
+ // setSelectedAppAuth(decodedString.authentication)
+ }).catch((error) => {
+ console.log("Error getting app config: " + error);
+ })
+}
+
const testWorkflowModal = notificationWorkflowTestModal ?
(
) : null
-// getting comms & cases app from app framework
-var notificationAppList = [];
-if (selectedOrganization.security_framework.cases && selectedOrganization.security_framework.cases.name.length > 0) {
-notificationAppList = notificationAppList.concat(selectedOrganization.security_framework.cases);
-}
-if (selectedOrganization.security_framework.communication && selectedOrganization.security_framework.communication.name.length > 0) {
-notificationAppList = notificationAppList.concat(selectedOrganization.security_framework.communication);
-}
const renderChips = (apps) => {
if (!apps || apps.length === 0) {
@@ -725,7 +1018,9 @@ if (!apps || apps.length === 0) {
variant="outlined"
onClick={() => {
console.log(`Clicked EMAIL`)
+ setSelectedAppDetails("email")
setNotificationWorkflowModal(true)
+ // setNotificationWorkflowModal(true)
}}
avatar={
}
/>
@@ -743,8 +1038,8 @@ return (
console.log(`Clicked ${app.name}`)
setSelectedAppDetails(app)
setNotificationWorkflowModal(true)
- getAppAuth(app.name)
- console.log(selectedAppDetails)
+ // getAppAuth(app.name)
+ console.log("selectedAppDEtails",selectedAppDetails)
}}
avatar={}
/>
@@ -763,7 +1058,7 @@ return (
{modalView}
{/*{testWorkflowModal} */}