Got first working cloud sync trigger fully running

This commit is contained in:
frikky
2020-11-05 17:11:50 +01:00
parent 4d0f9f5bc4
commit 7b51b9ef22
9 changed files with 232 additions and 63 deletions
+4 -4
View File
@@ -478,7 +478,7 @@ class AppBase:
#Actionname: Start_node
print(f"Actionname: {actionname}")
print(f"Actionname: {actionname_lower}")
# 1. Find the action
baseresult = ""
@@ -556,14 +556,14 @@ class AppBase:
return ""+appendresult, False
if len(parsersplit) == 1:
return baseresult+appendresult, False
return str(baseresult)+str(appendresult), False
baseresult = baseresult.replace("\'", "\"")
basejson = {}
try:
basejson = json.loads(baseresult)
except json.decoder.JSONDecodeError as e:
return baseresult+appendresult, False
return str(baseresult)+str(appendresult), False
data, is_loop = recurse_json(basejson, parsersplit[1:])
parseditem = data
@@ -577,7 +577,7 @@ class AppBase:
print("SET DATA WRAPPER TO %s!" % parsersplit[-1])
parseditem = "${%s%s}$" % (parsersplit[-1], json.dumps(data))
return parseditem+appendresult, is_loop
return str(parseditem)+str(appendresult), is_loop
# Parses parameters sent to it and returns whether it did it successfully with the values found
def parse_params(action, fullexecution, parameter):
+6 -4
View File
@@ -397,10 +397,12 @@ func makePythoncode(swagger *openapi3.Swagger, name, url, method string, paramet
verifyAddin,
)
if strings.Contains(functionname, "search") {
log.Println(data)
log.Printf("Queries: %s", queryString)
}
/*
if strings.Contains(functionname, "search") {
log.Println(data)
log.Printf("Queries: %s", queryString)
}
*/
//log.Printf(data)
return functionname, data
+110 -21
View File
@@ -381,16 +381,17 @@ type HookAction struct {
}
type Hook struct {
Id string `json:"id" datastore:"id"`
Start string `json:"start" datastore:"start"`
Info Info `json:"info" datastore:"info"`
Actions []HookAction `json:"actions" datastore:"actions,noindex"`
Type string `json:"type" datastore:"type"`
Owner string `json:"owner" datastore:"owner"`
Status string `json:"status" datastore:"status"`
Workflows []string `json:"workflows" datastore:"workflows"`
Running bool `json:"running" datastore:"running"`
OrgId string `json:"org_id" datastore:"org_id"`
Id string `json:"id" datastore:"id"`
Start string `json:"start" datastore:"start"`
Info Info `json:"info" datastore:"info"`
Actions []HookAction `json:"actions" datastore:"actions,noindex"`
Type string `json:"type" datastore:"type"`
Owner string `json:"owner" datastore:"owner"`
Status string `json:"status" datastore:"status"`
Workflows []string `json:"workflows" datastore:"workflows"`
Running bool `json:"running" datastore:"running"`
OrgId string `json:"org_id" datastore:"org_id"`
Environment string `json:"environment" datastore:"environment"`
}
func createFileFromFile(ctx context.Context, bucket *storage.BucketHandle, remotePath, localPath string) error {
@@ -3420,6 +3421,10 @@ func handleWebhookCallback(resp http.ResponseWriter, request *http.Request) {
return
}
if hook.Environment == "cloud" {
log.Printf("This should trigger in the cloud. Duplicate action allowed onprem.")
}
for _, item := range hook.Workflows {
log.Printf("Running webhook for workflow %s with startnode %s", item, hook.Start)
workflow := Workflow{
@@ -3471,6 +3476,51 @@ func handleWebhookCallback(resp http.ResponseWriter, request *http.Request) {
}
}
func executeCloudAction(action CloudSyncJob, apikey string) error {
data, err := json.Marshal(action)
if err != nil {
log.Printf("Failed cloud webhook action marshalling", err)
return err
}
client := &http.Client{}
syncUrl := fmt.Sprintf("%s/api/v1/cloud/sync/handle_action", syncUrl)
req, err := http.NewRequest(
"POST",
syncUrl,
bytes.NewBuffer(data),
)
req.Header.Add("Authorization", fmt.Sprintf(`Bearer %s`, apikey))
newresp, err := client.Do(req)
if err != nil {
return err
}
respBody, err := ioutil.ReadAll(newresp.Body)
if err != nil {
return err
}
type Result struct {
Success bool `json:"success"`
Reason string `json:"reason"`
}
log.Printf("Data: %s", string(respBody))
responseData := Result{}
err = json.Unmarshal(respBody, &responseData)
if err != nil {
return err
}
if !responseData.Success {
return errors.New(fmt.Sprintf("Error from Shuffler: %s", responseData.Reason))
}
return nil
}
// Starts a new webhook
func handleNewHook(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
@@ -3493,6 +3543,7 @@ func handleNewHook(resp http.ResponseWriter, request *http.Request) {
Name string `json:"name"`
Workflow string `json:"workflow"`
Start string `json:"start"`
Environment string `json:"environment"`
}
body, err := ioutil.ReadAll(request.Body)
@@ -3551,6 +3602,37 @@ func handleNewHook(resp http.ResponseWriter, request *http.Request) {
return
}
// Let remote endpoint handle access checks (shuffler.io)
currentUrl := fmt.Sprintf("https://shuffler.io/api/v1/hooks/webhook_%s", newId)
if requestdata.Environment == "cloud" {
log.Printf("[INFO] Should START a cloud webhook for url %s", currentUrl)
// https://shuffler.io/v1/hooks/webhook_80184973-3e82-4852-842e-0290f7f34d7c
org, err := getOrg(ctx, user.ActiveOrg.Id)
if err != nil {
log.Printf("Failed finding org %s: %s", org.Id, err)
return
}
action := CloudSyncJob{
Type: "webhook",
Action: "start",
OrgId: org.Id,
PrimaryItemId: newId,
SecondaryItem: requestdata.Start,
ThirdItem: requestdata.Workflow,
}
err = executeCloudAction(action, org.SyncConfig.Apikey)
if err != nil {
log.Printf("Failed cloud action START execution", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return
} else {
log.Printf("Successfully set up cloud action schedule")
}
}
hook := Hook{
Id: newId,
Start: requestdata.Start,
@@ -3558,7 +3640,7 @@ func handleNewHook(resp http.ResponseWriter, request *http.Request) {
Info: Info{
Name: requestdata.Name,
Description: requestdata.Description,
Url: fmt.Sprintf("https://shuffler.io/functions/webhooks/webhook_%s", newId),
Url: fmt.Sprintf("https://shuffler.io/api/v1/hooks/webhook_%s", newId),
},
Type: "webhook",
Owner: user.Username,
@@ -3571,8 +3653,9 @@ func handleNewHook(resp http.ResponseWriter, request *http.Request) {
Field: "",
},
},
Running: false,
OrgId: user.ActiveOrg.Id,
Running: false,
OrgId: user.ActiveOrg.Id,
Environment: requestdata.Environment,
}
hook.Status = "running"
@@ -3587,10 +3670,10 @@ func handleNewHook(resp http.ResponseWriter, request *http.Request) {
err = increaseStatisticsField(ctx, "total_workflow_triggers", requestdata.Workflow, 1)
if err != nil {
log.Printf("Failed to increase total workflows: %s", err)
log.Printf("[INFO] Failed to increase total workflows: %s", err)
}
log.Println("Set up a new hook")
log.Printf("Set up a new hook with ID %s and environment %s", newId, hook.Environment)
resp.WriteHeader(200)
resp.Write([]byte(`{"success": true}`))
}
@@ -6476,6 +6559,7 @@ func handleAppHotload(location string, forceUpdate bool) error {
// Secondary = something to specify what inside workflow to execute
// Third = Some data to add to it
type CloudSyncJob struct {
Id string `json:"id" datastore:"id"`
Type string `json:"type" datastore:"type"`
Action string `json:"action" datastore:"action"`
OrgId string `json:"org_id" datastore:"org_id"`
@@ -6534,12 +6618,12 @@ func handleCloudJob(job CloudSyncJob) error {
log.Printf("Handle job with type %s and action %s", job.Type, job.Action)
if job.Type == "webhook" {
if job.Action == "execute" {
log.Printf("Should handle webhook for workflow %s with start node %s and data %s", job.PrimaryItemId, job.SecondaryItem, job.ThirdItem)
log.Printf("Should handle webhook for workflow %s with start node %s and data %s", job.PrimaryItemId, job.SecondaryItem)
err := handleCloudExecutionOnprem(job.PrimaryItemId, job.SecondaryItem, "webhook", job.ThirdItem)
if err != nil {
log.Printf("Failed executing workflow from cloud hook: %s", err)
} else {
log.Printf("Successfully executed workflow from cloud hook: %s", err)
log.Printf("Successfully executed workflow from cloud hook!")
}
}
@@ -6589,7 +6673,6 @@ func remoteOrgJobController(org Org, body []byte) error {
Jobs []CloudSyncJob `json:"jobs"`
}
log.Printf("Remote JOB ret: %s", string(body))
responseData := retStruct{}
err := json.Unmarshal(body, &responseData)
if err != nil {
@@ -6633,7 +6716,11 @@ func remoteOrgJobController(org Org, body []byte) error {
return errors.New("[ERROR] Remote job handler issues.")
}
log.Printf("Got job with reason %s and %d jobs", responseData.Reason, len(responseData.Jobs))
if len(responseData.Jobs) > 0 {
log.Printf("Remote JOB ret: %s", string(body))
log.Printf("Got job with reason %s and %d job(s)", responseData.Reason, len(responseData.Jobs))
}
for _, job := range responseData.Jobs {
err = handleCloudJob(job)
if err != nil {
@@ -6666,6 +6753,8 @@ func remoteOrgJobHandler(org Org, interval int) error {
return err
}
log.Printf("Data: %s", respBody)
err = remoteOrgJobController(org, respBody)
if err != nil {
log.Printf("Failed job controller run: %s", err)
@@ -7059,7 +7148,7 @@ func runInit(ctx context.Context) {
job := func() {
err := remoteOrgJobHandler(org, interval)
if err != nil {
log.Printf("Failed request with remote org setup: %s", err)
log.Printf("Failed request with remote org setup (2): %s", err)
}
}
@@ -7550,7 +7639,7 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) {
job := func() {
err := remoteOrgJobHandler(*org, interval)
if err != nil {
log.Printf("Failed request with remote org setup: err")
log.Printf("Failed request with remote org setup (1): %s", err)
}
}
+37 -3
View File
@@ -73,6 +73,10 @@ type SyncFeatures struct {
Schedules SyncData `json:"schedules" datastore:"schedules"`
Autocomplete SyncData `json:"autocomplete" datastore:"autocomplete"`
Authentication SyncData `json:"authentication" datastore:"authentication"`
Webhook SyncData `json:"webhook" datastore:"webhook"`
Schedule SyncData `json:"schedule" datastore:"schedule"`
UserInput SyncData `json:"user_input" datastore:"user_input"`
EmailTrigger SyncData `json:"email_trigger" datastore:"email_trigger"`
}
type SyncData struct {
@@ -2657,7 +2661,7 @@ func handleExecution(id string, workflow Workflow, request *http.Request) (Workf
if !startFound {
log.Printf("Startnode %s doesn't exist!", workflowExecution.Start)
return WorkflowExecution{}, fmt.Sprintf("Workflow action %s doesn't exist in workflow", workflowExecution.Start), errors.New(fmt.Sprintf("Workflow start node %s doesn't exist. Exiting!", workflowExecution.Start))
return WorkflowExecution{}, fmt.Sprintf("Workflow action %s doesn't exist in workflow", workflowExecution.Start), errors.New(fmt.Sprintf(`Workflow start node "%s" doesn't exist. Exiting!`, workflowExecution.Start))
}
// Verification for execution environments
@@ -4985,7 +4989,7 @@ func iterateOpenApiGithub(fs billy.Filesystem, dir []os.FileInfo, extra string,
}
if appCounter > 0 {
log.Printf("Preloaded %d OpenApi apps in %s!", appCounter, extra)
log.Printf("Preloaded %d OpenApi apps in folder %s!", appCounter, extra)
}
return nil
@@ -5662,7 +5666,7 @@ func handleDeleteHook(resp http.ResponseWriter, request *http.Request) {
return
}
if user.Id != hook.Owner && user.Role != "admin" {
if user.Id != hook.Owner && user.Role != "admin" && 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}`))
@@ -5685,6 +5689,36 @@ func handleDeleteHook(resp http.ResponseWriter, request *http.Request) {
return
}
log.Printf("Hook: %#v", hook)
if hook.Environment == "cloud" {
log.Printf("[INFO] Should STOP cloud webhook https://shuffler.io/api/v1/hooks/webhook_%s", hook.Id)
org, err := getOrg(ctx, user.ActiveOrg.Id)
if err != nil {
log.Printf("Failed finding org %s: %s", org.Id, err)
return
}
action := CloudSyncJob{
Type: "webhook",
Action: "stop",
OrgId: org.Id,
PrimaryItemId: hook.Id,
}
if len(hook.Workflows) > 0 {
action.SecondaryItem = hook.Workflows[0]
}
err = executeCloudAction(action, org.SyncConfig.Apikey)
if err != nil {
log.Printf("Failed cloud action STOP execution", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return
}
// https://shuffler.io/v1/hooks/webhook_80184973-3e82-4852-842e-0290f7f34d7c
}
// This is here to force stop and remove the old webhook
//image := "webhook"
//err = removeWebhookFunction(ctx, fileId)
+1 -11
View File
@@ -23,14 +23,4 @@
#curl -X POST "https://europe-west1-shuffle-241517.cloudfunctions.net/webhook_3ceff795-ce9a-43a2-a2f5-d4401a6e772d" -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26" --data 'wut'
#curl POST "https://europe-west1-shuffler.cloudfunctions.net/outlooktrigger_be4dbb0a-d396-4544-bc36-e57d1bdb2e40" -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26" --data 'wut' -vvv
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5001/api/v1/hooks/webhook_e38e0768-191c-42ec-a021-cf17a4339473" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}' -v
curl -X POST "http://localhost:5002/api/v1/hooks/webhook_f22b5e54-e55d-48e5-a1d1-f40453513fd3" -H "Content-Type:application/json" --data '{"test": {"hello": "HEYOOOO"}}'
+2 -2
View File
@@ -30,7 +30,7 @@ import SettingsPage from "./views/SettingsPage";
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles';
import AlertTemplate from "react-alert-template-basic";
import AlertTemplate from "./components/AlertTemplate";
import { positions, Provider } from "react-alert";
// Production - backend proxy forwarding in nginx
@@ -118,7 +118,7 @@ const App = (message, props) => {
const options = {
timeout: 5000,
position: positions.BOTTOM_CENTER
position: positions.BOTTOM_RIGHT
};
const includedData = window.location.pathname === "/home" || window.location.pathname === "/features" ?
+4 -3
View File
@@ -7,7 +7,7 @@ import CloseIcon from './icons/CloseIcon'
const alertStyle = {
backgroundColor: '#151515',
color: 'white',
padding: '10px',
padding: 15,
textTransform: 'uppercase',
borderRadius: '3px',
display: 'flex',
@@ -15,8 +15,9 @@ const alertStyle = {
alignItems: 'center',
boxShadow: '0px 2px 2px 2px rgba(0, 0, 0, 0.03)',
fontFamily: 'Arial',
width: '300px',
boxSizing: 'border-box'
width: 400,
boxSizing: 'border-box',
zIndex: 10001,
}
const buttonStyle = {
File diff suppressed because one or more lines are too long
+1
View File
@@ -884,6 +884,7 @@ const AppCreator = (props) => {
}
})
.catch(error => {
setAppBuilding(false)
setErrorCode(error.toString())
alert.error(error.toString())
});