diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 8ea76242..3bc29f9f 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -238,7 +238,7 @@ type AppInfo struct { type ScheduleOld struct { Id string `json:"id" datastore:"id"` Seconds int `json:"seconds" datastore:"seconds"` - WorkflowId string `json:"workflow_id datastore:"workflow_id", ` + WorkflowId string `json:"workflow_id" datastore:"workflow_id", ` Argument string `json:"argument" datastore:"argument"` AppInfo AppInfo `json:"appinfo" datastore:"appinfo,noindex"` Finished bool `json:"finished" finished:"id"` @@ -1803,6 +1803,49 @@ func getUserCount() (int, error) { return count, nil } +func handleGetSchedules(resp http.ResponseWriter, request *http.Request) { + cors := handleCors(resp, request) + if cors { + return + } + + user, err := 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) + 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 handleGetEnvironments(resp http.ResponseWriter, request *http.Request) { cors := handleCors(resp, request) if cors { @@ -2635,6 +2678,21 @@ func handleDeleteSchedule(resp http.ResponseWriter, request *http.Request) { return } + user, err := 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 + } + + // FIXME: IAM - Get workflow and check owner + if user.Role != "admin" { + resp.WriteHeader(401) + resp.Write([]byte(`{"success": false, "reason": "Admin required"}`)) + return + } + location := strings.Split(request.URL.String(), "/") var workflowId string @@ -2655,7 +2713,7 @@ func handleDeleteSchedule(resp http.ResponseWriter, request *http.Request) { } ctx := context.Background() - err := DeleteKey(ctx, "schedules", workflowId) + err = DeleteKey(ctx, "schedules", workflowId) if err != nil { resp.WriteHeader(401) resp.Write([]byte(`{"success": false, "message": "Can't delete"}`)) @@ -5914,6 +5972,7 @@ func init() { /* Everything below here increases the counters*/ r.HandleFunc("/api/v1/workflows", getWorkflows).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/workflows", setNewWorkflow).Methods("POST", "OPTIONS") + r.HandleFunc("/api/v1/workflows/schedules", handleGetSchedules).Methods("GET", "OPTIONS") //r.HandleFunc("/api/v1/workflows/{key}/execute_fs", executeWorkflowFS) r.HandleFunc("/api/v1/workflows/{key}/execute", executeWorkflow).Methods("GET", "POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/{key}/schedule", scheduleWorkflow).Methods("POST", "OPTIONS") diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index beda7595..5fa52be3 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -2021,6 +2021,7 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) { } func stopSchedule(resp http.ResponseWriter, request *http.Request) { + log.Printf("Delete?") cors := handleCors(resp, request) if cors { return @@ -2079,19 +2080,6 @@ func stopSchedule(resp http.ResponseWriter, request *http.Request) { return } - if len(workflow.Actions) == 0 { - workflow.Actions = []Action{} - } - if len(workflow.Branches) == 0 { - workflow.Branches = []Branch{} - } - if len(workflow.Triggers) == 0 { - workflow.Triggers = []Trigger{} - } - if len(workflow.Errors) == 0 { - workflow.Errors = []string{} - } - err = deleteSchedule(ctx, scheduleId) if err != nil { if strings.Contains(err.Error(), "Job not found") { diff --git a/frontend/src/Admin.js b/frontend/src/Admin.js index a0a1fa74..c3700307 100644 --- a/frontend/src/Admin.js +++ b/frontend/src/Admin.js @@ -8,7 +8,8 @@ import ListItem from '@material-ui/core/ListItem'; import Button from '@material-ui/core/Button'; import Tabs from '@material-ui/core/Tabs'; import Tab from '@material-ui/core/Tab'; - +import ListItemText from '@material-ui/core/ListItemText'; +import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; import { useAlert } from "react-alert"; @@ -29,9 +30,39 @@ const Admin = (props) => { const [curTab, setCurTab] = React.useState(0); const [users, setUsers] = React.useState([]); const [environments, setEnvironments] = React.useState([]); + const [schedules, setSchedules] = React.useState([]) const alert = useAlert() + const deleteSchedule = (data) => { + // FIXME - add some check here ROFL + console.log("INPUT: ", data) + + // Just use this one? + const url = globalUrl+'/api/v1/workflows/'+data["workflow_id datastore:"]+"/schedule/"+data.id + console.log("URL: ", url) + fetch(url, { + method: 'DELETE', + credentials: "include", + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + alert.error("Failed stopping schedule") + } else { + getSchedules() + alert.success("Successfully stopped schedule!") + } + }), + ) + .catch(error => { + console.log("Error in userdata: ", error) + }); + } + const submitUser = (data) => { // FIXME - add some check here ROFL console.log("INPUT: ", data) @@ -132,6 +163,31 @@ const Admin = (props) => { }); } + const getSchedules = () => { + fetch(globalUrl+"/api/v1/workflows/schedules", { + 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 + } + + return response.json() + }) + .then((responseJson) => { + setSchedules(responseJson) + }) + .catch(error => { + alert.error(error.toString()) + }); + } + const getEnvironments = () => { fetch(globalUrl+"/api/v1/getenvironments", { method: 'GET', @@ -329,6 +385,54 @@ const Admin = (props) => { : null + const schedulesView = curTab === 2 ? +
+

+ Schedules +

+ + + + + + + + {schedules === undefined || schedules === null ? null : schedules.map(schedule => { + return ( + + + + + + + + ) + })} + +
+ : null + const environmentView = curTab === 1 ?

@@ -359,6 +463,8 @@ const Admin = (props) => { const setConfig = (event, newValue) => { if (newValue === 1) { getEnvironments() + } else if (newValue === 2) { + getSchedules() } setModalUser({}) @@ -377,10 +483,12 @@ const Admin = (props) => { > +
{usersView} {environmentView} + {schedulesView}
diff --git a/frontend/src/AppCreator.js b/frontend/src/AppCreator.js index 697b585e..3a269b5c 100644 --- a/frontend/src/AppCreator.js +++ b/frontend/src/AppCreator.js @@ -1588,14 +1588,14 @@ const AppCreator = (props) => { {bearerAuth} {apiKey} - {authenticationOption === "No authentication" ? null : + {/*authenticationOption === "No authentication" ? null : Authentication required (default true)

control={ { setAuthenticationRequired(!authenticationRequired) }} />} - />} + />*/}
{actionView}