Made it possible to auto-authenticate oauth2 with clientid and secret
This commit is contained in:
@@ -2,7 +2,7 @@ module shuffle
|
||||
|
||||
go 1.13
|
||||
|
||||
//replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
|
||||
replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
|
||||
|
||||
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
|
||||
|
||||
|
||||
@@ -3502,7 +3502,7 @@ func handleAppHotload(ctx context.Context, location string, forceUpdate bool) er
|
||||
}
|
||||
|
||||
//log.Printf("Reading app folder: %#v", dir)
|
||||
_, _, err = iterateAppGithubFolders(fs, dir, "", "", forceUpdate)
|
||||
_, _, err = shuffle.IterateAppGithubFolders(ctx, fs, dir, "", "", forceUpdate)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Githubfolders error: %s", err)
|
||||
return err
|
||||
@@ -4174,7 +4174,7 @@ func runInitEs(ctx context.Context) {
|
||||
//iterateAppGithubFolders(fs, dir, "", "testing")
|
||||
|
||||
// FIXME: Get all the apps?
|
||||
_, _, err = iterateAppGithubFolders(fs, dir, "", "", forceUpdate)
|
||||
_, _, err = shuffle.IterateAppGithubFolders(ctx, fs, dir, "", "", forceUpdate)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Error from app load in init: %s", err)
|
||||
}
|
||||
@@ -4829,7 +4829,7 @@ func runInit(ctx context.Context) {
|
||||
//iterateAppGithubFolders(fs, dir, "", "testing")
|
||||
|
||||
// FIXME: Get all the apps?
|
||||
_, _, err = iterateAppGithubFolders(fs, dir, "", "", forceUpdate)
|
||||
_, _, err = shuffle.IterateAppGithubFolders(ctx, fs, dir, "", "", forceUpdate)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Error from app load in init: %s", err)
|
||||
}
|
||||
@@ -5791,8 +5791,8 @@ func initHandlers() {
|
||||
r.HandleFunc("/api/v1/apps/{appId}", shuffle.DeleteWorkflowApp).Methods("DELETE", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps/{appId}/config", shuffle.GetWorkflowAppConfig).Methods("GET", "OPTIONS")
|
||||
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/get_existing", shuffle.LoadSpecificApps).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps/download_remote", shuffle.LoadSpecificApps).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps", getWorkflowApps).Methods("GET", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS")
|
||||
|
||||
+4
-497
@@ -19,10 +19,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
//"github.com/docker/docker/api/types"
|
||||
//"github.com/docker/docker/client"
|
||||
//gyaml "github.com/ghodss/yaml"
|
||||
|
||||
gyaml "github.com/ghodss/yaml"
|
||||
"github.com/h2non/filetype"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
|
||||
@@ -2735,29 +2735,6 @@ func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
|
||||
resp.Write(newbody)
|
||||
}
|
||||
|
||||
// Bad check for workflowapps :)
|
||||
// FIXME - use tags and struct reflection
|
||||
func checkWorkflowApp(workflowApp shuffle.WorkflowApp) error {
|
||||
// Validate fields
|
||||
if workflowApp.Name == "" {
|
||||
return errors.New("App field name doesn't exist")
|
||||
}
|
||||
|
||||
if workflowApp.Description == "" {
|
||||
return errors.New("App field description doesn't exist")
|
||||
}
|
||||
|
||||
if workflowApp.AppVersion == "" {
|
||||
return errors.New("App field app_version doesn't exist")
|
||||
}
|
||||
|
||||
if workflowApp.ContactInfo.Name == "" {
|
||||
return errors.New("App field contact_info.name doesn't exist")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleGetfile(resp http.ResponseWriter, request *http.Request) ([]byte, error) {
|
||||
// Upload file here first
|
||||
request.ParseMultipartForm(32 << 20)
|
||||
@@ -3084,141 +3061,6 @@ func handleAppHotloadRequest(resp http.ResponseWriter, request *http.Request) {
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
|
||||
}
|
||||
|
||||
func loadSpecificApps(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
// Just need to be logged in
|
||||
// FIXME - should have some permissions?
|
||||
_, err := shuffle.HandleApiAuthentication(resp, request)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Api authentication failed in load specific apps: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
log.Printf("Error with body read: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// Field1 & 2 can be a lot of things.
|
||||
// Field1 = Username
|
||||
// Field2 = Password
|
||||
type tmpStruct struct {
|
||||
URL string `json:"url"`
|
||||
Branch string `json:"branch"`
|
||||
Field1 string `json:"field_1"`
|
||||
Field2 string `json:"field_2"`
|
||||
ForceUpdate bool `json:"force_update"`
|
||||
}
|
||||
//log.Printf("Body: %s", string(body))
|
||||
|
||||
var tmpBody tmpStruct
|
||||
err = json.Unmarshal(body, &tmpBody)
|
||||
if err != nil {
|
||||
log.Printf("Error with unmarshal tmpBody: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
fs := memfs.New()
|
||||
|
||||
if strings.Contains(tmpBody.URL, "github") || strings.Contains(tmpBody.URL, "gitlab") || strings.Contains(tmpBody.URL, "bitbucket") {
|
||||
cloneOptions := &git.CloneOptions{
|
||||
URL: tmpBody.URL,
|
||||
}
|
||||
|
||||
if len(tmpBody.Branch) > 0 && tmpBody.Branch != "master" && tmpBody.Branch != "main" {
|
||||
cloneOptions.ReferenceName = plumbing.ReferenceName(tmpBody.Branch)
|
||||
}
|
||||
|
||||
// FIXME: Better auth.
|
||||
if len(tmpBody.Field1) > 0 && len(tmpBody.Field2) > 0 {
|
||||
cloneOptions.Auth = &http2.BasicAuth{
|
||||
Username: tmpBody.Field1,
|
||||
Password: tmpBody.Field2,
|
||||
}
|
||||
}
|
||||
|
||||
storer := memory.NewStorage()
|
||||
r, err := git.Clone(storer, fs, cloneOptions)
|
||||
if err != nil {
|
||||
log.Printf("Failed loading repo %s into memory (github workflows 2): %s", tmpBody.URL, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
|
||||
return
|
||||
}
|
||||
|
||||
dir, err := fs.ReadDir("/")
|
||||
if err != nil {
|
||||
log.Printf("FAiled reading folder: %s", err)
|
||||
}
|
||||
_ = r
|
||||
|
||||
if tmpBody.ForceUpdate {
|
||||
log.Printf("[INFO] Running with force update!")
|
||||
} else {
|
||||
log.Printf("[INFO] Updating apps with updates (no force)")
|
||||
}
|
||||
|
||||
if tmpBody.ForceUpdate {
|
||||
ctx := context.Background()
|
||||
dockercli, err := client.NewEnvClient()
|
||||
if err == nil {
|
||||
_, err := dockercli.ImagePull(ctx, "frikky/shuffle:app_sdk", types.ImagePullOptions{})
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed to download apps with the new App SDK: %s", err)
|
||||
}
|
||||
} else {
|
||||
log.Printf("[WARNING] Failed to download apps with the new App SDK because of docker cli: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
iterateAppGithubFolders(fs, dir, "", "", tmpBody.ForceUpdate)
|
||||
|
||||
} else if strings.Contains(tmpBody.URL, "s3") {
|
||||
//https://docs.aws.amazon.com/sdk-for-go/api/service/s3/
|
||||
|
||||
//sess := session.Must(session.NewSession())
|
||||
//downloader := s3manager.NewDownloader(sess)
|
||||
|
||||
//// Write the contents of S3 Object to the file
|
||||
//storer := memory.NewStorage()
|
||||
//n, err := downloader.Download(storer, &s3.GetObjectInput{
|
||||
// Bucket: aws.String(myBucket),
|
||||
// Key: aws.String(myString),
|
||||
//})
|
||||
//if err != nil {
|
||||
// return fmt.Errorf("failed to download file, %v", err)
|
||||
//}
|
||||
//fmt.Printf("file downloaded, %d bytes\n", n)
|
||||
} else {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s is unsupported"}`, tmpBody.URL)))
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
cacheKey := fmt.Sprintf("workflowapps-sorted-100")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
cacheKey = fmt.Sprintf("workflowapps-sorted-500")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
cacheKey = fmt.Sprintf("workflowapps-sorted-1000")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
|
||||
}
|
||||
|
||||
func iterateOpenApiGithub(fs billy.Filesystem, dir []os.FileInfo, extra string, onlyname string) error {
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -3482,341 +3324,6 @@ func iterateWorkflowGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra
|
||||
return err
|
||||
}
|
||||
|
||||
type buildLaterStruct struct {
|
||||
Tags []string
|
||||
Extra string
|
||||
Id string
|
||||
}
|
||||
|
||||
// Onlyname is used to
|
||||
func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra string, onlyname string, forceUpdate bool) ([]buildLaterStruct, []buildLaterStruct, error) {
|
||||
var err error
|
||||
|
||||
allapps := []shuffle.WorkflowApp{}
|
||||
|
||||
// These are slow apps to build with some funky mechanisms
|
||||
reservedNames := []string{
|
||||
"OWA",
|
||||
"NLP",
|
||||
"YARA",
|
||||
}
|
||||
|
||||
// It's here to prevent getting them in every iteration
|
||||
buildLaterFirst := []buildLaterStruct{}
|
||||
buildLaterList := []buildLaterStruct{}
|
||||
ctx := context.Background()
|
||||
for _, file := range dir {
|
||||
if len(onlyname) > 0 && file.Name() != onlyname {
|
||||
continue
|
||||
}
|
||||
|
||||
// Folder?
|
||||
switch mode := file.Mode(); {
|
||||
case mode.IsDir():
|
||||
tmpExtra := fmt.Sprintf("%s%s/", extra, file.Name())
|
||||
dir, err := fs.ReadDir(tmpExtra)
|
||||
if err != nil {
|
||||
log.Printf("Failed to read dir: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Go routine? Hmm, this can be super quick I guess
|
||||
buildFirst, buildLast, err := iterateAppGithubFolders(fs, dir, tmpExtra, "", forceUpdate)
|
||||
|
||||
for _, item := range buildFirst {
|
||||
buildLaterFirst = append(buildLaterFirst, item)
|
||||
}
|
||||
|
||||
for _, item := range buildLast {
|
||||
buildLaterList = append(buildLaterList, item)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Error reading folder: %s", err)
|
||||
//buildFirst, buildLast, err := iterateAppGithubFolders(fs, dir, tmpExtra, "", forceUpdate)
|
||||
|
||||
if !forceUpdate {
|
||||
return buildLaterFirst, buildLaterList, err
|
||||
}
|
||||
}
|
||||
|
||||
case mode.IsRegular():
|
||||
// Check the file
|
||||
filename := file.Name()
|
||||
if filename == "Dockerfile" {
|
||||
// Set up to make md5 and check if the app is new (api.yaml+src/app.py+Dockerfile)
|
||||
// Check if Dockerfile, app.py or api.yaml has changed. Hash?
|
||||
//log.Printf("Handle Dockerfile in location %s", extra)
|
||||
// Try api.yaml and api.yml
|
||||
fullPath := fmt.Sprintf("%s%s", extra, "api.yaml")
|
||||
fileReader, err := fs.Open(fullPath)
|
||||
if err != nil {
|
||||
fullPath = fmt.Sprintf("%s%s", extra, "api.yml")
|
||||
fileReader, err = fs.Open(fullPath)
|
||||
if err != nil {
|
||||
log.Printf("Failed finding api.yaml/yml: %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
//log.Printf("HANDLING DOCKER FILEREADER - SEARCH&REPLACE?")
|
||||
|
||||
appfileData, err := ioutil.ReadAll(fileReader)
|
||||
if err != nil {
|
||||
log.Printf("Failed reading %s: %s", fullPath, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(appfileData) == 0 {
|
||||
log.Printf("Failed reading %s - length is 0.", fullPath)
|
||||
continue
|
||||
}
|
||||
|
||||
// func md5sum(data []byte) string {
|
||||
// Make hash
|
||||
appPython := fmt.Sprintf("%s/src/app.py", extra)
|
||||
appPythonReader, err := fs.Open(appPython)
|
||||
if err != nil {
|
||||
log.Printf("Failed to read python app %s", appPython)
|
||||
continue
|
||||
}
|
||||
|
||||
appPythonData, err := ioutil.ReadAll(appPythonReader)
|
||||
if err != nil {
|
||||
log.Printf("Failed reading appdata %s: %s", appPython, err)
|
||||
continue
|
||||
}
|
||||
|
||||
dockerFp := fmt.Sprintf("%s/Dockerfile", extra)
|
||||
dockerfile, err := fs.Open(dockerFp)
|
||||
if err != nil {
|
||||
log.Printf("Failed to read dockerfil %s", appPython)
|
||||
continue
|
||||
}
|
||||
|
||||
dockerfileData, err := ioutil.ReadAll(dockerfile)
|
||||
if err != nil {
|
||||
log.Printf("Failed to read dockerfile")
|
||||
continue
|
||||
}
|
||||
|
||||
combined := []byte{}
|
||||
combined = append(combined, appfileData...)
|
||||
combined = append(combined, appPythonData...)
|
||||
combined = append(combined, dockerfileData...)
|
||||
md5 := md5sum(combined)
|
||||
|
||||
var workflowapp shuffle.WorkflowApp
|
||||
err = gyaml.Unmarshal(appfileData, &workflowapp)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed building workflowapp %s: %s", extra, err)
|
||||
return buildLaterFirst, buildLaterList, errors.New(fmt.Sprintf("Failed building %s: %s", extra, err))
|
||||
//continue
|
||||
}
|
||||
|
||||
newName := workflowapp.Name
|
||||
newName = strings.ReplaceAll(newName, " ", "-")
|
||||
|
||||
tags := []string{
|
||||
fmt.Sprintf("%s:%s_%s", baseDockerName, strings.ToLower(newName), workflowapp.AppVersion),
|
||||
}
|
||||
|
||||
if len(allapps) == 0 {
|
||||
allapps, err = shuffle.GetAllWorkflowApps(ctx, 0)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed getting apps to verify: %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Make an option to override existing apps?
|
||||
//Hash string `json:"hash" datastore:"hash" yaml:"hash"` // api.yaml+dockerfile+src/app.py for apps
|
||||
removeApps := []string{}
|
||||
skip := false
|
||||
for _, app := range allapps {
|
||||
if app.Name == workflowapp.Name && app.AppVersion == workflowapp.AppVersion {
|
||||
// FIXME: Check if there's a new APP_SDK as well.
|
||||
// Skip this check if app_sdk is new.
|
||||
if app.Hash == md5 && app.Hash != "" && !forceUpdate {
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
|
||||
//log.Printf("Overriding app %s:%s as it exists but has different hash.", app.Name, app.AppVersion)
|
||||
removeApps = append(removeApps, app.ID)
|
||||
}
|
||||
}
|
||||
|
||||
if skip && !forceUpdate {
|
||||
continue
|
||||
}
|
||||
|
||||
// Fixes (appends) authentication parameters if they're required
|
||||
if workflowapp.Authentication.Required {
|
||||
//log.Printf("[INFO] Checking authentication fields and appending for %s!", workflowapp.Name)
|
||||
// FIXME:
|
||||
// Might require reflection into the python code to append the fields as well
|
||||
for index, action := range workflowapp.Actions {
|
||||
if action.AuthNotRequired {
|
||||
log.Printf("Skipping auth setup: %s", action.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
// 1. Check if authentication params exists at all
|
||||
// 2. Check if they're present in the action
|
||||
// 3. Add them IF they DONT exist
|
||||
// 4. Fix python code with reflection (FIXME)
|
||||
appendParams := []shuffle.WorkflowAppActionParameter{}
|
||||
for _, fieldname := range workflowapp.Authentication.Parameters {
|
||||
found := false
|
||||
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, shuffle.WorkflowAppActionParameter{
|
||||
Name: fieldname.Name,
|
||||
Description: fieldname.Description,
|
||||
Example: fieldname.Example,
|
||||
Required: fieldname.Required,
|
||||
Configuration: true,
|
||||
Schema: fieldname.Schema,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(appendParams) > 0 {
|
||||
//log.Printf("[AUTH] Appending %d params to the START of %s", len(appendParams), action.Name)
|
||||
workflowapp.Actions[index].Parameters = append(appendParams, workflowapp.Actions[index].Parameters...)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
err = checkWorkflowApp(workflowapp)
|
||||
if err != nil {
|
||||
log.Printf("[DEBUG] %s for app %s:%s", err, workflowapp.Name, workflowapp.AppVersion)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(removeApps) > 0 {
|
||||
for _, item := range removeApps {
|
||||
log.Printf("[WARNING] Removing duplicate app: %s", item)
|
||||
err = shuffle.DeleteKey(ctx, "workflowapp", item)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed deleting duplicate %s: %s", item, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
workflowapp.ID = uuid.NewV4().String()
|
||||
workflowapp.IsValid = true
|
||||
workflowapp.Verified = true
|
||||
workflowapp.Sharing = true
|
||||
workflowapp.Downloaded = true
|
||||
workflowapp.Hash = md5
|
||||
workflowapp.Public = true
|
||||
|
||||
err = shuffle.SetWorkflowAppDatastore(ctx, workflowapp, workflowapp.ID)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed setting workflowapp in intro: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
/*
|
||||
err = increaseStatisticsField(ctx, "total_apps_created", workflowapp.ID, 1, "")
|
||||
if err != nil {
|
||||
log.Printf("Failed to increase total apps created stats: %s", err)
|
||||
}
|
||||
|
||||
err = increaseStatisticsField(ctx, "total_apps_loaded", workflowapp.ID, 1, "")
|
||||
if err != nil {
|
||||
log.Printf("Failed to increase total apps loaded stats: %s", err)
|
||||
}
|
||||
*/
|
||||
|
||||
//log.Printf("Added %s:%s to the database", workflowapp.Name, workflowapp.AppVersion)
|
||||
|
||||
// ID can be used to e.g. set a build status.
|
||||
buildLater := buildLaterStruct{
|
||||
Tags: tags,
|
||||
Extra: extra,
|
||||
Id: workflowapp.ID,
|
||||
}
|
||||
|
||||
reservedFound := false
|
||||
for _, appname := range reservedNames {
|
||||
if strings.ToUpper(workflowapp.Name) == strings.ToUpper(appname) {
|
||||
buildLaterList = append(buildLaterList, buildLater)
|
||||
|
||||
reservedFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/// Only upload if successful and no errors
|
||||
if !reservedFound {
|
||||
buildLaterFirst = append(buildLaterFirst, buildLater)
|
||||
} else {
|
||||
log.Printf("[WARNING] Skipping build of %s to later", workflowapp.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(buildLaterFirst) == 0 && len(buildLaterList) == 0 {
|
||||
return buildLaterFirst, buildLaterList, err
|
||||
}
|
||||
|
||||
// This is getting silly
|
||||
cacheKey := fmt.Sprintf("workflowapps-sorted-100")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
cacheKey = fmt.Sprintf("workflowapps-sorted-500")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
cacheKey = fmt.Sprintf("workflowapps-sorted-1000")
|
||||
shuffle.DeleteCache(ctx, cacheKey)
|
||||
|
||||
//log.Printf("BUILDLATERFIRST: %d, BUILDLATERLIST: %d", len(buildLaterFirst), len(buildLaterList))
|
||||
if len(extra) == 0 {
|
||||
log.Printf("[INFO] Starting build of %d containers (FIRST)", len(buildLaterFirst))
|
||||
for _, item := range buildLaterFirst {
|
||||
err = buildImageMemory(fs, item.Tags, item.Extra, true)
|
||||
if err != nil {
|
||||
log.Printf("Failed image build memory: %s", err)
|
||||
} else {
|
||||
if len(item.Tags) > 0 {
|
||||
log.Printf("[INFO] Successfully built image %s", item.Tags[0])
|
||||
|
||||
} else {
|
||||
log.Printf("[INFO] Successfully built Docker image")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[INFO] Starting build of %d skipped docker images", len(buildLaterList))
|
||||
for _, item := range buildLaterList {
|
||||
err = buildImageMemory(fs, item.Tags, item.Extra, true)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Failed image build memory: %s", err)
|
||||
} else {
|
||||
if len(item.Tags) > 0 {
|
||||
log.Printf("[INFO] Successfully built image %s", item.Tags[0])
|
||||
} else {
|
||||
log.Printf("[INFO] Successfully built Docker image")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buildLaterFirst, buildLaterList, err
|
||||
}
|
||||
|
||||
func setNewWorkflowApp(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
@@ -3875,7 +3382,7 @@ func setNewWorkflowApp(resp http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = checkWorkflowApp(workflowapp)
|
||||
err = shuffle.CheckWorkflowApp(workflowapp)
|
||||
if err != nil {
|
||||
log.Printf("%s for app %s:%s", err, workflowapp.Name, workflowapp.AppVersion)
|
||||
resp.WriteHeader(401)
|
||||
|
||||
+1
-2
@@ -36,8 +36,7 @@ services:
|
||||
- SHUFFLE_FILE_LOCATION=/shuffle-files
|
||||
restart: unless-stopped
|
||||
#depends_on:
|
||||
#- opensearch
|
||||
#- database
|
||||
# - opensearch #- Not necessary because dependancy is handled within the backend itself instead
|
||||
orborus:
|
||||
#build: ./functions/onprem/orborus
|
||||
image: ghcr.io/frikky/shuffle-orborus:nightly
|
||||
|
||||
@@ -12,7 +12,7 @@ import { FixName } from "../views/Apps.jsx";
|
||||
//
|
||||
// Specifically used for UNSAVED workflows only?
|
||||
const Workflow = (props) => {
|
||||
const { globalUrl, theme, workflow, appAuthentication, setSelectedAction, setAuthenticationModalOpen, setSelectedApp, apps, selectedAction,setConfigureWorkflowModalOpen, saveWorkflow, newWebhook, submitSchedule, referenceUrl, isCloud, } = props
|
||||
const { globalUrl, theme, workflow, appAuthentication, setSelectedAction, setAuthenticationModalOpen, setSelectedApp, apps, selectedAction,setConfigureWorkflowModalOpen, saveWorkflow, newWebhook, submitSchedule, referenceUrl, isCloud, setAuthenticationType, } = props
|
||||
const [requiredActions, setRequiredActions] = React.useState([])
|
||||
const [requiredVariables, setRequiredVariables] = React.useState([])
|
||||
const [requiredTriggers, setRequiredTriggers] = React.useState([])
|
||||
@@ -374,6 +374,17 @@ const Workflow = (props) => {
|
||||
<CircularProgress />
|
||||
:
|
||||
<Button color="primary" variant="contained" onClick={() => {
|
||||
setAuthenticationType(action.app.authentication.type === "oauth2" && action.app.authentication.redirect_uri !== undefined && action.app.authentication.redirect_uri !== null ?
|
||||
{
|
||||
"type": "oauth2",
|
||||
"redirect_uri": action.app.authentication.redirect_uri,
|
||||
"token_uri": action.app.authentication.token_uri,
|
||||
"scope": action.app.authentication.scope,
|
||||
} : {
|
||||
"type": ""
|
||||
}
|
||||
)
|
||||
|
||||
setItemChanged(true)
|
||||
setSelectedAction(action.action)
|
||||
setSelectedApp(action.app)
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
import React, {useRef, useState, useEffect, useLayoutEffect} from 'react';
|
||||
import { useTheme } from '@material-ui/core/styles';
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { TextField, Drawer, Button, Paper, Grid, Tabs, InputAdornment, Tab, ButtonBase, Tooltip, Select, MenuItem, Divider, Dialog, Modal, DialogActions, DialogTitle, InputLabel, DialogContent, FormControl, IconButton, Menu, Input, FormGroup, FormControlLabel, Typography, Checkbox, Breadcrumbs, CircularProgress, Switch, Fade } from '@material-ui/core';
|
||||
import { LockOpen as LockOpenIcon } from '@material-ui/icons';
|
||||
|
||||
const AuthenticationOauth2 = (props) => {
|
||||
const { saveWorkflow, selectedApp, workflow, selectedAction, authenticationType, getAppAuthentication, appAuthentication, setSelectedAction, setNewAppAuth, setAuthenticationModalOpen} = props;
|
||||
const theme = useTheme();
|
||||
|
||||
//const [update, setUpdate] = React.useState("|")
|
||||
const [clientId, setClientId] = React.useState("")
|
||||
const [clientSecret, setClientSecret] = React.useState("")
|
||||
const [buttonClicked, setButtonClicked] = React.useState(false)
|
||||
const [authenticationOption, setAuthenticationOptions] = React.useState({
|
||||
app: JSON.parse(JSON.stringify(selectedApp)),
|
||||
fields: {},
|
||||
label: "",
|
||||
usage: [{
|
||||
workflow_id: workflow.id,
|
||||
}],
|
||||
id: uuidv4(),
|
||||
active: true,
|
||||
})
|
||||
|
||||
const handleOauth2Request = (client_id, client_secret) => {
|
||||
setButtonClicked(true)
|
||||
//if (authenticationType.type === "oauth2" && authenticationType.redirect_uri !== undefined && authenticationType.redirect_uri !== null) {
|
||||
// These are test credentials
|
||||
//const client_id = "dae24316-4bec-4832-b660-4cba6dc2477b"
|
||||
//const client_secret = "._Qu3EvYY-OW_D57uy79qwEo.32qD6.l0z"
|
||||
|
||||
const authentication_url = authenticationType.token_uri
|
||||
|
||||
const resources = "UserAuthenticationMethod.ReadWrite.All"
|
||||
if (authenticationType.scope !== undefined && authenticationType.scope !== null) {
|
||||
console.log("EDIT SCOPE!")
|
||||
}
|
||||
|
||||
const redirectUri = `http://${window.location.host}/set_authentication`
|
||||
const state = `workflow_id%3D${workflow.id}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`
|
||||
|
||||
const url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${resources}&state=${state}`
|
||||
// &resource=https%3A%2F%2Fgraph.microsoft.com&
|
||||
|
||||
// FIXME: Awful, but works for prototyping
|
||||
// How can we get a callback properly realtime?
|
||||
// How can we properly try-catch without breaks on error?
|
||||
try {
|
||||
|
||||
var newwin = window.open(url, "", "width=400,height=200")
|
||||
console.log(newwin)
|
||||
setTimeout(() => {
|
||||
console.log(newwin)
|
||||
console.log("CLOSED", newwin.closed)
|
||||
}, 1000)
|
||||
|
||||
setTimeout(() => {
|
||||
console.log(newwin)
|
||||
console.log("CLOSED", newwin.closed)
|
||||
if (newwin.closed) {
|
||||
getAppAuthentication(true, true)
|
||||
setTimeout(() => {
|
||||
console.log("APPAUTH: ", appAuthentication)
|
||||
|
||||
//{selectedAction.authentication.map(data => {
|
||||
|
||||
setAuthenticationModalOpen(false)
|
||||
saveWorkflow(workflow)
|
||||
}, 1500)
|
||||
}
|
||||
}, 10000)
|
||||
} catch (e) {
|
||||
alert.error("Failed authentication - probably bad credentials. Try again")
|
||||
setButtonClicked(false)
|
||||
}
|
||||
|
||||
return
|
||||
//do {
|
||||
//} while (
|
||||
}
|
||||
|
||||
if (selectedApp.authentication === undefined) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (selectedApp.authentication.parameters === null || selectedApp.authentication.parameters === undefined || selectedApp.authentication.parameters.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
authenticationOption.app.actions = []
|
||||
|
||||
for (var key in selectedApp.authentication.parameters) {
|
||||
if (authenticationOption.fields[selectedApp.authentication.parameters[key].name] === undefined) {
|
||||
authenticationOption.fields[selectedApp.authentication.parameters[key].name] = ""
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmitCheck = () => {
|
||||
console.log("NEW AUTH: ", authenticationOption)
|
||||
if (authenticationOption.label.length === 0) {
|
||||
authenticationOption.label = `Auth for ${selectedApp.name}`
|
||||
//alert.info("Label can't be empty")
|
||||
//return
|
||||
}
|
||||
|
||||
// Automatically mapping fields that already exist (predefined).
|
||||
// Warning if fields are NOT filled
|
||||
for (var key in selectedApp.authentication.parameters) {
|
||||
if (authenticationOption.fields[selectedApp.authentication.parameters[key].name].length === 0) {
|
||||
if (selectedApp.authentication.parameters[key].value !== undefined && selectedApp.authentication.parameters[key].value !== null && selectedApp.authentication.parameters[key].value.length > 0) {
|
||||
authenticationOption.fields[selectedApp.authentication.parameters[key].name] = selectedApp.authentication.parameters[key].value
|
||||
} else {
|
||||
if (selectedApp.authentication.parameters[key].schema.type === "bool") {
|
||||
authenticationOption.fields[selectedApp.authentication.parameters[key].name] = "false"
|
||||
} else {
|
||||
alert.info("Field "+selectedApp.authentication.parameters[key].name+" can't be empty")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Action: ", selectedAction)
|
||||
selectedAction.authentication_id = authenticationOption.id
|
||||
selectedAction.selectedAuthentication = 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))
|
||||
var newFields = []
|
||||
for (const key in newAuthOption.fields) {
|
||||
const value = newAuthOption.fields[key]
|
||||
newFields.push({
|
||||
key: key,
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
|
||||
console.log("FIELDS: ", newFields)
|
||||
newAuthOption.fields = newFields
|
||||
setNewAppAuth(newAuthOption)
|
||||
//appAuthentication.push(newAuthOption)
|
||||
//setAppAuthentication(appAuthentication)
|
||||
//
|
||||
|
||||
//if (configureWorkflowModalOpen) {
|
||||
// setSelectedAction({})
|
||||
//}
|
||||
//setUpdate(authenticationOption.id)
|
||||
|
||||
/*
|
||||
{selectedAction.authentication.map(data => (
|
||||
<MenuItem key={data.id} style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
if (authenticationOption.label === null || authenticationOption.label === undefined) {
|
||||
authenticationOption.label = selectedApp.name+" authentication"
|
||||
}
|
||||
|
||||
//console.log(
|
||||
return (
|
||||
<div>
|
||||
<DialogContent>
|
||||
<span style={{}}>
|
||||
<b>Oauth2 requires a client ID and secret to authenticate. This is usually made in the remote system.</b>
|
||||
<a target="_blank" rel="norefferer" href="https://shuffler.io/docs/apps#authentication" style={{textDecoration: "none", color: "#f85a3e"}}>Learn more about Oauth2</a><div/>
|
||||
</span>
|
||||
{/*<TextField
|
||||
style={{backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
height: 50,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"Auth july 2020"}
|
||||
defaultValue={`Auth for ${selectedApp.name}`}
|
||||
onChange={(event) => {
|
||||
authenticationOption.label = event.target.value
|
||||
}}
|
||||
/>
|
||||
<Divider style={{marginTop: 15, marginBottom: 15, backgroundColor: "rgb(91, 96, 100)"}}/>
|
||||
*/}
|
||||
<TextField
|
||||
style={{marginTop: 20, backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
height: 50,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"Client ID"}
|
||||
onChange={(event) => {
|
||||
setClientId(event.target.value)
|
||||
//authenticationOption.label = event.target.value
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
style={{backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
height: 50,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"Client Secret"}
|
||||
onChange={(event) => {
|
||||
setClientSecret(event.target.value)
|
||||
//authenticationOption.label = event.target.value
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
style={{marginTop: 20, borderRadius: theme.palette.borderRadius}}
|
||||
disabled={clientSecret.length === 0 || clientId.length === 0}
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
//setAuthenticationModalOpen(false)
|
||||
handleOauth2Request(clientId, clientSecret)
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
{buttonClicked ?
|
||||
<CircularProgress style={{}} />
|
||||
:
|
||||
"Oauth2 request"
|
||||
}
|
||||
</Button>
|
||||
</DialogContent>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AuthenticationOauth2
|
||||
@@ -1116,6 +1116,14 @@ const ParsedAction = (props) => {
|
||||
// itemColor = "#ffeb3b"
|
||||
//}
|
||||
{/*<div style={{width: 17, height: 17, borderRadius: 17 / 2, backgroundColor: itemColor, marginRight: 10, marginTop: 2, marginTop: "auto", marginBottom: "auto",}}/>*/}
|
||||
|
||||
|
||||
|
||||
if (authenticationType.type === "oauth2" && data.configuration === true) {
|
||||
return null
|
||||
}
|
||||
//&& authenticationType.redirect_uri !== undefined && authenticationType.redirect_uri !== null) {
|
||||
|
||||
return (
|
||||
<div key={data.name}>
|
||||
<div style={{marginTop: 20, marginBottom: 0, display: "flex"}}>
|
||||
@@ -1390,46 +1398,6 @@ const ParsedAction = (props) => {
|
||||
<span>
|
||||
<Button color="primary" style={{}} fullWidth variant="contained" onClick={() => {
|
||||
console.log(authenticationType)
|
||||
if (authenticationType.type === "oauth2" && authenticationType.redirect_uri !== undefined && authenticationType.redirect_uri !== null) {
|
||||
// FIXME: Sending client secret and senitive info like this may not be ok.
|
||||
const client_id = "dae24316-4bec-4832-b660-4cba6dc2477b"
|
||||
const client_secret = "._Qu3EvYY-OW_D57uy79qwEo.32qD6.l0z"
|
||||
|
||||
const authentication_url = authenticationType.token_uri
|
||||
|
||||
const resources = "UserAuthenticationMethod.ReadWrite.All"
|
||||
if (authenticationType.scope !== undefined && authenticationType.scope !== null) {
|
||||
console.log("EDIT SCOPE!")
|
||||
}
|
||||
|
||||
const redirectUri = `http://${window.location.host}/set_authentication`
|
||||
const state = `workflow_id%3D${workflow.id}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`
|
||||
|
||||
const url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${resources}&state=${state}`
|
||||
// &resource=https%3A%2F%2Fgraph.microsoft.com&
|
||||
|
||||
// Awful, but works for prototyping
|
||||
var newwin = window.open(url, "", "width=200,height=100")
|
||||
console.log(newwin)
|
||||
setTimeout(() => {
|
||||
console.log(newwin)
|
||||
console.log("CLOSED", newwin.closed)
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
console.log(newwin)
|
||||
console.log("CLOSED", newwin.closed)
|
||||
if (newwin.closed) {
|
||||
getAppAuthentication(true)
|
||||
setTimeout(() => {
|
||||
console.log("APPAUTH: ", appAuthentication)
|
||||
}, 1500)
|
||||
}
|
||||
}, 10000)
|
||||
|
||||
return
|
||||
//do {
|
||||
//} while (
|
||||
}
|
||||
|
||||
setAuthenticationModalOpen(true)
|
||||
}}>
|
||||
|
||||
@@ -28,6 +28,7 @@ import { useAlert } from "react-alert";
|
||||
import { validateJson, GetIconInfo } from "./Workflows.jsx";
|
||||
import { GetParsedPaths } from "./Apps.jsx";
|
||||
import ConfigureWorkflow from '../components/ConfigureWorkflow.jsx';
|
||||
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
|
||||
import ParsedAction from '../components/ParsedAction.jsx';
|
||||
import Scroll from 'react-scroll'
|
||||
import { Element as ScrollElement, animateScroll as scroll, scrollSpy, scroller } from 'react-scroll'
|
||||
@@ -404,7 +405,7 @@ const AngularWorkflow = (props) => {
|
||||
if (!responseJson.success) {
|
||||
alert.error("Failed to set app auth: "+responseJson.reason)
|
||||
} else {
|
||||
getAppAuthentication(true)
|
||||
getAppAuthentication(true, false)
|
||||
setAuthenticationModalOpen(false)
|
||||
|
||||
// Needs a refresh with the new authentication..
|
||||
@@ -1128,7 +1129,7 @@ const AngularWorkflow = (props) => {
|
||||
"http",
|
||||
]
|
||||
|
||||
const getAppAuthentication = (reset) => {
|
||||
const getAppAuthentication = (reset, updateAction) => {
|
||||
fetch(globalUrl+"/api/v1/apps/authentication", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
@@ -1155,6 +1156,8 @@ const AngularWorkflow = (props) => {
|
||||
newauth.push(responseJson.data[key])
|
||||
}
|
||||
|
||||
//{selectedAction.authentication.map(data => {
|
||||
|
||||
if (cy !== undefined) {
|
||||
console.log("NEW AUTH = reset cy's onnodeselect")
|
||||
|
||||
@@ -1166,6 +1169,65 @@ const AngularWorkflow = (props) => {
|
||||
|
||||
setAppAuthentication(newauth)
|
||||
setAuthLoaded(true)
|
||||
|
||||
if (updateAction === true) {
|
||||
//console.log("Should update authentication for selectedAction!!")
|
||||
console.log(responseJson)
|
||||
|
||||
if (selectedApp.authentication.required) {
|
||||
//console.log("App requires auth!!")
|
||||
// Setup auth here :)
|
||||
const authenticationOptions = []
|
||||
var findAuthId = ""
|
||||
if (selectedAction.authentication_id !== null && selectedAction.authentication_id !== undefined && selectedAction.authentication_id.length > 0) {
|
||||
findAuthId = selectedAction.authentication_id
|
||||
}
|
||||
|
||||
var tmpAuth = JSON.parse(JSON.stringify(responseJson.data))
|
||||
console.log("FOUND AUTH: ", tmpAuth)
|
||||
|
||||
//console.log("Checking authentication: ", tmpAuth)
|
||||
var latest = 0
|
||||
for (var key in tmpAuth) {
|
||||
var item = tmpAuth[key]
|
||||
|
||||
const newfields = {}
|
||||
for (var filterkey in item.fields) {
|
||||
newfields[item.fields[filterkey].key] = item.fields[filterkey].value
|
||||
}
|
||||
|
||||
item.fields = newfields
|
||||
if (item.app.name === selectedApp.name) {
|
||||
authenticationOptions.push(item)
|
||||
|
||||
// Always becoming the last one
|
||||
if (item.edited > latest) {
|
||||
latest = item.edited
|
||||
selectedAction.selectedAuthentication = item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (item.id === findAuthId) {
|
||||
// selectedAction.selectedAuthentication = item
|
||||
//}
|
||||
|
||||
console.log("ACTION: ", selectedAction)
|
||||
|
||||
//console.log("OPTIONS: ", authenticationOptions)
|
||||
selectedAction.authentication = authenticationOptions
|
||||
//console.log("Authentication: ", authenticationOptions)
|
||||
if (selectedAction.selectedAuthentication === null || selectedAction.selectedAuthentication === undefined || selectedAction.selectedAuthentication.length === "") {
|
||||
selectedAction.selectedAuthentication = {}
|
||||
}
|
||||
|
||||
setSelectedAction(selectedAction)
|
||||
|
||||
alert.info("Updated authentication for app?")
|
||||
} else {
|
||||
alert.info("No authentication to update")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setAuthLoaded(true)
|
||||
//alert.error("Failed getting authentications")
|
||||
@@ -1945,7 +2007,8 @@ const AngularWorkflow = (props) => {
|
||||
setSelectedAction(curaction)
|
||||
//return
|
||||
} else {
|
||||
console.log("AUTHENTICATION: ", curapp.authentication)
|
||||
//console.log("AUTHENTICATION: ", curapp.authentication)
|
||||
//console.log(curapp.authentication)
|
||||
setAuthenticationType(curapp.authentication.type === "oauth2" && curapp.authentication.redirect_uri !== undefined && curapp.authentication.redirect_uri !== null ?
|
||||
{
|
||||
"type": "oauth2",
|
||||
@@ -5450,6 +5513,10 @@ const AngularWorkflow = (props) => {
|
||||
setLocalFirstrequest(false)
|
||||
}
|
||||
|
||||
const handleButtonRequest = () => {
|
||||
|
||||
}
|
||||
|
||||
const outlookButton =
|
||||
<Button
|
||||
fullWidth
|
||||
@@ -8625,6 +8692,7 @@ const AngularWorkflow = (props) => {
|
||||
: null
|
||||
|
||||
|
||||
|
||||
const AuthenticationData = (props) => {
|
||||
const selectedApp = props.app
|
||||
|
||||
@@ -8883,12 +8951,13 @@ const AngularWorkflow = (props) => {
|
||||
}}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
<ConfigureWorkflow theme={theme} globalUrl={globalUrl} workflow={workflow} setSelectedAction={setSelectedAction} setSelectedApp={setSelectedApp} setAuthenticationModalOpen={setAuthenticationModalOpen} appAuthentication={appAuthentication} selectedAction={selectedAction} apps={apps} setConfigureWorkflowModalOpen={setConfigureWorkflowModalOpen} saveWorkflow={saveWorkflow} newWebhook={newWebhook} submitSchedule={submitSchedule} referenceUrl={referenceUrl} isCloud={isCloud} />
|
||||
<ConfigureWorkflow theme={theme} setAuthenticationType={setAuthenticationType} globalUrl={globalUrl} workflow={workflow} setSelectedAction={setSelectedAction} setSelectedApp={setSelectedApp} setAuthenticationModalOpen={setAuthenticationModalOpen} appAuthentication={appAuthentication} selectedAction={selectedAction} apps={apps} setConfigureWorkflowModalOpen={setConfigureWorkflowModalOpen} saveWorkflow={saveWorkflow} newWebhook={newWebhook} submitSchedule={submitSchedule} referenceUrl={referenceUrl} isCloud={isCloud} />
|
||||
</Dialog>
|
||||
: null
|
||||
|
||||
|
||||
// This whole part is redundant. Made it part of Arguments instead.
|
||||
//console.log("TYPE: ", authenticationType)
|
||||
const authenticationModal = authenticationModalOpen ?
|
||||
<Dialog
|
||||
open={authenticationModalOpen}
|
||||
@@ -8917,7 +8986,11 @@ const AngularWorkflow = (props) => {
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
<DialogTitle><div style={{color: "white"}}>Authentication for {selectedApp.name}</div></DialogTitle>
|
||||
<AuthenticationData app={selectedApp} />
|
||||
{authenticationType.type === "oauth2" ?
|
||||
<AuthenticationOauth2 saveWorkflow={saveWorkflow} selectedApp={selectedApp} workflow={workflow} selectedAction={selectedAction} authenticationType={authenticationType} getAppAuthentication={getAppAuthentication} appAuthentication={appAuthentication} setSelectedAction={setSelectedAction} setNewAppAuth={setNewAppAuth} setAuthenticationModalOpen={setAuthenticationModalOpen} />
|
||||
:
|
||||
<AuthenticationData app={selectedApp} />
|
||||
}
|
||||
</Dialog> : null
|
||||
|
||||
//const loadedCheck = isLoaded && isLoggedIn && workflowDone ?
|
||||
|
||||
+21
-19
@@ -984,19 +984,19 @@ const Apps = (props) => {
|
||||
</div>
|
||||
{isCloud ? null :
|
||||
<span>
|
||||
<Tooltip title={"Reload apps locally"} style={{marginTop: "28px", width: "100%"}} aria-label={"Upload"}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
component="label"
|
||||
color="primary"
|
||||
style={{margin: 5, maxHeight: 50, marginTop: 10}}
|
||||
onClick={() => {
|
||||
hotloadApps()
|
||||
}}
|
||||
>
|
||||
<CachedIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={"Reload apps locally"} style={{marginTop: "28px", width: "100%"}} aria-label={"Upload"}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
component="label"
|
||||
color="primary"
|
||||
style={{margin: 5, maxHeight: 50, marginTop: 10}}
|
||||
onClick={() => {
|
||||
hotloadApps()
|
||||
}}
|
||||
>
|
||||
<CachedIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={"Download from Github"} style={{marginTop: "28px", width: "100%"}} aria-label={"Upload"}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
@@ -1012,7 +1012,7 @@ const Apps = (props) => {
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div style={{height: 50}}>
|
||||
<TextField
|
||||
@@ -1575,11 +1575,13 @@ const Apps = (props) => {
|
||||
<Button style={{borderRadius: "0px"}} onClick={() => setLoadAppsModalOpen(false)} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button style={{borderRadius: "0px"}} disabled={openApi.length === 0 || !openApi.includes("http")} onClick={() => {
|
||||
handleGithubValidation(true)
|
||||
}} color="primary">
|
||||
Force update
|
||||
</Button>
|
||||
{isCloud ? null :
|
||||
<Button style={{borderRadius: "0px"}} disabled={openApi.length === 0 || !openApi.includes("http")} onClick={() => {
|
||||
handleGithubValidation(true)
|
||||
}} color="primary">
|
||||
Force update
|
||||
</Button>
|
||||
}
|
||||
<Button variant="outlined" style={{float: "left", borderRadius: "0px"}} disabled={openApi.length === 0 || !openApi.includes("http")} onClick={() => {
|
||||
handleGithubValidation(false)
|
||||
}} color="primary">
|
||||
|
||||
@@ -51,7 +51,6 @@ var baseimagetagsuffix = os.Getenv("SHUFFLE_BASE_IMAGE_TAG_SUFFIX")
|
||||
|
||||
var orgId = os.Getenv("ORG_ID")
|
||||
var baseUrl = os.Getenv("BASE_URL")
|
||||
|
||||
var environment = os.Getenv("ENVIRONMENT_NAME")
|
||||
var dockerApiVersion = os.Getenv("DOCKER_API_VERSION")
|
||||
var runningMode = strings.ToLower(os.Getenv("RUNNING_MODE"))
|
||||
|
||||
Reference in New Issue
Block a user