More Shuffle-Hybrid migration

This commit is contained in:
frikky
2021-03-24 18:45:39 +01:00
parent 7e422c4d8b
commit feab975320
7 changed files with 196 additions and 983 deletions
+34 -806
View File
@@ -665,90 +665,6 @@ func parseLoginParameters(resp http.ResponseWriter, request *http.Request) (logi
return t, nil
}
func deleteUser(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
}
userInfo, userErr := shuffle.HandleApiAuthentication(resp, request)
if userErr != nil {
log.Printf("Api authentication failed in edit workflow: %s", userErr)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
if userInfo.Role != "admin" {
log.Printf("Wrong user (%s) when deleting - must be admin", userInfo.Username)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Must be admin"}`))
return
}
location := strings.Split(request.URL.String(), "/")
var userId string
if location[1] == "api" {
if len(location) <= 4 {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
userId = location[4]
}
ctx := context.Background()
foundUser, err := shuffle.GetUser(ctx, userId)
if err != nil {
log.Printf("Can't find user %s (delete user): %s", userId, err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
return
}
orgFound := false
if userInfo.ActiveOrg.Id == foundUser.ActiveOrg.Id {
orgFound = true
} else {
log.Printf("FoundUser: %#v", foundUser.Orgs)
for _, item := range foundUser.Orgs {
if item == userInfo.ActiveOrg.Id {
orgFound = true
break
}
}
}
if !orgFound {
log.Printf("User %s is admin, but can't delete users outside their own org.", userInfo.Id)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't change users outside your org."}`)))
return
}
// Invert. No user deletion.
if foundUser.Active {
foundUser.Active = false
} else {
foundUser.Active = true
}
err = shuffle.SetUser(ctx, foundUser)
if err != nil {
log.Printf("Failed swapping active for user %s (%s)", foundUser.Username, foundUser.Id)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
return
}
log.Printf("Successfully inverted %s", foundUser.Username)
resp.WriteHeader(200)
resp.Write([]byte(`{"success": true}`))
}
// No more emails :)
func checkUsername(Username string) error {
// Stupid first check of email loool
@@ -1390,6 +1306,8 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) {
userInfo.ActiveOrg.Users = []shuffle.User{}
}
userInfo.ActiveOrg.Users = []shuffle.User{}
userInfo.ActiveOrg.SyncConfig = shuffle.SyncConfig{}
currentOrg, err := json.Marshal(userInfo.ActiveOrg)
if err != nil {
currentOrg = []byte("{}")
@@ -1616,163 +1534,6 @@ func handleGetSchedules(resp http.ResponseWriter, request *http.Request) {
resp.Write(newjson)
}
func handleGetEnvironments(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
}
user, err := shuffle.HandleApiAuthentication(resp, request)
if err != nil {
log.Printf("Api authentication failed in set new workflowhandler: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
ctx := context.Background()
var environments []shuffle.Environment
q := datastore.NewQuery("Environments").Filter("org_id =", user.ActiveOrg.Id)
_, err = dbclient.GetAll(ctx, q, &environments)
if err != nil {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Can't get environments"}`))
return
}
newjson, err := json.Marshal(environments)
if err != nil {
log.Printf("Failed unmarshal: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed unpacking environments"}`)))
return
}
//log.Printf("Existing environments: %s", string(newjson))
resp.WriteHeader(200)
resp.Write(newjson)
}
func handleGetOrg(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
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]
}
user, err := shuffle.HandleApiAuthentication(resp, request)
if err != nil {
log.Printf("Api authentication failed in set new workflowhandler: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
ctx := context.Background()
org, err := shuffle.GetOrg(ctx, fileId)
if err != nil {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Failed getting org users"}`))
return
}
//FIXME : cleanup org before marshal
userFound := false
for _, foundUser := range org.Users {
if foundUser.Id == user.Id {
userFound = true
break
}
}
if !userFound {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Use doesn't have access to org"}`))
return
}
org.Users = []shuffle.User{}
org.SyncConfig.Apikey = ""
newjson, err := json.Marshal(org)
if err != nil {
log.Printf("Failed unmarshal of org: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed unpacking"}`)))
return
}
resp.WriteHeader(200)
resp.Write(newjson)
}
func handleGetOrgs(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
}
user, err := shuffle.HandleApiAuthentication(resp, request)
if err != nil {
log.Printf("Api authentication failed in set new workflowhandler: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
if user.Role != "global_admin" {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Not admin"}`))
return
}
ctx := context.Background()
var orgs []shuffle.Org
q := datastore.NewQuery("Organizations")
_, err = dbclient.GetAll(ctx, q, &orgs)
if err != nil {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Can't get users"}`))
return
}
//newUsers := []User{}
//for _, item := range users {
// if len(item.Username) == 0 {
// continue
// }
// item.Password = ""
// item.Session = ""
// item.VerificationToken = ""
// newUsers = append(newUsers, item)
//}
newjson, err := json.Marshal(orgs)
if err != nil {
log.Printf("Failed unmarshal: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed unpacking"}`)))
return
}
resp.WriteHeader(200)
resp.Write(newjson)
}
func checkAdminLogin(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
@@ -4698,7 +4459,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 := shuffle.GetAllWorkflowApps(ctx, 500)
workflowApps, err := shuffle.GetPrioritizedApps(ctx, user)
if err != nil {
log.Printf("Failed getting all workflow apps from database to verify: %s", err)
resp.WriteHeader(401)
@@ -4875,20 +4636,23 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
// Backup every single one
setOpenApiDatastore(ctx, api.ID, parsed)
err = increaseStatisticsField(ctx, "total_apps_created", newmd5, 1, user.ActiveOrg.Id)
if err != nil {
log.Printf("Failed to increase success execution stats: %s", err)
}
/*
err = increaseStatisticsField(ctx, "total_apps_created", newmd5, 1, user.ActiveOrg.Id)
if err != nil {
log.Printf("Failed to increase success execution stats: %s", err)
}
err = increaseStatisticsField(ctx, "openapi_apps_created", newmd5, 1, user.ActiveOrg.Id)
if err != nil {
log.Printf("Failed to increase success execution stats: %s", err)
}
err = increaseStatisticsField(ctx, "openapi_apps_created", newmd5, 1, user.ActiveOrg.Id)
if err != nil {
log.Printf("Failed to increase success execution stats: %s", err)
}
*/
cacheKey := fmt.Sprintf("workflowapps-sorted-100")
shuffle.DeleteCache(ctx, cacheKey)
cacheKey = fmt.Sprintf("workflowapps-sorted-500")
shuffle.DeleteCache(ctx, cacheKey)
shuffle.DeleteCache(ctx, fmt.Sprintf("apps_%s", user.Id))
resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true, "id": "%s"}`, api.ID)))
@@ -4984,6 +4748,7 @@ func handleAppHotload(ctx context.Context, location string, forceUpdate bool) er
shuffle.DeleteCache(ctx, cacheKey)
cacheKey = fmt.Sprintf("workflowapps-sorted-500")
shuffle.DeleteCache(ctx, cacheKey)
shuffle.DeleteCache(ctx, fmt.Sprintf("apps_%s", user.Id))
return nil
}
@@ -5797,11 +5562,10 @@ func runInit(ctx context.Context) {
// Getting apps to see if we should initialize a test
log.Printf("Getting remote workflow apps")
workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 500)
workflowapps, err := shuffle.GetPrioritizedApps(ctx, user)
if err != nil {
log.Printf("Failed getting apps (runInit): %s", err)
} else if err == nil && len(workflowapps) > 0 {
//shuffle.GetAllWorkflowApps(ctx context.Context) ([]WorkflowApp, error) {
var allworkflowapps []shuffle.WorkflowApp
q := datastore.NewQuery("workflowapp")
_, err := dbclient.GetAll(ctx, q, &allworkflowapps)
@@ -5860,7 +5624,11 @@ func runInit(ctx context.Context) {
//iterateAppGithubFolders(fs, dir, "", "testing")
// FIXME: Get all the apps?
iterateAppGithubFolders(fs, dir, "", "", forceUpdate)
_, _, err = iterateAppGithubFolders(fs, dir, "", "", forceUpdate)
if err != nil {
log.Printf("[WARNING] Error from app load in init: %s", err)
}
//_, _, err = iterateAppGithubFolders(fs, dir, "", "", forceUpdate)
// Hotloads locally
location := os.Getenv("SHUFFLE_APP_HOTLOAD_FOLDER")
@@ -6060,368 +5828,6 @@ func handleStopCloudSync(syncUrl string, org shuffle.Org) error {
return nil
}
func handleKeyValueCheck(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
}
body, err := ioutil.ReadAll(request.Body)
if err != nil {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Failed reading body"}`))
return
}
// Append: Checks if the value should be appended
// WorkflowCheck: Checks if the value should only check for workflow in org, or entire org
// Authorization: the Authorization to use
// ExecutionRef: Ref for the execution
// Values: The values to use
type DataValues struct {
App string
Actions string
ParameterNames []string
ParameterValues []string
}
type ReturnData struct {
Append bool `json:"append"`
WorkflowCheck bool `json:"workflow_check"`
Authorization string `json:"authorization"`
ExecutionRef string `json:"execution_ref"`
OrgId string `json:"org_id"`
Values []DataValues `json:"values"`
}
//for key, value := range data.Apps {
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]
}
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
}
if tmpData.OrgId != fileId {
log.Printf("[INFO] OrgId %s and %s don't match", tmpData.OrgId, fileId)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "Organization ID's don't match"}`))
return
}
ctx := context.Background()
org, err := shuffle.GetOrg(ctx, tmpData.OrgId)
if err != nil {
log.Printf("[INFO] Organization doesn't exist: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
workflowExecution, err := shuffle.GetWorkflowExecution(ctx, tmpData.ExecutionRef)
if err != nil {
log.Printf("[INFO] User can't edit the org")
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "No permission to get execution"}`))
return
}
if workflowExecution.Authorization != tmpData.Authorization {
log.Printf("[INFO] Execution auth %s and %s don't match", workflowExecution.Authorization, tmpData.Authorization)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "Auth doesn't match"}`))
return
}
if workflowExecution.Status != "EXECUTING" {
log.Printf("[INFO] Workflow isn't executing and shouldn't be searching", workflowExecution.ExecutionId)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "Workflow isn't executing"}`))
return
}
if workflowExecution.ExecutionOrg != org.Id {
log.Printf("[INFO] Org %s wasn't used to execute %s", org.Id, workflowExecution.ExecutionId)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "Bad organization specified"}`))
return
}
// Prepared for the future~
if len(tmpData.Values) != 1 {
log.Printf("[INFO] Filter data can only hande 1 value right now, not %d", len(tmpData.Values))
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "Can't handle multiple apps yet, just one"}`))
return
}
value := tmpData.Values[0]
// FIXME: Alphabetically sort the parameternames
// FIXME: Add organization wide search, not just workflow based
found := []string{}
notFound := []string{}
dbKey := fmt.Sprintf("app_execution_values")
parameterNames := fmt.Sprintf("%s_%s", value.App, strings.Join(value.ParameterNames, "_"))
log.Printf("[INFO] PARAMNAME: %s", parameterNames)
if tmpData.WorkflowCheck {
//for _, item := range tmpData.Values {
// log.Printf("[INFO] Should validate if values %#v in app parameter %#v exists WITH WORKFLOW %s", item.ParameterValues, item.ParameterNames, workflowExecution.Workflow.ID)
// FIXME: Make this alphabetical
for _, value := range value.ParameterValues {
if len(value) == 0 {
log.Printf("Shouldn't have value of length 0!")
continue
}
log.Printf("[INFO] Looking for value %s in Workflow %s of ORG %s", value, workflowExecution.Workflow.ID, org.Id)
q := datastore.NewQuery(dbKey).Filter("org_id =", org.Id).Filter("workflow_id =", workflowExecution.Workflow.ID).Filter("parameter_name =", parameterNames).Filter("value =", value)
foundCount, err := dbclient.Count(ctx, q)
if err != nil {
log.Printf("[WARNING] Failed getting key %s: %s", dbKey, err)
notFound = append(notFound, value)
//found = append(found, value)
continue
}
if foundCount > 0 {
found = append(found, value)
} else {
log.Printf("[INFO] Found for %s: %d", dbKey, foundCount)
notFound = append(notFound, value)
}
}
} else {
//log.Printf("[INFO] Should validate if value %s in app %s exists WITH ORG %s", workflowExecution.Workflow.ID)
for _, value := range value.ParameterValues {
if len(value) == 0 {
log.Printf("Shouldn't have value of length 0!")
continue
}
log.Printf("[INFO] Looking for value %s in ORG %s", value, org.Id)
q := datastore.NewQuery(dbKey).Filter("org_id =", org.Id).Filter("workflow_id =", "").Filter("parameter_name =", parameterNames).Filter("value =", value)
foundCount, err := dbclient.Count(ctx, q)
if err != nil {
log.Printf("[WARNING] Failed getting key %s: %s", dbKey, err)
notFound = append(notFound, value)
//found = append(found, value)
continue
}
if foundCount > 0 {
found = append(found, value)
} else {
log.Printf("[INFO] Found for %s: %d", dbKey, foundCount)
notFound = append(notFound, value)
}
}
}
//App string
//Actions string
//ParameterNames string
//ParamererValues []string
appended := 0
if tmpData.Append {
log.Printf("[INFO] Should append %d values!", len(notFound))
dbKey := fmt.Sprintf("app_execution_values")
//q := datastore.NewQuery(dbKey).Filter("org_id =", org.Id).Filter("workflow_id", workflowExecution.Workflow.ID).Filter("app_name =", parameterNames).Filter("value =", value)
key := datastore.NameKey(dbKey, "", nil)
type NewValue struct {
OrgId string `json:"org_id" datastore:"org_id"`
WorkflowId string `json:"workflow_id" datastore:"workflow_id"`
WorkflowExecutionId string `json:"workflow_execution_id" datastore:"workflow_execution_id"`
ParameterName string `json:"parameter_name" datastore:"parameter_name"`
Value string `json:"value" datastore:"value"`
}
//parameterNames := strings.Join(value.ParameterNames, "_")
for _, notFoundValue := range notFound {
newRequest := NewValue{
OrgId: org.Id,
WorkflowExecutionId: workflowExecution.ExecutionId,
ParameterName: parameterNames,
Value: notFoundValue,
}
if tmpData.WorkflowCheck {
newRequest.WorkflowId = workflowExecution.Workflow.ID
}
if _, err := dbclient.Put(ctx, key, &newRequest); err != nil {
log.Printf("Error adding %s to appvalue: %s", notFoundValue, err)
continue
}
appended += 1
log.Printf("[INFO] Added %s as new appvalue to datastore", notFoundValue)
}
}
type returnStruct struct {
Success bool `json:"success"`
Appended int `json:"appended"`
Found []string `json:"found"`
}
returnData := returnStruct{
Success: true,
Appended: appended,
Found: found,
}
b, _ := json.Marshal(returnData)
resp.WriteHeader(200)
resp.Write(b)
}
func handleEditOrg(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
}
user, err := shuffle.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
}
if user.Role != "admin" {
log.Printf("Not admin.")
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"`
Defaults shuffle.Defaults `json:"defaults" datastore:"defaults"`
}
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")
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "No permission to edit this org"}`))
return
}
ctx := context.Background()
org, err := shuffle.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
}
org.Image = tmpData.Image
org.Name = tmpData.Name
org.Description = tmpData.Description
org.Defaults = tmpData.Defaults
//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
}
log.Printf("SUCCESSFULLY UPDATED ORG")
resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "Successfully updated org"}`)))
}
// INFO: https://docs.google.com/drawings/d/1JJebpPeEVEbmH_qsAC6zf9Noygp7PytvesrkhE19QrY/edit
/*
This is here to both enable and disable cloud sync features for an organization
@@ -6707,182 +6113,6 @@ 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 := shuffle.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 := shuffle.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()
@@ -6919,7 +6149,7 @@ func initHandlers() {
r.HandleFunc("/api/v1/users/getsettings", shuffle.HandleSettings).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/users/getusers", shuffle.HandleGetUsers).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/users/updateuser", handleUpdateUser).Methods("PUT", "OPTIONS")
r.HandleFunc("/api/v1/users/{user}", deleteUser).Methods("DELETE", "OPTIONS")
r.HandleFunc("/api/v1/users/{user}", shuffle.DeleteUser).Methods("DELETE", "OPTIONS")
r.HandleFunc("/api/v1/users/passwordchange", shuffle.HandlePasswordChange).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/users", shuffle.HandleGetUsers).Methods("GET", "OPTIONS")
@@ -6934,8 +6164,8 @@ func initHandlers() {
r.HandleFunc("/api/v1/generateapikey", shuffle.HandleApiGeneration).Methods("GET", "POST", "OPTIONS")
r.HandleFunc("/api/v1/passwordchange", shuffle.HandlePasswordChange).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/getenvironments", handleGetEnvironments).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/setenvironments", handleSetEnvironments).Methods("PUT", "OPTIONS")
r.HandleFunc("/api/v1/getenvironments", shuffle.HandleGetEnvironments).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/setenvironments", shuffle.HandleSetEnvironments).Methods("PUT", "OPTIONS")
r.HandleFunc("/api/v1/docs", getDocList).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/docs/{key}", getDocs).Methods("GET", "OPTIONS")
@@ -6953,12 +6183,12 @@ func initHandlers() {
// App specific
// From here down isnt checked for org specific
r.HandleFunc("/api/v1/apps/{appId}", shuffle.UpdateWorkflowAppConfig).Methods("PATCH", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}", shuffle.DeleteWorkflowApp).Methods("DELETE", "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/{appId}", updateWorkflowAppConfig).Methods("PATCH", "OPTIONS")
r.HandleFunc("/api/v1/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}", deleteWorkflowApp).Methods("DELETE", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}/config", getWorkflowAppConfig).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps", getWorkflowApps).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS")
@@ -6980,6 +6210,8 @@ func initHandlers() {
/* Everything below here increases the counters*/
r.HandleFunc("/api/v1/workflows", shuffle.GetWorkflows).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows", shuffle.SetNewWorkflow).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/workflows/{key}", shuffle.GetSpecificWorkflow).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/{key}", shuffle.SaveWorkflow).Methods("PUT", "OPTIONS")
r.HandleFunc("/api/v1/workflows/schedules", handleGetSchedules).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/{key}/schedule", scheduleWorkflow).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/workflows/download_remote", loadSpecificWorkflows).Methods("POST", "OPTIONS")
@@ -6989,8 +6221,6 @@ func initHandlers() {
r.HandleFunc("/api/v1/workflows/{key}/outlook/{triggerId}", handleDeleteOutlookSub).Methods("DELETE", "OPTIONS")
r.HandleFunc("/api/v1/workflows/{key}/executions", getWorkflowExecutions).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/{key}/executions/{key}/abort", abortExecution).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/{key}", shuffle.GetSpecificWorkflow).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/{key}", shuffle.SaveWorkflow).Methods("PUT", "OPTIONS")
r.HandleFunc("/api/v1/workflows/{key}", deleteWorkflow).Methods("DELETE", "OPTIONS")
// Triggers
@@ -7007,16 +6237,14 @@ func initHandlers() {
// NEW for 0.8.0
r.HandleFunc("/api/v1/cloud/setup", handleCloudSetup).Methods("POST", "OPTIONS")
// Orgs
r.HandleFunc("/api/v1/orgs", handleGetOrgs).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/orgs/", handleGetOrgs).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/orgs/{orgId}", handleGetOrg).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/orgs/{orgId}", handleEditOrg).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/orgs", shuffle.HandleGetOrgs).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/orgs/", shuffle.HandleGetOrgs).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/orgs/{orgId}", shuffle.HandleGetOrg).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/orgs/{orgId}", shuffle.HandleEditOrg).Methods("POST", "OPTIONS")
// This is a new API that validates if a key has been seen before.
// Not sure what the best course of action is for it.
r.HandleFunc("/api/v1/orgs/{orgId}/validate_app_values", handleKeyValueCheck).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/orgs/{orgId}/validate_app_values", shuffle.HandleKeyValueCheck).Methods("POST", "OPTIONS")
//r.HandleFunc("/api/v1/orgs/{orgId}", handleEditOrg).Methods("POST", "OPTIONS")
// Docker orborus specific
+33 -119
View File
@@ -1802,7 +1802,7 @@ func deleteWorkflow(resp http.ResponseWriter, request *http.Request) {
}
// FIXME - have a check for org etc too..
if user.Id != workflow.Owner && user.Role != "admin" {
if user.Id != workflow.Owner {
log.Printf("Wrong user (%s) for workflow %s", user.Username, workflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -1956,7 +1956,7 @@ func abortExecution(resp http.ResponseWriter, request *http.Request) {
}
// FIXME - have a check for org etc too..
if user.Id != workflowExecution.Workflow.Owner && user.Role != "admin" {
if user.Id != workflowExecution.Workflow.Owner {
log.Printf("[INFO] Wrong user (%s) for workflowexecution workflow %s", user.Username, workflowExecution.Workflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -2912,7 +2912,7 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) {
// FIXME - have a check for org etc too..
// FIXME - admin check like this? idk
if user.Id != workflow.Owner && user.Role != "admin" && user.Role != "scheduler" && user.Role != fmt.Sprintf("workflow_%s", fileId) {
if user.Id != workflow.Owner && user.Role != "scheduler" && user.Role != fmt.Sprintf("workflow_%s", fileId) {
log.Printf("Wrong user (%s) for workflow %s (execute)", user.Username, workflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -2987,7 +2987,7 @@ func stopSchedule(resp http.ResponseWriter, request *http.Request) {
// FIXME - have a check for org etc too..
// FIXME - admin check like this? idk
if user.Id != workflow.Owner && user.Role != "admin" && user.Role != "scheduler" {
if user.Id != workflow.Owner && user.Role != "scheduler" {
log.Printf("[WARNING] Wrong user (%s) for workflow %s (stop schedule)", user.Username, workflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -3116,7 +3116,7 @@ func stopScheduleGCP(resp http.ResponseWriter, request *http.Request) {
// FIXME - have a check for org etc too..
// FIXME - admin check like this? idk
if user.Id != workflow.Owner && user.Role != "admin" && user.Role != "scheduler" {
if user.Id != workflow.Owner && user.Role != "scheduler" {
log.Printf("Wrong user (%s) for workflow %s (stop schedule)", user.Username, workflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -3237,7 +3237,7 @@ func scheduleWorkflow(resp http.ResponseWriter, request *http.Request) {
// FIXME - have a check for org etc too..
// FIXME - admin check like this? idk
if user.Id != workflow.Owner && user.Role != "admin" && user.Role != "scheduler" {
if user.Id != workflow.Owner && user.Role != "scheduler" {
log.Printf("Wrong user (%s) for workflow %s", user.Username, workflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -3478,14 +3478,14 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) {
// FIXME - actually delete other than private apps too..
private := false
if app.Downloaded && user.Role == "admin" {
log.Printf("Deleting downloaded app (authenticated users can do this)")
} else if user.Id != app.Owner && user.Role != "admin" {
log.Printf("Wrong user (%s) for app %s (delete)", user.Username, app.Name)
log.Printf("[INFO] Deleting downloaded app (authenticated users can do this)")
} else if user.Id != app.Owner {
log.Printf("[WARNING] Wrong user (%s) for app %s (delete)", user.Username, app.Name)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
} else {
log.Printf("App to be deleted is private")
log.Printf("[WARNING] App to be deleted is private")
private = true
}
@@ -3494,7 +3494,7 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) {
var workflows []shuffle.Workflow
_, err = dbclient.GetAll(ctx, q, &workflows)
if err != nil {
log.Printf("Failed getting related workflows for the app: %s", err)
log.Printf("[WARNING] Failed getting related workflows for the app: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return
@@ -3671,7 +3671,7 @@ func getWorkflowAppConfig(resp http.ResponseWriter, request *http.Request) {
return
}
if user.Id != app.Owner && user.Role != "admin" {
if user.Id != app.Owner {
log.Printf("[WARNING] Wrong user (%s) for app %s", user.Username, app.Name)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -3705,96 +3705,6 @@ func getWorkflowAppConfig(resp http.ResponseWriter, request *http.Request) {
resp.Write(data)
}
func updateWorkflowAppConfig(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
}
user, userErr := shuffle.HandleApiAuthentication(resp, request)
if userErr != nil {
log.Printf("Api authentication failed in get all apps: %s", userErr)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
location := strings.Split(request.URL.String(), "/")
var fileId string
if location[1] == "api" {
if len(location) <= 4 {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
fileId = location[4]
}
ctx := context.Background()
app, err := shuffle.GetApp(ctx, fileId)
if err != nil {
log.Printf("Error getting app (update app): %s", fileId)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
if user.Id != app.Owner && user.Role != "admin" {
log.Printf("Wrong user (%s) for app %s in update app", user.Username, app.Name)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
body, err := ioutil.ReadAll(request.Body)
if err != nil {
log.Printf("Error with body read in update app: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
type updatefields struct {
Sharing bool `json:"sharing"`
SharingConfig string `json:"sharing_config"`
}
var tmpfields updatefields
err = json.Unmarshal(body, &tmpfields)
if err != nil {
log.Printf("Error with unmarshal body in update app: %s\n%s", err, string(body))
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
if tmpfields.Sharing != app.Sharing {
app.Sharing = tmpfields.Sharing
}
if tmpfields.SharingConfig != app.SharingConfig {
app.SharingConfig = tmpfields.SharingConfig
}
err = shuffle.SetWorkflowAppDatastore(ctx, *app, app.ID)
if err != nil {
log.Printf("Failed patching workflowapp: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
cacheKey := fmt.Sprintf("workflowapps-sorted-100")
shuffle.DeleteCache(ctx, cacheKey)
cacheKey = fmt.Sprintf("workflowapps-sorted-500")
shuffle.DeleteCache(ctx, cacheKey)
log.Printf("Changed workflow app %s", app.ID)
resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
}
func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
@@ -4432,9 +4342,9 @@ func handleAppHotloadRequest(resp http.ResponseWriter, request *http.Request) {
log.Printf("[INFO] Starting hotloading from %s", location)
err = handleAppHotload(ctx, location, true)
if err != nil {
log.Printf("Failed app hotload: %s", err)
log.Printf("[WARNING] Failed app hotload: %s", err)
resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed loading apps: %s"}`, err)))
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return
}
@@ -4625,7 +4535,7 @@ func iterateOpenApiGithub(fs billy.Filesystem, dir []os.FileInfo, extra string,
}
if contOuter {
log.Printf("Skipping %s", filename)
//log.Printf("Skipping %s", filename)
continue
}
@@ -4859,12 +4769,10 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
"YARA",
}
// It's here to prevent getting them in every iteration
buildLaterFirst := []buildLaterStruct{}
buildLaterList := []buildLaterStruct{}
ctx := context.Background()
// It's here to prevent getting them in every iteration
for _, file := range dir {
if len(onlyname) > 0 && file.Name() != onlyname {
continue
@@ -4882,10 +4790,6 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
// Go routine? Hmm, this can be super quick I guess
buildFirst, buildLast, err := iterateAppGithubFolders(fs, dir, tmpExtra, "", forceUpdate)
if err != nil {
log.Printf("Error reading folder: %s", err)
continue
}
for _, item := range buildFirst {
buildLaterFirst = append(buildLaterFirst, item)
@@ -4895,6 +4799,15 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
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()
@@ -4964,8 +4877,9 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
var workflowapp shuffle.WorkflowApp
err = gyaml.Unmarshal(appfileData, &workflowapp)
if err != nil {
log.Printf("Failed unmarshaling workflowapp %s: %s", fullPath, err)
continue
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
@@ -5007,7 +4921,7 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
// Fixes (appends) authentication parameters if they're required
if workflowapp.Authentication.Required {
log.Printf("Checking authentication fields and appending for %s!", workflowapp.Name)
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 {
@@ -5305,7 +5219,7 @@ func getWorkflowExecutions(resp http.ResponseWriter, request *http.Request) {
}
// FIXME - have a check for org etc too..
if user.Id != workflow.Owner && user.Role != "admin" {
if user.Id != workflow.Owner {
log.Printf("Wrong user (%s) for workflow %s (get execution)", user.Username, workflow.ID)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -5637,7 +5551,7 @@ func handleStopHook(resp http.ResponseWriter, request *http.Request) {
return
}
if user.Id != hook.Owner && user.Role != "admin" {
if user.Id != hook.Owner {
log.Printf("Wrong user (%s) for workflow %s", user.Username, hook.Id)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -5720,7 +5634,7 @@ func handleDeleteHook(resp http.ResponseWriter, request *http.Request) {
return
}
if user.Id != hook.Owner && user.Role != "admin" && user.ActiveOrg.Id != hook.OrgId {
if user.Id != hook.Owner && user.ActiveOrg.Id != hook.OrgId {
log.Printf("Wrong user (%s) for workflow %s", user.Username, hook.Id)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
@@ -5861,7 +5775,7 @@ func handleStartHook(resp http.ResponseWriter, request *http.Request) {
return
}
if user.Id != hook.Owner && user.Role != "admin" {
if user.Id != hook.Owner {
log.Printf("Wrong user (%s) for workflow %s", user.Username, hook.Id)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
+63 -39
View File
@@ -348,7 +348,9 @@ const Admin = (props) => {
const deleteUser = (data) => {
// Just use this one?
const url = globalUrl + '/api/v1/users/' + data.id
const userId = isCloud ? data.username : data.id
const url = globalUrl + '/api/v1/users/' + userId
fetch(url, {
method: 'DELETE',
credentials: "include",
@@ -1038,7 +1040,8 @@ const Admin = (props) => {
const generateApikey = (userId) => {
const generateApikey = (user) => {
const userId = isCloud ? user.username : user.id
const data = { "user_id": userId }
fetch(globalUrl + "/api/v1/generateapikey", {
@@ -1209,7 +1212,7 @@ const Admin = (props) => {
style={{}}
variant="outlined"
color="primary"
onClick={() => generateApikey(selectedUser.id)}
onClick={() => generateApikey(selectedUser)}
>
Get new API key
</Button>
@@ -1748,12 +1751,12 @@ const Admin = (props) => {
<ListItem>
<ListItemText
primary="Username"
style={{ minWidth: 200, maxWidth: 200 }}
style={{ minWidth: 300, maxWidth: 300}}
/>
<ListItemText
primary="API key"
style={{ minWidth: 360, maxWidth: 360, overflow: "hidden" }}
style={{ minWidth: 100, maxWidth: 100, overflow: "hidden" }}
/>
<ListItemText
@@ -1779,42 +1782,61 @@ const Admin = (props) => {
<ListItem key={index} style={{backgroundColor: bgColor}}>
<ListItemText
primary={data.username}
style={{ minWidth: 200, maxWidth: 200 }}
style={{ minWidth: 300, maxWidth: 300, overflow: "hidden",}}
/>
<ListItemText
primary={data.apikey === undefined || data.apikey.length === 0 ? "" : data.apikey}
style={{ maxWidth: 360, minWidth: 360, }}
/>
style={{ maxWidth: 100, minWidth: 100, }}
primary={data.apikey === undefined || data.apikey.length === 0 ? "" :
<Tooltip title={"Copy Api Key"} style={{}} aria-label={"Copy APIkey"}>
<IconButton style={{}} onClick={() => {
const elementName = "copy_element_shuffle"
var copyText = document.getElementById(elementName);
if (copyText !== null && copyText !== undefined) {
navigator.clipboard.writeText(data.apikey)
copyText.select();
copyText.setSelectionRange(0, 99999); /* For mobile devices */
/* Copy the text inside the text field */
document.execCommand("copy");
alert.info("Apikey copied to clipboard")
}
}}>
<FileCopyIcon style={{color: "rgba(255,255,255,0.8)"}}/>
</IconButton>
</Tooltip>
}/>
<ListItemText
primary=
{<Select
SelectDisplayProps={{
style: {
marginLeft: 10,
{<Select
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
value={data.role}
fullWidth
onChange={(e) => {
console.log("VALUE: ", e.target.value)
if (isCloud) {
setUser(data.username, "role", e.target.value)
} else {
setUser(data.id, "role", e.target.value)
}
}}
value={data.role}
fullWidth
onChange={(e) => {
console.log("VALUE: ", e.target.value)
if (isCloud) {
setUser(data.username, "role", e.target.value)
} else {
setUser(data.id, "role", e.target.value)
}
}}
style={{ backgroundColor: theme.palette.surfaceColor, color: "white", height: "50px" }}
>
<MenuItem style={{ backgroundColor: theme.palette.inputColor, color: "white" }} value={"admin"}>
Admin
</MenuItem>
<MenuItem style={{ backgroundColor: theme.palette.inputColor, color: "white" }} value={"user"}>
User
</MenuItem>
</Select>}
>
<MenuItem style={{ backgroundColor: theme.palette.inputColor, color: "white" }} value={"admin"}>
Admin
</MenuItem>
<MenuItem style={{ backgroundColor: theme.palette.inputColor, color: "white" }} value={"user"}>
User
</MenuItem>
</Select>
}
style ={{ minWidth: 135, maxWidth: 135, marginRight: 15,}}
/>
<ListItemText
@@ -1831,7 +1853,9 @@ const Admin = (props) => {
<EditIcon color="primary"/>
</IconButton>
<Button
onClick={() => generateApikey(data.id)}
onClick={() => {
generateApikey(data)
}}
variant="outlined"
color="primary"
>
@@ -1932,7 +1956,7 @@ const Admin = (props) => {
/>
<ListItemText
primary="Status"
style={{minWidth: 75, maxWidth: 75}}
style={{minWidth: 75, maxWidth: 75, marginLeft: 10,}}
/>
<ListItemText
primary="Filesize"
@@ -1984,7 +2008,7 @@ const Admin = (props) => {
/>
<ListItemText
primary={file.status}
style={{minWidth: 75, maxWidth: 75, overflow: "hidden"}}
style={{minWidth: 75, maxWidth: 75, overflow: "hidden", marginLeft: 10,}}
/>
<ListItemText
primary={file.filesize}
@@ -2221,7 +2245,7 @@ const Admin = (props) => {
/>
<ListItemText
primary="App Name"
style={{minWidth: 150, maxWidth: 150}}
style={{minWidth: 175, maxWidth: 175, marginLeft: 10,}}
/>
<ListItemText
primary="Ready"
@@ -2257,15 +2281,15 @@ const Admin = (props) => {
/>
<ListItemText
primary={data.label}
style={{minWidth: 225, maxWidth: 225}}
style={{minWidth: 225, maxWidth: 225, overflow: "hidden",}}
/>
<ListItemText
primary={data.app.name}
style={{minWidth: 150, maxWidth: 150}}
style={{minWidth: 175, maxWidth: 175, marginLeft: 10}}
/>
<ListItemText
primary={data.defined === false ? "No" : "Yes"}
style={{minWidth: 100, maxWidth: 100}}
style={{minWidth: 100, maxWidth: 100, marginLeft: 10,}}
/>
<ListItemText
primary={data.workflow_count === null ? 0 : data.workflow_count}
+35 -6
View File
@@ -88,7 +88,7 @@ const AngularWorkflow = (props) => {
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
const referenceUrl = globalUrl+"/api/v1/hooks/"
const alert = useAlert()
const borderRadius = 3
const borderRadius = 5
const theme = useTheme();
const [bodyWidth, bodyHeight] = useWindowSize();
@@ -883,6 +883,19 @@ const AngularWorkflow = (props) => {
setExecutionRequestStarted(false)
}
if (responseJson.execution_id === "" || responseJson.execution_id === undefined || responseJson.authorization === "" || responseJson.authorization === undefined ) {
alert.error("Something went wrong during execution startup")
console.log("BAD RESPONSE FOR EXECUTION: ", responseJson)
setExecutionRunning(false)
setExecutionRequestStarted(false)
stop()
for (var i = 0; i < curelements.length; i++) {
curelements[i].removeClass("not-executing-highlight")
}
return
}
setExecutionRequest({
"execution_id": responseJson.execution_id,
"authorization": responseJson.authorization,
@@ -1021,7 +1034,7 @@ const AngularWorkflow = (props) => {
const getApps = () => {
fetch(globalUrl+"/api/v1/workflows/apps", {
fetch(globalUrl+"/api/v1/apps", {
method: 'GET',
headers: {
'Content-Type': 'application/json',
@@ -1042,11 +1055,16 @@ const AngularWorkflow = (props) => {
//var tmpapps = []
//tmpapps = tmpapps.concat(getExtraApps())
//tmpapps = tmpapps.concat(responseJson)
console.log("APPS: ", responseJson)
setApps(responseJson)
//getAppAuthentication()
setFilteredApps(responseJson.filter(app => !internalIds.includes(app.name) && !(!app.activated && app.generated)))
setPrioritizedApps(responseJson.filter(app => internalIds.includes(app.name)))
if (isCloud) {
setFilteredApps(responseJson.filter(app => !internalIds.includes(app.name)))
setPrioritizedApps(responseJson.filter(app => internalIds.includes(app.name)))
} else {
setFilteredApps(responseJson.filter(app => !internalIds.includes(app.name) && !(!app.activated && app.generated)))
setPrioritizedApps(responseJson.filter(app => internalIds.includes(app.name)))
}
})
.catch(error => {
alert.error(error.toString())
@@ -1172,6 +1190,12 @@ const AngularWorkflow = (props) => {
const onNodeSelect = (event, newAppAuth) => {
const data = event.target.data()
setLastSaved(false)
const node = cy.getElementById(data.id)
if (node.length > 0) {
node.addClass('shuffle-hover-highlight')
}
//const branch = workflow.branches.filter(branch => branch.source_id === data.id || branch.destination_id === data.id)
console.log("NODE: ", data)
//console.log("BRANCHES: ", branch)
@@ -2757,6 +2781,7 @@ const AngularWorkflow = (props) => {
//setSelectedActionEnvironment(env)
setSelectedAction(selectedAction)
setUpdate(Math.random())
}
// APPSELECT at top
@@ -2996,6 +3021,7 @@ const AngularWorkflow = (props) => {
selectedActionParameters[count]["value_replace"] = paramcheck
selectedAction.parameters[count]["value_replace"] = paramcheck
setSelectedAction(selectedAction)
//setUpdate(Math.random())
return
}
}
@@ -3088,6 +3114,7 @@ const AngularWorkflow = (props) => {
selectedActionParameters[count].value = event.target.value
selectedAction.parameters[count].value = event.target.value
setSelectedAction(selectedAction)
//setUpdate(Math.random())
//setUpdate(event.target.value)
}
@@ -3125,7 +3152,7 @@ const AngularWorkflow = (props) => {
setSelectedApp(selectedApp)
setSelectedAction(selectedAction)
setUpdate(fieldvalue)
setUpdate(Math.random())
}
const changeActionParameterVariant = (data, count) => {
@@ -3157,6 +3184,7 @@ const AngularWorkflow = (props) => {
// Set value
setSelectedApp(selectedApp)
setSelectedAction(selectedAction)
setUpdate(Math.random())
}
// FIXME: Issue #40 - selectedActionParameters not reset
@@ -3177,6 +3205,7 @@ const AngularWorkflow = (props) => {
selectedActionParameters[count].value = selectedAction.selectedAuthentication.fields[data.name]
selectedAction.parameters[count].value = selectedAction.selectedAuthentication.fields[data.name]
setSelectedAction(selectedAction)
//setUpdate(Math.random())
return null
}
+3 -1
View File
@@ -2502,7 +2502,9 @@ const AppCreator = (props) => {
}}>
{appBuilding ? <CircularProgress /> : "Save"}
</Button>
{errorCode.length > 0 ? `Error: ${errorCode}` : null}
<Typography style={{marginTop: 5}}>
{errorCode.length > 0 ? `Error: ${errorCode}` : null}
</Typography>
</Paper>
</div>
+25 -11
View File
@@ -195,6 +195,10 @@ const Apps = (props) => {
setIsLoading(false)
if (response.status !== 200) {
console.log("Status not 200 for apps :O!")
if (isCloud) {
window.location.pathname = "/search"
}
}
return response.json()
@@ -648,11 +652,17 @@ const Apps = (props) => {
<Select
value={sharingConfiguration}
onChange={(event) => {
setSharingConfiguration(event.target.value)
alert.info("Changed sharing to "+event.target.value)
alert.info("Changing sharing to "+event.target.value)
updateAppField(selectedApp.id, "sharing", !selectedApp.sharing)
//setSelectedAction(event.target.value)
setSharingConfiguration(event.target.value)
if (event.target.value === "you") {
updateAppField(selectedApp.id, "sharing", false)
} else if (event.target.value === "everyone") {
updateAppField(selectedApp.id, "sharing", true)
} else {
console.log("Can't handle value for sharing: ", event.target.value)
}
}}
style={{width: 150, backgroundColor: theme.palette.surfaceColor, backgroundColor: inputColor, color: "white", height: 35, marginleft: 10,}}
SelectDisplayProps={{
@@ -910,9 +920,8 @@ const Apps = (props) => {
</span>
}
</div>
{isCloud ? null :
<TextField
style={{backgroundColor: inputColor}}
style={{backgroundColor: inputColor, borderRadius: 5,}}
InputProps={{
style:{
color: "white",
@@ -920,6 +929,7 @@ const Apps = (props) => {
marginLeft: "5px",
maxWidth: "95%",
fontSize: "1em",
borderRadius: 5,
},
}}
fullWidth
@@ -930,7 +940,6 @@ const Apps = (props) => {
setCursearch(event.target.value)
}}
/>
}
<div style={{marginTop: 15}}>
{apps.length > 0 ?
filteredApps.length > 0 ?
@@ -1057,8 +1066,11 @@ const Apps = (props) => {
return response.json()
})
.then((responseJson) => {
if (responseJson.reason !== undefined && responseJson.reason.length > 0) {
alert.info("Hotloading: ", responseJson.reason)
if (responseJson.success === true) {
alert.info("Successfully finished hotload")
} else {
alert.error("Failed hotload: ", responseJson.reason)
//(responseJson.reason !== undefined && responseJson.reason.length > 0) {
}
})
.catch(error => {
@@ -1116,6 +1128,8 @@ const Apps = (props) => {
const data = {}
data[fieldname] = fieldvalue
console.log("DATA: ", data)
fetch(globalUrl+"/api/v1/apps/"+app_id, {
method: 'PATCH',
headers: {
@@ -1132,9 +1146,9 @@ const Apps = (props) => {
//console.log(responseJson)
//alert.info(responseJson)
if (responseJson.success) {
alert.info("Success")
alert.success("Successfully updated app configuration")
} else {
alert.error("Error updating app")
alert.error("Error updating app configuration")
}
})
.catch(error => {
+3 -1
View File
@@ -527,7 +527,6 @@ const Workflows = (props) => {
const deleteWorkflow = (id) => {
alert.success("Deleted workflow "+id)
fetch(globalUrl+"/api/v1/workflows/"+id, {
method: 'DELETE',
headers: {
@@ -539,6 +538,9 @@ const Workflows = (props) => {
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for setting workflows :O!")
alert.error("Failed deleting workflow")
} else {
alert.success("Deleted workflow "+id)
}
return response.json()