From 76652ddab55cb59713a0316a33e2dba6d1f301b9 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 30 Jul 2024 15:07:34 +0100 Subject: [PATCH 1/4] Fixes some issues with row actions which were allowing them to be added from the automation section (which is not allowed) as well as breaking app access once they were added - this hides them properly so they can't be added as well as fixing the issue when they exist. --- .../AutomationPanel/AutomationPanel.svelte | 2 +- .../server/src/api/controllers/automation.ts | 9 ++++++--- packages/server/src/automations/utils.ts | 20 +++++++++++++++---- .../server/src/sdk/app/automations/crud.ts | 8 ++++---- .../server/src/sdk/app/automations/utils.ts | 7 ++++--- .../types/src/documents/app/automation.ts | 4 +--- 6 files changed, 32 insertions(+), 18 deletions(-) diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte index e017e6a26a..65a48a59f0 100644 --- a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte @@ -20,7 +20,7 @@ .map(automation => ({ ...automation, displayName: - $automationStore.automationDisplayData[automation._id].displayName || + $automationStore.automationDisplayData[automation._id]?.displayName || automation.name, })) .sort((a, b) => { diff --git a/packages/server/src/api/controllers/automation.ts b/packages/server/src/api/controllers/automation.ts index 6177868303..f2b9428f69 100644 --- a/packages/server/src/api/controllers/automation.ts +++ b/packages/server/src/api/controllers/automation.ts @@ -1,7 +1,10 @@ import * as triggers from "../../automations/triggers" import { sdk as coreSdk } from "@budibase/shared-core" import { DocumentType } from "../../db/utils" -import { updateTestHistory, removeDeprecated } from "../../automations/utils" +import { + updateTestHistory, + removeInvalidDefinitions, +} from "../../automations/utils" import { setTestFlag, clearTestFlag } from "../../utilities/redis" import { context, cache, events, db as dbCore } from "@budibase/backend-core" import { automations, features } from "@budibase/pro" @@ -20,11 +23,11 @@ import { builderSocket } from "../../websockets" import env from "../../environment" async function getActionDefinitions() { - return removeDeprecated(await actionDefs()) + return removeInvalidDefinitions(await actionDefs()) } function getTriggerDefinitions() { - return removeDeprecated(triggers.TRIGGER_DEFINITIONS) + return removeInvalidDefinitions(triggers.TRIGGER_DEFINITIONS) } /************************* diff --git a/packages/server/src/automations/utils.ts b/packages/server/src/automations/utils.ts index c75cc5e8dc..e7f3dad225 100644 --- a/packages/server/src/automations/utils.ts +++ b/packages/server/src/automations/utils.ts @@ -3,11 +3,17 @@ import { definitions } from "./triggerInfo" import { automationQueue } from "./bullboard" import { updateEntityMetadata } from "../utilities" import { MetadataTypes } from "../constants" -import { db as dbCore, context, utils } from "@budibase/backend-core" +import { context, db as dbCore, utils } from "@budibase/backend-core" import { getAutomationMetadataParams } from "../db/utils" import { cloneDeep } from "lodash/fp" import { quotas } from "@budibase/pro" -import { Automation, AutomationJob } from "@budibase/types" +import { + Automation, + AutomationActionStepId, + AutomationJob, + AutomationStepSchema, + AutomationTriggerStepId, +} from "@budibase/types" import { automationsEnabled } from "../features" import { helpers, REBOOT_CRON } from "@budibase/shared-core" import tracer from "dd-trace" @@ -111,10 +117,16 @@ export async function updateTestHistory( ) } -export function removeDeprecated(definitions: any) { +export function removeInvalidDefinitions( + definitions: Record +) { + const disallowedStepIds: ( + | AutomationTriggerStepId + | AutomationActionStepId + )[] = [AutomationTriggerStepId.ROW_ACTION] const base = cloneDeep(definitions) for (let key of Object.keys(base)) { - if (base[key].deprecated) { + if (base[key].deprecated || disallowedStepIds.includes(base[key].stepId)) { delete base[key] } } diff --git a/packages/server/src/sdk/app/automations/crud.ts b/packages/server/src/sdk/app/automations/crud.ts index 2b36e32397..3888e6882a 100644 --- a/packages/server/src/sdk/app/automations/crud.ts +++ b/packages/server/src/sdk/app/automations/crud.ts @@ -87,10 +87,10 @@ export async function fetch() { include_docs: true, }) ) - return response.rows - .map(row => row.doc) - .filter(doc => !!doc) - .map(trimUnexpectedObjectFields) + const automations: PersistedAutomation[] = response.rows + .filter(row => !!row.doc) + .map(row => row.doc!) + return automations.map(trimUnexpectedObjectFields) } export async function get(automationId: string) { diff --git a/packages/server/src/sdk/app/automations/utils.ts b/packages/server/src/sdk/app/automations/utils.ts index e89006d618..5d057697ca 100644 --- a/packages/server/src/sdk/app/automations/utils.ts +++ b/packages/server/src/sdk/app/automations/utils.ts @@ -29,8 +29,7 @@ export async function getBuilderData( const rowActionNameCache: Record = {} async function getRowActionName(tableId: string, rowActionId: string) { if (!rowActionNameCache[tableId]) { - const rowActions = await sdk.rowActions.get(tableId) - rowActionNameCache[tableId] = rowActions + rowActionNameCache[tableId] = await sdk.rowActions.get(tableId) } return rowActionNameCache[tableId].actions[rowActionId]?.name @@ -45,9 +44,11 @@ export async function getBuilderData( } const { tableId, rowActionId } = automation.definition.trigger.inputs + if (!tableId || !rowActionId) { + continue + } const tableName = await getTableName(tableId) - const rowActionName = await getRowActionName(tableId, rowActionId) result[automation._id!] = { diff --git a/packages/types/src/documents/app/automation.ts b/packages/types/src/documents/app/automation.ts index b53895e57b..d5d7fe667c 100644 --- a/packages/types/src/documents/app/automation.ts +++ b/packages/types/src/documents/app/automation.ts @@ -174,9 +174,7 @@ export interface AutomationStepSchema { deprecated?: boolean stepId: AutomationTriggerStepId | AutomationActionStepId blockToLoop?: string - inputs: { - [key: string]: any - } + inputs: Record schema: { inputs: InputOutputBlock outputs: InputOutputBlock From 7a68db4274d5461f4eb22f4dc46496fba5fdd2cb Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 30 Jul 2024 15:33:43 +0100 Subject: [PATCH 2/4] Fix test to remove invalid definitions. --- packages/server/src/api/routes/tests/automation.spec.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/routes/tests/automation.spec.ts b/packages/server/src/api/routes/tests/automation.spec.ts index 990828dcde..f420c57cf7 100644 --- a/packages/server/src/api/routes/tests/automation.spec.ts +++ b/packages/server/src/api/routes/tests/automation.spec.ts @@ -14,6 +14,7 @@ import sdk from "../../../sdk" import { Automation, FieldType, Table } from "@budibase/types" import { mocks } from "@budibase/backend-core/tests" import { FilterConditions } from "../../../automations/steps/filter" +import { removeInvalidDefinitions } from "../../../automations/utils" const MAX_RETRIES = 4 let { @@ -69,14 +70,15 @@ describe("/automations", () => { .expect("Content-Type", /json/) .expect(200) - let definitionsLength = Object.keys(BUILTIN_ACTION_DEFINITIONS).length - definitionsLength-- // OUTGOING_WEBHOOK is deprecated + let definitionsLength = Object.keys( + removeInvalidDefinitions(BUILTIN_ACTION_DEFINITIONS) + ).length expect(Object.keys(res.body.action).length).toBeGreaterThanOrEqual( definitionsLength ) expect(Object.keys(res.body.trigger).length).toEqual( - Object.keys(TRIGGER_DEFINITIONS).length + Object.keys(removeInvalidDefinitions(TRIGGER_DEFINITIONS)).length ) }) }) From 8f7a88ce862e86f96469cff1bb5c8b07a55c3ad2 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 30 Jul 2024 16:04:33 +0100 Subject: [PATCH 3/4] Moving logic to frontend - definitions are returned unless they are deprecated, frontend decides which it can use to create. --- .../CreateAutomationModal.svelte | 4 +- .../grid/GridCreateAutomationButton.svelte | 2 +- .../builder/src/stores/builder/automations.js | 37 ++++++++++++++----- .../server/src/api/controllers/automation.ts | 9 ++--- .../src/api/routes/tests/automation.spec.ts | 6 +-- packages/server/src/automations/utils.ts | 8 +--- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte index 41799cd7f3..365d3d358f 100644 --- a/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte @@ -21,7 +21,9 @@ $: nameError = nameTouched && !name ? "Please specify a name for the automation." : null - $: triggers = Object.entries($automationStore.blockDefinitions.TRIGGER) + $: triggers = Object.entries( + $automationStore.blockDefinitions.CREATABLE_TRIGGER + ) async function createAutomation() { try { diff --git a/packages/builder/src/components/backend/DataTable/buttons/grid/GridCreateAutomationButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/grid/GridCreateAutomationButton.svelte index 8e3d90be41..148db7554c 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/grid/GridCreateAutomationButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/grid/GridCreateAutomationButton.svelte @@ -13,7 +13,7 @@ const { datasource } = getContext("grid") - $: triggers = $automationStore.blockDefinitions.TRIGGER + $: triggers = $automationStore.blockDefinitions.CREATABLE_TRIGGER $: table = $tables.list.find(table => table._id === $datasource.tableId) diff --git a/packages/builder/src/stores/builder/automations.js b/packages/builder/src/stores/builder/automations.js index cab8090424..fdb0991911 100644 --- a/packages/builder/src/stores/builder/automations.js +++ b/packages/builder/src/stores/builder/automations.js @@ -5,14 +5,16 @@ import { generate } from "shortid" import { createHistoryStore } from "stores/builder/history" import { notifications } from "@budibase/bbui" import { updateReferencesInObject } from "dataBinding" +import { AutomationTriggerStepId } from "@budibase/types" const initialAutomationState = { automations: [], testResults: null, showTestPanel: false, blockDefinitions: { - TRIGGER: [], - ACTION: [], + TRIGGER: {}, + CREATABLE_TRIGGER: {}, + ACTION: {}, }, selectedAutomationId: null, automationDisplayData: {}, @@ -46,14 +48,29 @@ const updateStepReferences = (steps, modifiedIndex, action) => { }) } +const getFinalDefinitions = (triggers, actions) => { + const creatable = {} + Object.entries(triggers).forEach(entry => { + if (entry[0] === AutomationTriggerStepId.ROW_ACTION) { + return + } + creatable[entry[0]] = entry[1] + }) + return { + TRIGGER: triggers, + CREATABLE_TRIGGER: creatable, + ACTION: actions, + } +} + const automationActions = store => ({ definitions: async () => { const response = await API.getAutomationDefinitions() store.update(state => { - state.blockDefinitions = { - TRIGGER: response.trigger, - ACTION: response.action, - } + state.blockDefinitions = getFinalDefinitions( + response.trigger, + response.action + ) return state }) return response @@ -69,10 +86,10 @@ const automationActions = store => ({ return a.name < b.name ? -1 : 1 }) state.automationDisplayData = automationResponse.builderData - state.blockDefinitions = { - TRIGGER: definitions.trigger, - ACTION: definitions.action, - } + state.blockDefinitions = getFinalDefinitions( + definitions.trigger, + definitions.action + ) return state }) }, diff --git a/packages/server/src/api/controllers/automation.ts b/packages/server/src/api/controllers/automation.ts index f2b9428f69..6177868303 100644 --- a/packages/server/src/api/controllers/automation.ts +++ b/packages/server/src/api/controllers/automation.ts @@ -1,10 +1,7 @@ import * as triggers from "../../automations/triggers" import { sdk as coreSdk } from "@budibase/shared-core" import { DocumentType } from "../../db/utils" -import { - updateTestHistory, - removeInvalidDefinitions, -} from "../../automations/utils" +import { updateTestHistory, removeDeprecated } from "../../automations/utils" import { setTestFlag, clearTestFlag } from "../../utilities/redis" import { context, cache, events, db as dbCore } from "@budibase/backend-core" import { automations, features } from "@budibase/pro" @@ -23,11 +20,11 @@ import { builderSocket } from "../../websockets" import env from "../../environment" async function getActionDefinitions() { - return removeInvalidDefinitions(await actionDefs()) + return removeDeprecated(await actionDefs()) } function getTriggerDefinitions() { - return removeInvalidDefinitions(triggers.TRIGGER_DEFINITIONS) + return removeDeprecated(triggers.TRIGGER_DEFINITIONS) } /************************* diff --git a/packages/server/src/api/routes/tests/automation.spec.ts b/packages/server/src/api/routes/tests/automation.spec.ts index f420c57cf7..d9d48ede38 100644 --- a/packages/server/src/api/routes/tests/automation.spec.ts +++ b/packages/server/src/api/routes/tests/automation.spec.ts @@ -14,7 +14,7 @@ import sdk from "../../../sdk" import { Automation, FieldType, Table } from "@budibase/types" import { mocks } from "@budibase/backend-core/tests" import { FilterConditions } from "../../../automations/steps/filter" -import { removeInvalidDefinitions } from "../../../automations/utils" +import { removeDeprecated } from "../../../automations/utils" const MAX_RETRIES = 4 let { @@ -71,14 +71,14 @@ describe("/automations", () => { .expect(200) let definitionsLength = Object.keys( - removeInvalidDefinitions(BUILTIN_ACTION_DEFINITIONS) + removeDeprecated(BUILTIN_ACTION_DEFINITIONS) ).length expect(Object.keys(res.body.action).length).toBeGreaterThanOrEqual( definitionsLength ) expect(Object.keys(res.body.trigger).length).toEqual( - Object.keys(removeInvalidDefinitions(TRIGGER_DEFINITIONS)).length + Object.keys(removeDeprecated(TRIGGER_DEFINITIONS)).length ) }) }) diff --git a/packages/server/src/automations/utils.ts b/packages/server/src/automations/utils.ts index e7f3dad225..775fdfe7fb 100644 --- a/packages/server/src/automations/utils.ts +++ b/packages/server/src/automations/utils.ts @@ -117,16 +117,12 @@ export async function updateTestHistory( ) } -export function removeInvalidDefinitions( +export function removeDeprecated( definitions: Record ) { - const disallowedStepIds: ( - | AutomationTriggerStepId - | AutomationActionStepId - )[] = [AutomationTriggerStepId.ROW_ACTION] const base = cloneDeep(definitions) for (let key of Object.keys(base)) { - if (base[key].deprecated || disallowedStepIds.includes(base[key].stepId)) { + if (base[key].deprecated) { delete base[key] } } From 8a7e0793d479203f95d069b9de85ce33539d8ab4 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 30 Jul 2024 16:07:09 +0100 Subject: [PATCH 4/4] Linting. --- packages/server/src/automations/utils.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/server/src/automations/utils.ts b/packages/server/src/automations/utils.ts index 775fdfe7fb..93b8f907fd 100644 --- a/packages/server/src/automations/utils.ts +++ b/packages/server/src/automations/utils.ts @@ -9,10 +9,8 @@ import { cloneDeep } from "lodash/fp" import { quotas } from "@budibase/pro" import { Automation, - AutomationActionStepId, AutomationJob, AutomationStepSchema, - AutomationTriggerStepId, } from "@budibase/types" import { automationsEnabled } from "../features" import { helpers, REBOOT_CRON } from "@budibase/shared-core"