Merge branch 'master' of github.com:budibase/budibase into sql-security
This commit is contained in:
commit
26192515b3
|
@ -83,7 +83,7 @@ function getPackageJsonFields(): {
|
||||||
if (isDev() && !isTest()) {
|
if (isDev() && !isTest()) {
|
||||||
try {
|
try {
|
||||||
const lerna = getParentFile("lerna.json")
|
const lerna = getParentFile("lerna.json")
|
||||||
localVersion = lerna.version
|
localVersion = `${lerna.version}+local`
|
||||||
} catch {
|
} catch {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { goto } from "@roxi/routify"
|
||||||
import { automationStore } from "stores/builder"
|
import { automationStore } from "stores/builder"
|
||||||
import {
|
import {
|
||||||
notifications,
|
notifications,
|
||||||
|
@ -32,11 +33,12 @@
|
||||||
triggerVal.stepId,
|
triggerVal.stepId,
|
||||||
triggerVal
|
triggerVal
|
||||||
)
|
)
|
||||||
await automationStore.actions.create(name, trigger)
|
const automation = await automationStore.actions.create(name, trigger)
|
||||||
if (triggerVal.stepId === TriggerStepID.WEBHOOK) {
|
if (triggerVal.stepId === TriggerStepID.WEBHOOK) {
|
||||||
webhookModal.show()
|
webhookModal.show()
|
||||||
}
|
}
|
||||||
notifications.success(`Automation ${name} created`)
|
notifications.success(`Automation ${name} created`)
|
||||||
|
$goto(`../automation/${automation._id}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Error creating automation")
|
notifications.error("Error creating automation")
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,6 +159,7 @@ export async function trigger(ctx: UserCtx) {
|
||||||
automation,
|
automation,
|
||||||
{
|
{
|
||||||
fields: ctx.request.body.fields,
|
fields: ctx.request.body.fields,
|
||||||
|
user: sdk.users.getUserContextBindings(ctx.user),
|
||||||
timeout:
|
timeout:
|
||||||
ctx.request.body.timeout * 1000 || env.AUTOMATION_THREAD_TIMEOUT,
|
ctx.request.body.timeout * 1000 || env.AUTOMATION_THREAD_TIMEOUT,
|
||||||
},
|
},
|
||||||
|
@ -183,6 +184,7 @@ export async function trigger(ctx: UserCtx) {
|
||||||
await triggers.externalTrigger(automation, {
|
await triggers.externalTrigger(automation, {
|
||||||
...ctx.request.body,
|
...ctx.request.body,
|
||||||
appId: ctx.appId,
|
appId: ctx.appId,
|
||||||
|
user: sdk.users.getUserContextBindings(ctx.user),
|
||||||
})
|
})
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
message: `Automation ${automation._id} has been triggered.`,
|
message: `Automation ${automation._id} has been triggered.`,
|
||||||
|
@ -212,6 +214,7 @@ export async function test(ctx: UserCtx) {
|
||||||
{
|
{
|
||||||
...testInput,
|
...testInput,
|
||||||
appId: ctx.appId,
|
appId: ctx.appId,
|
||||||
|
user: sdk.users.getUserContextBindings(ctx.user),
|
||||||
},
|
},
|
||||||
{ getResponses: true }
|
{ getResponses: true }
|
||||||
)
|
)
|
||||||
|
|
|
@ -65,7 +65,14 @@ export async function patch(
|
||||||
}
|
}
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
ctx.eventEmitter &&
|
ctx.eventEmitter &&
|
||||||
ctx.eventEmitter.emitRow(`row:update`, appId, row, table, oldRow)
|
ctx.eventEmitter.emitRow({
|
||||||
|
eventName: `row:update`,
|
||||||
|
appId,
|
||||||
|
row,
|
||||||
|
table,
|
||||||
|
oldRow,
|
||||||
|
user: sdk.users.getUserContextBindings(ctx.user),
|
||||||
|
})
|
||||||
ctx.message = `${table.name} updated successfully.`
|
ctx.message = `${table.name} updated successfully.`
|
||||||
ctx.body = row
|
ctx.body = row
|
||||||
gridSocket?.emitRowUpdate(ctx, row)
|
gridSocket?.emitRowUpdate(ctx, row)
|
||||||
|
@ -96,7 +103,14 @@ export const save = async (ctx: UserCtx<Row, Row>) => {
|
||||||
sdk.rows.save(sourceId, ctx.request.body, ctx.user?._id)
|
sdk.rows.save(sourceId, ctx.request.body, ctx.user?._id)
|
||||||
)
|
)
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:save`, appId, row, table)
|
ctx.eventEmitter &&
|
||||||
|
ctx.eventEmitter.emitRow({
|
||||||
|
eventName: `row:save`,
|
||||||
|
appId,
|
||||||
|
row,
|
||||||
|
table,
|
||||||
|
user: sdk.users.getUserContextBindings(ctx.user),
|
||||||
|
})
|
||||||
ctx.message = `${table.name} saved successfully`
|
ctx.message = `${table.name} saved successfully`
|
||||||
// prefer squashed for response
|
// prefer squashed for response
|
||||||
ctx.body = row || squashed
|
ctx.body = row || squashed
|
||||||
|
@ -168,10 +182,15 @@ async function deleteRows(ctx: UserCtx<DeleteRowRequest>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
|
ctx.eventEmitter &&
|
||||||
|
ctx.eventEmitter.emitRow({
|
||||||
|
eventName: `row:delete`,
|
||||||
|
appId,
|
||||||
|
row,
|
||||||
|
user: sdk.users.getUserContextBindings(ctx.user),
|
||||||
|
})
|
||||||
gridSocket?.emitRowDeletion(ctx, row)
|
gridSocket?.emitRowDeletion(ctx, row)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rows
|
return rows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +203,13 @@ async function deleteRow(ctx: UserCtx<DeleteRowRequest>) {
|
||||||
await quotas.removeRow()
|
await quotas.removeRow()
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, resp.row)
|
ctx.eventEmitter &&
|
||||||
|
ctx.eventEmitter.emitRow({
|
||||||
|
eventName: `row:delete`,
|
||||||
|
appId,
|
||||||
|
row: resp.row,
|
||||||
|
user: sdk.users.getUserContextBindings(ctx.user),
|
||||||
|
})
|
||||||
gridSocket?.emitRowDeletion(ctx, resp.row)
|
gridSocket?.emitRowDeletion(ctx, resp.row)
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
|
@ -5,6 +5,6 @@ export async function run(ctx: Ctx<RowActionTriggerRequest, void>) {
|
||||||
const { tableId, actionId } = ctx.params
|
const { tableId, actionId } = ctx.params
|
||||||
const { rowId } = ctx.request.body
|
const { rowId } = ctx.request.body
|
||||||
|
|
||||||
await sdk.rowActions.run(tableId, actionId, rowId)
|
await sdk.rowActions.run(tableId, actionId, rowId, ctx.user)
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,12 @@ import { InvalidFileExtensions } from "@budibase/shared-core"
|
||||||
import AppComponent from "./templates/BudibaseApp.svelte"
|
import AppComponent from "./templates/BudibaseApp.svelte"
|
||||||
import { join } from "../../../utilities/centralPath"
|
import { join } from "../../../utilities/centralPath"
|
||||||
import * as uuid from "uuid"
|
import * as uuid from "uuid"
|
||||||
import { devClientVersion, ObjectStoreBuckets } from "../../../constants"
|
import { ObjectStoreBuckets } from "../../../constants"
|
||||||
import { processString } from "@budibase/string-templates"
|
import { processString } from "@budibase/string-templates"
|
||||||
import {
|
import {
|
||||||
loadHandlebarsFile,
|
loadHandlebarsFile,
|
||||||
NODE_MODULES_PATH,
|
NODE_MODULES_PATH,
|
||||||
|
shouldServeLocally,
|
||||||
TOP_LEVEL_PATH,
|
TOP_LEVEL_PATH,
|
||||||
} from "../../../utilities/fileSystem"
|
} from "../../../utilities/fileSystem"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
|
@ -257,25 +258,29 @@ export const serveBuilderPreview = async function (ctx: Ctx) {
|
||||||
export const serveClientLibrary = async function (ctx: Ctx) {
|
export const serveClientLibrary = async function (ctx: Ctx) {
|
||||||
const version = ctx.request.query.version
|
const version = ctx.request.query.version
|
||||||
|
|
||||||
|
if (Array.isArray(version)) {
|
||||||
|
ctx.throw(400)
|
||||||
|
}
|
||||||
|
|
||||||
const appId = context.getAppId() || (ctx.request.query.appId as string)
|
const appId = context.getAppId() || (ctx.request.query.appId as string)
|
||||||
let rootPath = join(NODE_MODULES_PATH, "@budibase", "client", "dist")
|
let rootPath = join(NODE_MODULES_PATH, "@budibase", "client", "dist")
|
||||||
if (!appId) {
|
if (!appId) {
|
||||||
ctx.throw(400, "No app ID provided - cannot fetch client library.")
|
ctx.throw(400, "No app ID provided - cannot fetch client library.")
|
||||||
}
|
}
|
||||||
if (env.isProd() || (env.isDev() && version !== devClientVersion)) {
|
|
||||||
|
const serveLocally = shouldServeLocally(version || "")
|
||||||
|
if (!serveLocally) {
|
||||||
ctx.body = await objectStore.getReadStream(
|
ctx.body = await objectStore.getReadStream(
|
||||||
ObjectStoreBuckets.APPS,
|
ObjectStoreBuckets.APPS,
|
||||||
objectStore.clientLibraryPath(appId!)
|
objectStore.clientLibraryPath(appId!)
|
||||||
)
|
)
|
||||||
ctx.set("Content-Type", "application/javascript")
|
ctx.set("Content-Type", "application/javascript")
|
||||||
} else if (env.isDev() && version === devClientVersion) {
|
} else {
|
||||||
// incase running from TS directly
|
// incase running from TS directly
|
||||||
const tsPath = join(require.resolve("@budibase/client"), "..")
|
const tsPath = join(require.resolve("@budibase/client"), "..")
|
||||||
return send(ctx, "budibase-client.js", {
|
return send(ctx, "budibase-client.js", {
|
||||||
root: !fs.existsSync(rootPath) ? tsPath : rootPath,
|
root: !fs.existsSync(rootPath) ? tsPath : rootPath,
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
ctx.throw(500, "Unable to retrieve client library.")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -767,7 +767,6 @@ describe("/rowsActions", () => {
|
||||||
it("can trigger an automation given valid data", async () => {
|
it("can trigger an automation given valid data", async () => {
|
||||||
expect(await getAutomationLogs()).toBeEmpty()
|
expect(await getAutomationLogs()).toBeEmpty()
|
||||||
await config.api.rowAction.trigger(viewId, rowAction.id, { rowId })
|
await config.api.rowAction.trigger(viewId, rowAction.id, { rowId })
|
||||||
|
|
||||||
const automationLogs = await getAutomationLogs()
|
const automationLogs = await getAutomationLogs()
|
||||||
expect(automationLogs).toEqual([
|
expect(automationLogs).toEqual([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
@ -783,6 +782,10 @@ describe("/rowsActions", () => {
|
||||||
...(await config.api.table.get(tableId)),
|
...(await config.api.table.get(tableId)),
|
||||||
views: expect.anything(),
|
views: expect.anything(),
|
||||||
},
|
},
|
||||||
|
user: expect.objectContaining({
|
||||||
|
_id: "ro_ta_users_" + config.getUser()._id,
|
||||||
|
}),
|
||||||
|
|
||||||
automation: expect.objectContaining({
|
automation: expect.objectContaining({
|
||||||
_id: rowAction.automationId,
|
_id: rowAction.automationId,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -482,4 +482,38 @@ describe("Automation Scenarios", () => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("Check user is passed through from row trigger", async () => {
|
||||||
|
const table = await config.createTable()
|
||||||
|
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test a user is successfully passed from the trigger",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.rowUpdated(
|
||||||
|
{ tableId: table._id! },
|
||||||
|
{
|
||||||
|
row: { name: "Test", description: "TEST" },
|
||||||
|
id: "1234",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.serverLog({ text: "{{ [user].[email] }}" })
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps[0].outputs.message).toContain("example.com")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Check user is passed through from app trigger", async () => {
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test a user is successfully passed from the trigger",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.serverLog({ text: "{{ [user].[email] }}" })
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps[0].outputs.message).toContain("example.com")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
AutomationStoppedReason,
|
AutomationStoppedReason,
|
||||||
AutomationStatus,
|
AutomationStatus,
|
||||||
AutomationRowEvent,
|
AutomationRowEvent,
|
||||||
|
UserBindings,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { executeInThread } from "../threads/automation"
|
import { executeInThread } from "../threads/automation"
|
||||||
import { dataFilters, sdk } from "@budibase/shared-core"
|
import { dataFilters, sdk } from "@budibase/shared-core"
|
||||||
|
@ -140,7 +141,12 @@ function rowPassesFilters(row: Row, filters: SearchFilters) {
|
||||||
|
|
||||||
export async function externalTrigger(
|
export async function externalTrigger(
|
||||||
automation: Automation,
|
automation: Automation,
|
||||||
params: { fields: Record<string, any>; timeout?: number; appId?: string },
|
params: {
|
||||||
|
fields: Record<string, any>
|
||||||
|
timeout?: number
|
||||||
|
appId?: string
|
||||||
|
user?: UserBindings
|
||||||
|
},
|
||||||
{ getResponses }: { getResponses?: boolean } = {}
|
{ getResponses }: { getResponses?: boolean } = {}
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
if (automation.disabled) {
|
if (automation.disabled) {
|
||||||
|
|
|
@ -152,8 +152,6 @@ export enum AutomationErrors {
|
||||||
FAILURE_CONDITION = "FAILURE_CONDITION_MET",
|
FAILURE_CONDITION = "FAILURE_CONDITION_MET",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const devClientVersion = "0.0.0"
|
|
||||||
|
|
||||||
// pass through the list from the auth/core lib
|
// pass through the list from the auth/core lib
|
||||||
export const ObjectStoreBuckets = objectStore.ObjectStoreBuckets
|
export const ObjectStoreBuckets = objectStore.ObjectStoreBuckets
|
||||||
export const MAX_AUTOMATION_RECURRING_ERRORS = 5
|
export const MAX_AUTOMATION_RECURRING_ERRORS = 5
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { AutomationResults, LoopStepType } from "@budibase/types"
|
import { AutomationResults, LoopStepType, UserBindings } from "@budibase/types"
|
||||||
|
|
||||||
export interface LoopInput {
|
export interface LoopInput {
|
||||||
option: LoopStepType
|
option: LoopStepType
|
||||||
|
@ -18,5 +18,6 @@ export interface AutomationContext extends AutomationResults {
|
||||||
stepsById: Record<string, any>
|
stepsById: Record<string, any>
|
||||||
stepsByName: Record<string, any>
|
stepsByName: Record<string, any>
|
||||||
env?: Record<string, string>
|
env?: Record<string, string>
|
||||||
|
user?: UserBindings
|
||||||
trigger: any
|
trigger: any
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,17 @@ class AutomationEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async emitRow(eventName: string, appId: string, row: Row, table?: Table) {
|
async emitRow({
|
||||||
|
eventName,
|
||||||
|
appId,
|
||||||
|
row,
|
||||||
|
table,
|
||||||
|
}: {
|
||||||
|
eventName: string
|
||||||
|
appId: string
|
||||||
|
row: Row
|
||||||
|
table?: Table
|
||||||
|
}) {
|
||||||
let MAX_AUTOMATION_CHAIN = await this.getMaxAutomationChain()
|
let MAX_AUTOMATION_CHAIN = await this.getMaxAutomationChain()
|
||||||
|
|
||||||
// don't emit even if we've reached max automation chain
|
// don't emit even if we've reached max automation chain
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { EventEmitter } from "events"
|
import { EventEmitter } from "events"
|
||||||
import { rowEmission, tableEmission } from "./utils"
|
import { rowEmission, tableEmission } from "./utils"
|
||||||
import { Table, Row } from "@budibase/types"
|
import { Table, Row, User } from "@budibase/types"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* keeping event emitter in one central location as it might be used for things other than
|
* keeping event emitter in one central location as it might be used for things other than
|
||||||
|
@ -13,14 +13,22 @@ import { Table, Row } from "@budibase/types"
|
||||||
* This is specifically quite important for template strings used in automations.
|
* This is specifically quite important for template strings used in automations.
|
||||||
*/
|
*/
|
||||||
class BudibaseEmitter extends EventEmitter {
|
class BudibaseEmitter extends EventEmitter {
|
||||||
emitRow(
|
emitRow({
|
||||||
eventName: string,
|
eventName,
|
||||||
appId: string,
|
appId,
|
||||||
row: Row,
|
row,
|
||||||
table?: Table,
|
table,
|
||||||
|
oldRow,
|
||||||
|
user,
|
||||||
|
}: {
|
||||||
|
eventName: string
|
||||||
|
appId: string
|
||||||
|
row: Row
|
||||||
|
table?: Table
|
||||||
oldRow?: Row
|
oldRow?: Row
|
||||||
) {
|
user: User
|
||||||
rowEmission({ emitter: this, eventName, appId, row, table, oldRow })
|
}) {
|
||||||
|
rowEmission({ emitter: this, eventName, appId, row, table, oldRow, user })
|
||||||
}
|
}
|
||||||
|
|
||||||
emitTable(eventName: string, appId: string, table?: Table) {
|
emitTable(eventName: string, appId: string, table?: Table) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Table, Row } from "@budibase/types"
|
import { Table, Row, User } from "@budibase/types"
|
||||||
import BudibaseEmitter from "./BudibaseEmitter"
|
import BudibaseEmitter from "./BudibaseEmitter"
|
||||||
|
|
||||||
type BBEventOpts = {
|
type BBEventOpts = {
|
||||||
|
@ -9,6 +9,7 @@ type BBEventOpts = {
|
||||||
row?: Row
|
row?: Row
|
||||||
oldRow?: Row
|
oldRow?: Row
|
||||||
metadata?: any
|
metadata?: any
|
||||||
|
user?: User
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BBEventTable extends Table {
|
interface BBEventTable extends Table {
|
||||||
|
@ -24,6 +25,7 @@ type BBEvent = {
|
||||||
id?: string
|
id?: string
|
||||||
revision?: string
|
revision?: string
|
||||||
metadata?: any
|
metadata?: any
|
||||||
|
user?: User
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rowEmission({
|
export function rowEmission({
|
||||||
|
@ -34,12 +36,14 @@ export function rowEmission({
|
||||||
table,
|
table,
|
||||||
metadata,
|
metadata,
|
||||||
oldRow,
|
oldRow,
|
||||||
|
user,
|
||||||
}: BBEventOpts) {
|
}: BBEventOpts) {
|
||||||
let event: BBEvent = {
|
let event: BBEvent = {
|
||||||
row,
|
row,
|
||||||
oldRow,
|
oldRow,
|
||||||
appId,
|
appId,
|
||||||
tableId: row?.tableId,
|
tableId: row?.tableId,
|
||||||
|
user,
|
||||||
}
|
}
|
||||||
if (table) {
|
if (table) {
|
||||||
event.table = table
|
event.table = table
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
SEPARATOR,
|
SEPARATOR,
|
||||||
TableRowActions,
|
TableRowActions,
|
||||||
|
User,
|
||||||
VirtualDocumentType,
|
VirtualDocumentType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { generateRowActionsID } from "../../db/utils"
|
import { generateRowActionsID } from "../../db/utils"
|
||||||
|
@ -236,7 +237,12 @@ export async function remove(tableId: string, rowActionId: string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run(tableId: any, rowActionId: any, rowId: string) {
|
export async function run(
|
||||||
|
tableId: any,
|
||||||
|
rowActionId: any,
|
||||||
|
rowId: string,
|
||||||
|
user: User
|
||||||
|
) {
|
||||||
const table = await sdk.tables.getTable(tableId)
|
const table = await sdk.tables.getTable(tableId)
|
||||||
if (!table) {
|
if (!table) {
|
||||||
throw new HTTPError("Table not found", 404)
|
throw new HTTPError("Table not found", 404)
|
||||||
|
@ -258,6 +264,7 @@ export async function run(tableId: any, rowActionId: any, rowId: string) {
|
||||||
row,
|
row,
|
||||||
table,
|
table,
|
||||||
},
|
},
|
||||||
|
user,
|
||||||
appId: context.getAppId(),
|
appId: context.getAppId(),
|
||||||
},
|
},
|
||||||
{ getResponses: true }
|
{ getResponses: true }
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
UserMetadata,
|
UserMetadata,
|
||||||
Database,
|
Database,
|
||||||
ContextUserMetadata,
|
ContextUserMetadata,
|
||||||
|
UserBindings,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export function combineMetadataAndUser(
|
export function combineMetadataAndUser(
|
||||||
|
@ -125,7 +126,7 @@ export async function syncGlobalUsers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserContextBindings(user: ContextUser) {
|
export function getUserContextBindings(user: ContextUser): UserBindings {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
BranchStep,
|
BranchStep,
|
||||||
LoopStep,
|
LoopStep,
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
|
UserBindings,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { AutomationContext, TriggerOutput } from "../definitions/automations"
|
import { AutomationContext, TriggerOutput } from "../definitions/automations"
|
||||||
import { WorkerCallback } from "./definitions"
|
import { WorkerCallback } from "./definitions"
|
||||||
|
@ -75,6 +76,7 @@ class Orchestrator {
|
||||||
private loopStepOutputs: LoopStep[]
|
private loopStepOutputs: LoopStep[]
|
||||||
private stopped: boolean
|
private stopped: boolean
|
||||||
private executionOutput: Omit<AutomationContext, "stepsByName" | "stepsById">
|
private executionOutput: Omit<AutomationContext, "stepsByName" | "stepsById">
|
||||||
|
private currentUser: UserBindings | undefined
|
||||||
|
|
||||||
constructor(job: AutomationJob) {
|
constructor(job: AutomationJob) {
|
||||||
let automation = job.data.automation
|
let automation = job.data.automation
|
||||||
|
@ -106,6 +108,7 @@ class Orchestrator {
|
||||||
this.updateExecutionOutput(triggerId, triggerStepId, null, triggerOutput)
|
this.updateExecutionOutput(triggerId, triggerStepId, null, triggerOutput)
|
||||||
this.loopStepOutputs = []
|
this.loopStepOutputs = []
|
||||||
this.stopped = false
|
this.stopped = false
|
||||||
|
this.currentUser = triggerOutput.user
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanupTriggerOutputs(stepId: string, triggerOutput: TriggerOutput) {
|
cleanupTriggerOutputs(stepId: string, triggerOutput: TriggerOutput) {
|
||||||
|
@ -258,6 +261,7 @@ class Orchestrator {
|
||||||
automationId: this.automation._id,
|
automationId: this.automation._id,
|
||||||
})
|
})
|
||||||
this.context.env = await sdkUtils.getEnvironmentVariables()
|
this.context.env = await sdkUtils.getEnvironmentVariables()
|
||||||
|
this.context.user = this.currentUser
|
||||||
|
|
||||||
let metadata
|
let metadata
|
||||||
|
|
||||||
|
@ -572,7 +576,6 @@ class Orchestrator {
|
||||||
originalStepInput,
|
originalStepInput,
|
||||||
this.processContext(this.context)
|
this.processContext(this.context)
|
||||||
)
|
)
|
||||||
|
|
||||||
inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs)
|
inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs)
|
||||||
|
|
||||||
const outputs = await stepFn({
|
const outputs = await stepFn({
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { budibaseTempDir } from "../budibaseDir"
|
import { budibaseTempDir } from "../budibaseDir"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
import { ObjectStoreBuckets, devClientVersion } from "../../constants"
|
import { ObjectStoreBuckets } from "../../constants"
|
||||||
import { updateClientLibrary } from "./clientLibrary"
|
import { shouldServeLocally, updateClientLibrary } from "./clientLibrary"
|
||||||
import env from "../../environment"
|
import env from "../../environment"
|
||||||
import { objectStore, context } from "@budibase/backend-core"
|
import { objectStore, context } from "@budibase/backend-core"
|
||||||
import { TOP_LEVEL_PATH } from "./filesystem"
|
import { TOP_LEVEL_PATH } from "./filesystem"
|
||||||
|
@ -40,7 +40,7 @@ export const getComponentLibraryManifest = async (library: string) => {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
const app = await db.get<App>(DocumentType.APP_METADATA)
|
const app = await db.get<App>(DocumentType.APP_METADATA)
|
||||||
|
|
||||||
if (app.version === devClientVersion || env.isTest()) {
|
if (shouldServeLocally(app.version) || env.isTest()) {
|
||||||
const paths = [
|
const paths = [
|
||||||
join(TOP_LEVEL_PATH, "packages/client", filename),
|
join(TOP_LEVEL_PATH, "packages/client", filename),
|
||||||
join(process.cwd(), "client", filename),
|
join(process.cwd(), "client", filename),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import semver from "semver"
|
||||||
import path, { join } from "path"
|
import path, { join } from "path"
|
||||||
import { ObjectStoreBuckets } from "../../constants"
|
import { ObjectStoreBuckets } from "../../constants"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
|
@ -183,3 +184,19 @@ export async function revertClientLibrary(appId: string) {
|
||||||
|
|
||||||
return JSON.parse(await manifestSrc)
|
return JSON.parse(await manifestSrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shouldServeLocally(version: string) {
|
||||||
|
if (env.isProd() || !env.isDev()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version === "0.0.0") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedSemver = semver.parse(version)
|
||||||
|
if (parsedSemver?.build?.[0] === "local") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -261,6 +261,7 @@ export type UpdatedRowEventEmitter = {
|
||||||
oldRow: Row
|
oldRow: Row
|
||||||
table: Table
|
table: Table
|
||||||
appId: string
|
appId: string
|
||||||
|
user: User
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum LoopStepType {
|
export enum LoopStepType {
|
||||||
|
|
|
@ -68,6 +68,16 @@ export interface User extends Document {
|
||||||
appSort?: string
|
appSort?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UserBindings extends Document {
|
||||||
|
firstName?: string
|
||||||
|
lastName?: string
|
||||||
|
email?: string
|
||||||
|
status?: string
|
||||||
|
roleId?: string | null
|
||||||
|
globalId?: string
|
||||||
|
userId?: string
|
||||||
|
}
|
||||||
|
|
||||||
export enum UserStatus {
|
export enum UserStatus {
|
||||||
ACTIVE = "active",
|
ACTIVE = "active",
|
||||||
INACTIVE = "inactive",
|
INACTIVE = "inactive",
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
import { Automation, AutomationMetadata, Row } from "../../documents"
|
import {
|
||||||
|
Automation,
|
||||||
|
AutomationMetadata,
|
||||||
|
Row,
|
||||||
|
UserBindings,
|
||||||
|
} from "../../documents"
|
||||||
import { Job } from "bull"
|
import { Job } from "bull"
|
||||||
|
|
||||||
export interface AutomationDataEvent {
|
export interface AutomationDataEvent {
|
||||||
|
@ -8,6 +13,7 @@ export interface AutomationDataEvent {
|
||||||
timeout?: number
|
timeout?: number
|
||||||
row?: Row
|
row?: Row
|
||||||
oldRow?: Row
|
oldRow?: Row
|
||||||
|
user?: UserBindings
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutomationData {
|
export interface AutomationData {
|
||||||
|
|
Loading…
Reference in New Issue