Merge branch 'master' of github.com:Budibase/budibase into develop
This commit is contained in:
commit
6455f51d4f
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/auth",
|
"name": "@budibase/auth",
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"description": "Authentication middlewares for budibase builder and apps",
|
"description": "Authentication middlewares for budibase builder and apps",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
|
|
|
@ -6,6 +6,7 @@ exports.UserStatus = {
|
||||||
exports.Cookies = {
|
exports.Cookies = {
|
||||||
CurrentApp: "budibase:currentapp",
|
CurrentApp: "budibase:currentapp",
|
||||||
Auth: "budibase:auth",
|
Auth: "budibase:auth",
|
||||||
|
Init: "budibase:init",
|
||||||
OIDC_CONFIG: "budibase:oidc:config",
|
OIDC_CONFIG: "budibase:oidc:config",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/bbui",
|
"name": "@budibase/bbui",
|
||||||
"description": "A UI solution used in the different Budibase projects.",
|
"description": "A UI solution used in the different Budibase projects.",
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -65,10 +65,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^0.9.176-alpha.3",
|
"@budibase/bbui": "^0.9.179",
|
||||||
"@budibase/client": "^0.9.176-alpha.3",
|
"@budibase/client": "^0.9.179",
|
||||||
"@budibase/colorpicker": "1.1.2",
|
"@budibase/colorpicker": "1.1.2",
|
||||||
"@budibase/string-templates": "^0.9.176-alpha.3",
|
"@budibase/string-templates": "^0.9.179",
|
||||||
"@sentry/browser": "5.19.1",
|
"@sentry/browser": "5.19.1",
|
||||||
"@spectrum-css/page": "^3.0.1",
|
"@spectrum-css/page": "^3.0.1",
|
||||||
"@spectrum-css/vars": "^3.0.1",
|
"@spectrum-css/vars": "^3.0.1",
|
||||||
|
|
|
@ -8,10 +8,13 @@
|
||||||
|
|
||||||
let name
|
let name
|
||||||
let selectedTrigger
|
let selectedTrigger
|
||||||
|
let nameTouched = false
|
||||||
let triggerVal
|
let triggerVal
|
||||||
export let webhookModal
|
export let webhookModal
|
||||||
|
|
||||||
$: instanceId = $database._id
|
$: instanceId = $database._id
|
||||||
|
$: nameError =
|
||||||
|
nameTouched && !name ? "Please specify a name for the automation." : null
|
||||||
|
|
||||||
async function createAutomation() {
|
async function createAutomation() {
|
||||||
await automationStore.actions.create({
|
await automationStore.actions.create({
|
||||||
|
@ -51,13 +54,18 @@
|
||||||
confirmText="Save"
|
confirmText="Save"
|
||||||
size="M"
|
size="M"
|
||||||
onConfirm={createAutomation}
|
onConfirm={createAutomation}
|
||||||
disabled={!selectedTrigger}
|
disabled={!selectedTrigger || !name}
|
||||||
>
|
>
|
||||||
<Body size="XS"
|
<Body size="XS"
|
||||||
>Please name your automation, then select a trigger. Every automation must
|
>Please name your automation, then select a trigger. Every automation must
|
||||||
start with a trigger.
|
start with a trigger.
|
||||||
</Body>
|
</Body>
|
||||||
<Input bind:value={name} label="Name" />
|
<Input
|
||||||
|
bind:value={name}
|
||||||
|
on:change={() => (nameTouched = true)}
|
||||||
|
bind:error={nameError}
|
||||||
|
label="Name"
|
||||||
|
/>
|
||||||
|
|
||||||
<Layout noPadding>
|
<Layout noPadding>
|
||||||
<Body size="S">Triggers</Body>
|
<Body size="S">Triggers</Body>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
Checkbox,
|
Checkbox,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { store, automationStore, hostingStore } from "builderStore"
|
import { store, automationStore, hostingStore } from "builderStore"
|
||||||
import { admin } from "stores/portal"
|
import { admin, auth } from "stores/portal"
|
||||||
import { string, mixed, object } from "yup"
|
import { string, mixed, object } from "yup"
|
||||||
import api, { get, post } from "builderStore/api"
|
import api, { get, post } from "builderStore/api"
|
||||||
import analytics, { Events } from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
@ -139,6 +139,7 @@
|
||||||
}
|
}
|
||||||
const userResp = await api.post(`/api/users/metadata/self`, user)
|
const userResp = await api.post(`/api/users/metadata/self`, user)
|
||||||
await userResp.json()
|
await userResp.json()
|
||||||
|
await auth.setInitInfo({})
|
||||||
$goto(`/builder/app/${appJson.instance._id}`)
|
$goto(`/builder/app/${appJson.instance._id}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
@ -146,6 +147,16 @@
|
||||||
submitting = false
|
submitting = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getModalTitle() {
|
||||||
|
let title = "Create App"
|
||||||
|
if (template.fromFile) {
|
||||||
|
title = "Import App"
|
||||||
|
} else if (template.key) {
|
||||||
|
title = "Create app from template"
|
||||||
|
}
|
||||||
|
return title
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if showTemplateSelection}
|
{#if showTemplateSelection}
|
||||||
|
@ -172,7 +183,7 @@
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
{:else}
|
{:else}
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title={template?.fromFile ? "Import app" : "Create app"}
|
title={getModalTitle()}
|
||||||
confirmText={template?.fromFile ? "Import app" : "Create app"}
|
confirmText={template?.fromFile ? "Import app" : "Create app"}
|
||||||
onConfirm={createNewApp}
|
onConfirm={createNewApp}
|
||||||
onCancel={inline ? () => (template = null) : null}
|
onCancel={inline ? () => (template = null) : null}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { isActive, redirect } from "@roxi/routify"
|
import { isActive, redirect, params } from "@roxi/routify"
|
||||||
import { admin, auth } from "stores/portal"
|
import { admin, auth } from "stores/portal"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
@ -47,6 +47,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
if ($params["?template"]) {
|
||||||
|
await auth.setInitInfo({ init_template: $params["?template"] })
|
||||||
|
}
|
||||||
|
|
||||||
await auth.checkAuth()
|
await auth.checkAuth()
|
||||||
await admin.init()
|
await admin.init()
|
||||||
|
|
||||||
|
|
|
@ -184,9 +184,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createAppFromTemplateUrl(templateKey) {
|
||||||
|
// validate the template key just to make sure
|
||||||
|
const templateParts = templateKey.split("/")
|
||||||
|
if (templateParts.length === 2 && templateParts[0] === "app") {
|
||||||
|
template = {
|
||||||
|
key: templateKey,
|
||||||
|
}
|
||||||
|
initiateAppCreation()
|
||||||
|
} else {
|
||||||
|
notifications.error("Your Template URL is invalid. Please try another.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await apps.load()
|
await apps.load()
|
||||||
loaded = true
|
loaded = true
|
||||||
|
// if the portal is loaded from an external URL with a template param
|
||||||
|
const initInfo = await auth.getInitInfo()
|
||||||
|
if (initInfo.init_template) {
|
||||||
|
createAppFromTemplateUrl(initInfo.init_template)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,13 @@ export function createAuthStore() {
|
||||||
return {
|
return {
|
||||||
subscribe: store.subscribe,
|
subscribe: store.subscribe,
|
||||||
setOrganisation: setOrganisation,
|
setOrganisation: setOrganisation,
|
||||||
|
getInitInfo: async () => {
|
||||||
|
const response = await api.get(`/api/global/auth/init`)
|
||||||
|
return await response.json()
|
||||||
|
},
|
||||||
|
setInitInfo: async info => {
|
||||||
|
await api.post(`/api/global/auth/init`, info)
|
||||||
|
},
|
||||||
checkQueryString: async () => {
|
checkQueryString: async () => {
|
||||||
const urlParams = new URLSearchParams(window.location.search)
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
if (urlParams.has("tenantId")) {
|
if (urlParams.has("tenantId")) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"module": "dist/budibase-client.js",
|
"module": "dist/budibase-client.js",
|
||||||
"main": "dist/budibase-client.js",
|
"main": "dist/budibase-client.js",
|
||||||
|
@ -19,9 +19,9 @@
|
||||||
"dev:builder": "rollup -cw"
|
"dev:builder": "rollup -cw"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^0.9.176-alpha.3",
|
"@budibase/bbui": "^0.9.179",
|
||||||
"@budibase/standard-components": "^0.9.139",
|
"@budibase/standard-components": "^0.9.139",
|
||||||
"@budibase/string-templates": "^0.9.176-alpha.3",
|
"@budibase/string-templates": "^0.9.179",
|
||||||
"regexparam": "^1.3.0",
|
"regexparam": "^1.3.0",
|
||||||
"shortid": "^2.2.15",
|
"shortid": "^2.2.15",
|
||||||
"svelte-spa-router": "^3.0.5"
|
"svelte-spa-router": "^3.0.5"
|
||||||
|
|
|
@ -59,11 +59,10 @@ export const createDataSourceStore = () => {
|
||||||
|
|
||||||
// Emit this as a window event, so parent screens which are iframing us in
|
// Emit this as a window event, so parent screens which are iframing us in
|
||||||
// can also invalidate the same datasource
|
// can also invalidate the same datasource
|
||||||
window.dispatchEvent(
|
window.parent.postMessage({
|
||||||
new CustomEvent("invalidate-datasource", {
|
type: "close-screen-modal",
|
||||||
detail: { dataSourceId },
|
detail: { dataSourceId },
|
||||||
})
|
})
|
||||||
)
|
|
||||||
|
|
||||||
let invalidations = [dataSourceId]
|
let invalidations = [dataSourceId]
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,6 @@ const createNotificationStore = () => {
|
||||||
icon,
|
icon,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
// window.dispatchEvent(
|
|
||||||
// new CustomEvent("notification", {
|
|
||||||
// detail: { message, type, icon },
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ const changeFormStepHandler = async (action, context) => {
|
||||||
const closeScreenModalHandler = () => {
|
const closeScreenModalHandler = () => {
|
||||||
// Emit this as a window event, so parent screens which are iframing us in
|
// Emit this as a window event, so parent screens which are iframing us in
|
||||||
// can close the modal
|
// can close the modal
|
||||||
window.dispatchEvent(new Event("close-screen-modal"))
|
window.parent.postMessage({ type: "close-screen-modal" })
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateStateHandler = action => {
|
const updateStateHandler = action => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -68,9 +68,9 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/auth": "^0.9.176-alpha.3",
|
"@budibase/auth": "^0.9.179",
|
||||||
"@budibase/client": "^0.9.176-alpha.3",
|
"@budibase/client": "^0.9.179",
|
||||||
"@budibase/string-templates": "^0.9.176-alpha.3",
|
"@budibase/string-templates": "^0.9.179",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
"@koa/router": "8.0.0",
|
"@koa/router": "8.0.0",
|
||||||
"@sendgrid/mail": "7.1.1",
|
"@sendgrid/mail": "7.1.1",
|
||||||
|
|
|
@ -23,9 +23,6 @@ function formatResponse(resp) {
|
||||||
try {
|
try {
|
||||||
resp = JSON.parse(resp)
|
resp = JSON.parse(resp)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(
|
|
||||||
"Error parsing JSON response. Returning string in array instead."
|
|
||||||
)
|
|
||||||
resp = { response: resp }
|
resp = { response: resp }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ const { generateWebhookID, getWebhookParams } = require("../../db/utils")
|
||||||
const toJsonSchema = require("to-json-schema")
|
const toJsonSchema = require("to-json-schema")
|
||||||
const validate = require("jsonschema").validate
|
const validate = require("jsonschema").validate
|
||||||
const triggers = require("../../automations/triggers")
|
const triggers = require("../../automations/triggers")
|
||||||
|
const { getDeployedAppID } = require("@budibase/auth/db")
|
||||||
|
|
||||||
const AUTOMATION_DESCRIPTION = "Generated from Webhook Schema"
|
const AUTOMATION_DESCRIPTION = "Generated from Webhook Schema"
|
||||||
|
|
||||||
|
@ -76,24 +77,34 @@ exports.buildSchema = async ctx => {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.trigger = async ctx => {
|
exports.trigger = async ctx => {
|
||||||
const db = new CouchDB(ctx.params.instance)
|
const prodAppId = getDeployedAppID(ctx.params.instance)
|
||||||
const webhook = await db.get(ctx.params.id)
|
try {
|
||||||
// validate against the schema
|
const db = new CouchDB(prodAppId)
|
||||||
if (webhook.bodySchema) {
|
const webhook = await db.get(ctx.params.id)
|
||||||
validate(ctx.request.body, webhook.bodySchema)
|
// validate against the schema
|
||||||
}
|
if (webhook.bodySchema) {
|
||||||
const target = await db.get(webhook.action.target)
|
validate(ctx.request.body, webhook.bodySchema)
|
||||||
if (webhook.action.type === exports.WebhookType.AUTOMATION) {
|
}
|
||||||
// trigger with both the pure request and then expand it
|
const target = await db.get(webhook.action.target)
|
||||||
// incase the user has produced a schema to bind to
|
if (webhook.action.type === exports.WebhookType.AUTOMATION) {
|
||||||
await triggers.externalTrigger(target, {
|
// trigger with both the pure request and then expand it
|
||||||
body: ctx.request.body,
|
// incase the user has produced a schema to bind to
|
||||||
...ctx.request.body,
|
await triggers.externalTrigger(target, {
|
||||||
appId: ctx.params.instance,
|
body: ctx.request.body,
|
||||||
})
|
...ctx.request.body,
|
||||||
}
|
appId: prodAppId,
|
||||||
ctx.status = 200
|
})
|
||||||
ctx.body = {
|
}
|
||||||
message: "Webhook trigger fired successfully",
|
ctx.status = 200
|
||||||
|
ctx.body = {
|
||||||
|
message: "Webhook trigger fired successfully",
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
ctx.status = 200
|
||||||
|
ctx.body = {
|
||||||
|
message: "Application not deployed yet.",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,18 @@ exports.run = async function ({ inputs }) {
|
||||||
const request = {
|
const request = {
|
||||||
method: requestMethod,
|
method: requestMethod,
|
||||||
}
|
}
|
||||||
|
if (headers) {
|
||||||
|
try {
|
||||||
|
const customHeaders =
|
||||||
|
typeof headers === "string" ? JSON.parse(headers) : headers
|
||||||
|
request.headers = { ...request.headers, ...customHeaders }
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
response: "Unable to process headers, must be a JSON object.",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
requestBody &&
|
requestBody &&
|
||||||
requestBody.length !== 0 &&
|
requestBody.length !== 0 &&
|
||||||
|
@ -95,21 +107,9 @@ exports.run = async function ({ inputs }) {
|
||||||
? requestBody
|
? requestBody
|
||||||
: JSON.stringify(requestBody)
|
: JSON.stringify(requestBody)
|
||||||
request.headers = {
|
request.headers = {
|
||||||
|
...request.headers,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers) {
|
|
||||||
try {
|
|
||||||
const customHeaders =
|
|
||||||
typeof headers === "string" ? JSON.parse(headers) : headers
|
|
||||||
request.headers = { ...request.headers, ...customHeaders }
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
response: "Unable to process headers, must be a JSON object.",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -122,7 +122,7 @@ exports.run = async function ({ inputs }) {
|
||||||
return {
|
return {
|
||||||
httpStatus: status,
|
httpStatus: status,
|
||||||
response: message,
|
response: message,
|
||||||
success: status === 200,
|
success: status >= 200 && status <= 206,
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
|
|
|
@ -6,6 +6,7 @@ const { queue } = require("./bullboard")
|
||||||
const newid = require("../db/newid")
|
const newid = require("../db/newid")
|
||||||
const { updateEntityMetadata } = require("../utilities")
|
const { updateEntityMetadata } = require("../utilities")
|
||||||
const { MetadataTypes } = require("../constants")
|
const { MetadataTypes } = require("../constants")
|
||||||
|
const { getDeployedAppID } = require("@budibase/auth/db")
|
||||||
|
|
||||||
const WH_STEP_ID = definitions.WEBHOOK.stepId
|
const WH_STEP_ID = definitions.WEBHOOK.stepId
|
||||||
const CRON_STEP_ID = definitions.CRON.stepId
|
const CRON_STEP_ID = definitions.CRON.stepId
|
||||||
|
@ -150,9 +151,13 @@ exports.checkForWebhooks = async ({ appId, oldAuto, newAuto }) => {
|
||||||
await webhooks.save(ctx)
|
await webhooks.save(ctx)
|
||||||
const id = ctx.body.webhook._id
|
const id = ctx.body.webhook._id
|
||||||
newTrigger.webhookId = id
|
newTrigger.webhookId = id
|
||||||
|
// the app ID has to be development for this endpoint
|
||||||
|
// it can only be used when building the app
|
||||||
|
// but the trigger endpoint will always be used in production
|
||||||
|
const prodAppId = getDeployedAppID(appId)
|
||||||
newTrigger.inputs = {
|
newTrigger.inputs = {
|
||||||
schemaUrl: `api/webhooks/schema/${appId}/${id}`,
|
schemaUrl: `api/webhooks/schema/${appId}/${id}`,
|
||||||
triggerUrl: `api/webhooks/trigger/${appId}/${id}`,
|
triggerUrl: `api/webhooks/trigger/${prodAppId}/${id}`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newAuto
|
return newAuto
|
||||||
|
|
|
@ -142,13 +142,11 @@ module RestModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
async parseResponse(response: any) {
|
async parseResponse(response: any) {
|
||||||
switch (this.headers.Accept) {
|
const contentType = response.headers.get("content-type")
|
||||||
case "application/json":
|
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||||
return await response.json()
|
return await response.json()
|
||||||
case "text/html":
|
} else {
|
||||||
return await response.text()
|
return await response.text()
|
||||||
default:
|
|
||||||
return await response.json()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +189,7 @@ module RestModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(this.getUrl(path, queryString), {
|
const response = await fetch(this.getUrl(path, queryString), {
|
||||||
method: "POST",
|
method: "PUT",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify(json),
|
body: JSON.stringify(json),
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
jest.mock("node-fetch", () =>
|
jest.mock("node-fetch", () =>
|
||||||
jest.fn(() => ({ json: jest.fn(), text: jest.fn() }))
|
jest.fn(() => ({
|
||||||
|
headers: {
|
||||||
|
get: () => ["application/json"]
|
||||||
|
},
|
||||||
|
json: jest.fn(),
|
||||||
|
text: jest.fn()
|
||||||
|
}))
|
||||||
)
|
)
|
||||||
const fetch = require("node-fetch")
|
const fetch = require("node-fetch")
|
||||||
const RestIntegration = require("../rest")
|
const RestIntegration = require("../rest")
|
||||||
|
|
|
@ -5,20 +5,17 @@ const {
|
||||||
doesHaveBasePermission,
|
doesHaveBasePermission,
|
||||||
} = require("@budibase/auth/permissions")
|
} = require("@budibase/auth/permissions")
|
||||||
const builderMiddleware = require("./builder")
|
const builderMiddleware = require("./builder")
|
||||||
|
const { isWebhookEndpoint } = require("./utils")
|
||||||
|
|
||||||
function hasResource(ctx) {
|
function hasResource(ctx) {
|
||||||
return ctx.resourceId != null
|
return ctx.resourceId != null
|
||||||
}
|
}
|
||||||
|
|
||||||
const WEBHOOK_ENDPOINTS = new RegExp(
|
|
||||||
["webhooks/trigger", "webhooks/schema"].join("|")
|
|
||||||
)
|
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
(permType, permLevel = null) =>
|
(permType, permLevel = null) =>
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
// webhooks don't need authentication, each webhook unique
|
// webhooks don't need authentication, each webhook unique
|
||||||
if (WEBHOOK_ENDPOINTS.test(ctx.request.url)) {
|
if (isWebhookEndpoint(ctx)) {
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ const { isUserInAppTenant } = require("@budibase/auth/tenancy")
|
||||||
const { getCachedSelf } = require("../utilities/global")
|
const { getCachedSelf } = require("../utilities/global")
|
||||||
const CouchDB = require("../db")
|
const CouchDB = require("../db")
|
||||||
const env = require("../environment")
|
const env = require("../environment")
|
||||||
|
const { isWebhookEndpoint } = require("./utils")
|
||||||
|
|
||||||
module.exports = async (ctx, next) => {
|
module.exports = async (ctx, next) => {
|
||||||
// try to get the appID from the request
|
// try to get the appID from the request
|
||||||
|
@ -38,6 +39,7 @@ module.exports = async (ctx, next) => {
|
||||||
// deny access to application preview
|
// deny access to application preview
|
||||||
if (
|
if (
|
||||||
isDevAppID(requestAppId) &&
|
isDevAppID(requestAppId) &&
|
||||||
|
!isWebhookEndpoint(ctx) &&
|
||||||
(!ctx.user || !ctx.user.builder || !ctx.user.builder.global)
|
(!ctx.user || !ctx.user.builder || !ctx.user.builder.global)
|
||||||
) {
|
) {
|
||||||
clearCookie(ctx, Cookies.CurrentApp)
|
clearCookie(ctx, Cookies.CurrentApp)
|
||||||
|
|
|
@ -2,6 +2,10 @@ const CouchDB = require("../db")
|
||||||
const usageQuota = require("../utilities/usageQuota")
|
const usageQuota = require("../utilities/usageQuota")
|
||||||
const env = require("../environment")
|
const env = require("../environment")
|
||||||
const { getTenantId } = require("@budibase/auth/tenancy")
|
const { getTenantId } = require("@budibase/auth/tenancy")
|
||||||
|
const {
|
||||||
|
isExternalTable,
|
||||||
|
isRowId: isExternalRowId,
|
||||||
|
} = require("../integrations/utils")
|
||||||
|
|
||||||
// tenants without limits
|
// tenants without limits
|
||||||
const EXCLUDED_TENANTS = ["bb", "default", "bbtest", "bbstaging"]
|
const EXCLUDED_TENANTS = ["bb", "default", "bbtest", "bbstaging"]
|
||||||
|
@ -46,14 +50,24 @@ module.exports = async (ctx, next) => {
|
||||||
}
|
}
|
||||||
// post request could be a save of a pre-existing entry
|
// post request could be a save of a pre-existing entry
|
||||||
if (ctx.request.body && ctx.request.body._id && ctx.request.body._rev) {
|
if (ctx.request.body && ctx.request.body._id && ctx.request.body._rev) {
|
||||||
|
const usageId = ctx.request.body._id
|
||||||
try {
|
try {
|
||||||
if (ctx.appId) {
|
if (ctx.appId) {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
await db.get(ctx.request.body._id)
|
await db.get(usageId)
|
||||||
}
|
}
|
||||||
return next()
|
return next()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.throw(404, `${ctx.request.body._id} does not exist`)
|
if (
|
||||||
|
isExternalTable(usageId) ||
|
||||||
|
(ctx.request.body.tableId &&
|
||||||
|
isExternalTable(ctx.request.body.tableId)) ||
|
||||||
|
isExternalRowId(usageId)
|
||||||
|
) {
|
||||||
|
return next()
|
||||||
|
} else {
|
||||||
|
ctx.throw(404, `${usageId} does not exist`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
const WEBHOOK_ENDPOINTS = new RegExp(
|
||||||
|
["webhooks/trigger", "webhooks/schema"].join("|")
|
||||||
|
)
|
||||||
|
|
||||||
|
exports.isWebhookEndpoint = ctx => {
|
||||||
|
return WEBHOOK_ENDPOINTS.test(ctx.request.url)
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"description": "Handlebars wrapper for Budibase templating.",
|
"description": "Handlebars wrapper for Budibase templating.",
|
||||||
"main": "src/index.cjs",
|
"main": "src/index.cjs",
|
||||||
"module": "dist/bundle.mjs",
|
"module": "dist/bundle.mjs",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "0.9.176-alpha.3",
|
"version": "0.9.179",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -29,8 +29,8 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/auth": "^0.9.176-alpha.3",
|
"@budibase/auth": "^0.9.179",
|
||||||
"@budibase/string-templates": "^0.9.176-alpha.3",
|
"@budibase/string-templates": "^0.9.179",
|
||||||
"@koa/router": "^8.0.0",
|
"@koa/router": "^8.0.0",
|
||||||
"@sentry/node": "^6.0.0",
|
"@sentry/node": "^6.0.0",
|
||||||
"@techpass/passport-openidconnect": "^0.3.0",
|
"@techpass/passport-openidconnect": "^0.3.0",
|
||||||
|
|
|
@ -77,6 +77,17 @@ exports.authenticate = async (ctx, next) => {
|
||||||
})(ctx, next)
|
})(ctx, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.setInitInfo = ctx => {
|
||||||
|
const initInfo = ctx.request.body
|
||||||
|
setCookie(ctx, initInfo, Cookies.Init)
|
||||||
|
ctx.status = 200
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getInitInfo = ctx => {
|
||||||
|
const initInfo = getCookie(ctx, Cookies.Init)
|
||||||
|
ctx.body = initInfo
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the user password, used as part of a forgotten password flow.
|
* Reset the user password, used as part of a forgotten password flow.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -56,6 +56,8 @@ router
|
||||||
authController.resetUpdate
|
authController.resetUpdate
|
||||||
)
|
)
|
||||||
.post("/api/global/auth/logout", authController.logout)
|
.post("/api/global/auth/logout", authController.logout)
|
||||||
|
.post("/api/global/auth/init", authController.setInitInfo)
|
||||||
|
.get("/api/global/auth/init", authController.getInitInfo)
|
||||||
.get(
|
.get(
|
||||||
"/api/global/auth/:tenantId/google",
|
"/api/global/auth/:tenantId/google",
|
||||||
updateTenant,
|
updateTenant,
|
||||||
|
|
Loading…
Reference in New Issue