diff --git a/README.md b/README.md index f8b0baf9..5c5bfd74 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,12 @@ Please consider [sponsoring](https://github.com/sponsors/frikky) the project if https://shuffler.io ## Contributors +![ICPL logo](https://github.com/frikky/Shuffle/blob/launch/frontend/src/assets/img/icpl_logo.png) + **Shuffle** -![ICPL logo](https://github.com/frikky/Shuffle/blob/launch/frontend/src/assets/img/icpl_logo.png) **Shuffle Apps** diff --git a/backend/go-app/codegen.go b/backend/go-app/codegen.go index 337a33e5..9de39237 100644 --- a/backend/go-app/codegen.go +++ b/backend/go-app/codegen.go @@ -466,6 +466,7 @@ func generateYaml(swagger *openapi3.Swagger, newmd5 string) (*openapi3.Swagger, api.Sharing = false api.Verified = false api.Tested = false + api.Invalid = false api.PrivateID = newmd5 api.Generated = 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 // Could just as well be go at this point lol pythonFunctions := []string{} + //Verified bool `json:"verified" yaml:"verified" required:false datastore:"verified"` for actualPath, path := range swagger.Paths { 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. // 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 { err := setWorkflowAppDatastore(ctx, workflowapp, workflowapp.ID) if err != nil { - log.Printf("Failed setting workflowapp: %s", err) + log.Printf("[ERROR] Failed setting workflowapp: %s", err) return err } 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 diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod index b9bbe755..0bf0ccce 100644 --- a/backend/go-app/go.mod +++ b/backend/go-app/go.mod @@ -23,7 +23,7 @@ require ( github.com/gorilla/mux v1.7.4 github.com/h2non/filetype v1.0.12 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 golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 5f246044..b7e9a7fd 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -34,6 +34,11 @@ import ( "github.com/getkin/kin-openapi/openapi2" "github.com/getkin/kin-openapi/openapi2conv" "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" "golang.org/x/oauth2" @@ -2801,6 +2806,20 @@ func fixOrgUser(ctx context.Context, org *Org) *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 { found := false for _, id := range user.Orgs { @@ -2856,33 +2875,18 @@ func fixUserOrg(ctx context.Context, user *User) *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. func handleCors(resp http.ResponseWriter, request *http.Request) bool { //allowedOrigins := "http://localhost:3000" allowedOrigins := "http://localhost:3002" 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-Credentials", "true") resp.Header().Set("Access-Control-Allow-Origin", allowedOrigins) if request.Method == "OPTIONS" { - resp.WriteHeader(200) resp.Write([]byte("OK")) return true @@ -3731,7 +3735,7 @@ func handleNewHook(resp http.ResponseWriter, request *http.Request) { resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err))) return } 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 } - 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 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.") { //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 { + log.Printf("Failed parsing OpenAPI: %s", 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))) return } else { - log.Printf("Successfully parsed YAML (3)!") + log.Printf("[INFO] Successfully parsed YAML (3)!") } } else { isJson = true - log.Printf("Successfully parsed JSON!") + log.Printf("[INFO] Successfully parsed JSON!") } if len(version.SwaggerVersion) > 0 && len(version.Swagger) == 0 { version.Swagger = version.SwaggerVersion } - log.Printf("Version: %#v", version) - log.Printf("OpenAPI: %s", version.OpenAPI) + log.Printf("[INFO] Version: %#v", version) + log.Printf("[INFO] OpenAPI: %s", version.OpenAPI) if strings.HasPrefix(version.Swagger, "3.") || strings.HasPrefix(version.OpenAPI, "3.") { - log.Println("Handling v3 API") - swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(body) + log.Println("[INFO] Handling v3 API") + swaggerLoader := openapi3.NewSwaggerLoader() + swaggerLoader.IsExternalRefsAllowed = true + swagger, err := swaggerLoader.LoadSwaggerFromData(body) if err != nil { + log.Printf("[WARNING] Failed to convert v3 API: %s", err) resp.WriteHeader(401) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err))) return @@ -6187,11 +6197,10 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) { hasher.Write(body) idstring := hex.EncodeToString(hasher.Sum(nil)) - log.Printf("Swagger v3 validation success with ID %s!", idstring) - log.Printf("Paths: %d", len(swagger.Paths)) + log.Printf("Swagger v3 validation success with ID %s and %d paths!", idstring, len(swagger.Paths)) 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) @@ -6215,7 +6224,7 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) { return } - log.Printf("Successfully set OpenAPI with ID %s", idstring) + log.Printf("[INFO] Successfully set OpenAPI with ID %s", idstring) resp.WriteHeader(200) resp.Write([]byte(fmt.Sprintf(`{"success": true, "id": "%s"}`, idstring))) return @@ -6303,6 +6312,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) { return } + log.Printf("[INFO] SETTING APP TO LIVE!!!") user, err := handleApiAuthentication(resp, request) if err != nil { 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? ctx := context.Background() - - swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(body) + swaggerLoader := openapi3.NewSwaggerLoader() + swaggerLoader.IsExternalRefsAllowed = true + swagger, err := swaggerLoader.LoadSwaggerFromData(body) if err != nil { - log.Printf("Swagger validation error: %s", err) + log.Printf("[ERROR] Swagger validation error: %s", err) resp.WriteHeader(500) resp.Write([]byte(`{"success": false, "reason": "Failed verifying openapi"}`)) 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, " ") { - strings.Replace(swagger.Info.Title, " ", "", -1) + swagger.Info.Title = strings.Replace(swagger.Info.Title, " ", "_", -1) } 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 // Can't overwrite existing normal app - workflowApps, err := getAllWorkflowApps(ctx, 100) + workflowApps, err := getAllWorkflowApps(ctx, 500) if err != nil { log.Printf("Failed getting all workflow apps from database to verify: %s", err) resp.WriteHeader(401) @@ -6451,7 +6469,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) { if err != nil { log.Printf("Failed adding app to db: %s", err) 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 } @@ -6477,13 +6495,13 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) { // 3. Zip and stream it directly in the directory _, err = streamZipdata(ctx, identifier, stitched, "requests\nurllib3") if err != nil { - log.Printf("Zipfile error: %s", err) + log.Printf("[ERROR] Zipfile error: %s", err) resp.WriteHeader(500) resp.Write([]byte(`{"success": false, "reason": "Failed to build zipfile"}`)) 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 //environmentVariables := map[string]string{ @@ -6502,7 +6520,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) { // 4. Build the image locally. // FIXME: Should be moved to a local docker registry 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) dockerTags := []string{ @@ -6512,15 +6530,15 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) { err = buildImage(dockerTags, dockerLocation) if err != nil { - log.Printf("Docker build error: %s", err) + log.Printf("[ERROR] Docker build error: %s", err) 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 } found := false 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 { if app.ID == api.ID { found = true @@ -6546,25 +6564,25 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) { err = setUser(ctx, &user) 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.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "Failed updating user"}`))) return } - log.Printf("DO I REACH HERE WHEN SAVING?") + //log.Printf("DO I REACH HERE WHEN SAVING?") parsed := ParsedOpenApi{ ID: newmd5, 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: Need a way to track different versions of the same app properly. // Hint: Save API.id somewhere, and use newmd5 to save latest version err = setOpenApiDatastore(ctx, newmd5, parsed) if err != nil { - log.Printf("Failed saving to datastore: %s", err) + log.Printf("[ERROR] Failed saving to datastore: %s", err) resp.WriteHeader(500) 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 log.Printf("Getting remote workflow apps") - workflowapps, err := getAllWorkflowApps(ctx, 100) + workflowapps, err := getAllWorkflowApps(ctx, 500) if err != nil { log.Printf("Failed getting apps (runInit): %s", err) } else if err == nil && len(workflowapps) > 0 { @@ -8094,6 +8112,182 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) { 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() { var err error ctx := context.Background() diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index 30984f02..c77f4345 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -106,20 +106,34 @@ type SyncConfig struct { // Role is just used for feedback for a user type Org struct { - Name string `json:"name" datastore:"name"` - Description string `json:"description" datastore:"description"` - Image string `json:"image" datastore:"image,noindex"` - Id string `json:"id" datastore:"id"` - Org string `json:"org" datastore:"org"` - Users []User `json:"users" datastore:"users"` - Role string `json:"role" datastore:"role"` - Roles []string `json:"roles" datastore:"roles"` - CloudSync bool `json:"cloud_sync" datastore:"CloudSync"` - SyncConfig SyncConfig `json:"sync_config" datastore:"sync_config"` - SyncFeatures SyncFeatures `json:"sync_features" datastore:"sync_features"` - Created int64 `json:"created" datastore:"created"` - Edited int64 `json:"edited" datastore:"edited"` - Defaults Defaults `json:"defaults" datastore:"defaults"` + Name string `json:"name" datastore:"name"` + Description string `json:"description" datastore:"description"` + Image string `json:"image" datastore:"image,noindex"` + Id string `json:"id" datastore:"id"` + Org string `json:"org" datastore:"org"` + Users []User `json:"users" datastore:"users"` + Role string `json:"role" datastore:"role"` + Roles []string `json:"roles" datastore:"roles"` + CloudSync bool `json:"cloud_sync" datastore:"CloudSync"` + SyncConfig SyncConfig `json:"sync_config" datastore:"sync_config"` + SyncFeatures SyncFeatures `json:"sync_features" datastore:"sync_features"` + Subscriptions []PaymentSubscription `json:"subscriptions" datastore:"subscriptions"` + Created int64 `json:"created" datastore:"created"` + 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 { @@ -162,6 +176,7 @@ type WorkflowApp struct { Downloaded bool `json:"downloaded" yaml:"downloaded" required:false datastore:"downloaded"` Sharing bool `json:"sharing" yaml:"sharing" required:false datastore:"sharing"` 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"` Tested bool `json:"tested" yaml:"tested" required:false datastore:"tested"` 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") // Adds the Testing app if it's a new workflow - workflowapps, err := getAllWorkflowApps(ctx, 100) + workflowapps, err := getAllWorkflowApps(ctx, 500) if err == nil { // FIXME: Add real env envName := "Shuffle" @@ -2185,7 +2200,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { log.Printf("[WORKFLOW INIT] NOT PREVIOUSLY SAVED - SET ACTION AUTH!") //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) if err == nil && len(workflowapps) > 0 && apperr == nil { log.Printf("Setting actions") @@ -2300,7 +2315,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { //outerapp.Authentication.Required // 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.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. // 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") 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) newBody, err := json.Marshal(returndata) if err != nil { @@ -2825,7 +2840,7 @@ func abortExecution(resp http.ResponseWriter, request *http.Request) { ctx := context.Background() workflowExecution, err := getWorkflowExecution(ctx, executionId) 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.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed getting execution ID %s because it doesn't exist (abort)."}`, executionId))) return @@ -4597,7 +4612,7 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) { // Not really deleting it, just removing from user cache if private { - log.Printf("Deleting private app") + log.Printf("[INFO] Deleting private app") var privateApps []WorkflowApp for _, item := range user.PrivateApps { if item.ID == fileId { @@ -4610,14 +4625,14 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) { user.PrivateApps = privateApps err = setUser(ctx, &user) 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.Write([]byte(fmt.Sprintf(`{"success": true"}`))) return } } - log.Printf("Deleting public app") + log.Printf("[INFO] Deleting public app") err = DeleteKey(ctx, "workflowapp", fileId) if err != nil { log.Printf("Failed deleting workflowapp") @@ -4948,7 +4963,7 @@ func addAppAuthentication(resp http.ResponseWriter, request *http.Request) { app, err := getApp(ctx, appAuth.App.ID) if err != nil { 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 { resp.WriteHeader(409) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err))) @@ -5255,7 +5270,7 @@ func getWorkflowApps(resp http.ResponseWriter, request *http.Request) { // return //} - workflowapps, err := getAllWorkflowApps(ctx, 100) + workflowapps, err := getAllWorkflowApps(ctx, 500) if err != nil { log.Printf("Failed getting apps (getworkflowapps): %s", err) 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. - skipApps := []string{"Shuffle Subflow"} - newapps := []WorkflowApp{} - baseApps := []WorkflowApp{} - for _, workflowapp := range workflowapps { - //if !workflowapp.Activated && workflowapp.Generated { - // continue - //} + newapps := workflowapps + /* + skipApps := []string{"Shuffle Subflow"} + newapps := []WorkflowApp{} + baseApps := []WorkflowApp{} + for _, workflowapp := range workflowapps { + //if !workflowapp.Activated && workflowapp.Generated { + // continue + //} - if workflowapp.Owner != user.Id && user.Role != "admin" && !workflowapp.Sharing { - continue - } + if workflowapp.Owner != user.Id && user.Role != "admin" && !workflowapp.Sharing { + continue + } - continueOuter := false - for _, skip := range skipApps { - if workflowapp.Name == skip { - continueOuter = true - break + continueOuter := false + for _, skip := range skipApps { + if workflowapp.Name == skip { + continueOuter = true + 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 { found := false @@ -5445,7 +5463,7 @@ func getSpecificApps(resp http.ResponseWriter, request *http.Request) { // FIXME - continue the search here with github repos etc. // Caching might be smart :D ctx := context.Background() - workflowapps, err := getAllWorkflowApps(ctx, 100) + workflowapps, err := getAllWorkflowApps(ctx, 500) if err != nil { log.Printf("Error: Failed getting workflowapps: %s", err) 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 { ctx := context.Background() - workflowapps, err := getAllWorkflowApps(ctx, 100) + workflowapps, err := getAllWorkflowApps(ctx, 500) appCounter := 0 if err != nil { 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 { - allapps, err = getAllWorkflowApps(ctx, 100) + allapps, err = getAllWorkflowApps(ctx, 500) if err != nil { log.Printf("Failed getting apps to verify: %s", err) continue @@ -6549,7 +6567,7 @@ func setNewWorkflowApp(resp http.ResponseWriter, request *http.Request) { } ctx := context.Background() - allapps, err := getAllWorkflowApps(ctx, 100) + allapps, err := getAllWorkflowApps(ctx, 500) if err != nil { log.Printf("Failed getting apps to verify: %s", err) 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(40) - cacheKey := fmt.Sprintf("workflowapps-sorted") + cacheKey := fmt.Sprintf("workflowapps-sorted-%d", maxLen) if value, found := requestCache.Get(cacheKey); found { parsedValue := value.(*[]WorkflowApp) 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 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 } diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index fdad720f..f590ad60 100644 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -64,6 +64,7 @@ const Admin = (props) => { const theme = useTheme(); const classes = useStyles(); const [firstRequest, setFirstRequest] = React.useState(true); + const [orgRequest, setOrgRequest] = React.useState(true); const [modalUser, setModalUser] = React.useState({}); const [modalOpen, setModalOpen] = React.useState(false); @@ -942,8 +943,8 @@ const Admin = (props) => { } } - if (selectedOrganization.id === undefined && userdata !== undefined && userdata.active_org !== undefined) { - //setSelectedOrganization(userdata.active_org) + if (selectedOrganization.id === undefined && userdata !== undefined && userdata.active_org !== undefined && orgRequest) { + setOrgRequest(false) handleGetOrg(userdata.active_org.id) } @@ -1655,6 +1656,7 @@ const Admin = (props) => {
+
+ + {actionAmount > 0 && actionAmount < actions.length ? null : + + } +
diff --git a/frontend/src/views/Apps.jsx b/frontend/src/views/Apps.jsx index 430645ef..15289670 100644 --- a/frontend/src/views/Apps.jsx +++ b/frontend/src/views/Apps.jsx @@ -21,6 +21,7 @@ import {Link} from 'react-router-dom'; import Breadcrumbs from '@material-ui/core/Breadcrumbs'; import ReactJson from 'react-json-view' import Chip from '@material-ui/core/Chip'; +import { useTheme } from '@material-ui/core/styles'; import CachedIcon from '@material-ui/icons/Cached'; import CloudDownloadIcon from '@material-ui/icons/CloudDownload'; @@ -113,6 +114,7 @@ const Apps = (props) => { const { globalUrl, isLoggedIn, isLoaded, userdata } = props; //const [workflows, setWorkflows] = React.useState([]); + const theme = useTheme(); const baseRepository = "https://github.com/frikky/shuffle-apps" const alert = useAlert() const [selectedApp, setSelectedApp] = React.useState({}); @@ -316,10 +318,18 @@ const Apps = (props) => { boxColor = "orange" } + if (data.invalid) { + boxColor = "red" + } + + //
+ //
var imageline = data.large_image.length === 0 ? - {data.title} + {data.title} : - {data.title} + {data.title} { + //console.log("IMG LOADED!: ", event.target) + }} /> // FIXME - add label to apps, as this might be slow with A LOT of apps var newAppname = data.name @@ -341,7 +351,7 @@ const Apps = (props) => { } var description = data.description - const maxDescLen = 56 + const maxDescLen = 51 if (description.length > maxDescLen) { description = data.description.slice(0, maxDescLen)+"..." } @@ -364,8 +374,8 @@ const Apps = (props) => { } } }}> - - + + {imageline}
@@ -520,9 +530,9 @@ const Apps = (props) => { : null var imageline = selectedApp.large_image === undefined || selectedApp.large_image.length === 0 ? - {selectedApp.title} + {selectedApp.title} : - {selectedApp.title} + {selectedApp.title} const GetAppExample = () => { if (selectedAction.returns === undefined) { @@ -639,7 +649,7 @@ const Apps = (props) => { updateAppField(selectedApp.id, "sharing", !selectedApp.sharing) //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={{ style: { marginLeft: 10,