Adding an outgoing webhook action, so that we have both incoming and outgoing ability.

This commit is contained in:
mike12345567 2020-10-27 12:33:25 +00:00
parent f9eeefb4dc
commit 3ae82b95a3
10 changed files with 119 additions and 8 deletions

View File

@ -47,6 +47,7 @@
"@sendgrid/mail": "^7.1.1", "@sendgrid/mail": "^7.1.1",
"@sentry/node": "^5.19.2", "@sentry/node": "^5.19.2",
"aws-sdk": "^2.767.0", "aws-sdk": "^2.767.0",
"axios": "^0.21.0",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"chmodr": "^1.2.0", "chmodr": "^1.2.0",
"csvtojson": "^2.0.10", "csvtojson": "^2.0.10",

View File

@ -81,10 +81,9 @@ exports.trigger = async ctx => {
const db = new CouchDB(ctx.params.instance) const db = new CouchDB(ctx.params.instance)
const webhook = await db.get(ctx.params.id) const webhook = await db.get(ctx.params.id)
// validate against the schema // validate against the schema
if (!webhook.bodySchema) { if (webhook.bodySchema) {
ctx.throw(400, "Webhook has not been fully configured, no schema created") validate(ctx.request.body, webhook.bodySchema)
} }
validate(ctx.request.body, webhook.bodySchema)
const target = await db.get(webhook.action.target) const target = await db.get(webhook.action.target)
if (webhook.action.type === exports.WebhookType.AUTOMATION) { if (webhook.action.type === exports.WebhookType.AUTOMATION) {
// trigger with both the pure request and then expand it // trigger with both the pure request and then expand it

View File

@ -3,6 +3,7 @@ const createRow = require("./steps/createRow")
const updateRow = require("./steps/updateRow") const updateRow = require("./steps/updateRow")
const deleteRow = require("./steps/deleteRow") const deleteRow = require("./steps/deleteRow")
const createUser = require("./steps/createUser") const createUser = require("./steps/createUser")
const outgoingWebhook = require("./steps/outgoingWebhook")
const environment = require("../environment") const environment = require("../environment")
const download = require("download") const download = require("download")
const fetch = require("node-fetch") const fetch = require("node-fetch")
@ -21,6 +22,7 @@ const BUILTIN_ACTIONS = {
UPDATE_ROW: updateRow.run, UPDATE_ROW: updateRow.run,
DELETE_ROW: deleteRow.run, DELETE_ROW: deleteRow.run,
CREATE_USER: createUser.run, CREATE_USER: createUser.run,
OUTGOING_WEBHOOK: outgoingWebhook.run,
} }
const BUILTIN_DEFINITIONS = { const BUILTIN_DEFINITIONS = {
SEND_EMAIL: sendEmail.definition, SEND_EMAIL: sendEmail.definition,
@ -28,6 +30,7 @@ const BUILTIN_DEFINITIONS = {
UPDATE_ROW: updateRow.definition, UPDATE_ROW: updateRow.definition,
DELETE_ROW: deleteRow.definition, DELETE_ROW: deleteRow.definition,
CREATE_USER: createUser.definition, CREATE_USER: createUser.definition,
OUTGOING_WEBHOOK: outgoingWebhook.definition,
} }
let AUTOMATION_BUCKET = environment.AUTOMATION_BUCKET let AUTOMATION_BUCKET = environment.AUTOMATION_BUCKET

View File

@ -6,7 +6,7 @@ const usage = require("../../utilities/usageQuota")
module.exports.definition = { module.exports.definition = {
name: "Create Row", name: "Create Row",
tagline: "Create a {{inputs.enriched.table.name}} row", tagline: "Create a {{inputs.enriched.table.name}} row",
icon: "ri-save-3-fill", icon: "ri-save-3-line",
description: "Add a row to your database", description: "Add a row to your database",
type: "ACTION", type: "ACTION",
stepId: "CREATE_ROW", stepId: "CREATE_ROW",

View File

@ -6,7 +6,7 @@ const usage = require("../../utilities/usageQuota")
module.exports.definition = { module.exports.definition = {
description: "Create a new user", description: "Create a new user",
tagline: "Create user {{inputs.username}}", tagline: "Create user {{inputs.username}}",
icon: "ri-user-add-fill", icon: "ri-user-add-line",
name: "Create User", name: "Create User",
type: "ACTION", type: "ACTION",
stepId: "CREATE_USER", stepId: "CREATE_USER",

View File

@ -2,7 +2,7 @@ let { wait } = require("../../utilities")
module.exports.definition = { module.exports.definition = {
name: "Delay", name: "Delay",
icon: "ri-time-fill", icon: "ri-time-line",
tagline: "Delay for {{inputs.time}} milliseconds", tagline: "Delay for {{inputs.time}} milliseconds",
description: "Delay the automation until an amount of time has passed", description: "Delay the automation until an amount of time has passed",
stepId: "DELAY", stepId: "DELAY",

View File

@ -0,0 +1,96 @@
const axios = require("axios")
const RequestType = {
POST: "POST",
GET: "GET",
PUT: "PUT",
DELETE: "DELETE",
PATCH: "PATCH",
}
const BODY_REQUESTS = [RequestType.POST, RequestType.PUT, RequestType.PATCH]
/**
* Note, there is some functionality in this that is not currently exposed as it
* is complex and maybe better to be opinionated here.
* GET/DELETE requests cannot handle body elements so they will not be sent if configured.
*/
module.exports.definition = {
name: "Outgoing webhook",
tagline: "Send a {{inputs.requestMethod}} request",
icon: "ri-send-plane-line",
description: "Send a request of specified method to a URL",
type: "ACTION",
stepId: "OUTGOING_WEBHOOK",
inputs: {
requestMethod: "POST",
url: "http://",
requestBody: "{}",
},
schema: {
inputs: {
properties: {
requestMethod: {
type: "string",
enum: Object.values(RequestType),
title: "Request method",
},
url: {
type: "string",
title: "URL",
},
requestBody: {
type: "string",
title: "JSON Body",
customType: "wide",
},
},
required: ["requestMethod", "url"],
},
outputs: {
properties: {
response: {
type: "object",
description: "The response from the webhook",
},
success: {
type: "boolean",
description: "Whether the action was successful",
},
},
required: ["response", "success"],
},
},
}
module.exports.run = async function({ inputs }) {
let { requestMethod, url, requestBody } = inputs
if (!url.startsWith("http")) {
url = `http://${url}`
}
const request = {
method: requestMethod,
url,
}
if (
requestBody &&
requestBody.length !== 0 &&
BODY_REQUESTS.indexOf(requestMethod) !== -1
) {
request.data = JSON.parse(requestBody)
}
try {
const response = await axios(request)
return {
response: response.data,
success: response.status === 200,
}
} catch (err) {
return {
success: false,
response: err,
}
}
}

View File

@ -1,7 +1,7 @@
module.exports.definition = { module.exports.definition = {
description: "Send an email", description: "Send an email",
tagline: "Send email to {{inputs.to}}", tagline: "Send email to {{inputs.to}}",
icon: "ri-mail-open-fill", icon: "ri-mail-open-line",
name: "Send Email", name: "Send Email",
type: "ACTION", type: "ACTION",
stepId: "SEND_EMAIL", stepId: "SEND_EMAIL",

View File

@ -4,7 +4,7 @@ const automationUtils = require("../automationUtils")
module.exports.definition = { module.exports.definition = {
name: "Update Row", name: "Update Row",
tagline: "Update a {{inputs.enriched.table.name}} row", tagline: "Update a {{inputs.enriched.table.name}} row",
icon: "ri-refresh-fill", icon: "ri-refresh-line",
description: "Update a row in your database", description: "Update a row in your database",
type: "ACTION", type: "ACTION",
stepId: "UPDATE_ROW", stepId: "UPDATE_ROW",

View File

@ -1352,6 +1352,13 @@ axios@^0.19.2:
dependencies: dependencies:
follow-redirects "1.5.10" follow-redirects "1.5.10"
axios@^0.21.0:
version "0.21.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.0.tgz#26df088803a2350dff2c27f96fef99fe49442aca"
integrity sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==
dependencies:
follow-redirects "^1.10.0"
babel-jest@^24.9.0: babel-jest@^24.9.0:
version "24.9.0" version "24.9.0"
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54"
@ -3178,6 +3185,11 @@ follow-redirects@1.5.10:
dependencies: dependencies:
debug "=3.1.0" debug "=3.1.0"
follow-redirects@^1.10.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==
for-in@^1.0.2: for-in@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"