From 7c0dda2c52a57f2d62e4d90d958786c764c62d34 Mon Sep 17 00:00:00 2001 From: frikky Date: Fri, 17 Jul 2020 07:00:13 +0200 Subject: [PATCH] #26: Fixed app authentication issues --- backend/go-app/walkoff.go | 114 ++++++++++++++++++++++++-------- frontend/src/Admin.js | 61 +++++++++++------ frontend/src/AngularWorkflow.js | 38 +++++++---- 3 files changed, 153 insertions(+), 60 deletions(-) diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index 39ecabaf..e8d8bdf7 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -122,16 +122,17 @@ type WorkflowApp struct { } type WorkflowAppActionParameter struct { - Description string `json:"description" datastore:"description" yaml:"description"` - ID string `json:"id" datastore:"id" yaml:"id,omitempty"` - Name string `json:"name" datastore:"name" yaml:"name"` - Example string `json:"example" datastore:"example" yaml:"example"` - Value string `json:"value" datastore:"value" yaml:"value,omitempty"` - Multiline bool `json:"multiline" datastore:"multiline" yaml:"multiline"` - ActionField string `json:"action_field" datastore:"action_field" yaml:"actionfield,omitempty"` - Variant string `json:"variant" datastore:"variant" yaml:"variant,omitempty"` - Required bool `json:"required" datastore:"required" yaml:"required"` - Schema SchemaDefinition `json:"schema" datastore:"schema" yaml:"schema"` + Description string `json:"description" datastore:"description" yaml:"description"` + ID string `json:"id" datastore:"id" yaml:"id,omitempty"` + Name string `json:"name" datastore:"name" yaml:"name"` + Example string `json:"example" datastore:"example" yaml:"example"` + Value string `json:"value" datastore:"value" yaml:"value,omitempty"` + Multiline bool `json:"multiline" datastore:"multiline" yaml:"multiline"` + ActionField string `json:"action_field" datastore:"action_field" yaml:"actionfield,omitempty"` + Variant string `json:"variant" datastore:"variant" yaml:"variant,omitempty"` + Required bool `json:"required" datastore:"required" yaml:"required"` + Configuration bool `json:"configuration" datastore:"configuration" yaml:"configuration"` + Schema SchemaDefinition `json:"schema" datastore:"schema" yaml:"schema"` } type SchemaDefinition struct { @@ -621,6 +622,7 @@ func handleGetWorkflowqueueConfirm(resp http.ResponseWriter, request *http.Reque resp.Write([]byte("OK")) } +// FIXME: Authenticate this one (especially since we have a default: shuffle) func handleGetWorkflowqueue(resp http.ResponseWriter, request *http.Request) { cors := handleCors(resp, request) if cors { @@ -1410,7 +1412,6 @@ func updateAppAuth(auth AppAuthenticationStorage, workflowId, nodeId string, add // Check if node exists workflowFound = true workflowIndex = index - log.Printf("Found workflow: %#v", workflow) for _, actionId := range workflow.Nodes { if actionId == nodeId { nodeFound = true @@ -1721,19 +1722,18 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { } } - // FIXME: Check auth + // Check auth + // 1. Find the auth in question + // 2. Update the node and workflow info in the auth + // 3. Get the values in the auth and add them to the action values if len(action.AuthenticationId) > 0 { authFound := false - for _, auth := range allAuths { if auth.Id == action.AuthenticationId { authFound = true - // Fix stuff here - err := updateAppAuth(auth, workflow.ID, action.ID, true) - if err != nil { - log.Printf("Failed updating the app auth reference: %s (not critical)", err) - } + // Updates the auth item itself IF necessary + go updateAppAuth(auth, workflow.ID, action.ID, true) break } } @@ -1796,9 +1796,6 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { for _, param := range curappaction.Parameters { found := false - // FIXME: Check if the name exists in authentication.parameters and doesn't use the auth required field - // If it does, the auth should be saved somehow. - // Handles check for parameter exists + value not empty in used fields for _, actionParam := range action.Parameters { if actionParam.Name == param.Name { @@ -1817,6 +1814,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { } newParams = append(newParams, actionParam) + break } } @@ -2308,6 +2306,8 @@ func handleExecution(id string, workflow Workflow, request *http.Request) (Workf // FIXME - remove this? newActions := []Action{} defaultResults := []ActionResult{} + + allAuths := []AppAuthenticationStorage{} for _, action := range workflowExecution.Workflow.Actions { action.LargeImage = "" if action.ID == workflowExecution.Start { @@ -2319,6 +2319,47 @@ func handleExecution(id string, workflow Workflow, request *http.Request) (Workf return WorkflowExecution{}, fmt.Sprintf("Environment is not defined for %s", action.Name), errors.New("Environment not defined!") } + // FIXME: Authentication parameters + if len(action.AuthenticationId) > 0 { + if len(allAuths) == 0 { + allAuths, err = getAllWorkflowAppAuth(ctx) + if err != nil { + log.Printf("Api authentication failed in get all app auth: %s", err) + return WorkflowExecution{}, fmt.Sprintf("Api authentication failed in get all app auth: %s", err), err + } + } + + curAuth := AppAuthenticationStorage{Id: ""} + for _, auth := range allAuths { + if auth.Id == action.AuthenticationId { + curAuth = auth + break + } + } + + if len(curAuth.Id) == 0 { + return WorkflowExecution{}, fmt.Sprintf("Auth ID %s doesn't exist", action.AuthenticationId), errors.New(fmt.Sprintf("Auth ID %s doesn't exist", action.AuthenticationId)) + } + + // Rebuild params with the right data. This is to prevent issues on the frontend + newParams := []WorkflowAppActionParameter{} + for _, param := range action.Parameters { + + for _, authparam := range curAuth.Fields { + if param.Name == authparam.Key { + log.Printf("Name: %s - value: %s", param.Name, param.Value) + param.Value = authparam.Value + log.Printf("Name: %s - value: %s\n", param.Name, param.Value) + break + } + } + + newParams = append(newParams, param) + } + + action.Parameters = newParams + } + newActions = append(newActions, action) // If the node is NOT found, it's supposed to be set to SKIPPED, @@ -3471,8 +3512,8 @@ func getAppAuthentication(resp http.ResponseWriter, request *http.Request) { //} ctx := context.Background() allAuths, err := getAllWorkflowAppAuth(ctx) - if userErr != nil { - log.Printf("Api authentication failed in get all app auth: %s", userErr) + if err != nil { + log.Printf("Api authentication failed in get all app auth: %s", err) resp.WriteHeader(401) resp.Write([]byte(`{"success": false}`)) return @@ -3484,6 +3525,17 @@ func getAppAuthentication(resp http.ResponseWriter, request *http.Request) { return } + // Cleanup for frontend + newAuth := []AppAuthenticationStorage{} + for _, auth := range allAuths { + newAuthField := auth + for index, _ := range auth.Fields { + newAuthField.Fields[index].Value = "" + } + + newAuth = append(newAuth, newAuthField) + } + newbody, err := json.Marshal(allAuths) if err != nil { log.Printf("Failed unmarshalling all app auths: %s", err) @@ -4586,20 +4638,24 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin appendParams := []WorkflowAppActionParameter{} for _, fieldname := range workflowapp.Authentication.Parameters { found := false - for _, param := range action.Parameters { + for index, param := range action.Parameters { if param.Name == fieldname.Name { found = true + + action.Parameters[index].Configuration = true + log.Printf("Set config to true for field %s!", param.Name) break } } if !found { appendParams = append(appendParams, WorkflowAppActionParameter{ - Name: fieldname.Name, - Description: fieldname.Description, - Example: fieldname.Example, - Required: fieldname.Required, - Schema: fieldname.Schema, + Name: fieldname.Name, + Description: fieldname.Description, + Example: fieldname.Example, + Required: fieldname.Required, + Configuration: true, + Schema: fieldname.Schema, }) } } diff --git a/frontend/src/Admin.js b/frontend/src/Admin.js index ca71c372..6fce60d1 100644 --- a/frontend/src/Admin.js +++ b/frontend/src/Admin.js @@ -21,6 +21,7 @@ import DialogTitle from '@material-ui/core/DialogTitle'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; +import CachedIcon from '@material-ui/icons/Cached'; const surfaceColor = "#27292D" const inputColor = "#383B40" @@ -305,6 +306,7 @@ const Admin = (props) => { }) .then((responseJson) => { if (responseJson.success) { + console.log(responseJson.data) setAuthentication(responseJson.data) } else { alert.error("Failed getting authentications") @@ -333,6 +335,7 @@ const Admin = (props) => { return response.json() }) .then((responseJson) => { + console.log(responseJson) setEnvironments(responseJson) }) .catch(error => { @@ -536,7 +539,7 @@ const Admin = (props) => {
{ const usersView = curTab === 0 ?
-

- User management -

+
+

User management

+ Add, edit, block or change passwords +
+ @@ -941,6 +956,10 @@ const Admin = (props) => { primary="Name" style={{minWidth: 150, maxWidth: 150}} /> + { primary={environment.Name} style={{minWidth: 150, maxWidth: 150, overflow: "hidden"}} /> + @@ -960,11 +983,11 @@ const Admin = (props) => { ) })} - -
: null + // primary={environment.Registered ? "true" : "false"} + const setConfig = (event, newValue) => { if (newValue === 1) { getAppAuthentication() diff --git a/frontend/src/AngularWorkflow.js b/frontend/src/AngularWorkflow.js index 03e02b23..2e316983 100644 --- a/frontend/src/AngularWorkflow.js +++ b/frontend/src/AngularWorkflow.js @@ -54,6 +54,7 @@ import KeyboardArrowLeftIcon from '@material-ui/icons/KeyboardArrowLeft'; import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight'; import ArrowBackIcon from '@material-ui/icons/ArrowBack'; import SettingsIcon from '@material-ui/icons/Settings'; +import LockOpenIcon from '@material-ui/icons/LockOpen'; import * as cytoscape from 'cytoscape'; import * as edgehandles from 'cytoscape-edgehandles'; @@ -926,7 +927,9 @@ const AngularWorkflow = (props) => { const newfields = {} for (var filterkey in item.fields) { - newfields[item.fields[filterkey].key] = item.fields[filterkey].value + if (item.fields[filterkey] !== undefined) { + newfields[item.fields[filterkey].key] = item.fields[filterkey].value + } } item.fields = newfields @@ -2585,9 +2588,10 @@ const AngularWorkflow = (props) => { if (!selectedAction.auth_not_required && selectedAction.selectedAuthentication !== undefined && selectedAction.selectedAuthentication.fields !== undefined) { if (selectedAction.selectedAuthentication.fields[data.name] !== undefined) { // FIXME - this should be skipped in the frontend - selectedActionParameters[count].value = selectedAction.selectedAuthentication.fields[data.name] - selectedAction.parameters[count].value = selectedAction.selectedAuthentication.fields[data.name] - setSelectedAction(selectedAction) + //selectedActionParameters[count].value = selectedAction.selectedAuthentication.fields[data.name] + //selectedAction.parameters[count].value = selectedAction.selectedAuthentication.fields[data.name] + //setSelectedAction(selectedAction) + return null } } @@ -2757,8 +2761,16 @@ const AngularWorkflow = (props) => { } return (
-
-
+
+ {data.configuration === true ? + + { + setAuthenticationModalOpen(true) + }}/> + + : +
+ }
{data.name}
@@ -3036,7 +3048,7 @@ const AngularWorkflow = (props) => { /> {selectedAction.authentication.length === 0 && requiresAuthentication ?
- Authentication (reusable): + Authenticate {selectedApp.name}: