diff --git a/backend/go-app/main.go b/backend/go-app/main.go index edd8e863..e775ebf5 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -1506,49 +1506,6 @@ func getUserCount() (int, error) { return count, nil } -func handleGetSchedules(resp http.ResponseWriter, request *http.Request) { - cors := handleCors(resp, request) - if cors { - return - } - - user, err := shuffle.HandleApiAuthentication(resp, request) - if err != nil { - log.Printf("Api authentication failed in set new workflowhandler: %s", err) - resp.WriteHeader(401) - resp.Write([]byte(`{"success": false}`)) - return - } - - if user.Role != "admin" { - resp.WriteHeader(401) - resp.Write([]byte(`{"success": false, "reason": "Admin required"}`)) - return - } - - ctx := context.Background() - schedules, err := getAllSchedules(ctx, user.ActiveOrg.Id) - if err != nil { - log.Printf("Failed getting schedules: %s", err) - resp.WriteHeader(401) - resp.Write([]byte(`{"success": false, "reason": "Couldn't get schedules"}`)) - return - } - - newjson, err := json.Marshal(schedules) - if err != nil { - log.Printf("Failed unmarshal: %s", err) - resp.WriteHeader(401) - resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed unpacking environments"}`))) - return - } - - //log.Printf("Existing environments: %s", string(newjson)) - - resp.WriteHeader(200) - resp.Write(newjson) -} - func checkAdminLogin(resp http.ResponseWriter, request *http.Request) { cors := handleCors(resp, request) if cors { @@ -5379,7 +5336,7 @@ func runInit(ctx context.Context) { // Gets schedules and starts them log.Printf("Relaunching schedules") - schedules, err := getAllSchedules(ctx, "ALL") + schedules, err := shuffle.GetAllSchedules(ctx, "ALL") if err != nil { log.Printf("Failed getting schedules during service init: %s", err) } else { @@ -6214,18 +6171,18 @@ func initHandlers() { /* Everything below here increases the counters*/ r.HandleFunc("/api/v1/workflows", shuffle.GetWorkflows).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/workflows", shuffle.SetNewWorkflow).Methods("POST", "OPTIONS") - r.HandleFunc("/api/v1/workflows/{key}", shuffle.GetSpecificWorkflow).Methods("GET", "OPTIONS") - r.HandleFunc("/api/v1/workflows/{key}", shuffle.SaveWorkflow).Methods("PUT", "OPTIONS") - r.HandleFunc("/api/v1/workflows/schedules", handleGetSchedules).Methods("GET", "OPTIONS") + r.HandleFunc("/api/v1/workflows/schedules", shuffle.HandleGetSchedules).Methods("GET", "OPTIONS") + r.HandleFunc("/api/v1/workflows/{key}/executions", shuffle.GetWorkflowExecutions).Methods("GET", "OPTIONS") + r.HandleFunc("/api/v1/workflows/{key}/executions/{key}/abort", shuffle.AbortExecution).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/workflows/{key}/schedule", scheduleWorkflow).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/download_remote", loadSpecificWorkflows).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/{key}/execute", executeWorkflow).Methods("GET", "POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/{key}/schedule/{schedule}", stopSchedule).Methods("DELETE", "OPTIONS") r.HandleFunc("/api/v1/workflows/{key}/outlook", createOutlookSub).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/{key}/outlook/{triggerId}", handleDeleteOutlookSub).Methods("DELETE", "OPTIONS") - r.HandleFunc("/api/v1/workflows/{key}/executions", shuffle.GetWorkflowExecutions).Methods("GET", "OPTIONS") - r.HandleFunc("/api/v1/workflows/{key}/executions/{key}/abort", shuffle.AbortExecution).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/workflows/{key}", deleteWorkflow).Methods("DELETE", "OPTIONS") + r.HandleFunc("/api/v1/workflows/{key}", shuffle.SaveWorkflow).Methods("PUT", "OPTIONS") + r.HandleFunc("/api/v1/workflows/{key}", shuffle.GetSpecificWorkflow).Methods("GET", "OPTIONS") // Triggers r.HandleFunc("/api/v1/hooks/new", shuffle.HandleNewHook).Methods("POST", "OPTIONS") diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index 3b780cdf..20ab9791 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -1079,7 +1079,7 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) { } if actionResult.Status == "WAITING" && actionResult.Action.AppName == "User Input" { - log.Printf("SHOULD WAIT A BIT AND RUN CLOUD STUFF WITH USER INPUT! WAITING!") + log.Printf("[INFO] SHOULD WAIT A BIT AND RUN CLOUD STUFF WITH USER INPUT! WAITING!") var trigger shuffle.Trigger err = json.Unmarshal([]byte(actionResult.Result), &trigger) @@ -4919,187 +4919,6 @@ func getWorkflowExecutions(resp http.ResponseWriter, request *http.Request) { resp.Write(newjson) } -func getAllSchedules(ctx context.Context, orgId string) ([]ScheduleOld, error) { - var schedules []ScheduleOld - - q := datastore.NewQuery("schedules").Filter("org = ", orgId) - if orgId == "ALL" { - q = datastore.NewQuery("schedules") - } - - _, err := dbclient.GetAll(ctx, q, &schedules) - if err != nil { - return []ScheduleOld{}, err - } - - return schedules, nil -} - -//FIXME: Add cursor -//func shuffle.GetAllWorkflowApps(ctx context.Context, maxLen int) ([]shuffle.WorkflowApp, error) { -// var apps []WorkflowApp -// query := datastore.NewQuery("workflowapp").Order("-edited").Limit(10) -// //query := datastore.NewQuery("workflowapp").Order("-edited").Limit(40) -// -// cacheKey := fmt.Sprintf("workflowapps-sorted-%d", maxLen) -// if value, found := requestCache.Get(cacheKey); found { -// parsedValue := value.(*[]WorkflowApp) -// log.Printf("[INFO] Returning %d apps from cache", len(*parsedValue)) -// return *parsedValue, nil -// } -// -// cursorStr := "" -// -// // NOT BEING UPDATED -// // FIXME: Update the app with the correct actions. HOW DOES THIS WORK?? -// // Seems like only actions are wrong. Could get the app individually. -// // Guessing it's a memory issue. -// //Actions []WorkflowAppAction `json:"actions" yaml:"actions" required:true datastore:"actions,noindex"` -// //errors.New(nil) -// var err error -// for { -// it := dbclient.Run(ctx, query) -// //_, err = it.Next(&app) -// for { -// var app WorkflowApp -// _, err := it.Next(&app) -// if err != nil { -// break -// } -// -// if app.Name == "Shuffle Subflow" { -// continue -// } -// -// found := false -// //log.Printf("ACTIONS: %d - %s", len(app.Actions), app.Name) -// for _, innerapp := range apps { -// if innerapp.Name == app.Name { -// found = true -// break -// } -// } -// -// if !found { -// apps = append(apps, app) -// } -// } -// -// if err != iterator.Done { -// //log.Printf("[INFO] Failed fetching results: %v", err) -// //break -// } -// -// // Get the cursor for the next page of results. -// nextCursor, err := it.Cursor() -// if err != nil { -// log.Printf("Cursorerror: %s", err) -// break -// } else { -// //log.Printf("NEXTCURSOR: %s", nextCursor) -// nextStr := fmt.Sprintf("%s", nextCursor) -// if cursorStr == nextStr { -// break -// } -// -// cursorStr = nextStr -// query = query.Start(nextCursor) -// //cursorStr = nextCursor -// //break -// } -// -// if len(apps) > maxLen { -// break -// } -// } -// -// if len(apps) > 20 { -// log.Printf("[INFO] Setting %d apps in cache", len(apps)) -// requestCache.Set(cacheKey, &apps, cache.DefaultExpiration) -// } -// -// //var allworkflowapps []WorkflowApp -// //_, err := dbclient.GetAll(ctx, query, &allworkflowapps) -// //if err != nil { -// // if strings.Contains(fmt.Sprintf("%s", err), "ResourceExhausted") { -// // //datastore.NewQuery("workflowapp").Limit(30).Order("-edited") -// // query = datastore.NewQuery("workflowapp").Order("-edited").Limit(25) -// // //q := q.Limit(25) -// // _, err := dbclient.GetAll(ctx, query, &allworkflowapps) -// // if err != nil { -// // return []WorkflowApp{}, err -// // } -// // } else { -// // return []WorkflowApp{}, err -// // } -// //} -// -// return apps, nil -//} - -//func shuffle.GetAllWorkflowAppAuth(ctx context.Context, OrgId string) ([]shuffle.AppAuthenticationStorage, error) { -// var allworkflowapps []AppAuthenticationStorage -// q := datastore.NewQuery("workflowappauth").Filter("org_id = ", OrgId) -// -// _, err := dbclient.GetAll(ctx, q, &allworkflowapps) -// if err != nil { -// return []AppAuthenticationStorage{}, err -// } -// -// return allworkflowapps, nil -//} -// -//func getWorkflowAppAuthDatastore(ctx context.Context, id string) (*AppAuthenticationStorage, error) { -// -// key := datastore.NameKey("workflowappauth", id, nil) -// appAuth := &AppAuthenticationStorage{} -// // New struct, to not add body, author etc -// if err := dbclient.Get(ctx, key, appAuth); err != nil { -// return &AppAuthenticationStorage{}, err -// } -// -// return appAuth, nil -//} -// -//func shuffle.SetWorkflowAppAuthDatastore(ctx context.Context, workflowappauth AppAuthenticationStorage, id string) error { -// timeNow := int64(time.Now().Unix()) -// if workflowappauth.Created == 0 { -// workflowappauth.Created = timeNow -// } -// -// workflowappauth.Edited = timeNow -// -// key := datastore.NameKey("workflowappauth", id, nil) -// -// // New struct, to not add body, author etc -// if _, err := dbclient.Put(ctx, key, &workflowappauth); err != nil { -// log.Printf("Error adding workflow app auth: %s", err) -// return err -// } -// -// return nil -//} -// -//// Hmm, so I guess this should use uuid :( -//// Consistency PLX -//func SetWorkflowAppDatastore(ctx context.Context, workflowapp WorkflowApp, id string) error { -// timeNow := int64(time.Now().Unix()) -// if workflowapp.Created == 0 { -// workflowapp.Created = timeNow -// } -// -// workflowapp.Edited = timeNow -// key := datastore.NameKey("workflowapp", id, nil) -// -// // New struct, to not add body, author etc -// if _, err := dbclient.Put(ctx, key, &workflowapp); err != nil { -// log.Printf("Error adding workflow app: %s", err) -// return err -// } -// -// return nil -//} - // Starts a new webhook func handleStopHook(resp http.ResponseWriter, request *http.Request) { cors := handleCors(resp, request) @@ -5372,7 +5191,7 @@ func handleUserInput(trigger shuffle.Trigger, organizationId string, workflowId return err } - log.Printf("Should send email to %s during execution.", email) + log.Printf("[INFO] Should send email to %s during execution.", email) } if strings.Contains(triggerType, "sms") { action := shuffle.CloudSyncJob{ diff --git a/frontend/src/components/ConfigureWorkflow.jsx b/frontend/src/components/ConfigureWorkflow.jsx index 0e83f81b..b311dc95 100644 --- a/frontend/src/components/ConfigureWorkflow.jsx +++ b/frontend/src/components/ConfigureWorkflow.jsx @@ -1,13 +1,24 @@ import React, {useState} from 'react'; -import {Typography, } from '@material-ui/core'; +import { InputAdornment, Tooltip, TextField, CircularProgress, ButtonGroup, Button, Avatar, ListItemAvatar, Typography, List, ListItem, ListItemText} from '@material-ui/core'; +import {FavoriteBorder as FavoriteBorderIcon} from '@material-ui/icons'; +// Handles workflow updates on first open to highlight the issues of the workflow +// Variables +// Action (exists, missing fields) +// Action auth +// Triggers +// +// Specifically used for UNSAVED workflows only? const Workflow = (props) => { - const { workflow, appAuthentication, apps } = props + const { globalUrl, theme, workflow, appAuthentication, setSelectedAction, setAuthenticationModalOpen, setSelectedApp, apps, selectedAction,setConfigureWorkflowModalOpen, saveWorkflow, newWebhook, submitSchedule, referenceUrl, isCloud, } = props const [requiredActions, setRequiredActions] = React.useState([]) + const [requiredVariables, setRequiredVariables] = React.useState([]) + const [requiredTriggers, setRequiredTriggers] = React.useState([]) + const [previousAuth, setPreviousAuth] = React.useState(appAuthentication) const [firstLoad, setFirstLoad] = React.useState("") - - // Rofl + var finished = false + if (workflow === undefined || workflow === null) { return null } @@ -20,63 +31,349 @@ const Workflow = (props) => { return null } + const getApp = (actionId, appId) => { + fetch(globalUrl+"/api/v1/apps/"+appId+"/config?openapi=false", { + headers: { + 'Accept': 'application/json', + }, + credentials: "include", + }) + .then((response) => { + if (response.status === 200) { + //alert.success("Successfully GOT app "+appId) + } else { + alert.error("Failed getting app") + } + + return response.json() + }) + .then((responseJson) => { + console.log("ACTION: ", responseJson) + if (responseJson.actions !== undefined && responseJson.actions !== null) { + } + }) + .catch(error => { + alert.error(error.toString()) + }); + } + if (firstLoad.length === 0 || firstLoad !== workflow.id) { + if (finished) { + setConfigureWorkflowModalOpen(false) + return null + } + setFirstLoad(workflow.id) const newactions = [] for (var key in workflow.actions) { + const action = workflow.actions[key] var newaction = { - "large_image": "", - "app_name": "", - "app_version": "", + "large_image": action.large_image, + "app_name": action.app_name, + "app_version": action.app_version, + "activation_done": false, "must_activate": false, "must_authenticate": false, + "auth_done": false, "action_ids": [], + "action": action, + "app": {}, } - const action = workflow.actions[key] - console.log(action) - const app = apps.find(app => app.name === action.app_name && app.app_version === action.app_version) + const app = apps.find(app => app.name === action.app_name && (app.app_version === action.app_version || app.loop_versions.includes(action.app_version))) if (app === undefined || app === null) { - console.log("COULDNT FIND APP - SEARCH BACKEND") + console.log("App not found!") - newaction.app_name = action.app_name - newaction.app_version = action.app_version + newaction.must_activate = true } else { - newaction.app_name = app.name - newaction.app_version = app.app_version - - console.log("APP: ", app) if (action.authentication_id === "" && app.authentication.required === true) { - console.log("Requires auth!") newaction.must_authenticate = true newaction.action_ids.push(action.id) } - //newaction.app_name = action.app_name - //newaction.app_name = action.app_version + newaction.app = app } if (action.errors !== undefined && action.errors !== null && action.errors.length > 0) { - console.log("Has errors!") + console.log("Node has errors!: ", action.errors) } - console.log("NEWACTION: ", newaction) - if (newaction.must_authenticate || newaction.must_activate) { - newactions.push(newaction) + if (newaction.must_authenticate) { + var authenticationOptions = [] + for (var key in appAuthentication) { + const auth = appAuthentication[key] + if (auth.app.name === app.name && auth.active) { + console.log("Found auth: ", auth) + authenticationOptions.push(auth) + newaction.authenticationId = auth.id + break + } + } + + console.log("APPAUTH: ", app.authentication, action) + if (newaction.authenticationId === null || newaction.authenticationId === undefined || newaction.authenticationId.length === "") { + console.log("FAILED to authentication node!") + newactions.push(newaction) + } else { + console.log("Skipping node as it's already authenticated.") + newaction.authentication = authenticationOptions + workflow.actions[key] = newaction + } + } else if (newaction.must_activate) { + + if (newactions.find(tmpaction => tmpaction.app_id === newaction.app_id && tmpaction.app_name === newaction.app_name) !== undefined) { + console.log("Action already found.") + } else { + newactions.push(newaction) + } } } + for (var key in workflow.workflow_variables) { + const variable = workflow.workflow_variables[key] + if (variable.value === undefined || variable.value === undefined || variable.value.length < 2) { + variable.value = "" + variable.index = key + requiredVariables.push(variable) + } + } + + for (var key in workflow.triggers) { + var trigger = workflow.triggers[key] + trigger.index = key + + if (trigger.status === "running") { + continue + } + + if (trigger.trigger_type === "SUBFLOW" || trigger.trigger_type === "USERINPUT") { + continue + } + + requiredTriggers.push(trigger) + } + + if (requiredTriggers.length === 0 && requiredVariables.length === 0 && newactions.length === 0) { + setConfigureWorkflowModalOpen(false) + } + + console.log("VARIABLES: ", requiredVariables) console.log("ACTIONS: ", newactions) + setRequiredTriggers(requiredTriggers) + setRequiredVariables(requiredVariables) setRequiredActions(newactions) } + console.log("AUTH: ", appAuthentication) + if (appAuthentication.length !== previousAuth.length) { + console.log("APP AUTH CHANGED!") + var newactions = [] + for (var actionkey in requiredActions) { + var newaction = requiredActions[actionkey] + const app = newaction.app + + for (var key in appAuthentication) { + const auth = appAuthentication[key] + if (auth.app.name === app.name && auth.active) { + console.log("FOUND AUTH FOR: ", auth.app.name) + newaction.auth_done = true + break + } + } + + newactions.push(newaction) + } + + setRequiredActions(newactions) + setPreviousAuth(appAuthentication) + // Set auth done to true + //"auth_done": false + } + + const TriggerSection = (props) => { + const {trigger} = props + + console.log(trigger) + + return ( +
+ + + + {trigger.label} + + + + {trigger.trigger_type === "WEBHOOK" && trigger.status !== "running" ? + + : + trigger.trigger_type === "SCHEDULE" && trigger.status !== "running" ? + + : + null} + {/* + + + ) + }} + fullWidth + color="primary" + type={"text"} + placeholder={`New value for ${trigger.name}`} + onChange={(event) => { + console.log("NEW VALUE ON INDEX", trigger.value) + }} + onBlur={(event) => { + //workflow.variables[variable.index] = event.target.value + }} + /> + } + style={{}} + /> + */} + +
+ ) + } + + const VariableSection = (props) => { + const {variable} = props + + //Name: {variable.name} - {variable.value}. + return ( + + + + + + + + + + ) + }} + fullWidth + color="primary" + type={"text"} + placeholder={`New value for ${variable.name}`} + onChange={(event) => { + console.log("NEW VALUE ON INDEX", variable.index, variable.value) + }} + onBlur={(event) => { + workflow.workflow_variables[variable.index].value = event.target.value + }} + /> + } + style={{}} + /> + + ) + } + const AppSection = (props) => { const {action} = props return ( -
- Name: {action.app_name}:{action.app_version}. -
+ + + + {action.app_name} + + + + {action.must_authenticate ? + action.auth_done ? +
+ +
+ : + selectedAction.app_name === action.app_name ? + + : + + : + null} + {action.must_activate ? + + : null} +
) } @@ -84,12 +381,62 @@ const Workflow = (props) => { return (
- Workflow: {workflow.id} - {requiredActions.map((data, index) => { - return ( - - ) - })} + {workflow.name} + + The following configuration makes the workflow ready immediately. + + {requiredActions.length > 0 ? + + Actions + + {requiredActions.map((data, index) => { + return ( + + ) + })} + + + : null} + + {requiredVariables.length > 0 ? + + Variables + {requiredVariables.map((data, index) => { + return ( + + ) + })} + + : null} + + + {requiredTriggers.length > 0 ? + + Triggers + {requiredTriggers.map((data, index) => { + return ( + + ) + })} + + : null } +
+ + + + +
) } diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index b73af2fb..3749f4d0 100644 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -459,9 +459,9 @@ const Admin = (props) => { // FIXME: Set up features - Object.keys(responseJson.sync_features).map(function(key, index) { - //console.log(responseJson.sync_features[key]) - }) + //Object.keys(responseJson.sync_features).map(function(key, index) { + // //console.log(responseJson.sync_features[key]) + //}) //setOrgName(responseJson.name) //setOrgDescription(responseJson.description) @@ -849,7 +849,6 @@ const Admin = (props) => { return response.json() }) .then((responseJson) => { - console.log(responseJson) setSchedules(responseJson) }) .catch(error => { @@ -988,34 +987,45 @@ const Admin = (props) => { }); } + const views = { + 0: "organization", + 1: "users", + 2: "app_auth", + 3: "files", + 4: "schedules", + 5: "environments", + 6: "categories", + } const setConfig = (event, newValue) => { + console.log("Value: ", newValue) + + setCurTab(parseInt(newValue)) if (newValue === 1) { + document.title = "Shuffle - admin - users" getUsers() } else if (newValue === 2) { + document.title = "Shuffle - admin - app authentication" getAppAuthentication() } else if (newValue === 3) { + document.title = "Shuffle - admin - files" getFiles() } else if (newValue === 4) { + document.title = "Shuffle - admin - schedules" getSchedules() } else if (newValue === 5) { + document.title = "Shuffle - admin - environments" getEnvironments() } else if (newValue === 6) { + document.title = "Shuffle - admin - orgs" getOrgs() + } else { + document.title = "Shuffle - admin" } if (newValue === 6) { console.log("Should get apps for categories.") } - const views = { - 0: "organization", - 1: "users", - 2: "app_auth", - 3: "environments", - 4: "schedules", - 5: "files", - 6: "categories", - } //var theURL = window.location.pathname //FIXME: Add url edits @@ -1027,33 +1037,21 @@ const Admin = (props) => { //window.location.pathame = newpath setModalUser({}) - setCurTab(newValue) } if (firstRequest) { setFirstRequest(false) + document.title = "Shuffle - admin" if (!isCloud) { getUsers() } else { getSettings() } - const views = { - "organization": 0, - "users": 1, - "app_auth": 2, - "environments": 3, - "schedules": 4, - "files": 5, - } - if (props.match.params.key !== undefined) { - const tmpitem = views[props.match.params.key] - if (tmpitem !== undefined) { - //setCurTab(tmpitem) - setConfig("", tmpitem) - } + //const tmpitem = views[props.match.params.key] + setConfig("", props.match.params.key) } } @@ -2092,11 +2090,13 @@ const Admin = (props) => { : - - - - - + + + + + + + } style={{minWidth: 100, maxWidth: 100, overflow: "hidden"}} @@ -2116,11 +2116,13 @@ const Admin = (props) => { - { - downloadFile(file) - }}> - - + + { + downloadFile(file) + }}> + + + style={{minWidth: 75, maxWidth: 75, overflow: "hidden"}} /> diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 96bdb439..b32fb4b2 100644 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -128,7 +128,7 @@ const AngularWorkflow = (props) => { const [rightSideBarOpen, setRightSideBarOpen] = React.useState(false) const [showSkippedActions, setShowSkippedActions] = React.useState(false) const [lastExecution, setLastExecution] = React.useState("") - const [configureWorkflowModalOpen, setConfigureWorkflowModalOpen] = React.useState(false) + const [configureWorkflowModalOpen, setConfigureWorkflowModalOpen] = React.useState(true) const [curpath, setCurpath] = useState(typeof window === 'undefined' || window.location === undefined ? "" : window.location.pathname) // 0 = normal, 1 = just done, 2 = normal @@ -707,8 +707,10 @@ const AngularWorkflow = (props) => { newBranches.push(parsedElement) } else { if (type === "ACTION") { - // FIXME - check whether position is new to not fuck up params etc. - var curworkflowAction = useworkflow.actions.find(a => a.id === cyelements[key].data()["id"]) + const cyelement = cyelements[key].data() + const elementid = cyelement.id === undefined || cyelement.id === null ? cyelement["_id"] : cyelement.id + + var curworkflowAction = useworkflow.actions.find(a => a !== undefined && (a["id"] === elementid || a["_id"] === elementid)) if (curworkflowAction === undefined) { curworkflowAction = cyelements[key].data() } @@ -1114,13 +1116,13 @@ const AngularWorkflow = (props) => { const getWorkflow = () => { fetch(globalUrl+"/api/v1/workflows/"+props.match.params.key, { - method: 'GET', + method: 'GET', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, - credentials: "include", - }) + credentials: "include", + }) .then((response) => { if (response.status !== 200) { console.log("Status not 200 for workflows :O!") @@ -1146,6 +1148,12 @@ const AngularWorkflow = (props) => { setWorkflow(responseJson) setWorkflowDone(true) + + //console.log(responseJson) + // Add error checks + if (!responseJson.public && (!responseJson.previously_saved || (!responseJson.is_valid || (responseJson.errors !== undefined || responseJson.errors !== null || responseJson.errors !== responseJson.errors.length > 0)))) { + setConfigureWorkflowModalOpen(true) + } }) .catch(error => { alert.error(error.toString()) @@ -1289,11 +1297,6 @@ const AngularWorkflow = (props) => { //console.log("BRANCHES: ", branch) if (data.type === "ACTION") { - - - // FIXME - unselect - //console.log(cy.elements('[_id!="${data._id}"]`)) - // Does it choose the wrong action? var curaction = workflow.actions.find(a => a.id === data.id) if (!curaction || curaction === undefined) { //event.target.unselect() @@ -1301,15 +1304,27 @@ const AngularWorkflow = (props) => { return } - - console.log(apps) + //console.log(apps) const curapp = apps.find(a => a.name === curaction.app_name && (a.app_version === curaction.app_version || a.loop_versions.includes(curaction.app_version))) if (!curapp || curapp === undefined) { alert.error(`App ${curaction.app_name}:${curaction.app_version} not found. Is it activated?`) + + const tmpapp = { + name: curaction.app_name, + app_name: curaction.app_name, + app_version: curaction.app_version, + id: curaction.app_id, + actions: [curaction], + } + + console.log(tmpapp) + console.log(curaction) + setSelectedApp(tmpapp) + setSelectedAction(curaction) //return } else { - console.log("AUTHENTICATION: ", curapp.authentication) + //console.log("AUTHENTICATION: ", curapp.authentication) setRequiresAuthentication(curapp.authentication.required && curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null) if (curapp.authentication.required) { // Setup auth here :) @@ -2147,6 +2162,7 @@ const AngularWorkflow = (props) => { } const deleteVariable = (variableName) => { + console.log("Delete:" ,variableName) workflow.workflow_variables = workflow.workflow_variables.filter(data => data.name !== variableName) setWorkflow(workflow) } @@ -2208,7 +2224,7 @@ const AngularWorkflow = (props) => { setOpen(false) setAnchorEl(null) }} - > + > { setOpen(false) @@ -4232,8 +4248,6 @@ const AngularWorkflow = (props) => { return response.json() }) .then((responseJson) => { - console.log(responseJson) - if (setApp && responseJson.actions !== undefined && responseJson.actions !== null) { if (selectedApp.versions !== undefined && selectedApp.versions !== null) { responseJson.versions = selectedApp.versions @@ -4244,17 +4258,14 @@ const AngularWorkflow = (props) => { } var foundAction = responseJson.actions.find(action => action.name === selectedAction.name) - console.log("Old : ", selectedAction) - console.log("Found: ", foundAction) if (foundAction !== null && foundAction !== undefined) { for (var paramkey in foundAction.parameters) { const param = foundAction.parameters[paramkey] const foundParam = selectedAction.parameters.find(item => item.name === param.name) if (foundParam === undefined) { - console.log("COULDNT find Param: ", param) + //console.log("COULDNT find Param: ", param) } else { - console.log("FoundP: ", foundParam) foundAction.parameters[paramkey] = foundParam } } @@ -7878,9 +7889,15 @@ const AngularWorkflow = (props) => { } } + console.log("Action: ", selectedAction) selectedAction.authentication_id = authenticationOption.id selectedAction.selectedAuthentication = authenticationOption - selectedAction.authentication.push(authenticationOption) + if (selectedAction.authentication === undefined || selectedAction.authentication === null) { + selectedAction.authentication = [authenticationOption] + } else { + selectedAction.authentication.push(authenticationOption) + } + setSelectedAction(selectedAction) var newAuthOption = JSON.parse(JSON.stringify(authenticationOption)) @@ -7898,6 +7915,12 @@ const AngularWorkflow = (props) => { setNewAppAuth(newAuthOption) //appAuthentication.push(newAuthOption) //setAppAuthentication(appAuthentication) + // + + if (configureWorkflowModalOpen) { + setSelectedAction({}) + } + setUpdate(authenticationOption.id) /* @@ -8024,18 +8047,23 @@ const AngularWorkflow = (props) => { { - setConfigureWorkflowModalOpen(false) + //setConfigureWorkflowModalOpen(false) }} PaperProps={{ style: { backgroundColor: surfaceColor, color: "white", minWidth: 600, - padding: 15, + padding: 50, }, }} > - + { + setConfigureWorkflowModalOpen(false) + }}> + + + : null @@ -8046,6 +8074,10 @@ const AngularWorkflow = (props) => { open={authenticationModalOpen} onClose={() => { //setAuthenticationModalOpen(false) + // + if (configureWorkflowModalOpen) { + setSelectedAction({}) + } }} PaperProps={{ style: { @@ -8056,6 +8088,14 @@ const AngularWorkflow = (props) => { }, }} > + { + setAuthenticationModalOpen(false) + if (configureWorkflowModalOpen) { + setSelectedAction({}) + } + }}> + +
Authentication for {selectedApp.name}
: null diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx index 5d1dad88..8a2c9176 100644 --- a/frontend/src/views/Workflows.jsx +++ b/frontend/src/views/Workflows.jsx @@ -585,7 +585,7 @@ const Workflows = (props) => { for (var subkey in data.actions[key].parameters) { const param = data.actions[key].parameters[subkey] - if (param.name.includes("key") || param.name.includes("user") || param.name.includes("pass") || param.name.includes("api") || param.name.includes("auth") || param.name.includes("secret")) { + if (param.name.includes("key") || param.name.includes("user") || param.name.includes("pass") || param.name.includes("api") || param.name.includes("auth") || param.name.includes("secret") || param.name.includes("domain") || param.name.includes("url")) { // FIXME: This may be a vuln if api-keys are generated that start with $ if (param.value.startsWith("$")) { console.log("Skipping field, as it's referencing a variable") @@ -645,8 +645,8 @@ const Workflows = (props) => { let exportFileDefaultName = data.name+'.json'; data = sanitizeWorkflow(data) - //console.log("EXPORT: ", data) - //return + // Add correct ID's for triggers + // Add mag let dataStr = JSON.stringify(data) let dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);