Fixed parts of mod migration

This commit is contained in:
frikky
2021-01-26 17:27:19 +01:00
parent 788e02b112
commit 7c5ae7e914
9 changed files with 436 additions and 157 deletions
+2 -1
View File
@@ -44,11 +44,12 @@ Please consider [sponsoring](https://github.com/sponsors/frikky) the project if
https://shuffler.io https://shuffler.io
## Contributors ## Contributors
![ICPL logo](https://github.com/frikky/Shuffle/blob/launch/frontend/src/assets/img/icpl_logo.png)
**Shuffle** **Shuffle**
<a href="https://github.com/frikky/shuffle/graphs/contributors"> <a href="https://github.com/frikky/shuffle/graphs/contributors">
<img src="https://contrib.rocks/image?repo=frikky/shuffle" /> <img src="https://contrib.rocks/image?repo=frikky/shuffle" />
</a> </a>
![ICPL logo](https://github.com/frikky/Shuffle/blob/launch/frontend/src/assets/img/icpl_logo.png)
**Shuffle Apps** **Shuffle Apps**
<a href="https://github.com/frikky/shuffle-apps/graphs/contributors"> <a href="https://github.com/frikky/shuffle-apps/graphs/contributors">
+8 -2
View File
@@ -466,6 +466,7 @@ func generateYaml(swagger *openapi3.Swagger, newmd5 string) (*openapi3.Swagger,
api.Sharing = false api.Sharing = false
api.Verified = false api.Verified = false
api.Tested = false api.Tested = false
api.Invalid = false
api.PrivateID = newmd5 api.PrivateID = newmd5
api.Generated = true api.Generated = true
api.Activated = true api.Activated = true
@@ -658,10 +659,15 @@ func generateYaml(swagger *openapi3.Swagger, newmd5 string) (*openapi3.Swagger,
// This is the python code to be generated // This is the python code to be generated
// Could just as well be go at this point lol // Could just as well be go at this point lol
pythonFunctions := []string{} pythonFunctions := []string{}
//Verified bool `json:"verified" yaml:"verified" required:false datastore:"verified"`
for actualPath, path := range swagger.Paths { for actualPath, path := range swagger.Paths {
actualPath = strings.Replace(actualPath, " ", "_", -1) actualPath = strings.Replace(actualPath, " ", "_", -1)
//actualPath = strings.Replace(actualPath, ".", "", -1) //actualPath = strings.Replace(actualPath, ".", "", -1)
actualPath = strings.Replace(actualPath, "\\", "", -1) actualPath = strings.Replace(actualPath, "\\", "", -1)
if !api.Invalid && strings.HasPrefix(actualPath, "tmp") {
log.Printf("[WARNING] Set api %s to invalid because of path %s", swagger.Info.Title, actualPath)
api.Invalid = true
}
// FIXME: Handle everything behind questionmark (?) with dots as well. // FIXME: Handle everything behind questionmark (?) with dots as well.
// https://godoc.org/github.com/getkin/kin-openapi/openapi3#PathItem // https://godoc.org/github.com/getkin/kin-openapi/openapi3#PathItem
@@ -866,10 +872,10 @@ def run(request):
func deployAppToDatastore(ctx context.Context, workflowapp WorkflowApp) error { func deployAppToDatastore(ctx context.Context, workflowapp WorkflowApp) error {
err := setWorkflowAppDatastore(ctx, workflowapp, workflowapp.ID) err := setWorkflowAppDatastore(ctx, workflowapp, workflowapp.ID)
if err != nil { if err != nil {
log.Printf("Failed setting workflowapp: %s", err) log.Printf("[ERROR] Failed setting workflowapp: %s", err)
return err return err
} else { } else {
log.Printf("Added %s:%s to the database", workflowapp.Name, workflowapp.AppVersion) log.Printf("[INFO] Added %s:%s to the database", workflowapp.Name, workflowapp.AppVersion)
} }
return nil return nil
+1 -1
View File
@@ -23,7 +23,7 @@ require (
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/h2non/filetype v1.0.12 github.com/h2non/filetype v1.0.12
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/satori/go.uuid v1.2.0 github.com/satori/go.uuid v1.2.0
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
+240 -46
View File
@@ -34,6 +34,11 @@ import (
"github.com/getkin/kin-openapi/openapi2" "github.com/getkin/kin-openapi/openapi2"
"github.com/getkin/kin-openapi/openapi2conv" "github.com/getkin/kin-openapi/openapi2conv"
"github.com/getkin/kin-openapi/openapi3" "github.com/getkin/kin-openapi/openapi3"
/*
"github.com/frikky/kin-openapi/openapi2"
"github.com/frikky/kin-openapi/openapi2conv"
"github.com/frikky/kin-openapi/openapi3"
*/
"github.com/google/go-github/v28/github" "github.com/google/go-github/v28/github"
"golang.org/x/oauth2" "golang.org/x/oauth2"
@@ -2801,6 +2806,20 @@ func fixOrgUser(ctx context.Context, org *Org) *Org {
return org return org
} }
// ListBooks returns a list of books, ordered by title.
func setUser(ctx context.Context, data *User) error {
data = fixUserOrg(ctx, data)
// clear session_token and API_token for user
k := datastore.NameKey("Users", data.Id, nil)
if _, err := dbclient.Put(ctx, k, data); err != nil {
log.Println(err)
return err
}
return nil
}
func fixUserOrg(ctx context.Context, user *User) *User { func fixUserOrg(ctx context.Context, user *User) *User {
found := false found := false
for _, id := range user.Orgs { for _, id := range user.Orgs {
@@ -2856,33 +2875,18 @@ func fixUserOrg(ctx context.Context, user *User) *User {
return user return user
} }
// ListBooks returns a list of books, ordered by title.
func setUser(ctx context.Context, data *User) error {
data = fixUserOrg(ctx, data)
// clear session_token and API_token for user
k := datastore.NameKey("Users", data.Id, nil)
if _, err := dbclient.Put(ctx, k, data); err != nil {
log.Println(err)
return err
}
return nil
}
// Used for testing only. Shouldn't impact production. // Used for testing only. Shouldn't impact production.
func handleCors(resp http.ResponseWriter, request *http.Request) bool { func handleCors(resp http.ResponseWriter, request *http.Request) bool {
//allowedOrigins := "http://localhost:3000" //allowedOrigins := "http://localhost:3000"
allowedOrigins := "http://localhost:3002" allowedOrigins := "http://localhost:3002"
resp.Header().Set("Vary", "Origin") resp.Header().Set("Vary", "Origin")
resp.Header().Set("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me") resp.Header().Set("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization")
resp.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, PATCH") resp.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, PATCH")
resp.Header().Set("Access-Control-Allow-Credentials", "true") resp.Header().Set("Access-Control-Allow-Credentials", "true")
resp.Header().Set("Access-Control-Allow-Origin", allowedOrigins) resp.Header().Set("Access-Control-Allow-Origin", allowedOrigins)
if request.Method == "OPTIONS" { if request.Method == "OPTIONS" {
resp.WriteHeader(200) resp.WriteHeader(200)
resp.Write([]byte("OK")) resp.Write([]byte("OK"))
return true return true
@@ -3731,7 +3735,7 @@ func handleNewHook(resp http.ResponseWriter, request *http.Request) {
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return return
} else { } else {
log.Printf("Successfully set up cloud action schedule") log.Printf("[INFO] Successfully set up cloud action schedule")
} }
} }
@@ -5908,7 +5912,7 @@ func getOpenapi(resp http.ResponseWriter, request *http.Request) {
return return
} }
log.Printf("API LENGTH GET: %d, ID: %s", len(parsedApi.Body), id) log.Printf("[INFO] API LENGTH GET: %d, ID: %s", len(parsedApi.Body), id)
parsedApi.Success = true parsedApi.Success = true
data, err := json.Marshal(parsedApi) data, err := json.Marshal(parsedApi)
@@ -6037,8 +6041,11 @@ func handleSwaggerValidation(body []byte) (ParsedOpenApi, error) {
if strings.HasPrefix(version.Swagger, "3.") || strings.HasPrefix(version.OpenAPI, "3.") { if strings.HasPrefix(version.Swagger, "3.") || strings.HasPrefix(version.OpenAPI, "3.") {
//log.Println("Handling v3 API") //log.Println("Handling v3 API")
swaggerv3, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(body) swaggerLoader := openapi3.NewSwaggerLoader()
swaggerLoader.IsExternalRefsAllowed = true
swaggerv3, err := swaggerLoader.LoadSwaggerFromData(body)
if err != nil { if err != nil {
log.Printf("Failed parsing OpenAPI: %s", err)
return ParsedOpenApi{}, err return ParsedOpenApi{}, err
} }
@@ -6161,23 +6168,26 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed reading openapi to json and yaml. Is version defined?: %s"}`, err))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed reading openapi to json and yaml. Is version defined?: %s"}`, err)))
return return
} else { } else {
log.Printf("Successfully parsed YAML (3)!") log.Printf("[INFO] Successfully parsed YAML (3)!")
} }
} else { } else {
isJson = true isJson = true
log.Printf("Successfully parsed JSON!") log.Printf("[INFO] Successfully parsed JSON!")
} }
if len(version.SwaggerVersion) > 0 && len(version.Swagger) == 0 { if len(version.SwaggerVersion) > 0 && len(version.Swagger) == 0 {
version.Swagger = version.SwaggerVersion version.Swagger = version.SwaggerVersion
} }
log.Printf("Version: %#v", version) log.Printf("[INFO] Version: %#v", version)
log.Printf("OpenAPI: %s", version.OpenAPI) log.Printf("[INFO] OpenAPI: %s", version.OpenAPI)
if strings.HasPrefix(version.Swagger, "3.") || strings.HasPrefix(version.OpenAPI, "3.") { if strings.HasPrefix(version.Swagger, "3.") || strings.HasPrefix(version.OpenAPI, "3.") {
log.Println("Handling v3 API") log.Println("[INFO] Handling v3 API")
swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(body) swaggerLoader := openapi3.NewSwaggerLoader()
swaggerLoader.IsExternalRefsAllowed = true
swagger, err := swaggerLoader.LoadSwaggerFromData(body)
if err != nil { if err != nil {
log.Printf("[WARNING] Failed to convert v3 API: %s", err)
resp.WriteHeader(401) resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return return
@@ -6187,11 +6197,10 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
hasher.Write(body) hasher.Write(body)
idstring := hex.EncodeToString(hasher.Sum(nil)) idstring := hex.EncodeToString(hasher.Sum(nil))
log.Printf("Swagger v3 validation success with ID %s!", idstring) log.Printf("Swagger v3 validation success with ID %s and %d paths!", idstring, len(swagger.Paths))
log.Printf("Paths: %d", len(swagger.Paths))
if !isJson { if !isJson {
log.Printf("FIXME: NEED TO TRANSFORM FROM YAML TO JSON for %s", idstring) log.Printf("[INFO] NEED TO TRANSFORM FROM YAML TO JSON for %s", idstring)
} }
swaggerdata, err := json.Marshal(swagger) swaggerdata, err := json.Marshal(swagger)
@@ -6215,7 +6224,7 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
return return
} }
log.Printf("Successfully set OpenAPI with ID %s", idstring) log.Printf("[INFO] Successfully set OpenAPI with ID %s", idstring)
resp.WriteHeader(200) resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true, "id": "%s"}`, idstring))) resp.Write([]byte(fmt.Sprintf(`{"success": true, "id": "%s"}`, idstring)))
return return
@@ -6303,6 +6312,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
return return
} }
log.Printf("[INFO] SETTING APP TO LIVE!!!")
user, err := handleApiAuthentication(resp, request) user, err := handleApiAuthentication(resp, request)
if err != nil { if err != nil {
log.Printf("Api authentication failed in verify swagger: %s", err) log.Printf("Api authentication failed in verify swagger: %s", err)
@@ -6364,17 +6374,25 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
// Test = client side with fetch? // Test = client side with fetch?
ctx := context.Background() ctx := context.Background()
swaggerLoader := openapi3.NewSwaggerLoader()
swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(body) swaggerLoader.IsExternalRefsAllowed = true
swagger, err := swaggerLoader.LoadSwaggerFromData(body)
if err != nil { if err != nil {
log.Printf("Swagger validation error: %s", err) log.Printf("[ERROR] Swagger validation error: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(`{"success": false, "reason": "Failed verifying openapi"}`)) resp.Write([]byte(`{"success": false, "reason": "Failed verifying openapi"}`))
return return
} }
if swagger.Info == nil {
log.Printf("[ERORR] Info is nil?: %#v", swagger)
resp.WriteHeader(500)
resp.Write([]byte(`{"success": false, "reason": "Info not parsed"}`))
return
}
if strings.Contains(swagger.Info.Title, " ") { if strings.Contains(swagger.Info.Title, " ") {
strings.Replace(swagger.Info.Title, " ", "", -1) swagger.Info.Title = strings.Replace(swagger.Info.Title, " ", "_", -1)
} }
basePath, err := buildStructure(swagger, newmd5) basePath, err := buildStructure(swagger, newmd5)
@@ -6396,7 +6414,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
// FIXME: CHECK IF SAME NAME AS NORMAL APP // FIXME: CHECK IF SAME NAME AS NORMAL APP
// Can't overwrite existing normal app // Can't overwrite existing normal app
workflowApps, err := getAllWorkflowApps(ctx, 100) workflowApps, err := getAllWorkflowApps(ctx, 500)
if err != nil { if err != nil {
log.Printf("Failed getting all workflow apps from database to verify: %s", err) log.Printf("Failed getting all workflow apps from database to verify: %s", err)
resp.WriteHeader(401) resp.WriteHeader(401)
@@ -6451,7 +6469,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
if err != nil { if err != nil {
log.Printf("Failed adding app to db: %s", err) log.Printf("Failed adding app to db: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(`{"success": false, "reason": "Failed adding app to db"}`)) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed adding app to db: %s"}`, err)))
return return
} }
@@ -6477,13 +6495,13 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
// 3. Zip and stream it directly in the directory // 3. Zip and stream it directly in the directory
_, err = streamZipdata(ctx, identifier, stitched, "requests\nurllib3") _, err = streamZipdata(ctx, identifier, stitched, "requests\nurllib3")
if err != nil { if err != nil {
log.Printf("Zipfile error: %s", err) log.Printf("[ERROR] Zipfile error: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(`{"success": false, "reason": "Failed to build zipfile"}`)) resp.Write([]byte(`{"success": false, "reason": "Failed to build zipfile"}`))
return return
} }
log.Printf("Successfully stitched ZIPFILE for %s", identifier) log.Printf("[INFO] Successfully stitched ZIPFILE for %s", identifier)
// 4. Upload as cloud function - this apikey is specifically for cloud functions rofl // 4. Upload as cloud function - this apikey is specifically for cloud functions rofl
//environmentVariables := map[string]string{ //environmentVariables := map[string]string{
@@ -6502,7 +6520,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
// 4. Build the image locally. // 4. Build the image locally.
// FIXME: Should be moved to a local docker registry // FIXME: Should be moved to a local docker registry
dockerLocation := fmt.Sprintf("%s/Dockerfile", basePath) dockerLocation := fmt.Sprintf("%s/Dockerfile", basePath)
log.Printf("Dockerfile: %s", dockerLocation) log.Printf("[INFO] Dockerfile: %s", dockerLocation)
versionName := fmt.Sprintf("%s_%s", strings.ToLower(strings.ReplaceAll(api.Name, " ", "-")), api.AppVersion) versionName := fmt.Sprintf("%s_%s", strings.ToLower(strings.ReplaceAll(api.Name, " ", "-")), api.AppVersion)
dockerTags := []string{ dockerTags := []string{
@@ -6512,15 +6530,15 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
err = buildImage(dockerTags, dockerLocation) err = buildImage(dockerTags, dockerLocation)
if err != nil { if err != nil {
log.Printf("Docker build error: %s", err) log.Printf("[ERROR] Docker build error: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error in Docker build"}`))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error in Docker build: %s"}`, err)))
return return
} }
found := false found := false
foundNumber := 0 foundNumber := 0
log.Printf("Checking for api with ID %s", newmd5) log.Printf("[INFO] Checking for api with ID %s", newmd5)
for appCounter, app := range user.PrivateApps { for appCounter, app := range user.PrivateApps {
if app.ID == api.ID { if app.ID == api.ID {
found = true found = true
@@ -6546,25 +6564,25 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
err = setUser(ctx, &user) err = setUser(ctx, &user)
if err != nil { if err != nil {
log.Printf("Failed adding verification for user %s: %s", user.Username, err) log.Printf("[ERROR] Failed adding verification for user %s: %s", user.Username, err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "Failed updating user"}`))) resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "Failed updating user"}`)))
return return
} }
log.Printf("DO I REACH HERE WHEN SAVING?") //log.Printf("DO I REACH HERE WHEN SAVING?")
parsed := ParsedOpenApi{ parsed := ParsedOpenApi{
ID: newmd5, ID: newmd5,
Body: string(body), Body: string(body),
} }
log.Printf("API LENGTH: %d, ID: %s", len(parsed.Body), newmd5) log.Printf("[INFO] API LENGTH: %d, ID: %s", len(parsed.Body), newmd5)
// FIXME: Might cause versioning issues if we re-use the same!! // FIXME: Might cause versioning issues if we re-use the same!!
// FIXME: Need a way to track different versions of the same app properly. // FIXME: Need a way to track different versions of the same app properly.
// Hint: Save API.id somewhere, and use newmd5 to save latest version // Hint: Save API.id somewhere, and use newmd5 to save latest version
err = setOpenApiDatastore(ctx, newmd5, parsed) err = setOpenApiDatastore(ctx, newmd5, parsed)
if err != nil { if err != nil {
log.Printf("Failed saving to datastore: %s", err) log.Printf("[ERROR] Failed saving to datastore: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "%"}`, err))) resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "%"}`, err)))
} }
@@ -7425,7 +7443,7 @@ func runInit(ctx context.Context) {
// Getting apps to see if we should initialize a test // Getting apps to see if we should initialize a test
log.Printf("Getting remote workflow apps") log.Printf("Getting remote workflow apps")
workflowapps, err := getAllWorkflowApps(ctx, 100) workflowapps, err := getAllWorkflowApps(ctx, 500)
if err != nil { if err != nil {
log.Printf("Failed getting apps (runInit): %s", err) log.Printf("Failed getting apps (runInit): %s", err)
} else if err == nil && len(workflowapps) > 0 { } else if err == nil && len(workflowapps) > 0 {
@@ -8094,6 +8112,182 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) {
resp.Write(respBody) resp.Write(respBody)
} }
//func handleEditOrg(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 cloud setup: %s", err)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// }
//
// ctx := context.Background()
// if user.Role != "admin" {
// /*
// log.Printf("User: %s", user.Role)
// dbclient, err := getDatastoreClient(ctx, gceProject)
// if err != nil {
// log.Printf("Err1: %s", err)
// }
//
// user.Role = "admin"
// key := datastore.NameKey("Users", strings.ToLower(user.Username), nil)
// if _, err := dbclient.Put(ctx, key, &user); err != nil {
// log.Printf("Err2: %s", err)
// }
// */
//
// log.Printf("Not admin, can't edit org.")
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false, "reason": "Not admin"}`))
// return
// }
//
// body, err := ioutil.ReadAll(request.Body)
// if err != nil {
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false, "reason": "Failed reading body"}`))
// return
// }
//
// type ReturnData struct {
// Image string `json:"image" datastore:"image"`
// Name string `json:"name" datastore:"name"`
// Description string `json:"description" datastore:"description"`
// OrgId string `json:"org_id" datastore:"org_id"`
// SubscriptionId string `json:"subscription_id" datastore:"subscription_id"`
// Action string `json:"action" datastore:"action"`
// }
//
// var tmpData ReturnData
// err = json.Unmarshal(body, &tmpData)
// if err != nil {
// log.Printf("Failed unmarshalling test: %s", err)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// }
//
// var fileId string
// location := strings.Split(request.URL.String(), "/")
// if location[1] == "api" {
// if len(location) <= 4 {
// log.Printf("Path too short: %d", len(location))
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// }
//
// fileId = location[4]
// }
//
// if tmpData.OrgId != user.ActiveOrg.Id || fileId != user.ActiveOrg.Id {
// log.Printf("User can't edit the org. Not part of ORG: %s vs %s", tmpData.OrgId, user.ActiveOrg.Id)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false, "No permission to edit this org"}`))
// return
// }
//
// org, err := getOrg(ctx, tmpData.OrgId)
// if err != nil {
// log.Printf("Organization doesn't exist: %s", err)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// }
//
// admin := false
// userFound := false
// for _, inneruser := range org.Users {
// if inneruser.Id == user.Id {
// userFound = true
// if inneruser.Role == "admin" {
// admin = true
// }
//
// break
// }
// }
//
// if !userFound {
// log.Printf("User %s doesn't exist in organization for edit %s", user.Id, org.Id)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// }
//
// if !admin {
// log.Printf("User %s doesn't have edit rights to %s", user.Id, org.Id)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// }
//
// if tmpData.Image != org.Image {
// org.Image = tmpData.Image
// }
//
// if tmpData.Name != org.Name {
// org.Name = tmpData.Name
// }
//
// if tmpData.Description != org.Description {
// org.Description = tmpData.Description
// }
//
// if len(tmpData.SubscriptionId) > 0 {
// log.Printf("Should update subscription %s with action %s if it exists", tmpData.SubscriptionId, tmpData.Action)
// found := false
// foundIndex := 0
// for index, sub := range org.Subscriptions {
// if tmpData.SubscriptionId == sub.Reference {
// found = true
// foundIndex = index
// }
// }
//
// if !found {
// log.Printf("Couldn't find sub %s in org %s", tmpData.SubscriptionId, tmpData.OrgId)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// }
//
// if tmpData.Action == "cancel" {
// _, err := sub.Cancel(tmpData.SubscriptionId, nil)
// //log.Printf("Ret: %#v", subReturn)
// if err != nil {
// log.Printf("Failed canceling sub %s.", tmpData.SubscriptionId)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// } else {
// log.Printf("Successfully canceled sub %s in org %s", tmpData.SubscriptionId, tmpData.OrgId)
// timeNow := time.Now().Unix()
// org.Subscriptions[foundIndex].Active = false
// org.Subscriptions[foundIndex].CancellationDate = timeNow
// }
// }
// }
//
// //log.Printf("Org: %#v", org)
// err = setOrg(ctx, *org, org.Id)
// if err != nil {
// log.Printf("User %s doesn't have edit rights to %s", user.Id, org.Id)
// resp.WriteHeader(401)
// resp.Write([]byte(`{"success": false}`))
// return
// }
//
// resp.WriteHeader(200)
// resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "Successfully updated org"}`)))
//}
func initHandlers() { func initHandlers() {
var err error var err error
ctx := context.Background() ctx := context.Background()
+85 -67
View File
@@ -106,20 +106,34 @@ type SyncConfig struct {
// Role is just used for feedback for a user // Role is just used for feedback for a user
type Org struct { type Org struct {
Name string `json:"name" datastore:"name"` Name string `json:"name" datastore:"name"`
Description string `json:"description" datastore:"description"` Description string `json:"description" datastore:"description"`
Image string `json:"image" datastore:"image,noindex"` Image string `json:"image" datastore:"image,noindex"`
Id string `json:"id" datastore:"id"` Id string `json:"id" datastore:"id"`
Org string `json:"org" datastore:"org"` Org string `json:"org" datastore:"org"`
Users []User `json:"users" datastore:"users"` Users []User `json:"users" datastore:"users"`
Role string `json:"role" datastore:"role"` Role string `json:"role" datastore:"role"`
Roles []string `json:"roles" datastore:"roles"` Roles []string `json:"roles" datastore:"roles"`
CloudSync bool `json:"cloud_sync" datastore:"CloudSync"` CloudSync bool `json:"cloud_sync" datastore:"CloudSync"`
SyncConfig SyncConfig `json:"sync_config" datastore:"sync_config"` SyncConfig SyncConfig `json:"sync_config" datastore:"sync_config"`
SyncFeatures SyncFeatures `json:"sync_features" datastore:"sync_features"` SyncFeatures SyncFeatures `json:"sync_features" datastore:"sync_features"`
Created int64 `json:"created" datastore:"created"` Subscriptions []PaymentSubscription `json:"subscriptions" datastore:"subscriptions"`
Edited int64 `json:"edited" datastore:"edited"` Created int64 `json:"created" datastore:"created"`
Defaults Defaults `json:"defaults" datastore:"defaults"` Edited int64 `json:"edited" datastore:"edited"`
Defaults Defaults `json:"defaults" datastore:"defaults"`
}
type PaymentSubscription struct {
Active bool `json:"active" datastore:"active"`
Startdate int64 `json:"startdate" datastore:"startdate"`
CancellationDate int64 `json:"cancellationdate" datastore:"cancellationdate"`
Enddate int64 `json:"enddate" datastore:"enddate"`
Name string `json:"name" datastore:"name"`
Recurrence string `json:"recurrence" datastore:"recurrence"`
Reference string `json:"reference" datastore:"reference"`
Level string `json:"level" datastore:"level"`
Amount string `json:"amount" datastore:"amount"`
Currency string `json:"currency" datastore:"currency"`
} }
type Defaults struct { type Defaults struct {
@@ -162,6 +176,7 @@ type WorkflowApp struct {
Downloaded bool `json:"downloaded" yaml:"downloaded" required:false datastore:"downloaded"` Downloaded bool `json:"downloaded" yaml:"downloaded" required:false datastore:"downloaded"`
Sharing bool `json:"sharing" yaml:"sharing" required:false datastore:"sharing"` Sharing bool `json:"sharing" yaml:"sharing" required:false datastore:"sharing"`
Verified bool `json:"verified" yaml:"verified" required:false datastore:"verified"` Verified bool `json:"verified" yaml:"verified" required:false datastore:"verified"`
Invalid bool `json:"invalid" yaml:"invalid" required:false datastore:"invalid"`
Activated bool `json:"activated" yaml:"activated" required:false datastore:"activated"` Activated bool `json:"activated" yaml:"activated" required:false datastore:"activated"`
Tested bool `json:"tested" yaml:"tested" required:false datastore:"tested"` Tested bool `json:"tested" yaml:"tested" required:false datastore:"tested"`
Owner string `json:"owner" datastore:"owner" yaml:"owner"` Owner string `json:"owner" datastore:"owner" yaml:"owner"`
@@ -1746,7 +1761,7 @@ func setNewWorkflow(resp http.ResponseWriter, request *http.Request) {
//log.Printf("APPENDING NEW APP FOR NEW WORKFLOW") //log.Printf("APPENDING NEW APP FOR NEW WORKFLOW")
// Adds the Testing app if it's a new workflow // Adds the Testing app if it's a new workflow
workflowapps, err := getAllWorkflowApps(ctx, 100) workflowapps, err := getAllWorkflowApps(ctx, 500)
if err == nil { if err == nil {
// FIXME: Add real env // FIXME: Add real env
envName := "Shuffle" envName := "Shuffle"
@@ -2185,7 +2200,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) {
log.Printf("[WORKFLOW INIT] NOT PREVIOUSLY SAVED - SET ACTION AUTH!") log.Printf("[WORKFLOW INIT] NOT PREVIOUSLY SAVED - SET ACTION AUTH!")
//AuthenticationId string `json:"authentication_id,omitempty" datastore:"authentication_id"` //AuthenticationId string `json:"authentication_id,omitempty" datastore:"authentication_id"`
workflowapps, apperr := getAllWorkflowApps(ctx, 100) workflowapps, apperr := getAllWorkflowApps(ctx, 500)
allAuths, err := getAllWorkflowAppAuth(ctx, user.ActiveOrg.Id) allAuths, err := getAllWorkflowAppAuth(ctx, user.ActiveOrg.Id)
if err == nil && len(workflowapps) > 0 && apperr == nil { if err == nil && len(workflowapps) > 0 && apperr == nil {
log.Printf("Setting actions") log.Printf("Setting actions")
@@ -2300,7 +2315,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) {
//outerapp.Authentication.Required //outerapp.Authentication.Required
// Authentication Authentication `json:"authentication" yaml:"authentication" required:false datastore:"authentication"` // Authentication Authentication `json:"authentication" yaml:"authentication" required:false datastore:"authentication"`
//workflowapps, apperr := getAllWorkflowApps(ctx) //workflowapps, apperr := getAllWorkflowApps(ctx, 100)
} }
} }
@@ -2707,7 +2722,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) {
workflow.Actions = newActions workflow.Actions = newActions
workflow.IsValid = true workflow.IsValid = true
log.Printf("Tags: %#v", workflow.Tags) log.Printf("[INFO] Tags: %#v", workflow.Tags)
// FIXME: Is this too drastic? May lead to issues in the future. // FIXME: Is this too drastic? May lead to issues in the future.
// Should maybe make a copy for the old org. // Should maybe make a copy for the old org.
@@ -2745,7 +2760,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) {
cacheKey := fmt.Sprintf("workflowapps-sorted") cacheKey := fmt.Sprintf("workflowapps-sorted")
requestCache.Delete(cacheKey) requestCache.Delete(cacheKey)
log.Printf("Saved new version of workflow %s (%s) for org %s", workflow.Name, fileId, workflow.OrgId) log.Printf("[INFO] Saved new version of workflow %s (%s) for org %s", workflow.Name, fileId, workflow.OrgId)
resp.WriteHeader(200) resp.WriteHeader(200)
newBody, err := json.Marshal(returndata) newBody, err := json.Marshal(returndata)
if err != nil { if err != nil {
@@ -2825,7 +2840,7 @@ func abortExecution(resp http.ResponseWriter, request *http.Request) {
ctx := context.Background() ctx := context.Background()
workflowExecution, err := getWorkflowExecution(ctx, executionId) workflowExecution, err := getWorkflowExecution(ctx, executionId)
if err != nil { if err != nil {
log.Printf("Failed getting execution (abort) %s: %s", executionId, err) log.Printf("[ERROR] Failed getting execution (abort) %s: %s", executionId, err)
resp.WriteHeader(401) resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed getting execution ID %s because it doesn't exist (abort)."}`, executionId))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed getting execution ID %s because it doesn't exist (abort)."}`, executionId)))
return return
@@ -4597,7 +4612,7 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) {
// Not really deleting it, just removing from user cache // Not really deleting it, just removing from user cache
if private { if private {
log.Printf("Deleting private app") log.Printf("[INFO] Deleting private app")
var privateApps []WorkflowApp var privateApps []WorkflowApp
for _, item := range user.PrivateApps { for _, item := range user.PrivateApps {
if item.ID == fileId { if item.ID == fileId {
@@ -4610,14 +4625,14 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) {
user.PrivateApps = privateApps user.PrivateApps = privateApps
err = setUser(ctx, &user) err = setUser(ctx, &user)
if err != nil { if err != nil {
log.Printf("Failed removing %s app for user %s: %s", app.Name, user.Username, err) log.Printf("[ERROR]Failed removing %s app for user %s: %s", app.Name, user.Username, err)
resp.WriteHeader(401) resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": true"}`))) resp.Write([]byte(fmt.Sprintf(`{"success": true"}`)))
return return
} }
} }
log.Printf("Deleting public app") log.Printf("[INFO] Deleting public app")
err = DeleteKey(ctx, "workflowapp", fileId) err = DeleteKey(ctx, "workflowapp", fileId)
if err != nil { if err != nil {
log.Printf("Failed deleting workflowapp") log.Printf("Failed deleting workflowapp")
@@ -4948,7 +4963,7 @@ func addAppAuthentication(resp http.ResponseWriter, request *http.Request) {
app, err := getApp(ctx, appAuth.App.ID) app, err := getApp(ctx, appAuth.App.ID)
if err != nil { if err != nil {
log.Printf("[WARNING] Failed finding app %s while setting auth. Finding it by looping apps.", appAuth.App.ID) log.Printf("[WARNING] Failed finding app %s while setting auth. Finding it by looping apps.", appAuth.App.ID)
workflowapps, err := getAllWorkflowApps(ctx, 100) workflowapps, err := getAllWorkflowApps(ctx, 500)
if err != nil { if err != nil {
resp.WriteHeader(409) resp.WriteHeader(409)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
@@ -5255,7 +5270,7 @@ func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
// return // return
//} //}
workflowapps, err := getAllWorkflowApps(ctx, 100) workflowapps, err := getAllWorkflowApps(ctx, 500)
if err != nil { if err != nil {
log.Printf("Failed getting apps (getworkflowapps): %s", err) log.Printf("Failed getting apps (getworkflowapps): %s", err)
resp.WriteHeader(401) resp.WriteHeader(401)
@@ -5266,45 +5281,48 @@ func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
// FIXME - this is really garbage, but is here to protect again null values etc. // FIXME - this is really garbage, but is here to protect again null values etc.
skipApps := []string{"Shuffle Subflow"} newapps := workflowapps
newapps := []WorkflowApp{} /*
baseApps := []WorkflowApp{} skipApps := []string{"Shuffle Subflow"}
for _, workflowapp := range workflowapps { newapps := []WorkflowApp{}
//if !workflowapp.Activated && workflowapp.Generated { baseApps := []WorkflowApp{}
// continue for _, workflowapp := range workflowapps {
//} //if !workflowapp.Activated && workflowapp.Generated {
// continue
//}
if workflowapp.Owner != user.Id && user.Role != "admin" && !workflowapp.Sharing { if workflowapp.Owner != user.Id && user.Role != "admin" && !workflowapp.Sharing {
continue continue
} }
continueOuter := false continueOuter := false
for _, skip := range skipApps { for _, skip := range skipApps {
if workflowapp.Name == skip { if workflowapp.Name == skip {
continueOuter = true continueOuter = true
break break
}
}
if continueOuter {
continue
}
//workflowapp.Environment = "cloud"
newactions := []WorkflowAppAction{}
for _, action := range workflowapp.Actions {
//action.Environment = workflowapp.Environment
if len(action.Parameters) == 0 {
action.Parameters = []WorkflowAppActionParameter{}
}
newactions = append(newactions, action)
}
workflowapp.Actions = newactions
newapps = append(newapps, workflowapp)
baseApps = append(baseApps, workflowapp)
} }
} */
if continueOuter {
continue
}
//workflowapp.Environment = "cloud"
newactions := []WorkflowAppAction{}
for _, action := range workflowapp.Actions {
//action.Environment = workflowapp.Environment
if len(action.Parameters) == 0 {
action.Parameters = []WorkflowAppActionParameter{}
}
newactions = append(newactions, action)
}
workflowapp.Actions = newactions
newapps = append(newapps, workflowapp)
baseApps = append(baseApps, workflowapp)
}
if len(user.PrivateApps) > 0 { if len(user.PrivateApps) > 0 {
found := false found := false
@@ -5445,7 +5463,7 @@ func getSpecificApps(resp http.ResponseWriter, request *http.Request) {
// FIXME - continue the search here with github repos etc. // FIXME - continue the search here with github repos etc.
// Caching might be smart :D // Caching might be smart :D
ctx := context.Background() ctx := context.Background()
workflowapps, err := getAllWorkflowApps(ctx, 100) workflowapps, err := getAllWorkflowApps(ctx, 500)
if err != nil { if err != nil {
log.Printf("Error: Failed getting workflowapps: %s", err) log.Printf("Error: Failed getting workflowapps: %s", err)
resp.WriteHeader(401) resp.WriteHeader(401)
@@ -5960,7 +5978,7 @@ func loadSpecificApps(resp http.ResponseWriter, request *http.Request) {
func iterateOpenApiGithub(fs billy.Filesystem, dir []os.FileInfo, extra string, onlyname string) error { func iterateOpenApiGithub(fs billy.Filesystem, dir []os.FileInfo, extra string, onlyname string) error {
ctx := context.Background() ctx := context.Background()
workflowapps, err := getAllWorkflowApps(ctx, 100) workflowapps, err := getAllWorkflowApps(ctx, 500)
appCounter := 0 appCounter := 0
if err != nil { if err != nil {
log.Printf("Failed to get existing generated apps") log.Printf("Failed to get existing generated apps")
@@ -6332,7 +6350,7 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
} }
if len(allapps) == 0 { if len(allapps) == 0 {
allapps, err = getAllWorkflowApps(ctx, 100) allapps, err = getAllWorkflowApps(ctx, 500)
if err != nil { if err != nil {
log.Printf("Failed getting apps to verify: %s", err) log.Printf("Failed getting apps to verify: %s", err)
continue continue
@@ -6549,7 +6567,7 @@ func setNewWorkflowApp(resp http.ResponseWriter, request *http.Request) {
} }
ctx := context.Background() ctx := context.Background()
allapps, err := getAllWorkflowApps(ctx, 100) allapps, err := getAllWorkflowApps(ctx, 500)
if err != nil { if err != nil {
log.Printf("Failed getting apps to verify: %s", err) log.Printf("Failed getting apps to verify: %s", err)
resp.WriteHeader(401) resp.WriteHeader(401)
@@ -6719,7 +6737,7 @@ func getAllWorkflowApps(ctx context.Context, maxLen int) ([]WorkflowApp, error)
query := datastore.NewQuery("workflowapp").Order("-edited").Limit(20) query := datastore.NewQuery("workflowapp").Order("-edited").Limit(20)
//query := datastore.NewQuery("workflowapp").Order("-edited").Limit(40) //query := datastore.NewQuery("workflowapp").Order("-edited").Limit(40)
cacheKey := fmt.Sprintf("workflowapps-sorted") cacheKey := fmt.Sprintf("workflowapps-sorted-%d", maxLen)
if value, found := requestCache.Get(cacheKey); found { if value, found := requestCache.Get(cacheKey); found {
parsedValue := value.(*[]WorkflowApp) parsedValue := value.(*[]WorkflowApp)
log.Printf("[INFO] Returning %d apps from cache", len(*parsedValue)) log.Printf("[INFO] Returning %d apps from cache", len(*parsedValue))
@@ -6847,7 +6865,7 @@ func setWorkflowAppAuthDatastore(ctx context.Context, workflowappauth AppAuthent
// New struct, to not add body, author etc // New struct, to not add body, author etc
if _, err := dbclient.Put(ctx, key, &workflowappauth); err != nil { if _, err := dbclient.Put(ctx, key, &workflowappauth); err != nil {
log.Printf("Error adding workflow app: %s", err) log.Printf("Error adding workflow app auth: %s", err)
return err return err
} }
+5 -3
View File
@@ -64,6 +64,7 @@ const Admin = (props) => {
const theme = useTheme(); const theme = useTheme();
const classes = useStyles(); const classes = useStyles();
const [firstRequest, setFirstRequest] = React.useState(true); const [firstRequest, setFirstRequest] = React.useState(true);
const [orgRequest, setOrgRequest] = React.useState(true);
const [modalUser, setModalUser] = React.useState({}); const [modalUser, setModalUser] = React.useState({});
const [modalOpen, setModalOpen] = React.useState(false); const [modalOpen, setModalOpen] = React.useState(false);
@@ -942,8 +943,8 @@ const Admin = (props) => {
} }
} }
if (selectedOrganization.id === undefined && userdata !== undefined && userdata.active_org !== undefined) { if (selectedOrganization.id === undefined && userdata !== undefined && userdata.active_org !== undefined && orgRequest) {
//setSelectedOrganization(userdata.active_org) setOrgRequest(false)
handleGetOrg(userdata.active_org.id) handleGetOrg(userdata.active_org.id)
} }
@@ -1655,6 +1656,7 @@ const Admin = (props) => {
</div> </div>
<div /> <div />
<Button <Button
disabled={isCloud}
style={{}} style={{}}
variant="contained" variant="contained"
color="primary" color="primary"
@@ -2399,7 +2401,7 @@ const Admin = (props) => {
aria-label="disabled tabs example" aria-label="disabled tabs example"
> >
<Tab label=<span><BusinessIcon style={iconStyle} /> Organization</span>/> <Tab label=<span><BusinessIcon style={iconStyle} /> Organization</span>/>
{isCloud ? null : <Tab label=<span><AccessibilityNewIcon style={iconStyle} />Users</span> />} <Tab label=<span><AccessibilityNewIcon style={iconStyle} />Users</span> />
{isCloud ? null : <Tab label=<span><LockIcon style={iconStyle} />App Authentication</span>/>} {isCloud ? null : <Tab label=<span><LockIcon style={iconStyle} />App Authentication</span>/>}
{isCloud ? null : <Tab label=<span><EcoIcon style={iconStyle} />Environments</span>/>} {isCloud ? null : <Tab label=<span><EcoIcon style={iconStyle} />Environments</span>/>}
{isCloud ? null : <Tab label=<span><ScheduleIcon style={iconStyle} />Schedules</span> />} {isCloud ? null : <Tab label=<span><ScheduleIcon style={iconStyle} />Schedules</span> />}
+7 -2
View File
@@ -1180,7 +1180,7 @@ const AngularWorkflow = (props) => {
setSelectedApp(curapp) setSelectedApp(curapp)
} }
if (environments !== undefined) { if (environments !== undefined && environments !== null) {
var env = environments.find(a => a.Name === curaction.environment) var env = environments.find(a => a.Name === curaction.environment)
if (!env || env === undefined) { if (!env || env === undefined) {
env = environments[defaultEnvironmentIndex] env = environments[defaultEnvironmentIndex]
@@ -2414,7 +2414,7 @@ const AngularWorkflow = (props) => {
app_id: app.id, app_id: app.id,
sharing: app.sharing, sharing: app.sharing,
private_id: app.private_id, private_id: app.private_id,
environment: environments[defaultEnvironmentIndex].Name, environment: environments === null ? "cloud" : environments[defaultEnvironmentIndex].Name,
errors: [], errors: [],
id_: newNodeId, id_: newNodeId,
_id_: newNodeId, _id_: newNodeId,
@@ -2601,6 +2601,11 @@ const AngularWorkflow = (props) => {
) )
})} })}
{filteredApps.filter(innerapp => !internalIds.includes(innerapp.id)).map((app, index) => { {filteredApps.filter(innerapp => !internalIds.includes(innerapp.id)).map((app, index) => {
if (app.invalid) {
return null
}
console.log("APP: ", app)
return( return(
<ParsedAppPaper key={index} app={app} /> <ParsedAppPaper key={index} app={app} />
) )
+70 -27
View File
@@ -195,6 +195,7 @@ const AppCreator = (props) => {
const alert = useAlert() const alert = useAlert()
var upload = "" var upload = ""
const increaseAmount = 30
const actionNonBodyRequest = ["GET", "HEAD", "DELETE", "CONNECT"] const actionNonBodyRequest = ["GET", "HEAD", "DELETE", "CONNECT"]
const actionBodyRequest = ["POST", "PUT", "PATCH",] const actionBodyRequest = ["POST", "PUT", "PATCH",]
const authenticationOptions = ["No authentication", "API key", "Bearer auth", "Basic auth", ] const authenticationOptions = ["No authentication", "API key", "Bearer auth", "Basic auth", ]
@@ -228,6 +229,7 @@ const AppCreator = (props) => {
const [appBuilding, setAppBuilding] = useState(false) const [appBuilding, setAppBuilding] = useState(false)
const [extraBodyFields, setExtraBodyFields] = useState([]) const [extraBodyFields, setExtraBodyFields] = useState([])
const [fileUploadEnabled, setFileUploadEnabled] = useState(false) const [fileUploadEnabled, setFileUploadEnabled] = useState(false)
const [actionAmount, setActionAmount] = useState(increaseAmount)
//const [actions, setActions] = useState([{ //const [actions, setActions] = useState([{
// "name": "Get workflows", // "name": "Get workflows",
@@ -447,11 +449,21 @@ const AppCreator = (props) => {
} }
if (data.tags !== undefined && data.tags.length > 0) { if (data.tags !== undefined && data.tags.length > 0) {
var newtags = []
for (var key in data.tags) { for (var key in data.tags) {
newWorkflowTags.push(data.tags[key].name) if (data.tags[key].name.length > 50) {
console.log("Skipping tag cus it's too long: ", data.tags[key].name.length)
continue
}
newtags.push(data.tags[key].name)
} }
setNewWorkflowTags(newWorkflowTags) if (newtags.length > 10) {
newtags = newtags.slice(0,9)
}
setNewWorkflowTags(newtags)
} }
// This is annoying (: // This is annoying (:
@@ -512,7 +524,7 @@ const AppCreator = (props) => {
//console.log("Handle requestbody: ", methodvalue["requestBody"]) //console.log("Handle requestbody: ", methodvalue["requestBody"])
if (methodvalue["requestBody"]["content"] !== undefined) { if (methodvalue["requestBody"]["content"] !== undefined) {
if (methodvalue["requestBody"]["content"]["application/json"] !== undefined) { if (methodvalue["requestBody"]["content"]["application/json"] !== undefined) {
if (methodvalue["requestBody"]["content"]["application/json"]["schema"] !== undefined) { if (methodvalue["requestBody"]["content"]["application/json"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["application/json"]["schema"] !== null) {
if (methodvalue["requestBody"]["content"]["application/json"]["schema"]["properties"] !== undefined) { if (methodvalue["requestBody"]["content"]["application/json"]["schema"]["properties"] !== undefined) {
var tmpobject = {} var tmpobject = {}
for (let [prop, propvalue] of Object.entries(methodvalue["requestBody"]["content"]["application/json"]["schema"]["properties"])) { for (let [prop, propvalue] of Object.entries(methodvalue["requestBody"]["content"]["application/json"]["schema"]["properties"])) {
@@ -529,7 +541,7 @@ const AppCreator = (props) => {
} }
} else if (methodvalue["requestBody"]["content"]["application/xml"] !== undefined) { } else if (methodvalue["requestBody"]["content"]["application/xml"] !== undefined) {
console.log("METHOD XML: ", methodvalue) console.log("METHOD XML: ", methodvalue)
if (methodvalue["requestBody"]["content"]["application/xml"]["schema"] !== undefined) { if (methodvalue["requestBody"]["content"]["application/xml"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["application/xml"]["schema"] !== null) {
if (methodvalue["requestBody"]["content"]["application/xml"]["schema"]["properties"] !== undefined) { if (methodvalue["requestBody"]["content"]["application/xml"]["schema"]["properties"] !== undefined) {
var tmpobject = {} var tmpobject = {}
for (let [prop, propvalue] of Object.entries(methodvalue["requestBody"]["content"]["application/xml"]["schema"]["properties"])) { for (let [prop, propvalue] of Object.entries(methodvalue["requestBody"]["content"]["application/xml"]["schema"]["properties"])) {
@@ -555,7 +567,7 @@ const AppCreator = (props) => {
console.log(methodvalue["requestBody"]["content"]) console.log(methodvalue["requestBody"]["content"])
if (methodvalue["requestBody"]["content"]["multipart/form-data"] !== undefined) { if (methodvalue["requestBody"]["content"]["multipart/form-data"] !== undefined) {
if (methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"] !== undefined) { if (methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"] !== null) {
if (methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"]["type"] === "object") { if (methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"]["type"] === "object") {
const fieldname = methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"]["properties"]["fieldname"] const fieldname = methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"]["properties"]["fieldname"]
if (fieldname !== undefined) { if (fieldname !== undefined) {
@@ -616,7 +628,7 @@ const AppCreator = (props) => {
} else if (parameter.in === "header") { } else if (parameter.in === "header") {
newaction.headers += `${parameter.name}=${parameter.example}\n` newaction.headers += `${parameter.name}=${parameter.example}\n`
} else { } else {
console.log("WARNING: don't know how to handle: ", parameter) console.log("WARNING: don't know how to handle this param: ", parameter)
} }
} }
@@ -734,6 +746,17 @@ const AppCreator = (props) => {
} }
} }
if (newActions.length > increaseAmount-1) {
setActionAmount(increaseAmount)
} else {
setActionAmount(newActions.length)
}
if (newActions.length > 1000) {
alert.error("Cut down actions from "+newActions.length+" to 999 because of limit")
newActions = newActions.slice(0,999)
}
setActions(newActions) setActions(newActions)
setIsAppLoaded(true) setIsAppLoaded(true)
} }
@@ -811,6 +834,11 @@ const AppCreator = (props) => {
} }
const regex = /[A-Za-z0-9 _]/g; const regex = /[A-Za-z0-9 _]/g;
if (item.name === undefined) {
console.log("Skipping action ", item)
continue
}
const found = item.name.match(regex); const found = item.name.match(regex);
if (found !== null) { if (found !== null) {
item.name = found.join("") item.name = found.join("")
@@ -1326,7 +1354,7 @@ const AppCreator = (props) => {
null null
: :
<div> <div>
{actions.map((data, index) => { {actions.slice(0,actionAmount).map((data, index) => {
var error = data.errors.length > 0 ? var error = data.errors.length > 0 ?
<Tooltip color="primary" title={data.errors.join("\n")} placement="bottom"> <Tooltip color="primary" title={data.errors.join("\n")} placement="bottom">
<ErrorOutline /> <ErrorOutline />
@@ -1745,11 +1773,13 @@ const AppCreator = (props) => {
id: 'method-option', id: 'method-option',
}} }}
> >
{actionNonBodyRequest.map(data => ( {actionNonBodyRequest.map((data, index) => {
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}> return (
<MenuItem key={index} style={{backgroundColor: inputColor, color: "white"}} value={data}>
{data} {data}
</MenuItem> </MenuItem>
))} )
})}
{actionBodyRequest.map(data => ( {actionBodyRequest.map(data => (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}> <MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
{data} {data}
@@ -2001,27 +2031,40 @@ const AppCreator = (props) => {
const actionView = const actionView =
<div style={{color: "white"}}> <div style={{color: "white"}}>
<h2>Actions</h2> <h2>Actions ({actions.length})</h2>
Actions are the tasks performed by an app. Read more about actions and apps Actions are the tasks performed by an app. Read more about actions and apps
<Link target="_blank" to="https://shuffler.io/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}> here</Link>. <Link target="_blank" to="https://shuffler.io/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}> here</Link>.
<div> <div>
{loopActions} {loopActions}
<Button color="primary" style={{marginTop: "20px", borderRadius: "0px"}} variant="outlined" onClick={() => { <div style={{display: "flex"}}>
setCurrentAction({ <Button color="primary" style={{marginTop: "20px", borderRadius: "0px"}} variant="outlined" onClick={() => {
"name": "", setCurrentAction({
"description": "", "name": "",
"url": "", "description": "",
"file_field": "", "url": "",
"headers": "", "file_field": "",
"queries": [], "headers": "",
"paths": [], "queries": [],
"body": "", "paths": [],
"errors": [], "body": "",
"method": actionNonBodyRequest[0], "errors": [],
}) "method": actionNonBodyRequest[0],
setCurrentActionMethod(actionNonBodyRequest[0]) })
setActionsModalOpen(true) setCurrentActionMethod(actionNonBodyRequest[0])
}}>New action</Button> setActionsModalOpen(true)
}}>New action</Button>
{actionAmount > 0 && actionAmount < actions.length ? null :
<Button color="primary" style={{marginTop: "20px", borderRadius: "0px", textAlign: "center"}} variant="outlined" onClick={() => {
if (actionAmount+increaseAmount > actions.length) {
setActionAmount(actions.length)
} else {
setActionAmount(actionAmount+increaseAmount)
}
}}>
See more actions
</Button>
}
</div>
</div> </div>
</div> </div>
+18 -8
View File
@@ -21,6 +21,7 @@ import {Link} from 'react-router-dom';
import Breadcrumbs from '@material-ui/core/Breadcrumbs'; import Breadcrumbs from '@material-ui/core/Breadcrumbs';
import ReactJson from 'react-json-view' import ReactJson from 'react-json-view'
import Chip from '@material-ui/core/Chip'; import Chip from '@material-ui/core/Chip';
import { useTheme } from '@material-ui/core/styles';
import CachedIcon from '@material-ui/icons/Cached'; import CachedIcon from '@material-ui/icons/Cached';
import CloudDownloadIcon from '@material-ui/icons/CloudDownload'; import CloudDownloadIcon from '@material-ui/icons/CloudDownload';
@@ -113,6 +114,7 @@ const Apps = (props) => {
const { globalUrl, isLoggedIn, isLoaded, userdata } = props; const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
//const [workflows, setWorkflows] = React.useState([]); //const [workflows, setWorkflows] = React.useState([]);
const theme = useTheme();
const baseRepository = "https://github.com/frikky/shuffle-apps" const baseRepository = "https://github.com/frikky/shuffle-apps"
const alert = useAlert() const alert = useAlert()
const [selectedApp, setSelectedApp] = React.useState({}); const [selectedApp, setSelectedApp] = React.useState({});
@@ -316,10 +318,18 @@ const Apps = (props) => {
boxColor = "orange" boxColor = "orange"
} }
if (data.invalid) {
boxColor = "red"
}
//<div style={{backgroundColor: theme.palette.inputColor, height: 100, width: 100, borderRadius: 3, verticalAlign: "middle", textAlign: "center", display: "table-cell"}}>
// <div style={{width: "100px", height: "100px", border: "1px solid black", verticalAlign: "middle", textAlign: "center", display: "table-cell"}}>
var imageline = data.large_image.length === 0 ? var imageline = data.large_image.length === 0 ?
<img alt={data.title} style={{width: 100, height: 100}} /> <img alt={data.title} style={{width: 100, height: 100, backgroundColor: theme.palette.inputColor,}} />
: :
<img alt={data.title} src={data.large_image} style={{width: 100, height: 100, maxWidth: "100%"}} /> <img alt={data.title} src={data.large_image} style={{maxWidth: 100, maxHeight: "100%", display: "block", margin: "0 auto"}} onLoad={(event) => {
//console.log("IMG LOADED!: ", event.target)
}} />
// FIXME - add label to apps, as this might be slow with A LOT of apps // FIXME - add label to apps, as this might be slow with A LOT of apps
var newAppname = data.name var newAppname = data.name
@@ -341,7 +351,7 @@ const Apps = (props) => {
} }
var description = data.description var description = data.description
const maxDescLen = 56 const maxDescLen = 51
if (description.length > maxDescLen) { if (description.length > maxDescLen) {
description = data.description.slice(0, maxDescLen)+"..." description = data.description.slice(0, maxDescLen)+"..."
} }
@@ -364,8 +374,8 @@ const Apps = (props) => {
} }
} }
}}> }}>
<Grid container style={{margin: 10, flex: "10"}}> <Grid container style={{margin: 10, flex: "10", maxHeight: 110, overflow: "hidden",}}>
<ButtonBase> <ButtonBase style={{backgroundColor: theme.palette.inputColor, border: 3}}>
{imageline} {imageline}
</ButtonBase> </ButtonBase>
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: boxWidth, backgroundColor: boxColor}}> <div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: boxWidth, backgroundColor: boxColor}}>
@@ -520,9 +530,9 @@ const Apps = (props) => {
: null : null
var imageline = selectedApp.large_image === undefined || selectedApp.large_image.length === 0 ? var imageline = selectedApp.large_image === undefined || selectedApp.large_image.length === 0 ?
<img alt={selectedApp.title} style={{width: 100, height: 100}} /> <img alt={selectedApp.title} style={{width: 100, height: 100, backgroundColor: theme.palette.inputColor,}} />
: :
<img alt={selectedApp.title} src={selectedApp.large_image} style={{width: 100, height: 100, maxWidth: "100%"}} /> <img alt={selectedApp.title} src={selectedApp.large_image} style={{maxHeight: 100, maxWidth: 100, backgroundColor: theme.palette.inputColor}} />
const GetAppExample = () => { const GetAppExample = () => {
if (selectedAction.returns === undefined) { if (selectedAction.returns === undefined) {
@@ -639,7 +649,7 @@ const Apps = (props) => {
updateAppField(selectedApp.id, "sharing", !selectedApp.sharing) updateAppField(selectedApp.id, "sharing", !selectedApp.sharing)
//setSelectedAction(event.target.value) //setSelectedAction(event.target.value)
}} }}
style={{width: 150, backgroundColor: inputColor, color: "white", height: 35, marginleft: 10,}} style={{width: 150, backgroundColor: theme.palette.surfaceColor, backgroundColor: inputColor, color: "white", height: 35, marginleft: 10,}}
SelectDisplayProps={{ SelectDisplayProps={{
style: { style: {
marginLeft: 10, marginLeft: 10,