mirror of https://github.com/Budibase/budibase.git
14 changed files with 382 additions and 7 deletions
@ -0,0 +1,94 @@ |
|||||
|
const CouchDB = require("../../db") |
||||
|
const { generateWebhookID, getWebhookParams } = require("../../db/utils") |
||||
|
const toJsonSchema = require("to-json-schema") |
||||
|
const validate = require("jsonschema").validate |
||||
|
const triggers = require("../../automations/triggers") |
||||
|
|
||||
|
const AUTOMATION_DESCRIPTION = "Generated from Webhook Schema" |
||||
|
|
||||
|
function Webhook(name, type, target) { |
||||
|
this.live = true |
||||
|
this.name = name |
||||
|
this.action = { |
||||
|
type, |
||||
|
target, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
exports.Webhook = Webhook |
||||
|
|
||||
|
exports.WebhookType = { |
||||
|
AUTOMATION: "automation", |
||||
|
} |
||||
|
|
||||
|
exports.fetch = async ctx => { |
||||
|
const db = new CouchDB(ctx.user.instanceId) |
||||
|
const response = await db.allDocs( |
||||
|
getWebhookParams(null, { |
||||
|
include_docs: true, |
||||
|
}) |
||||
|
) |
||||
|
ctx.body = response.rows.map(row => row.doc) |
||||
|
} |
||||
|
|
||||
|
exports.save = async ctx => { |
||||
|
const db = new CouchDB(ctx.user.instanceId) |
||||
|
const webhook = ctx.request.body |
||||
|
webhook.appId = ctx.user.appId |
||||
|
|
||||
|
// check that the webhook exists
|
||||
|
if (webhook._id) { |
||||
|
await db.get(webhook._id) |
||||
|
} else { |
||||
|
webhook._id = generateWebhookID() |
||||
|
} |
||||
|
const response = await db.put(webhook) |
||||
|
ctx.body = { |
||||
|
message: "Webhook created successfully", |
||||
|
webhook: { |
||||
|
...webhook, |
||||
|
...response, |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
exports.destroy = async ctx => { |
||||
|
const db = new CouchDB(ctx.user.instanceId) |
||||
|
ctx.body = await db.remove(ctx.params.id, ctx.params.rev) |
||||
|
} |
||||
|
|
||||
|
exports.buildSchema = async ctx => { |
||||
|
const db = new CouchDB(ctx.params.instance) |
||||
|
const webhook = await db.get(ctx.params.id) |
||||
|
webhook.bodySchema = toJsonSchema(ctx.request.body) |
||||
|
// update the automation outputs
|
||||
|
if (webhook.action.type === exports.WebhookType.AUTOMATION) { |
||||
|
let automation = await db.get(webhook.action.target) |
||||
|
const autoOutputs = automation.definition.trigger.schema.outputs |
||||
|
let properties = webhook.bodySchema.properties |
||||
|
for (let prop of Object.keys(properties)) { |
||||
|
autoOutputs.properties[prop] = { |
||||
|
type: properties[prop].type, |
||||
|
description: AUTOMATION_DESCRIPTION, |
||||
|
} |
||||
|
} |
||||
|
await db.put(automation) |
||||
|
} |
||||
|
ctx.body = await db.put(webhook) |
||||
|
} |
||||
|
|
||||
|
exports.trigger = async ctx => { |
||||
|
const db = new CouchDB(ctx.params.instance) |
||||
|
const webhook = await db.get(ctx.params.id) |
||||
|
// validate against the schema
|
||||
|
if (!webhook.bodySchema) { |
||||
|
ctx.throw(400, "Webhook has not been fully configured, no schema created") |
||||
|
} |
||||
|
validate(ctx.request.body, webhook.bodySchema) |
||||
|
const target = await db.get(webhook.action.target) |
||||
|
if (webhook.action.type === exports.WebhookType.AUTOMATION) { |
||||
|
await triggers.externalTrigger(target, ctx.request.body) |
||||
|
} |
||||
|
ctx.status = 200 |
||||
|
ctx.body = "Webhook trigger fired successfully" |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
const Router = require("@koa/router") |
||||
|
const controller = require("../controllers/webhook") |
||||
|
const authorized = require("../../middleware/authorized") |
||||
|
const joiValidator = require("../../middleware/joi-validator") |
||||
|
const { BUILDER, EXECUTE_WEBHOOK } = require("../../utilities/accessLevels") |
||||
|
const Joi = require("joi") |
||||
|
|
||||
|
const router = Router() |
||||
|
|
||||
|
function generateSaveValidator() { |
||||
|
// prettier-ignore
|
||||
|
return joiValidator.body(Joi.object({ |
||||
|
live: Joi.bool(), |
||||
|
_id: Joi.string().optional(), |
||||
|
_rev: Joi.string().optional(), |
||||
|
name: Joi.string().required(), |
||||
|
bodySchema: Joi.object().optional(), |
||||
|
action: Joi.object({ |
||||
|
type: Joi.string().required().valid(controller.WebhookType.AUTOMATION), |
||||
|
target: Joi.string().required(), |
||||
|
}).required(), |
||||
|
}).unknown(true)) |
||||
|
} |
||||
|
|
||||
|
router |
||||
|
.get("/api/webhooks", authorized(BUILDER), controller.fetch) |
||||
|
.put( |
||||
|
"/api/webhooks", |
||||
|
authorized(BUILDER), |
||||
|
generateSaveValidator(), |
||||
|
controller.save |
||||
|
) |
||||
|
.delete("/api/webhooks/:id/:rev", authorized(BUILDER), controller.destroy) |
||||
|
.post( |
||||
|
"/api/webhooks/schema/:instance/:id", |
||||
|
authorized(BUILDER), |
||||
|
controller.buildSchema |
||||
|
) |
||||
|
.post( |
||||
|
"/api/webhooks/trigger/:instance/:id", |
||||
|
authorized(EXECUTE_WEBHOOK), |
||||
|
controller.trigger |
||||
|
) |
||||
|
|
||||
|
module.exports = router |
||||
Loading…
Reference in new issue