#60: Created API endpoint to hotload apps from directory
This commit is contained in:
+159
-6
@@ -9,6 +9,7 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"path/filepath"
|
||||
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -36,7 +37,9 @@ import (
|
||||
"github.com/google/go-github/v28/github"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-git/go-billy/v5/memfs"
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/storage/memory"
|
||||
|
||||
@@ -238,7 +241,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 +1806,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 {
|
||||
@@ -1897,10 +1943,12 @@ func handleGetUsers(resp http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
|
||||
func checkAdminLogin(resp http.ResponseWriter, request *http.Request) {
|
||||
log.Printf("HELLO?")
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
log.Printf("HELLO2?")
|
||||
|
||||
count, err := getUserCount()
|
||||
if err != nil {
|
||||
@@ -2635,6 +2683,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 +2718,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"}`))
|
||||
@@ -4648,7 +4711,7 @@ func handleDeleteOutlookSub(resp http.ResponseWriter, request *http.Request) {
|
||||
ctx := context.Background()
|
||||
workflow, err := getWorkflow(ctx, workflowId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting the workflow locally: %s", err)
|
||||
log.Printf("Failed getting the workflow locally (delete outlook): %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
@@ -4782,7 +4845,7 @@ func createOutlookSub(resp http.ResponseWriter, request *http.Request) {
|
||||
ctx := context.Background()
|
||||
workflow, err := getWorkflow(ctx, workflowId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting the workflow locally: %s", err)
|
||||
log.Printf("Failed getting the workflow locally (outlook sub): %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
@@ -5729,6 +5792,86 @@ func healthCheckHandler(resp http.ResponseWriter, request *http.Request) {
|
||||
fmt.Fprint(resp, "OK")
|
||||
}
|
||||
|
||||
// Creates osfs from folderpath with a basepath as directory base
|
||||
func createFs(basepath, pathname string) (billy.Filesystem, error) {
|
||||
fs := osfs.New("")
|
||||
|
||||
err := filepath.Walk(pathname,
|
||||
func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.Contains(path, ".git") {
|
||||
return nil
|
||||
}
|
||||
|
||||
fullpath := fmt.Sprintf("%s%s", basepath, path)
|
||||
switch mode := info.Mode(); {
|
||||
case mode.IsDir():
|
||||
err = fs.MkdirAll(fullpath, 0644)
|
||||
if err != nil {
|
||||
log.Printf("Failed making folder: %s", err)
|
||||
}
|
||||
case mode.IsRegular():
|
||||
srcData, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Printf("Src error: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
//if strings.Contains(path, "yaml") {
|
||||
// log.Printf("PATH: %s -> %s", path, fullpath)
|
||||
// //log.Printf("DATA: %s", string(srcData))
|
||||
//}
|
||||
|
||||
dst, err := fs.Create(fullpath)
|
||||
if err != nil {
|
||||
log.Printf("Dst error: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = dst.Write(srcData)
|
||||
if err != nil {
|
||||
log.Printf("Dst write error: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return fs, err
|
||||
}
|
||||
|
||||
// Hotloads new apps from a folder
|
||||
// FIXME: Not finished
|
||||
func handleAppHotload(location string) error {
|
||||
basepath := "base"
|
||||
fs, err := createFs(basepath, location)
|
||||
if err != nil {
|
||||
log.Printf("Failed making files and stuff: %s", err)
|
||||
return err
|
||||
} else {
|
||||
log.Printf("Hotloading from %s finished", location)
|
||||
}
|
||||
|
||||
dir, err := fs.ReadDir(basepath)
|
||||
if err != nil {
|
||||
log.Printf("Failed reading folder: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = iterateAppGithubFolders(fs, dir, "", "")
|
||||
if err != nil {
|
||||
log.Printf("Err: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handles configuration items during Shuffle startup
|
||||
func runInit(ctx context.Context) {
|
||||
// Setting stats for backend starts (failure count as well)
|
||||
err := increaseStatisticsField(ctx, "backend_executions", "", 1)
|
||||
@@ -5765,7 +5908,7 @@ func runInit(ctx context.Context) {
|
||||
|
||||
_, _, err := handleExecution(schedule.WorkflowId, Workflow{}, request)
|
||||
if err != nil {
|
||||
log.Printf("Failed to execute: %s", err)
|
||||
log.Printf("Failed to execute %s: %s", schedule.WorkflowId, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5822,10 +5965,16 @@ func runInit(ctx context.Context) {
|
||||
|
||||
// FIXME: Get all the apps?
|
||||
iterateAppGithubFolders(fs, dir, "", "")
|
||||
|
||||
// Hotloads locally
|
||||
location := os.Getenv("APP_HOTLOAD_FOLDER")
|
||||
if len(location) != 0 {
|
||||
handleAppHotload(location)
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("Downloading OpenAPI data for search - EXTRA APPS")
|
||||
apis := "https://github.com/frikky/OpenAPI-security-definitions"
|
||||
apis := "https://github.com/frikky/security-openapis"
|
||||
|
||||
// THis gets memory problems hahah
|
||||
//apis := "https://github.com/APIs-guru/openapi-directory"
|
||||
@@ -5896,7 +6045,9 @@ func init() {
|
||||
r.HandleFunc("/api/v1/streams/results", handleGetStreamResults).Methods("POST", "OPTIONS")
|
||||
|
||||
// App specific
|
||||
r.HandleFunc("/api/v1/apps/run_hotload", handleAppHotloadRequest).Methods("GET", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps/get_existing", loadSpecificApps).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps/download_remote", loadSpecificApps).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps/{appId}", deleteWorkflowApp).Methods("DELETE", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps/{appId}/config", getWorkflowAppConfig).Methods("GET", "OPTIONS")
|
||||
@@ -5914,6 +6065,8 @@ 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/download_remote", loadSpecificWorkflows).Methods("POST", "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")
|
||||
|
||||
Reference in New Issue
Block a user