From 677880c633684e9adc66a770cd421c884df80d2e Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sun, 4 Dec 2022 16:47:24 +0100 Subject: [PATCH 01/64] feat(telegram-bot): add application --- .../src/apps/telegram-bot/assets/favicon.svg | 14 ++++++++++++++ packages/backend/src/apps/telegram-bot/index.d.ts | 0 packages/backend/src/apps/telegram-bot/index.ts | 15 +++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 packages/backend/src/apps/telegram-bot/assets/favicon.svg create mode 100644 packages/backend/src/apps/telegram-bot/index.d.ts create mode 100644 packages/backend/src/apps/telegram-bot/index.ts diff --git a/packages/backend/src/apps/telegram-bot/assets/favicon.svg b/packages/backend/src/apps/telegram-bot/assets/favicon.svg new file mode 100644 index 0000000..8f16fb1 --- /dev/null +++ b/packages/backend/src/apps/telegram-bot/assets/favicon.svg @@ -0,0 +1,14 @@ + + + Telegram + + + + + + + + + + + \ No newline at end of file diff --git a/packages/backend/src/apps/telegram-bot/index.d.ts b/packages/backend/src/apps/telegram-bot/index.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/backend/src/apps/telegram-bot/index.ts b/packages/backend/src/apps/telegram-bot/index.ts new file mode 100644 index 0000000..9f3c7db --- /dev/null +++ b/packages/backend/src/apps/telegram-bot/index.ts @@ -0,0 +1,15 @@ +import defineApp from '../../helpers/define-app'; +import addAuthHeader from './common/add-auth-header'; +import auth from './auth'; +import actions from './actions'; + +export default defineApp({ + name: 'Telegram', + key: 'telegram-bot', + iconUrl: '{BASE_URL}/apps/telegram-bot/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/telegram-bot/connection', + supportsConnections: true, + baseUrl: 'https://telegram.org', + apiBaseUrl: 'https://api.telegram.org', + primaryColor: '2AABEE', +}); From 39ac3ff4c205274f58a02f77652b380b619ba6aa Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sun, 4 Dec 2022 16:49:13 +0100 Subject: [PATCH 02/64] feat(telegram-bot): add authentication support --- .../src/apps/telegram-bot/auth/index.ts | 21 +++++++++++++++++++ .../telegram-bot/auth/is-still-verified.ts | 9 ++++++++ .../telegram-bot/auth/verify-credentials.ts | 12 +++++++++++ .../telegram-bot/common/add-auth-header.ts | 13 ++++++++++++ .../backend/src/apps/telegram-bot/index.ts | 2 ++ 5 files changed, 57 insertions(+) create mode 100644 packages/backend/src/apps/telegram-bot/auth/index.ts create mode 100644 packages/backend/src/apps/telegram-bot/auth/is-still-verified.ts create mode 100644 packages/backend/src/apps/telegram-bot/auth/verify-credentials.ts create mode 100644 packages/backend/src/apps/telegram-bot/common/add-auth-header.ts diff --git a/packages/backend/src/apps/telegram-bot/auth/index.ts b/packages/backend/src/apps/telegram-bot/auth/index.ts new file mode 100644 index 0000000..01e68c2 --- /dev/null +++ b/packages/backend/src/apps/telegram-bot/auth/index.ts @@ -0,0 +1,21 @@ +import verifyCredentials from './verify-credentials'; +import isStillVerified from './is-still-verified'; + +export default { + fields: [ + { + key: 'token', + label: 'Bot token', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: 'Bot token which should be retrieved from @botfather.', + clickToCopy: false, + }, + ], + + verifyCredentials, + isStillVerified, +}; diff --git a/packages/backend/src/apps/telegram-bot/auth/is-still-verified.ts b/packages/backend/src/apps/telegram-bot/auth/is-still-verified.ts new file mode 100644 index 0000000..66bb963 --- /dev/null +++ b/packages/backend/src/apps/telegram-bot/auth/is-still-verified.ts @@ -0,0 +1,9 @@ +import { IGlobalVariable } from '@automatisch/types'; +import verifyCredentials from './verify-credentials'; + +const isStillVerified = async ($: IGlobalVariable) => { + await verifyCredentials($); + return true; +}; + +export default isStillVerified; diff --git a/packages/backend/src/apps/telegram-bot/auth/verify-credentials.ts b/packages/backend/src/apps/telegram-bot/auth/verify-credentials.ts new file mode 100644 index 0000000..17bbfa9 --- /dev/null +++ b/packages/backend/src/apps/telegram-bot/auth/verify-credentials.ts @@ -0,0 +1,12 @@ +import { IGlobalVariable } from '@automatisch/types'; + +const verifyCredentials = async ($: IGlobalVariable) => { + const { data } = await $.http.get('/getMe'); + const { result: me } = data; + + await $.auth.set({ + screenName: me.first_name, + }); +}; + +export default verifyCredentials; diff --git a/packages/backend/src/apps/telegram-bot/common/add-auth-header.ts b/packages/backend/src/apps/telegram-bot/common/add-auth-header.ts new file mode 100644 index 0000000..aa17b14 --- /dev/null +++ b/packages/backend/src/apps/telegram-bot/common/add-auth-header.ts @@ -0,0 +1,13 @@ +import { TBeforeRequest } from '@automatisch/types'; +import { URL } from 'node:url'; + +const addAuthHeader: TBeforeRequest = ($, requestConfig) => { + if ($.auth.data?.token) { + const token = $.auth.data.token as string; + requestConfig.baseURL = (new URL(`/bot${token}`, requestConfig.baseURL)).toString(); + } + + return requestConfig; +}; + +export default addAuthHeader; diff --git a/packages/backend/src/apps/telegram-bot/index.ts b/packages/backend/src/apps/telegram-bot/index.ts index 9f3c7db..e57aecb 100644 --- a/packages/backend/src/apps/telegram-bot/index.ts +++ b/packages/backend/src/apps/telegram-bot/index.ts @@ -12,4 +12,6 @@ export default defineApp({ baseUrl: 'https://telegram.org', apiBaseUrl: 'https://api.telegram.org', primaryColor: '2AABEE', + beforeRequest: [addAuthHeader], + auth, }); From 8c343abac5970fc975aac4100c338a17a96ba2b1 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sun, 4 Dec 2022 16:49:30 +0100 Subject: [PATCH 03/64] feat(telegram-bot): add send message action --- .../src/apps/telegram-bot/actions/index.ts | 3 + .../actions/send-message/index.ts | 59 +++++++++++++++++++ .../backend/src/apps/telegram-bot/index.ts | 1 + 3 files changed, 63 insertions(+) create mode 100644 packages/backend/src/apps/telegram-bot/actions/index.ts create mode 100644 packages/backend/src/apps/telegram-bot/actions/send-message/index.ts diff --git a/packages/backend/src/apps/telegram-bot/actions/index.ts b/packages/backend/src/apps/telegram-bot/actions/index.ts new file mode 100644 index 0000000..37aeb33 --- /dev/null +++ b/packages/backend/src/apps/telegram-bot/actions/index.ts @@ -0,0 +1,3 @@ +import sendMessage from './send-message'; + +export default [sendMessage]; diff --git a/packages/backend/src/apps/telegram-bot/actions/send-message/index.ts b/packages/backend/src/apps/telegram-bot/actions/send-message/index.ts new file mode 100644 index 0000000..5d884cb --- /dev/null +++ b/packages/backend/src/apps/telegram-bot/actions/send-message/index.ts @@ -0,0 +1,59 @@ +import qs from 'qs'; +import defineAction from '../../../../helpers/define-action'; + +export default defineAction({ + name: 'Send message', + key: 'sendMessage', + description: 'Sends a message to a chat you specify.', + arguments: [ + { + label: 'Chat ID', + key: 'chatId', + type: 'string' as const, + required: true, + description: 'Unique identifier for the target chat or username of the target channel (in the format @channelusername).', + variables: true, + }, + { + label: 'Message text', + key: 'text', + type: 'string' as const, + required: true, + description: 'Text of the message to be sent, 1-4096 characters.', + variables: true, + }, + { + label: 'Disable notification?', + key: 'disableNotification', + type: 'dropdown' as const, + required: false, + value: false, + description: 'Sends the message silently. Users will receive a notification with no sound.', + variables: false, + options: [ + { + label: 'Yes', + value: true, + }, + { + label: 'No', + value: false, + }, + ], + }, + ], + + async run($) { + const payload = { + chat_id: $.step.parameters.chatId, + text: $.step.parameters.text, + disable_notification: $.step.parameters.disableNotification, + }; + + const response = await $.http.post('/sendMessage', payload); + + $.setActionItem({ + raw: response.data, + }); + }, +}); diff --git a/packages/backend/src/apps/telegram-bot/index.ts b/packages/backend/src/apps/telegram-bot/index.ts index e57aecb..364e01d 100644 --- a/packages/backend/src/apps/telegram-bot/index.ts +++ b/packages/backend/src/apps/telegram-bot/index.ts @@ -14,4 +14,5 @@ export default defineApp({ primaryColor: '2AABEE', beforeRequest: [addAuthHeader], auth, + actions, }); From 2e4ecfab163350185da1e6c434bb1ca771fcb508 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sun, 4 Dec 2022 17:27:19 +0100 Subject: [PATCH 04/64] docs(telegram-bot): describe actions and auth --- packages/docs/pages/.vitepress/config.js | 8 ++++++++ packages/docs/pages/apps/telegram-bot/actions.md | 12 ++++++++++++ .../docs/pages/apps/telegram-bot/connection.md | 14 ++++++++++++++ .../docs/pages/public/favicons/telegram-bot.svg | 14 ++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 packages/docs/pages/apps/telegram-bot/actions.md create mode 100644 packages/docs/pages/apps/telegram-bot/connection.md create mode 100644 packages/docs/pages/public/favicons/telegram-bot.svg diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 1841d88..912ef91 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -123,6 +123,14 @@ export default defineConfig({ { text: 'Connection', link: '/apps/stripe/connection' }, ], }, + { + text: 'Telegram', + collapsible: true, + items: [ + { text: 'Actions', link: '/apps/telegram-bot/actions' }, + { text: 'Connection', link: '/apps/telegram-bot/connection' }, + ], + }, { text: 'Twilio', collapsible: true, diff --git a/packages/docs/pages/apps/telegram-bot/actions.md b/packages/docs/pages/apps/telegram-bot/actions.md new file mode 100644 index 0000000..261d241 --- /dev/null +++ b/packages/docs/pages/apps/telegram-bot/actions.md @@ -0,0 +1,12 @@ +--- +favicon: /favicons/telegram-bot.svg +items: + - name: Send a message + desc: Sends a message to a chat you specify. +--- + + + + diff --git a/packages/docs/pages/apps/telegram-bot/connection.md b/packages/docs/pages/apps/telegram-bot/connection.md new file mode 100644 index 0000000..4a015cc --- /dev/null +++ b/packages/docs/pages/apps/telegram-bot/connection.md @@ -0,0 +1,14 @@ +# Telegram + +:::info +This page explains the steps you need to follow to set up the Telegram +connection in Automatisch. If any of the steps are outdated, please let us know! +::: + +1. Start a chat with [Botfather](https://telegram.me/BotFather). +1. Enter `/newbot`. +1. Enter a name for your bot. +1. Enter a username for your bot. +1. Copy the **token** value from the answer to the **Bot token** field on Automatisch. +1. Click **Submit** button on Automatisch. +1. Congrats! Start using your new Telegram connection within the flows. diff --git a/packages/docs/pages/public/favicons/telegram-bot.svg b/packages/docs/pages/public/favicons/telegram-bot.svg new file mode 100644 index 0000000..8f16fb1 --- /dev/null +++ b/packages/docs/pages/public/favicons/telegram-bot.svg @@ -0,0 +1,14 @@ + + + Telegram + + + + + + + + + + + \ No newline at end of file From e451dd2262351201630db70325438b59ec9e5694 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sun, 4 Dec 2022 21:16:16 +0100 Subject: [PATCH 05/64] fix(ControlledAutocomplete): use option value as option key --- packages/web/src/components/ControlledAutocomplete/index.tsx | 5 +++++ packages/web/src/components/Editor/index.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/web/src/components/ControlledAutocomplete/index.tsx b/packages/web/src/components/ControlledAutocomplete/index.tsx index d3f2905..198ff39 100644 --- a/packages/web/src/components/ControlledAutocomplete/index.tsx +++ b/packages/web/src/components/ControlledAutocomplete/index.tsx @@ -96,6 +96,11 @@ function ControlledAutocomplete( }} ref={ref} data-test={`${name}-autocomplete`} + renderOption={(optionProps, option) => ( +
  • + {option.label} +
  • + )} /> {flow?.steps?.map((step, index, steps) => ( - + Date: Sun, 4 Dec 2022 21:24:19 +0100 Subject: [PATCH 06/64] fix(AppRow): use app key for links instead of name --- packages/web/src/components/AppRow/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web/src/components/AppRow/index.tsx b/packages/web/src/components/AppRow/index.tsx index f059c6c..0ac728d 100644 --- a/packages/web/src/components/AppRow/index.tsx +++ b/packages/web/src/components/AppRow/index.tsx @@ -25,11 +25,11 @@ const countTranslation = (value: React.ReactNode) => ( function AppRow(props: AppRowProps): React.ReactElement { const formatMessage = useFormatMessage(); - const { name, primaryColor, iconUrl, connectionCount, flowCount } = + const { name, key, primaryColor, iconUrl, connectionCount, flowCount } = props.application; return ( - + From 14a8551e82454fa311447456d797ff1198b4a482 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sun, 4 Dec 2022 21:26:11 +0100 Subject: [PATCH 07/64] docs: add typeform and telegram in available apps --- packages/docs/pages/guide/available-apps.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md index 5697771..545a174 100644 --- a/packages/docs/pages/guide/available-apps.md +++ b/packages/docs/pages/guide/available-apps.md @@ -16,5 +16,7 @@ Following integrations are currently supported by Automatisch. - [Slack](/apps/slack/actions) - [SMTP](/apps/smtp/actions) - [Stripe](/apps/stripe/triggers) +- [Telegram](/apps/telegram-bot/triggers) - [Twilio](/apps/twilio/triggers) - [Twitter](/apps/twitter/triggers) +- [Typeform](/apps/typeform/triggers) From 4ab76e7507ecea7f68802066f6046db10bb3998a Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sun, 4 Dec 2022 22:33:28 +0100 Subject: [PATCH 08/64] feat(FlowSubstep): show autocomplete option value --- .../components/ControlledAutocomplete/index.tsx | 17 ++++++++++++++--- .../web/src/components/FlowSubstep/index.tsx | 1 + .../web/src/components/InputCreator/index.tsx | 12 +++++++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/web/src/components/ControlledAutocomplete/index.tsx b/packages/web/src/components/ControlledAutocomplete/index.tsx index 198ff39..c209afa 100644 --- a/packages/web/src/components/ControlledAutocomplete/index.tsx +++ b/packages/web/src/components/ControlledAutocomplete/index.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; -import FormHelperText from '@mui/material/FormHelperText'; import { Controller, useFormContext } from 'react-hook-form'; +import FormHelperText from '@mui/material/FormHelperText'; import Autocomplete, { AutocompleteProps } from '@mui/material/Autocomplete'; +import Typography from '@mui/material/Typography'; import type { IFieldDropdownOption } from '@automatisch/types'; interface ControlledAutocompleteProps @@ -9,6 +10,7 @@ interface ControlledAutocompleteProps shouldUnregister?: boolean; name: string; required?: boolean; + showOptionValue?: boolean; description?: string; dependsOn?: string[]; } @@ -31,6 +33,7 @@ function ControlledAutocomplete( description, options = [], dependsOn = [], + showOptionValue, ...autocompleteProps } = props; @@ -97,8 +100,16 @@ function ControlledAutocomplete( ref={ref} data-test={`${name}-autocomplete`} renderOption={(optionProps, option) => ( -
  • - {option.label} +
  • + {option.label} + + {showOptionValue && ( + {option.value} + )}
  • )} /> diff --git a/packages/web/src/components/FlowSubstep/index.tsx b/packages/web/src/components/FlowSubstep/index.tsx index c0aa1c2..cd9c0c2 100644 --- a/packages/web/src/components/FlowSubstep/index.tsx +++ b/packages/web/src/components/FlowSubstep/index.tsx @@ -94,6 +94,7 @@ function FlowSubstep(props: FlowSubstepProps): React.ReactElement { namePrefix="parameters" stepId={step.id} disabled={editorContext.readOnly} + showOptionValue={true} /> ))} diff --git a/packages/web/src/components/InputCreator/index.tsx b/packages/web/src/components/InputCreator/index.tsx index 0115816..f54d331 100644 --- a/packages/web/src/components/InputCreator/index.tsx +++ b/packages/web/src/components/InputCreator/index.tsx @@ -14,6 +14,7 @@ type InputCreatorProps = { namePrefix?: string; stepId?: string; disabled?: boolean; + showOptionValue?: boolean; }; type RawOption = { @@ -27,7 +28,15 @@ const optionGenerator = (options: RawOption[]): IFieldDropdownOption[] => export default function InputCreator( props: InputCreatorProps ): React.ReactElement { - const { onChange, onBlur, schema, namePrefix, stepId, disabled } = props; + const { + onChange, + onBlur, + schema, + namePrefix, + stepId, + disabled, + showOptionValue, + } = props; const { key: name, @@ -62,6 +71,7 @@ export default function InputCreator( description={description} loading={loading} disabled={disabled} + showOptionValue={showOptionValue} /> ); } From 46bfc597ec28999a931f858ac64bae82da8a91d6 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Mon, 5 Dec 2022 00:44:25 +0100 Subject: [PATCH 09/64] feat(ntfy): add application --- packages/backend/src/apps/ntfy/assets/favicon.svg | 1 + packages/backend/src/apps/ntfy/index.d.ts | 0 packages/backend/src/apps/ntfy/index.ts | 13 +++++++++++++ 3 files changed, 14 insertions(+) create mode 100644 packages/backend/src/apps/ntfy/assets/favicon.svg create mode 100644 packages/backend/src/apps/ntfy/index.d.ts create mode 100644 packages/backend/src/apps/ntfy/index.ts diff --git a/packages/backend/src/apps/ntfy/assets/favicon.svg b/packages/backend/src/apps/ntfy/assets/favicon.svg new file mode 100644 index 0000000..9e5b513 --- /dev/null +++ b/packages/backend/src/apps/ntfy/assets/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/backend/src/apps/ntfy/index.d.ts b/packages/backend/src/apps/ntfy/index.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/backend/src/apps/ntfy/index.ts b/packages/backend/src/apps/ntfy/index.ts new file mode 100644 index 0000000..b831828 --- /dev/null +++ b/packages/backend/src/apps/ntfy/index.ts @@ -0,0 +1,13 @@ +import defineApp from '../../helpers/define-app'; +import addAuthHeader from './common/add-auth-header'; + +export default defineApp({ + name: 'Ntfy', + key: 'ntfy', + iconUrl: '{BASE_URL}/apps/ntfy/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/ntfy/connection', + supportsConnections: true, + baseUrl: 'https://ntfy.sh', + apiBaseUrl: 'https://ntfy.sh', + primaryColor: '56bda8', +}); From 6995323a45a3dff56364d0317c1c43807ff0ca80 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Mon, 5 Dec 2022 00:45:02 +0100 Subject: [PATCH 10/64] feat(ntfy): add auth support --- packages/backend/src/apps/ntfy/auth/index.ts | 39 +++++++++++++++++++ .../src/apps/ntfy/auth/is-still-verified.ts | 9 +++++ .../src/apps/ntfy/auth/verify-credentials.ts | 16 ++++++++ .../src/apps/ntfy/common/add-auth-header.ts | 18 +++++++++ packages/backend/src/apps/ntfy/index.ts | 3 ++ 5 files changed, 85 insertions(+) create mode 100644 packages/backend/src/apps/ntfy/auth/index.ts create mode 100644 packages/backend/src/apps/ntfy/auth/is-still-verified.ts create mode 100644 packages/backend/src/apps/ntfy/auth/verify-credentials.ts create mode 100644 packages/backend/src/apps/ntfy/common/add-auth-header.ts diff --git a/packages/backend/src/apps/ntfy/auth/index.ts b/packages/backend/src/apps/ntfy/auth/index.ts new file mode 100644 index 0000000..5a96d5b --- /dev/null +++ b/packages/backend/src/apps/ntfy/auth/index.ts @@ -0,0 +1,39 @@ +import verifyCredentials from './verify-credentials'; +import isStillVerified from './is-still-verified'; + +export default { + fields: [ + { + key: 'serverUrl', + label: 'Server URL', + type: 'string' as const, + required: true, + readOnly: false, + value: 'https://ntfy.sh', + placeholder: null, + description: 'ntfy server to use.', + clickToCopy: false, + }, + { + key: 'username', + label: 'Username', + type: 'string' as const, + required: false, + readOnly: false, + placeholder: null, + clickToCopy: false, + }, + { + key: 'password', + label: 'Password', + type: 'string' as const, + required: false, + readOnly: false, + placeholder: null, + clickToCopy: false, + }, + ], + + verifyCredentials, + isStillVerified, +}; diff --git a/packages/backend/src/apps/ntfy/auth/is-still-verified.ts b/packages/backend/src/apps/ntfy/auth/is-still-verified.ts new file mode 100644 index 0000000..66bb963 --- /dev/null +++ b/packages/backend/src/apps/ntfy/auth/is-still-verified.ts @@ -0,0 +1,9 @@ +import { IGlobalVariable } from '@automatisch/types'; +import verifyCredentials from './verify-credentials'; + +const isStillVerified = async ($: IGlobalVariable) => { + await verifyCredentials($); + return true; +}; + +export default isStillVerified; diff --git a/packages/backend/src/apps/ntfy/auth/verify-credentials.ts b/packages/backend/src/apps/ntfy/auth/verify-credentials.ts new file mode 100644 index 0000000..84d1d62 --- /dev/null +++ b/packages/backend/src/apps/ntfy/auth/verify-credentials.ts @@ -0,0 +1,16 @@ +import { IGlobalVariable } from '@automatisch/types'; + +const verifyCredentials = async ($: IGlobalVariable) => { + await $.http.post('/', { topic: 'automatisch' }); + let screenName = $.auth.data.serverUrl; + + if ($.auth.data.username) { + screenName = `${$.auth.data.username} @ ${screenName}` + } + + await $.auth.set({ + screenName, + }); +}; + +export default verifyCredentials; diff --git a/packages/backend/src/apps/ntfy/common/add-auth-header.ts b/packages/backend/src/apps/ntfy/common/add-auth-header.ts new file mode 100644 index 0000000..ff19448 --- /dev/null +++ b/packages/backend/src/apps/ntfy/common/add-auth-header.ts @@ -0,0 +1,18 @@ +import { TBeforeRequest } from '@automatisch/types'; + +const addAuthHeader: TBeforeRequest = ($, requestConfig) => { + if ($.auth.data.apiBaseUrl) { + requestConfig.baseURL = $.auth.data.apiBaseUrl as string; + } + + if ($.auth.data?.username && $.auth.data?.password) { + requestConfig.auth = { + username: $.auth.data.username as string, + password: $.auth.data.password as string, + } + } + + return requestConfig; +}; + +export default addAuthHeader; diff --git a/packages/backend/src/apps/ntfy/index.ts b/packages/backend/src/apps/ntfy/index.ts index b831828..c1cddab 100644 --- a/packages/backend/src/apps/ntfy/index.ts +++ b/packages/backend/src/apps/ntfy/index.ts @@ -1,5 +1,6 @@ import defineApp from '../../helpers/define-app'; import addAuthHeader from './common/add-auth-header'; +import auth from './auth'; export default defineApp({ name: 'Ntfy', @@ -10,4 +11,6 @@ export default defineApp({ baseUrl: 'https://ntfy.sh', apiBaseUrl: 'https://ntfy.sh', primaryColor: '56bda8', + beforeRequest: [addAuthHeader], + auth, }); From e1c080f237f51fab9fc39cb7ca688384cc3ccf2d Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Mon, 5 Dec 2022 00:45:30 +0100 Subject: [PATCH 11/64] feat(ntfy): add send message action --- .../backend/src/apps/ntfy/actions/index.ts | 3 + .../apps/ntfy/actions/send-message/index.ts | 103 ++++++++++++++++++ packages/backend/src/apps/ntfy/index.ts | 2 + 3 files changed, 108 insertions(+) create mode 100644 packages/backend/src/apps/ntfy/actions/index.ts create mode 100644 packages/backend/src/apps/ntfy/actions/send-message/index.ts diff --git a/packages/backend/src/apps/ntfy/actions/index.ts b/packages/backend/src/apps/ntfy/actions/index.ts new file mode 100644 index 0000000..37aeb33 --- /dev/null +++ b/packages/backend/src/apps/ntfy/actions/index.ts @@ -0,0 +1,3 @@ +import sendMessage from './send-message'; + +export default [sendMessage]; diff --git a/packages/backend/src/apps/ntfy/actions/send-message/index.ts b/packages/backend/src/apps/ntfy/actions/send-message/index.ts new file mode 100644 index 0000000..8cc9158 --- /dev/null +++ b/packages/backend/src/apps/ntfy/actions/send-message/index.ts @@ -0,0 +1,103 @@ +import qs from 'qs'; +import defineAction from '../../../../helpers/define-action'; + +export default defineAction({ + name: 'Send message', + key: 'sendMessage', + description: 'Sends a message to a topic you specify.', + arguments: [ + { + label: 'Topic', + key: 'topic', + type: 'string' as const, + required: true, + description: 'Target topic name.', + variables: true, + }, + { + label: 'Message body', + key: 'message', + type: 'string' as const, + required: true, + description: 'Message body to be sent, set to triggered if empty or not passed.', + variables: true, + }, + { + label: 'Title', + key: 'title', + type: 'string' as const, + required: false, + description: 'Message title.', + variables: true, + }, + { + label: 'Email', + key: 'email', + type: 'string' as const, + required: false, + description: 'E-mail address for e-mail notifications.', + variables: true, + }, + { + label: 'Click URL', + key: 'click', + type: 'string' as const, + required: false, + description: 'Website opened when notification is clicked.', + variables: true, + }, + { + label: 'Attach file by URL', + key: 'attach', + type: 'string' as const, + required: false, + description: 'URL of an attachment.', + variables: true, + }, + { + label: 'Filename', + key: 'filename', + type: 'string' as const, + required: false, + description: 'File name of the attachment.', + variables: true, + }, + { + label: 'Delay', + key: 'delay', + type: 'string' as const, + required: false, + description: 'Timestamp or duration for delayed delivery. For example, 30min or 9am.', + variables: true, + }, + ], + + async run($) { + const { + topic, + message, + title, + email, + click, + attach, + filename, + delay + } = $.step.parameters; + const payload = { + topic, + message, + title, + email, + click, + attach, + filename, + delay + }; + + const response = await $.http.post('/', payload); + + $.setActionItem({ + raw: response.data, + }); + }, +}); diff --git a/packages/backend/src/apps/ntfy/index.ts b/packages/backend/src/apps/ntfy/index.ts index c1cddab..1ba2396 100644 --- a/packages/backend/src/apps/ntfy/index.ts +++ b/packages/backend/src/apps/ntfy/index.ts @@ -1,6 +1,7 @@ import defineApp from '../../helpers/define-app'; import addAuthHeader from './common/add-auth-header'; import auth from './auth'; +import actions from './actions'; export default defineApp({ name: 'Ntfy', @@ -13,4 +14,5 @@ export default defineApp({ primaryColor: '56bda8', beforeRequest: [addAuthHeader], auth, + actions, }); From 32e77de8bba009928f30467af4d79f252e3ace17 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Mon, 5 Dec 2022 00:52:13 +0100 Subject: [PATCH 12/64] docs(ntfy): describe actions and auth --- packages/docs/pages/.vitepress/config.js | 8 ++++++++ packages/docs/pages/apps/ntfy/actions.md | 12 ++++++++++++ packages/docs/pages/apps/ntfy/connection.md | 10 ++++++++++ packages/docs/pages/public/favicons/ntfy.svg | 1 + 4 files changed, 31 insertions(+) create mode 100644 packages/docs/pages/apps/ntfy/actions.md create mode 100644 packages/docs/pages/apps/ntfy/connection.md create mode 100644 packages/docs/pages/public/favicons/ntfy.svg diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 912ef91..5e207ea 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -69,6 +69,14 @@ export default defineConfig({ { text: 'Connection', link: '/apps/github/connection' }, ], }, + { + text: 'Ntfy', + collapsible: true, + items: [ + { text: 'Actions', link: '/apps/ntfy/actions' }, + { text: 'Connection', link: '/apps/ntfy/connection' }, + ], + }, { text: 'RSS', collapsible: true, diff --git a/packages/docs/pages/apps/ntfy/actions.md b/packages/docs/pages/apps/ntfy/actions.md new file mode 100644 index 0000000..efc1bfb --- /dev/null +++ b/packages/docs/pages/apps/ntfy/actions.md @@ -0,0 +1,12 @@ +--- +favicon: /favicons/ntfy.svg +items: + - name: Send a message + desc: Sends a message to a topic you specify. +--- + + + + diff --git a/packages/docs/pages/apps/ntfy/connection.md b/packages/docs/pages/apps/ntfy/connection.md new file mode 100644 index 0000000..d2d81ac --- /dev/null +++ b/packages/docs/pages/apps/ntfy/connection.md @@ -0,0 +1,10 @@ +# Ntfy + +:::info +This page explains the steps you need to follow to set up the Ntfy +connection in Automatisch. If any of the steps are outdated, please let us know! +::: + +If you use ntfy.sh, the official public server for this service, you do not need to set up a connection with a custom configuration. It's enough to create one with the default server URL. + +However, if you have a ntfy installation, that's different than ntfy.sh, you need to specify your server URL on Automatisch while creating a connection. Additionally, you may need to provide your username and password if your installation requires authentication. diff --git a/packages/docs/pages/public/favicons/ntfy.svg b/packages/docs/pages/public/favicons/ntfy.svg new file mode 100644 index 0000000..9e5b513 --- /dev/null +++ b/packages/docs/pages/public/favicons/ntfy.svg @@ -0,0 +1 @@ + \ No newline at end of file From 8300a4b6df0b36e8ad0dc198a34d6a142d6abd29 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Mon, 5 Dec 2022 09:57:42 +0100 Subject: [PATCH 13/64] docs: add ntfy in available apps --- packages/docs/pages/guide/available-apps.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md index 545a174..284f150 100644 --- a/packages/docs/pages/guide/available-apps.md +++ b/packages/docs/pages/guide/available-apps.md @@ -11,6 +11,7 @@ Following integrations are currently supported by Automatisch. - [Flickr](/apps/flickr/triggers) - [Github](/apps/github/triggers) - [RSS](/apps/rss/triggers) +- [Ntfy](/apps/ntfy/triggers) - [Salesforce](/apps/salesforce/triggers) - [Scheduler](/apps/scheduler/triggers) - [Slack](/apps/slack/actions) From c5fedda195f5f2225db24f30ddf8d207f6f0fed7 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Mon, 5 Dec 2022 23:53:57 +0100 Subject: [PATCH 14/64] feat(worker): log when workers are ready --- packages/backend/src/config/redis.ts | 2 ++ .../backend/src/helpers/check-worker-readiness.ts | 11 +++++++++++ packages/backend/src/worker.ts | 1 + 3 files changed, 14 insertions(+) create mode 100644 packages/backend/src/helpers/check-worker-readiness.ts diff --git a/packages/backend/src/config/redis.ts b/packages/backend/src/config/redis.ts index fedb5be..ea56ccd 100644 --- a/packages/backend/src/config/redis.ts +++ b/packages/backend/src/config/redis.ts @@ -6,6 +6,7 @@ type TRedisConfig = { username?: string, password?: string, tls?: Record, + enableReadyCheck?: boolean, enableOfflineQueue: boolean, } @@ -15,6 +16,7 @@ const redisConfig: TRedisConfig = { username: appConfig.redisUsername, password: appConfig.redisPassword, enableOfflineQueue: false, + enableReadyCheck: true, }; if (appConfig.redisTls) { diff --git a/packages/backend/src/helpers/check-worker-readiness.ts b/packages/backend/src/helpers/check-worker-readiness.ts new file mode 100644 index 0000000..8101192 --- /dev/null +++ b/packages/backend/src/helpers/check-worker-readiness.ts @@ -0,0 +1,11 @@ +import Redis from 'ioredis'; +import logger from './logger'; +import redisConfig from '../config/redis'; + +const redisClient = new Redis(redisConfig); + +redisClient.on('ready', () => { + logger.info(`Workers are ready!`); + + redisClient.disconnect(); +}); diff --git a/packages/backend/src/worker.ts b/packages/backend/src/worker.ts index a69b069..6a6358e 100644 --- a/packages/backend/src/worker.ts +++ b/packages/backend/src/worker.ts @@ -1,4 +1,5 @@ import './config/orm'; +import './helpers/check-worker-readiness'; import './workers/flow'; import './workers/trigger'; import './workers/action'; From 8ea547c1d71b132aba17702aae1928e42a8fcfbc Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Tue, 6 Dec 2022 18:14:21 +0100 Subject: [PATCH 15/64] docs(available-apps): fix telegram link --- packages/docs/pages/guide/available-apps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md index 545a174..4254315 100644 --- a/packages/docs/pages/guide/available-apps.md +++ b/packages/docs/pages/guide/available-apps.md @@ -16,7 +16,7 @@ Following integrations are currently supported by Automatisch. - [Slack](/apps/slack/actions) - [SMTP](/apps/smtp/actions) - [Stripe](/apps/stripe/triggers) -- [Telegram](/apps/telegram-bot/triggers) +- [Telegram](/apps/telegram-bot/actions) - [Twilio](/apps/twilio/triggers) - [Twitter](/apps/twitter/triggers) - [Typeform](/apps/typeform/triggers) From 3c62f182ab714bc0eb3ffff9d64e0bf87f9fa99e Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Wed, 7 Dec 2022 23:41:46 +0100 Subject: [PATCH 16/64] feat(webhook): add webhook application --- .../src/apps/webhook/assets/favicon.svg | 8 +++++ .../backend/src/apps/webhook/auth/index.ts | 5 ++++ .../src/apps/webhook/auth/verify-webhook.ts | 7 +++++ packages/backend/src/apps/webhook/index.d.ts | 0 packages/backend/src/apps/webhook/index.ts | 16 ++++++++++ .../triggers/catch-raw-webhook/index.ts | 20 +++++++++++++ .../src/apps/webhook/triggers/index.ts | 3 ++ .../src/controllers/webhooks/handler.ts | 29 ++++++++++++++----- packages/backend/src/graphql/schema.graphql | 1 + .../backend/src/helpers/global-variable.ts | 1 + packages/backend/src/models/step.ts | 20 +++++++++++-- packages/backend/src/routes/webhooks.ts | 2 ++ packages/types/index.d.ts | 15 ++++------ 13 files changed, 107 insertions(+), 20 deletions(-) create mode 100644 packages/backend/src/apps/webhook/assets/favicon.svg create mode 100644 packages/backend/src/apps/webhook/auth/index.ts create mode 100644 packages/backend/src/apps/webhook/auth/verify-webhook.ts create mode 100644 packages/backend/src/apps/webhook/index.d.ts create mode 100644 packages/backend/src/apps/webhook/index.ts create mode 100644 packages/backend/src/apps/webhook/triggers/catch-raw-webhook/index.ts create mode 100644 packages/backend/src/apps/webhook/triggers/index.ts diff --git a/packages/backend/src/apps/webhook/assets/favicon.svg b/packages/backend/src/apps/webhook/assets/favicon.svg new file mode 100644 index 0000000..140ebd6 --- /dev/null +++ b/packages/backend/src/apps/webhook/assets/favicon.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/backend/src/apps/webhook/auth/index.ts b/packages/backend/src/apps/webhook/auth/index.ts new file mode 100644 index 0000000..ca3b207 --- /dev/null +++ b/packages/backend/src/apps/webhook/auth/index.ts @@ -0,0 +1,5 @@ +import verifyWebhook from './verify-webhook'; + +export default { + verifyWebhook, +}; diff --git a/packages/backend/src/apps/webhook/auth/verify-webhook.ts b/packages/backend/src/apps/webhook/auth/verify-webhook.ts new file mode 100644 index 0000000..22c2eaa --- /dev/null +++ b/packages/backend/src/apps/webhook/auth/verify-webhook.ts @@ -0,0 +1,7 @@ +import { IGlobalVariable } from '@automatisch/types'; + +const verifyWebhook = async ($: IGlobalVariable) => { + return true; +}; + +export default verifyWebhook; diff --git a/packages/backend/src/apps/webhook/index.d.ts b/packages/backend/src/apps/webhook/index.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/backend/src/apps/webhook/index.ts b/packages/backend/src/apps/webhook/index.ts new file mode 100644 index 0000000..fbd480b --- /dev/null +++ b/packages/backend/src/apps/webhook/index.ts @@ -0,0 +1,16 @@ +import defineApp from '../../helpers/define-app'; +import auth from './auth'; +import triggers from './triggers'; + +export default defineApp({ + name: 'Webhook', + key: 'webhook', + iconUrl: '{BASE_URL}/apps/webhook/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/webhook/connection', + supportsConnections: false, + baseUrl: '', + apiBaseUrl: '', + primaryColor: '0059F7', + auth, + triggers, +}); diff --git a/packages/backend/src/apps/webhook/triggers/catch-raw-webhook/index.ts b/packages/backend/src/apps/webhook/triggers/catch-raw-webhook/index.ts new file mode 100644 index 0000000..88c52f9 --- /dev/null +++ b/packages/backend/src/apps/webhook/triggers/catch-raw-webhook/index.ts @@ -0,0 +1,20 @@ +import isEmpty from 'lodash/isEmpty'; +import defineTrigger from '../../../../helpers/define-trigger'; + +export default defineTrigger({ + name: 'Catch raw webhook', + key: 'catchRawWebhook', + type: 'webhook', + description: 'Triggers when the webhook receives a request.', + + async testRun($) { + if (!isEmpty($.lastExecutionStep?.dataOut)) { + $.pushTriggerItem({ + raw: $.lastExecutionStep.dataOut, + meta: { + internalId: '', + } + }); + } + }, +}); diff --git a/packages/backend/src/apps/webhook/triggers/index.ts b/packages/backend/src/apps/webhook/triggers/index.ts new file mode 100644 index 0000000..4915900 --- /dev/null +++ b/packages/backend/src/apps/webhook/triggers/index.ts @@ -0,0 +1,3 @@ +import catchRawWebhook from './catch-raw-webhook'; + +export default [catchRawWebhook]; diff --git a/packages/backend/src/controllers/webhooks/handler.ts b/packages/backend/src/controllers/webhooks/handler.ts index 72329ad..c8e51bb 100644 --- a/packages/backend/src/controllers/webhooks/handler.ts +++ b/packages/backend/src/controllers/webhooks/handler.ts @@ -13,18 +13,19 @@ export default async (request: IRequest, response: Response) => { .findById(request.params.flowId) .throwIfNotFound(); - if (!flow.active) { - return response.send(404); - } - const triggerStep = await flow.getTriggerStep(); const triggerCommand = await triggerStep.getTriggerCommand(); + const app = await triggerStep.getApp(); + const isWebhookApp = app.key === 'webhook'; - if (triggerCommand.type !== 'webhook') { - return response.send(404); + if (!flow.active && !isWebhookApp) { + return response.sendStatus(404); + } + + if (triggerCommand.type !== 'webhook') { + return response.sendStatus(404); } - const app = await triggerStep.getApp(); if (app.auth.verifyWebhook) { const $ = await globalVariable({ @@ -42,8 +43,20 @@ export default async (request: IRequest, response: Response) => { } } + // in case trigger type is 'webhook' + let payload = request.body; + + // in case it's our built-in generic webhook trigger + if (isWebhookApp) { + payload = { + headers: request.headers, + body: request.body, + query: request.query, + } + } + const triggerItem: ITriggerItem = { - raw: request.body, + raw: payload, meta: { internalId: await bcrypt.hash(request.rawBody, 1), }, diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index bd0c39b..3f9714a 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -342,6 +342,7 @@ type Step { key: String appKey: String iconUrl: String + webhookUrl: String type: StepEnumType parameters: JSONObject connection: Connection diff --git a/packages/backend/src/helpers/global-variable.ts b/packages/backend/src/helpers/global-variable.ts index de9a09e..6834b08 100644 --- a/packages/backend/src/helpers/global-variable.ts +++ b/packages/backend/src/helpers/global-variable.ts @@ -77,6 +77,7 @@ const globalVariable = async ( id: execution?.id, testRun, }, + lastExecutionStep: (await step?.getLastExecutionStep())?.toJSON(), triggerOutput: { data: [], }, diff --git a/packages/backend/src/models/step.ts b/packages/backend/src/models/step.ts index 719fbbf..294671a 100644 --- a/packages/backend/src/models/step.ts +++ b/packages/backend/src/models/step.ts @@ -1,10 +1,11 @@ +import { URL } from 'node:url'; import { QueryContext, ModelOptions } from 'objection'; +import type { IJSONObject, IStep } from '@automatisch/types'; import Base from './base'; import App from './app'; import Flow from './flow'; import Connection from './connection'; import ExecutionStep from './execution-step'; -import type { IJSONObject, IStep } from '@automatisch/types'; import Telemetry from '../helpers/telemetry'; import appConfig from '../config/app'; @@ -46,7 +47,7 @@ class Step extends Base { }; static get virtualAttributes() { - return ['iconUrl']; + return ['iconUrl', 'webhookUrl']; } static relationMappings = () => ({ @@ -82,6 +83,13 @@ class Step extends Base { return `${appConfig.baseUrl}/apps/${this.appKey}/assets/favicon.svg`; } + get webhookUrl() { + if (this.appKey !== 'webhook') return null; + + const url = new URL(`/webhooks/${this.flowId}`, appConfig.webhookUrl); + return url.toString(); + } + async $afterInsert(queryContext: QueryContext) { await super.$afterInsert(queryContext); Telemetry.stepCreated(this); @@ -106,6 +114,14 @@ class Step extends Base { return await App.findOneByKey(this.appKey); } + async getLastExecutionStep() { + const lastExecutionStep = await this.$relatedQuery('executionSteps') + .orderBy('created_at', 'desc') + .first(); + + return lastExecutionStep; + } + async getNextStep() { const flow = await this.$relatedQuery('flow'); diff --git a/packages/backend/src/routes/webhooks.ts b/packages/backend/src/routes/webhooks.ts index c26f4ad..ca040cc 100644 --- a/packages/backend/src/routes/webhooks.ts +++ b/packages/backend/src/routes/webhooks.ts @@ -3,6 +3,8 @@ import webhookHandler from '../controllers/webhooks/handler'; const router = Router(); +router.get('/:flowId', webhookHandler); +router.put('/:flowId', webhookHandler); router.post('/:flowId', webhookHandler); export default router; diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index 0b2fb1f..1386f96 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -54,6 +54,7 @@ export interface IStep { key?: string; appKey?: string; iconUrl: string; + webhookUrl: string; type: 'action' | 'trigger'; connectionId?: string; status: string; @@ -180,23 +181,16 @@ export interface IDynamicData { export interface IAuth { generateAuthUrl?($: IGlobalVariable): Promise; - verifyCredentials($: IGlobalVariable): Promise; - isStillVerified($: IGlobalVariable): Promise; + verifyCredentials?($: IGlobalVariable): Promise; + isStillVerified?($: IGlobalVariable): Promise; refreshToken?($: IGlobalVariable): Promise; verifyWebhook?($: IGlobalVariable): Promise; isRefreshTokenRequested?: boolean; - fields: IField[]; + fields?: IField[]; authenticationSteps?: IAuthenticationStep[]; reconnectionSteps?: IAuthenticationStep[]; } -export interface IService { - authenticationClient?: IAuthentication; - triggers?: any; - actions?: any; - data?: any; -} - export interface ITriggerOutput { data: ITriggerItem[]; error?: IJSONObject; @@ -300,6 +294,7 @@ export type IGlobalVariable = { id: string; testRun: boolean; }; + lastExecutionStep?: IExecutionStep; webhookUrl?: string; triggerOutput?: ITriggerOutput; actionOutput?: IActionOutput; From 346a706e41a8ff1285df5437d2379087907611b2 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Wed, 7 Dec 2022 23:42:01 +0100 Subject: [PATCH 17/64] feat(Editor): show webhook info in test substep --- .../src/components/AddAppConnection/index.tsx | 13 ++---- .../web/src/components/TestSubstep/index.tsx | 5 ++- .../src/components/WebhookUrlInfo/index.tsx | 44 +++++++++++++++++++ .../src/components/WebhookUrlInfo/style.ts | 14 ++++++ packages/web/src/config/urls.ts | 3 ++ packages/web/src/graphql/queries/get-flow.ts | 2 + .../web/src/helpers/translation-values.tsx | 6 +++ packages/web/src/locales/en.json | 6 ++- 8 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 packages/web/src/components/WebhookUrlInfo/index.tsx create mode 100644 packages/web/src/components/WebhookUrlInfo/style.ts create mode 100644 packages/web/src/helpers/translation-values.tsx diff --git a/packages/web/src/components/AddAppConnection/index.tsx b/packages/web/src/components/AddAppConnection/index.tsx index 7b54e0f..38ba620 100644 --- a/packages/web/src/components/AddAppConnection/index.tsx +++ b/packages/web/src/components/AddAppConnection/index.tsx @@ -6,22 +6,15 @@ import DialogContentText from '@mui/material/DialogContentText'; import Dialog from '@mui/material/Dialog'; import LoadingButton from '@mui/lab/LoadingButton'; import { FieldValues, SubmitHandler } from 'react-hook-form'; -import { IJSONObject } from '@automatisch/types'; +import type { IApp, IJSONObject, IField } from '@automatisch/types'; import useFormatMessage from 'hooks/useFormatMessage'; import computeAuthStepVariables from 'helpers/computeAuthStepVariables'; import { processStep } from 'helpers/authenticationSteps'; import InputCreator from 'components/InputCreator'; -import type { IApp, IField } from '@automatisch/types'; +import { generateExternalLink } from '../../helpers/translation-values'; import { Form } from './style'; -const generateDocsLink = (link: string) => (str: string) => - ( - - {str} - - ); - type AddAppConnectionProps = { onClose: (response: Record) => void; application: IApp; @@ -112,7 +105,7 @@ export default function AddAppConnection( {formatMessage('addAppConnection.callToDocs', { appName: name, - docsLink: generateDocsLink(authDocUrl), + docsLink: generateExternalLink(authDocUrl), })} )} diff --git a/packages/web/src/components/TestSubstep/index.tsx b/packages/web/src/components/TestSubstep/index.tsx index f2b895c..09a5f0c 100644 --- a/packages/web/src/components/TestSubstep/index.tsx +++ b/packages/web/src/components/TestSubstep/index.tsx @@ -9,8 +9,9 @@ import LoadingButton from '@mui/lab/LoadingButton'; import { EditorContext } from 'contexts/Editor'; import useFormatMessage from 'hooks/useFormatMessage'; -import JSONViewer from 'components/JSONViewer'; import { EXECUTE_FLOW } from 'graphql/mutations/execute-flow'; +import JSONViewer from 'components/JSONViewer'; +import WebhookUrlInfo from 'components/WebhookUrlInfo'; import FlowSubstepTitle from 'components/FlowSubstepTitle'; import type { IStep, ISubstep } from '@automatisch/types'; @@ -115,6 +116,8 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement { )} + {step.webhookUrl && } + {hasNoOutput && ( diff --git a/packages/web/src/components/WebhookUrlInfo/index.tsx b/packages/web/src/components/WebhookUrlInfo/index.tsx new file mode 100644 index 0000000..cc5ca10 --- /dev/null +++ b/packages/web/src/components/WebhookUrlInfo/index.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import Typography from '@mui/material/Typography'; + +import { generateExternalLink } from '../../helpers/translation-values'; +import { WEBHOOK_DOCS } from '../../config/urls'; +import TextField from '../TextField'; +import { Alert } from './style'; + +type WebhookUrlInfoProps = { + webhookUrl: string; +}; + +function WebhookUrlInfo(props: WebhookUrlInfoProps): React.ReactElement { + const { webhookUrl } = props; + + return ( + + + + + + + + + + + } + /> + + ); +} + +export default WebhookUrlInfo; diff --git a/packages/web/src/components/WebhookUrlInfo/style.ts b/packages/web/src/components/WebhookUrlInfo/style.ts new file mode 100644 index 0000000..b74a383 --- /dev/null +++ b/packages/web/src/components/WebhookUrlInfo/style.ts @@ -0,0 +1,14 @@ +import { styled } from '@mui/material/styles'; +import MuiAlert, { alertClasses } from '@mui/material/Alert'; + +export const Alert = styled(MuiAlert)(({ theme }) => ({ + [`&.${alertClasses.root}`]: { + fontWeight: 300, + width: '100%', + display: 'flex', + flexDirection: 'column' + }, + [`& .${alertClasses.message}`]: { + width: '100%' + } +})); diff --git a/packages/web/src/config/urls.ts b/packages/web/src/config/urls.ts index 27214fe..5f0830f 100644 --- a/packages/web/src/config/urls.ts +++ b/packages/web/src/config/urls.ts @@ -65,3 +65,6 @@ export const UPDATES = '/updates'; export const SETTINGS_PROFILE = `${SETTINGS}/${PROFILE}`; export const DASHBOARD = FLOWS; + +// External links +export const WEBHOOK_DOCS = 'https://automatisch.io/docs' diff --git a/packages/web/src/graphql/queries/get-flow.ts b/packages/web/src/graphql/queries/get-flow.ts index 3434598..f3e8644 100644 --- a/packages/web/src/graphql/queries/get-flow.ts +++ b/packages/web/src/graphql/queries/get-flow.ts @@ -11,6 +11,8 @@ export const GET_FLOW = gql` type key appKey + iconUrl + webhookUrl status position connection { diff --git a/packages/web/src/helpers/translation-values.tsx b/packages/web/src/helpers/translation-values.tsx new file mode 100644 index 0000000..86e84ce --- /dev/null +++ b/packages/web/src/helpers/translation-values.tsx @@ -0,0 +1,6 @@ +export const generateExternalLink = (link: string) => (str: string) => + ( + + {str} + + ); diff --git a/packages/web/src/locales/en.json b/packages/web/src/locales/en.json index 4d79ee2..1732120 100644 --- a/packages/web/src/locales/en.json +++ b/packages/web/src/locales/en.json @@ -87,5 +87,9 @@ "profileSettings.updatedPassword": "Your password has been updated.", "profileSettings.updatePassword": "Update password", "notifications.title": "Notifications", - "notification.releasedAt": "Released {relativeDate}" + "notification.releasedAt": "Released {relativeDate}", + "webhookUrlInfo.title": "Your webhook URL", + "webhookUrlInfo.description": "You'll need to configure your application with this webhook URL.", + "webhookUrlInfo.helperText": "We've generated a custom webhook URL for you to send requests to. Learn more about webhooks.", + "webhookUrlInfo.copy": "Copy" } \ No newline at end of file From f4611d88cd23cca9b8e6065057ebc002b19af331 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Dec 2022 01:56:18 +0000 Subject: [PATCH 18/64] chore(deps): bump decode-uri-component from 0.2.0 to 0.2.2 Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2. - [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases) - [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2) --- updated-dependencies: - dependency-name: decode-uri-component dependency-type: indirect ... Signed-off-by: dependabot[bot] --- packages/cli/yarn.lock | 8 ++++---- packages/web/yarn.lock | 8 ++++---- yarn.lock | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/cli/yarn.lock b/packages/cli/yarn.lock index 0e34a07..be07262 100644 --- a/packages/cli/yarn.lock +++ b/packages/cli/yarn.lock @@ -6463,10 +6463,10 @@ decimal.js@^10.2.1: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.1.tgz#be75eeac4a2281aace80c1a8753587c27ef053e7" integrity sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw== -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== +decode-uri-component@0.2.2, decode-uri-component@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== decompress-response@^6.0.0: version "6.0.0" diff --git a/packages/web/yarn.lock b/packages/web/yarn.lock index f8265d2..38be911 100644 --- a/packages/web/yarn.lock +++ b/packages/web/yarn.lock @@ -4697,10 +4697,10 @@ decimal.js@^10.2.1: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decode-uri-component@0.2.2, decode-uri-component@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== dedent@^0.7.0: version "0.7.0" diff --git a/yarn.lock b/yarn.lock index deece01..2fd0630 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7246,9 +7246,9 @@ decimal.js@^10.2.1: integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== decompress-response@^3.3.0: version "3.3.0" From 22dc61f39b8d5a11a67c529d9070573872e3a5a9 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 5 Dec 2022 16:43:31 +0100 Subject: [PATCH 19/64] docs: Add docker installation section --- packages/docs/pages/guide/installation.md | 87 +++++++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/packages/docs/pages/guide/installation.md b/packages/docs/pages/guide/installation.md index 376a71b..b6952e6 100644 --- a/packages/docs/pages/guide/installation.md +++ b/packages/docs/pages/guide/installation.md @@ -1,6 +1,16 @@ # Installation -You can install Automatisch by using docker compose. +:::tip + +You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. You can also change your email and password later on from the settings page. + +::: + +:::danger +Please be careful with the `ENCRYPTION_KEY` and `APP_SECRET_KEY` environment variables. They are used to encrypt your credentials from third-party services. If you change them, you will not be able to access your connections and thus, your existing flows and connections will be useless. +::: + +## Docker Compose ```bash # Clone the repository @@ -13,14 +23,81 @@ cd automatisch docker compose -p automatisch up ``` -## Let's discover! +✌️ That's it; you have Automatisch running. Let's check it out by browsing [http://localhost:3000](https://localhost:3000) -✌️ That's it; you have Automatisch running. Let's check it out by browsing `http://localhost:3000` +## Docker -:::tip +Automatisch comes with two services which are `main` and `worker`. They both use the same image and need to have the same environment variables except for the `WORKER` environment variable which is set to `true` for the worker service. -You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. You can also change your email and password later on from the settings page. +::: warning +We give the sample environment variable files for the setup but you should adjust them to include your own values. +::: + +To install the main: + +```bash +docker run --env-file=./main.env automatischio/automatisch +``` + +::: details main.env + +```bash +APP_ENV=production +HOST= +PROTOCOL= +PORT= +ENCRYPTION_KEY= +APP_SECRET_KEY= +POSTGRES_HOST= +POSTGRES_PORT= +POSTGRES_DATABASE= +POSTGRES_USERNAME= +POSTGRES_PASSWORD= +POSTGRES_ENABLE_SSL= +REDIS_HOST= +REDIS_PORT= +REDIS_USERNAME= +REDIS_PASSWORD= +REDIS_TLS= +``` ::: +To install the worker: + +```bash +docker run --env-file=./worker.env automatischio/automatisch +``` + +::: details worker.env + +```bash +WORKER=true +APP_ENV=production +HOST= +PROTOCOL= +PORT= +ENCRYPTION_KEY= +APP_SECRET_KEY= +POSTGRES_HOST= +POSTGRES_PORT= +POSTGRES_DATABASE= +POSTGRES_USERNAME= +POSTGRES_PASSWORD= +POSTGRES_ENABLE_SSL= +REDIS_HOST= +REDIS_PORT= +REDIS_USERNAME= +REDIS_PASSWORD= +REDIS_TLS= +``` + +::: + +## Production setup + +If you need to change any other environment variables for your production setup, let's check out the [environment variables](/advanced/configuration#environment-variables) section of the configuration page. + +## Let's discover! + If you see any problems while installing Automatisch, let us know via [github issues](https://github.com/automatisch/automatisch/issues) or our [discord server](https://discord.gg/dJSah9CVrC). From 5d80fd523ceb77e913c75401aa8ce213cc7cd973 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 7 Dec 2022 12:57:53 +0100 Subject: [PATCH 20/64] docs: Remind to change password after installation --- README.md | 2 +- packages/docs/pages/guide/installation.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cdded87..067cc14 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ cd automatisch docker compose -p automatisch up ``` -You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. You can also change your email and password later on from the settings page. +You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. Please do not forget to change your email and password from the settings page. ## Community Links diff --git a/packages/docs/pages/guide/installation.md b/packages/docs/pages/guide/installation.md index b6952e6..8dca2d2 100644 --- a/packages/docs/pages/guide/installation.md +++ b/packages/docs/pages/guide/installation.md @@ -2,7 +2,7 @@ :::tip -You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. You can also change your email and password later on from the settings page. +You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. Please do not forget to change your email and password from the settings page. ::: From 75196cbf84f340e8d8a81b9c9bcd6a9850a9f988 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 7 Dec 2022 13:09:04 +0100 Subject: [PATCH 21/64] feat: Introduce webhook secret key to verify webhook requests --- docker-compose.yml | 2 + docker/compose-entrypoint.sh | 2 + packages/backend/.env-example | 1 + .../src/apps/typeform/auth/verify-webhook.ts | 2 +- packages/backend/src/config/app.ts | 9 +++- packages/docs/pages/advanced/configuration.md | 47 ++++++++++--------- packages/docs/pages/advanced/credentials.md | 2 +- packages/docs/pages/guide/installation.md | 4 +- 8 files changed, 41 insertions(+), 28 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index fbbb0a1..c6fb050 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,6 +23,7 @@ services: - POSTGRES_USERNAME=automatisch_user - POSTGRES_PASSWORD=automatisch_password - ENCRYPTION_KEY + - WEBHOOK_SECRET_KEY - APP_SECRET_KEY volumes: - automatisch_storage:/automatisch/storage @@ -41,6 +42,7 @@ services: - POSTGRES_USERNAME=automatisch_user - POSTGRES_PASSWORD=automatisch_password - ENCRYPTION_KEY + - WEBHOOK_SECRET_KEY - APP_SECRET_KEY - WORKER=true volumes: diff --git a/docker/compose-entrypoint.sh b/docker/compose-entrypoint.sh index 3a5448c..60e59f8 100755 --- a/docker/compose-entrypoint.sh +++ b/docker/compose-entrypoint.sh @@ -5,8 +5,10 @@ set -e if [ ! -f /automatisch/storage/.env ]; then >&2 echo "Saving environment variables" ENCRYPTION_KEY="${ENCRYPTION_KEY:-$(openssl rand -base64 36)}" + WEBHOOK_SECRET_KEY="${WEBHOOK_SECRET_KEY:-$(openssl rand -base64 36)}" APP_SECRET_KEY="${APP_SECRET_KEY:-$(openssl rand -base64 36)}" echo "ENCRYPTION_KEY=$ENCRYPTION_KEY" >> /automatisch/storage/.env + echo "WEBHOOK_SECRET_KEY=$WEBHOOK_SECRET_KEY" >> /automatisch/storage/.env echo "APP_SECRET_KEY=$APP_SECRET_KEY" >> /automatisch/storage/.env fi diff --git a/packages/backend/.env-example b/packages/backend/.env-example index 924bd16..27ee434 100644 --- a/packages/backend/.env-example +++ b/packages/backend/.env-example @@ -11,6 +11,7 @@ POSTGRES_USERNAME=automatish_development_user POSTGRES_PASSWORD= POSTGRES_ENABLE_SSL=false ENCRYPTION_KEY=sample-encryption-key +WEBHOOK_SECRET_KEY=sample-webhook-key APP_SECRET_KEY=sample-app-secret-key REDIS_PORT=6379 REDIS_HOST=127.0.0.1 diff --git a/packages/backend/src/apps/typeform/auth/verify-webhook.ts b/packages/backend/src/apps/typeform/auth/verify-webhook.ts index f5ba0d4..19dd880 100644 --- a/packages/backend/src/apps/typeform/auth/verify-webhook.ts +++ b/packages/backend/src/apps/typeform/auth/verify-webhook.ts @@ -11,7 +11,7 @@ const verifyWebhook = async ($: IGlobalVariable) => { const verifySignature = function (receivedSignature: string, payload: string) { const hash = crypto - .createHmac('sha256', appConfig.appSecretKey) + .createHmac('sha256', appConfig.webhookSecretKey) .update(payload) .digest('base64'); return receivedSignature === `sha256=${hash}`; diff --git a/packages/backend/src/config/app.ts b/packages/backend/src/config/app.ts index 7403421..6f81c2e 100644 --- a/packages/backend/src/config/app.ts +++ b/packages/backend/src/config/app.ts @@ -18,6 +18,7 @@ type AppConfig = { postgresEnableSsl: boolean; baseUrl: string; encryptionKey: string; + webhookSecretKey: string; appSecretKey: string; serveWebAppSeparately: boolean; redisHost: string; @@ -63,6 +64,7 @@ const appConfig: AppConfig = { postgresPassword: process.env.POSTGRES_PASSWORD, postgresEnableSsl: process.env.POSTGRES_ENABLE_SSL === 'true', encryptionKey: process.env.ENCRYPTION_KEY || '', + webhookSecretKey: process.env.WEBHOOK_SECRET_KEY || '', appSecretKey: process.env.APP_SECRET_KEY || '', serveWebAppSeparately, redisHost: process.env.REDIS_HOST || '127.0.0.1', @@ -70,8 +72,7 @@ const appConfig: AppConfig = { redisUsername: process.env.REDIS_USERNAME, redisPassword: process.env.REDIS_PASSWORD, redisTls: process.env.REDIS_TLS === 'true', - enableBullMQDashboard: - process.env.ENABLE_BULLMQ_DASHBOARD === 'true', + enableBullMQDashboard: process.env.ENABLE_BULLMQ_DASHBOARD === 'true', bullMQDashboardUsername: process.env.BULLMQ_DASHBOARD_USERNAME, bullMQDashboardPassword: process.env.BULLMQ_DASHBOARD_PASSWORD, baseUrl, @@ -84,4 +85,8 @@ if (!appConfig.encryptionKey) { throw new Error('ENCRYPTION_KEY environment variable needs to be set!'); } +if (!appConfig.webhookSecretKey) { + throw new Error('WEBHOOK_SECRET_KEY environment variable needs to be set!'); +} + export default appConfig; diff --git a/packages/docs/pages/advanced/configuration.md b/packages/docs/pages/advanced/configuration.md index 88d90ba..cfcb25c 100644 --- a/packages/docs/pages/advanced/configuration.md +++ b/packages/docs/pages/advanced/configuration.md @@ -11,28 +11,29 @@ The default values for some environment variables might be different in our deve ::: :::danger -Please be careful with the `ENCRYPTION_KEY` environment variable. It is used to encrypt your credentials from third-party services. If you change it, you will not be able to access your connections and thus, your existing flows and connections will be useless. +Please be careful with the `ENCRYPTION_KEY` and `WEBHOOK_SECRET_KEY` environment variables. They are used to encrypt your credentials from third-party services and verify webhook requests. If you change them, your existing connections and flows will not continue to work. ::: -| Variable Name | Type | Default Value | Description | -| --------------------------- | ------- | ------------------ | ----------------------------------- | -| `HOST` | string | `localhost` | HTTP Host | -| `PROTOCOL` | string | `http` | HTTP Protocol | -| `PORT` | string | `3000` | HTTP Port | -| `APP_ENV` | string | `production` | Automatisch Environment | -| `POSTGRES_DATABASE` | string | `automatisch` | Database Name | -| `POSTGRES_PORT` | number | `5432` | Database Port | -| `POSTGRES_HOST` | string | `postgres` | Database Host | -| `POSTGRES_USERNAME` | string | `automatisch_user` | Database User | -| `POSTGRES_PASSWORD` | string | | Password of Database User | -| `ENCRYPTION_KEY` | string | | Encryption Key to store credentials | -| `APP_SECRET_KEY` | string | | Secret Key to authenticate the user | -| `REDIS_HOST` | string | `redis` | Redis Host | -| `REDIS_PORT` | number | `6379` | Redis Port | -| `REDIS_USERNAME` | string | `` | Redis Username | -| `REDIS_PASSWORD` | string | `` | Redis Password | -| `REDIS_TLS` | boolean | `false` | Redis TLS | -| `TELEMETRY_ENABLED` | boolean | `true` | Enable/Disable Telemetry | -| `ENABLE_BULLMQ_DASHBOARD` | boolean | `false` | Enable BullMQ Dashboard | -| `BULLMQ_DASHBOARD_USERNAME` | string | | Username to login BullMQ Dashboard | -| `BULLMQ_DASHBOARD_PASSWORD` | string | | Password to login BullMQ Dashboard | +| Variable Name | Type | Default Value | Description | +| --------------------------- | ------- | ------------------ | --------------------------------------------- | +| `HOST` | string | `localhost` | HTTP Host | +| `PROTOCOL` | string | `http` | HTTP Protocol | +| `PORT` | string | `3000` | HTTP Port | +| `APP_ENV` | string | `production` | Automatisch Environment | +| `POSTGRES_DATABASE` | string | `automatisch` | Database Name | +| `POSTGRES_PORT` | number | `5432` | Database Port | +| `POSTGRES_HOST` | string | `postgres` | Database Host | +| `POSTGRES_USERNAME` | string | `automatisch_user` | Database User | +| `POSTGRES_PASSWORD` | string | | Password of Database User | +| `ENCRYPTION_KEY` | string | | Encryption Key to store credentials | +| `WEBHOOK_SECRET_KEY` | string | | Webhook Secret Key to verify webhook requests | +| `APP_SECRET_KEY` | string | | Secret Key to authenticate the user | +| `REDIS_HOST` | string | `redis` | Redis Host | +| `REDIS_PORT` | number | `6379` | Redis Port | +| `REDIS_USERNAME` | string | `` | Redis Username | +| `REDIS_PASSWORD` | string | `` | Redis Password | +| `REDIS_TLS` | boolean | `false` | Redis TLS | +| `TELEMETRY_ENABLED` | boolean | `true` | Enable/Disable Telemetry | +| `ENABLE_BULLMQ_DASHBOARD` | boolean | `false` | Enable BullMQ Dashboard | +| `BULLMQ_DASHBOARD_USERNAME` | string | | Username to login BullMQ Dashboard | +| `BULLMQ_DASHBOARD_PASSWORD` | string | | Password to login BullMQ Dashboard | diff --git a/packages/docs/pages/advanced/credentials.md b/packages/docs/pages/advanced/credentials.md index f1223ac..e30a88a 100644 --- a/packages/docs/pages/advanced/credentials.md +++ b/packages/docs/pages/advanced/credentials.md @@ -5,5 +5,5 @@ We need to store your credentials in order to automatically communicate with thi Automatisch uses AES specification to encrypt and decrypt your credentials of third-party services. The Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated. AES is now used worldwide to protect sensitive information. :::danger -Please be careful with the `ENCRYPTION_KEY` environment variable. It is used to encrypt your credentials from third-party services. If you change it, you will not be able to access your connections and thus, your existing flows and connections will be useless. +Please be careful with the `ENCRYPTION_KEY` and `WEBHOOK_SECRET_KEY` environment variables. They are used to encrypt your credentials from third-party services and verify webhook requests. If you change them, your existing connections and flows will not continue to work. ::: diff --git a/packages/docs/pages/guide/installation.md b/packages/docs/pages/guide/installation.md index 8dca2d2..fb88f0b 100644 --- a/packages/docs/pages/guide/installation.md +++ b/packages/docs/pages/guide/installation.md @@ -7,7 +7,7 @@ You can use `user@automatisch.io` email address and `sample` password to login t ::: :::danger -Please be careful with the `ENCRYPTION_KEY` and `APP_SECRET_KEY` environment variables. They are used to encrypt your credentials from third-party services. If you change them, you will not be able to access your connections and thus, your existing flows and connections will be useless. +Please be careful with the `ENCRYPTION_KEY` and `WEBHOOK_SECRET_KEY` environment variables. They are used to encrypt your credentials from third-party services and verify webhook requests. If you change them, your existing connections and flows will not continue to work. ::: ## Docker Compose @@ -47,6 +47,7 @@ HOST= PROTOCOL= PORT= ENCRYPTION_KEY= +WEBHOOK_SECRET_KEY= APP_SECRET_KEY= POSTGRES_HOST= POSTGRES_PORT= @@ -78,6 +79,7 @@ HOST= PROTOCOL= PORT= ENCRYPTION_KEY= +WEBHOOK_SECRET_KEY= APP_SECRET_KEY= POSTGRES_HOST= POSTGRES_PORT= From 2c8b60ab9b323381309c3f183d43d7b581b5cf54 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 7 Dec 2022 13:09:57 +0100 Subject: [PATCH 22/64] chore: Remove project flag from docker compose command --- README.md | 2 +- packages/docs/pages/guide/installation.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 067cc14..e285f91 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ git clone git@github.com:automatisch/automatisch.git cd automatisch # Start -docker compose -p automatisch up +docker compose up ``` You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. Please do not forget to change your email and password from the settings page. diff --git a/packages/docs/pages/guide/installation.md b/packages/docs/pages/guide/installation.md index fb88f0b..976b96a 100644 --- a/packages/docs/pages/guide/installation.md +++ b/packages/docs/pages/guide/installation.md @@ -20,7 +20,7 @@ git clone git@github.com:automatisch/automatisch.git cd automatisch # Start -docker compose -p automatisch up +docker compose up ``` ✌️ That's it; you have Automatisch running. Let's check it out by browsing [http://localhost:3000](https://localhost:3000) From af45b8a1e4f712028b791ee3b5a43ec55474c4e0 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 7 Dec 2022 13:14:40 +0100 Subject: [PATCH 23/64] docs: Adjust docker setup to use one .env file --- packages/docs/pages/guide/installation.md | 36 ++++------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/packages/docs/pages/guide/installation.md b/packages/docs/pages/guide/installation.md index 976b96a..d1df563 100644 --- a/packages/docs/pages/guide/installation.md +++ b/packages/docs/pages/guide/installation.md @@ -33,47 +33,21 @@ Automatisch comes with two services which are `main` and `worker`. They both use We give the sample environment variable files for the setup but you should adjust them to include your own values. ::: -To install the main: +To run the main: ```bash -docker run --env-file=./main.env automatischio/automatisch +docker run --env-file=./.env automatischio/automatisch ``` -::: details main.env +To run the worker: ```bash -APP_ENV=production -HOST= -PROTOCOL= -PORT= -ENCRYPTION_KEY= -WEBHOOK_SECRET_KEY= -APP_SECRET_KEY= -POSTGRES_HOST= -POSTGRES_PORT= -POSTGRES_DATABASE= -POSTGRES_USERNAME= -POSTGRES_PASSWORD= -POSTGRES_ENABLE_SSL= -REDIS_HOST= -REDIS_PORT= -REDIS_USERNAME= -REDIS_PASSWORD= -REDIS_TLS= +docker run --env-file=./.env -e WORKER=true automatischio/automatisch ``` -::: - -To install the worker: +::: details .env ```bash -docker run --env-file=./worker.env automatischio/automatisch -``` - -::: details worker.env - -```bash -WORKER=true APP_ENV=production HOST= PROTOCOL= From b1dddcb51110148c7c8975c6d0bcb4b148f82345 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 7 Dec 2022 13:21:57 +0100 Subject: [PATCH 24/64] docs: Add installation types info box --- packages/docs/pages/guide/installation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/docs/pages/guide/installation.md b/packages/docs/pages/guide/installation.md index d1df563..7108e21 100644 --- a/packages/docs/pages/guide/installation.md +++ b/packages/docs/pages/guide/installation.md @@ -1,5 +1,9 @@ # Installation +:::info +We have installation guides for docker compose and docker setup at the moment, but if you need another installation type, let us know by [creating a GitHub issue](https://github.com/automatisch/automatisch/issues/new). +::: + :::tip You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. Please do not forget to change your email and password from the settings page. From e8d8a5e89d9b8eda8f187be7b0337dcc272d18e5 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 10:22:39 +0100 Subject: [PATCH 25/64] feat(webhook): mark test run in executions --- packages/backend/src/controllers/webhooks/handler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/controllers/webhooks/handler.ts b/packages/backend/src/controllers/webhooks/handler.ts index c8e51bb..c40a893 100644 --- a/packages/backend/src/controllers/webhooks/handler.ts +++ b/packages/backend/src/controllers/webhooks/handler.ts @@ -66,6 +66,7 @@ export default async (request: IRequest, response: Response) => { flowId: flow.id, stepId: triggerStep.id, triggerItem, + testRun: !flow.active }); const nextStep = await triggerStep.getNextStep(); From f79245d24aec3b31cba5dbe39435aa5ec0752f08 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 10:26:07 +0100 Subject: [PATCH 26/64] fix(webhook): remove registrations logic --- packages/backend/src/graphql/mutations/update-flow-status.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/graphql/mutations/update-flow-status.ts b/packages/backend/src/graphql/mutations/update-flow-status.ts index 1cb80d5..99a504c 100644 --- a/packages/backend/src/graphql/mutations/update-flow-status.ts +++ b/packages/backend/src/graphql/mutations/update-flow-status.ts @@ -49,9 +49,9 @@ const updateFlowStatus = async ( testRun: false, }); - if (flow.active) { + if (flow.active && trigger.registerHook) { await trigger.registerHook($); - } else { + } else if (!flow.active && trigger.unregisterHook) { await trigger.unregisterHook($); } } else { From 51ccdf3577aae1034c972d0600d259138dd9c8e5 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 10:40:05 +0100 Subject: [PATCH 27/64] feat(webhook): do not process actions in test run --- packages/backend/src/controllers/webhooks/handler.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/controllers/webhooks/handler.ts b/packages/backend/src/controllers/webhooks/handler.ts index c40a893..15a8d2e 100644 --- a/packages/backend/src/controllers/webhooks/handler.ts +++ b/packages/backend/src/controllers/webhooks/handler.ts @@ -13,12 +13,13 @@ export default async (request: IRequest, response: Response) => { .findById(request.params.flowId) .throwIfNotFound(); + const testRun = !flow.active; const triggerStep = await flow.getTriggerStep(); const triggerCommand = await triggerStep.getTriggerCommand(); const app = await triggerStep.getApp(); const isWebhookApp = app.key === 'webhook'; - if (!flow.active && !isWebhookApp) { + if (testRun && !isWebhookApp) { return response.sendStatus(404); } @@ -66,9 +67,13 @@ export default async (request: IRequest, response: Response) => { flowId: flow.id, stepId: triggerStep.id, triggerItem, - testRun: !flow.active + testRun }); + if (testRun) { + return response.sendStatus(200); + } + const nextStep = await triggerStep.getNextStep(); const jobName = `${executionId}-${nextStep.id}`; From 8c4970b5509694eb665e082d8733c51c78c72a68 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 8 Dec 2022 13:00:17 +0300 Subject: [PATCH 28/64] chore: Use webhook secret key for new entry trigger --- packages/backend/src/apps/typeform/triggers/new-entry/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/apps/typeform/triggers/new-entry/index.ts b/packages/backend/src/apps/typeform/triggers/new-entry/index.ts index 55eaf31..01b3c35 100644 --- a/packages/backend/src/apps/typeform/triggers/new-entry/index.ts +++ b/packages/backend/src/apps/typeform/triggers/new-entry/index.ts @@ -72,7 +72,7 @@ export default defineTrigger({ const subscriptionPayload = { enabled: true, url: $.webhookUrl, - secret: appConfig.appSecretKey, + secret: appConfig.webhookSecretKey, }; await $.http.put( From d326b5a36a571ec7f113ccb8632ec38efe805a24 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 8 Dec 2022 13:16:47 +0300 Subject: [PATCH 29/64] chore: Add migration for webhook secret key --- docker/compose-entrypoint.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docker/compose-entrypoint.sh b/docker/compose-entrypoint.sh index 60e59f8..c02ae98 100755 --- a/docker/compose-entrypoint.sh +++ b/docker/compose-entrypoint.sh @@ -15,6 +15,12 @@ fi # initiate env. vars. from /automatisch/storage/.env file export $(grep -v '^#' /automatisch/storage/.env | xargs) +# migration for webhook secret key, will be removed in the future. +if [[ -z "${WEBHOOK_SECRET_KEY}" ]]; then + WEBHOOK_SECRET_KEY="$(openssl rand -base64 36)" + echo "WEBHOOK_SECRET_KEY=$WEBHOOK_SECRET_KEY" >> /automatisch/storage/.env +fi + echo "Environment variables have been set!" sh /entrypoint.sh From d9f905651509a55abb6fcc905f7b0f66442554e3 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 11:57:06 +0100 Subject: [PATCH 30/64] refactor(webhook): remove auth placeholder --- packages/backend/src/apps/webhook/auth/index.ts | 5 ----- packages/backend/src/apps/webhook/auth/verify-webhook.ts | 7 ------- packages/backend/src/apps/webhook/index.ts | 2 -- packages/backend/src/controllers/webhooks/handler.ts | 3 +-- 4 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 packages/backend/src/apps/webhook/auth/index.ts delete mode 100644 packages/backend/src/apps/webhook/auth/verify-webhook.ts diff --git a/packages/backend/src/apps/webhook/auth/index.ts b/packages/backend/src/apps/webhook/auth/index.ts deleted file mode 100644 index ca3b207..0000000 --- a/packages/backend/src/apps/webhook/auth/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import verifyWebhook from './verify-webhook'; - -export default { - verifyWebhook, -}; diff --git a/packages/backend/src/apps/webhook/auth/verify-webhook.ts b/packages/backend/src/apps/webhook/auth/verify-webhook.ts deleted file mode 100644 index 22c2eaa..0000000 --- a/packages/backend/src/apps/webhook/auth/verify-webhook.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IGlobalVariable } from '@automatisch/types'; - -const verifyWebhook = async ($: IGlobalVariable) => { - return true; -}; - -export default verifyWebhook; diff --git a/packages/backend/src/apps/webhook/index.ts b/packages/backend/src/apps/webhook/index.ts index fbd480b..107ee47 100644 --- a/packages/backend/src/apps/webhook/index.ts +++ b/packages/backend/src/apps/webhook/index.ts @@ -1,5 +1,4 @@ import defineApp from '../../helpers/define-app'; -import auth from './auth'; import triggers from './triggers'; export default defineApp({ @@ -11,6 +10,5 @@ export default defineApp({ baseUrl: '', apiBaseUrl: '', primaryColor: '0059F7', - auth, triggers, }); diff --git a/packages/backend/src/controllers/webhooks/handler.ts b/packages/backend/src/controllers/webhooks/handler.ts index 15a8d2e..4871769 100644 --- a/packages/backend/src/controllers/webhooks/handler.ts +++ b/packages/backend/src/controllers/webhooks/handler.ts @@ -27,8 +27,7 @@ export default async (request: IRequest, response: Response) => { return response.sendStatus(404); } - - if (app.auth.verifyWebhook) { + if (app.auth?.verifyWebhook) { const $ = await globalVariable({ flow, connection: await triggerStep.$relatedQuery('connection'), From 0fefa4e43aced070ad7605f99e7e73247f2bdba9 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 8 Dec 2022 21:28:42 +0300 Subject: [PATCH 31/64] chore: Make telegram and ntfy apps collapsed for docs sidebar --- packages/docs/pages/.vitepress/config.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 5e207ea..4553156 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -72,6 +72,7 @@ export default defineConfig({ { text: 'Ntfy', collapsible: true, + collapsed: true, items: [ { text: 'Actions', link: '/apps/ntfy/actions' }, { text: 'Connection', link: '/apps/ntfy/connection' }, @@ -134,6 +135,7 @@ export default defineConfig({ { text: 'Telegram', collapsible: true, + collapsed: true, items: [ { text: 'Actions', link: '/apps/telegram-bot/actions' }, { text: 'Connection', link: '/apps/telegram-bot/connection' }, @@ -168,6 +170,12 @@ export default defineConfig({ { text: 'Connection', link: '/apps/typeform/connection' }, ], }, + { + text: 'Webhooks', + collapsible: true, + collapsed: true, + items: [{ text: 'Triggers', link: '/apps/webhooks/triggers' }], + }, ], '/': [ { From 179c0a39d4cfd3685143cc546f26d71d8ba6c1dd Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 19:36:41 +0100 Subject: [PATCH 32/64] feat(ntfy): describe user & psswd in auth dialog --- packages/backend/src/apps/ntfy/auth/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/apps/ntfy/auth/index.ts b/packages/backend/src/apps/ntfy/auth/index.ts index 5a96d5b..f783c90 100644 --- a/packages/backend/src/apps/ntfy/auth/index.ts +++ b/packages/backend/src/apps/ntfy/auth/index.ts @@ -22,6 +22,7 @@ export default { readOnly: false, placeholder: null, clickToCopy: false, + description: 'You may need to provide your username if your installation requires authentication.', }, { key: 'password', @@ -31,6 +32,7 @@ export default { readOnly: false, placeholder: null, clickToCopy: false, + description: 'You may need to provide your password if your installation requires authentication.', }, ], From 89bcaa96edb1387176956c31502c6be4274ef9e5 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 8 Dec 2022 21:58:58 +0300 Subject: [PATCH 33/64] docs: Add trigger and connection pages of webhooks app --- packages/backend/src/routes/webhooks.ts | 1 + packages/docs/pages/.vitepress/config.js | 5 ++++- packages/docs/pages/apps/webhooks/connection.md | 7 +++++++ packages/docs/pages/apps/webhooks/triggers.md | 12 ++++++++++++ packages/docs/pages/public/favicons/webhooks.svg | 8 ++++++++ packages/web/src/config/urls.ts | 3 ++- 6 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 packages/docs/pages/apps/webhooks/connection.md create mode 100644 packages/docs/pages/apps/webhooks/triggers.md create mode 100644 packages/docs/pages/public/favicons/webhooks.svg diff --git a/packages/backend/src/routes/webhooks.ts b/packages/backend/src/routes/webhooks.ts index ca040cc..e43aba1 100644 --- a/packages/backend/src/routes/webhooks.ts +++ b/packages/backend/src/routes/webhooks.ts @@ -5,6 +5,7 @@ const router = Router(); router.get('/:flowId', webhookHandler); router.put('/:flowId', webhookHandler); +router.patch('/:flowId', webhookHandler); router.post('/:flowId', webhookHandler); export default router; diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 4553156..4179c23 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -174,7 +174,10 @@ export default defineConfig({ text: 'Webhooks', collapsible: true, collapsed: true, - items: [{ text: 'Triggers', link: '/apps/webhooks/triggers' }], + items: [ + { text: 'Triggers', link: '/apps/webhooks/triggers' }, + { text: 'Connection', link: '/apps/webhooks/connection' }, + ], }, ], '/': [ diff --git a/packages/docs/pages/apps/webhooks/connection.md b/packages/docs/pages/apps/webhooks/connection.md new file mode 100644 index 0000000..a38b7e9 --- /dev/null +++ b/packages/docs/pages/apps/webhooks/connection.md @@ -0,0 +1,7 @@ +# Webhooks + +Webhooks is a built-in app shipped with Automatisch, and it doesn't need to authenticate with any other external service to run. + +## How to use + +You will be given a webhook URL in the test substep on the editor page, and you can use it to send a GET, POST, PUT, or PATCH request to Automatisch to trigger the flow. diff --git a/packages/docs/pages/apps/webhooks/triggers.md b/packages/docs/pages/apps/webhooks/triggers.md new file mode 100644 index 0000000..9dda3c3 --- /dev/null +++ b/packages/docs/pages/apps/webhooks/triggers.md @@ -0,0 +1,12 @@ +--- +favicon: /favicons/webhooks.svg +items: + - name: Catch raw webhook + desc: Triggers when the webhook receives a request. +--- + + + + diff --git a/packages/docs/pages/public/favicons/webhooks.svg b/packages/docs/pages/public/favicons/webhooks.svg new file mode 100644 index 0000000..894b13e --- /dev/null +++ b/packages/docs/pages/public/favicons/webhooks.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packages/web/src/config/urls.ts b/packages/web/src/config/urls.ts index 5f0830f..aeca5e8 100644 --- a/packages/web/src/config/urls.ts +++ b/packages/web/src/config/urls.ts @@ -67,4 +67,5 @@ export const SETTINGS_PROFILE = `${SETTINGS}/${PROFILE}`; export const DASHBOARD = FLOWS; // External links -export const WEBHOOK_DOCS = 'https://automatisch.io/docs' +export const WEBHOOK_DOCS = + 'https://automatisch.io/docs/apps/webhooks/connection'; From 1125f318108be3eb1045c61b9a2c334d58584251 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 20:12:28 +0100 Subject: [PATCH 34/64] Release v0.3.0 --- lerna.json | 2 +- packages/backend/package.json | 6 +++--- packages/cli/package.json | 4 ++-- packages/docs/package.json | 2 +- packages/e2e-tests/package.json | 2 +- packages/types/package.json | 2 +- packages/web/package.json | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lerna.json b/lerna.json index 4d1b27d..4c49a96 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "0.2.0", + "version": "0.3.0", "npmClient": "yarn", "useWorkspaces": true, "command": { diff --git a/packages/backend/package.json b/packages/backend/package.json index ee1c692..4a4f257 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "@automatisch/backend", - "version": "0.2.0", + "version": "0.3.0", "license": "AGPL-3.0", "description": "The open source Zapier alternative. Build workflow automation without spending time and money.", "scripts": { @@ -22,7 +22,7 @@ "prebuild": "rm -rf ./dist" }, "dependencies": { - "@automatisch/web": "^0.2.0", + "@automatisch/web": "^0.3.0", "@bull-board/express": "^3.10.1", "@graphql-tools/graphql-file-loader": "^7.3.4", "@graphql-tools/load": "^7.5.2", @@ -93,7 +93,7 @@ "url": "https://github.com/automatisch/automatisch/issues" }, "devDependencies": { - "@automatisch/types": "^0.2.0", + "@automatisch/types": "^0.3.0", "@types/bcrypt": "^5.0.0", "@types/bull": "^3.15.8", "@types/cors": "^2.8.12", diff --git a/packages/cli/package.json b/packages/cli/package.json index bb86f98..2917c69 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@automatisch/cli", - "version": "0.2.0", + "version": "0.3.0", "license": "AGPL-3.0", "description": "The open source Zapier alternative. Build workflow automation without spending time and money.", "contributors": [ @@ -33,7 +33,7 @@ "version": "oclif readme && git add README.md" }, "dependencies": { - "@automatisch/backend": "^0.2.0", + "@automatisch/backend": "^0.3.0", "@oclif/core": "^1", "@oclif/plugin-help": "^5", "@oclif/plugin-plugins": "^2.0.1", diff --git a/packages/docs/package.json b/packages/docs/package.json index 959a683..85dab65 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -1,6 +1,6 @@ { "name": "@automatisch/docs", - "version": "0.2.0", + "version": "0.3.0", "license": "AGPL-3.0", "description": "The open source Zapier alternative. Build workflow automation without spending time and money.", "private": true, diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index dbdee1c..10c1faf 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@automatisch/e2e-tests", - "version": "0.2.0", + "version": "0.3.0", "license": "AGPL-3.0", "private": true, "description": "The open source Zapier alternative. Build workflow automation without spending time and money.", diff --git a/packages/types/package.json b/packages/types/package.json index 0936b68..225f6eb 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@automatisch/types", - "version": "0.2.0", + "version": "0.3.0", "license": "AGPL-3.0", "description": "Type definitions for automatisch", "homepage": "https://github.com/automatisch/automatisch", diff --git a/packages/web/package.json b/packages/web/package.json index b7e91f7..2e7e780 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,11 +1,11 @@ { "name": "@automatisch/web", - "version": "0.2.0", + "version": "0.3.0", "license": "AGPL-3.0", "description": "The open source Zapier alternative. Build workflow automation without spending time and money.", "dependencies": { "@apollo/client": "^3.6.9", - "@automatisch/types": "^0.2.0", + "@automatisch/types": "^0.3.0", "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", "@hookform/resolvers": "^2.8.8", From dd8bab299dd3e118b78e8f67fbd0ab5ba1058650 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 20:15:06 +0100 Subject: [PATCH 35/64] chore: update cli version in dockerfiles --- docker/Dockerfile | 2 +- docker/Dockerfile.compose | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index afff33c..2468dde 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,7 +4,7 @@ WORKDIR /automatisch COPY ./entrypoint.sh /entrypoint.sh -RUN yarn global add @automatisch/cli@0.2.0 +RUN yarn global add @automatisch/cli@0.3.0 EXPOSE 3000 ENTRYPOINT ["sh", "/entrypoint.sh"] diff --git a/docker/Dockerfile.compose b/docker/Dockerfile.compose index 12e4bb9..285e7db 100644 --- a/docker/Dockerfile.compose +++ b/docker/Dockerfile.compose @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM automatischio/automatisch:0.2.0 +FROM automatischio/automatisch:0.3.0 WORKDIR /automatisch RUN apk add --no-cache openssl dos2unix From a5b0910b605610b1ad4e6ad51c1195f139a707ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Dec 2022 19:19:13 +0000 Subject: [PATCH 36/64] chore(deps): bump express from 4.16.4 to 4.17.3 Bumps [express](https://github.com/expressjs/express) from 4.16.4 to 4.17.3. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.16.4...4.17.3) --- updated-dependencies: - dependency-name: express dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- packages/backend/package.json | 2 +- yarn.lock | 281 ++++------------------------------ 2 files changed, 35 insertions(+), 248 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index 4a4f257..96d3814 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -37,7 +37,7 @@ "crypto-js": "^4.1.1", "debug": "~2.6.9", "dotenv": "^10.0.0", - "express": "~4.16.1", + "express": "~4.17.3", "express-basic-auth": "^1.2.1", "express-graphql": "^0.12.0", "fast-xml-parser": "^4.0.11", diff --git a/yarn.lock b/yarn.lock index 2fd0630..0f83b38 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4774,15 +4774,7 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@^1.3.7, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -accepts@~1.3.8: +accepts@^1.3.7, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -5661,38 +5653,6 @@ blueimp-md5@^2.10.0: resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0" integrity sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w== -body-parser@1.18.3: - version "1.18.3" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= - dependencies: - bytes "3.0.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "~1.6.3" - iconv-lite "0.4.23" - on-finished "~2.3.0" - qs "6.5.2" - raw-body "2.3.3" - type-is "~1.6.16" - -body-parser@1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" - integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== - dependencies: - bytes "3.1.1" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" - type-is "~1.6.18" - body-parser@1.19.2: version "1.19.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" @@ -6602,11 +6562,6 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control- resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= - content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -6718,16 +6673,6 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= - -cookie@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== - cookie@0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" @@ -7194,10 +7139,10 @@ debug@2.6.9, debug@^2.6.0, debug@^2.6.9, debug@~2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" @@ -7215,13 +7160,6 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - debuglog@^1.0.0, debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -8550,7 +8488,7 @@ express-graphql@^0.12.0: http-errors "1.8.0" raw-body "^2.4.1" -express@4.17.3: +express@4.17.3, express@^4.17.1, express@~4.17.3: version "4.17.3" resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== @@ -8586,78 +8524,6 @@ express@4.17.3: utils-merge "1.0.1" vary "~1.1.2" -express@^4.17.1: - version "4.17.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" - integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.1" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.4.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.9.6" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" - setprototypeof "1.2.0" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -express@~4.16.1: - version "4.16.4" - resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" - integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== - dependencies: - accepts "~1.3.5" - array-flatten "1.1.1" - body-parser "1.18.3" - content-disposition "0.5.2" - content-type "~1.0.4" - cookie "0.3.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.1.1" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.2" - path-to-regexp "0.1.7" - proxy-addr "~2.0.4" - qs "6.5.2" - range-parser "~1.2.0" - safe-buffer "5.1.2" - send "0.16.2" - serve-static "1.13.2" - setprototypeof "1.1.0" - statuses "~1.4.0" - type-is "~1.6.16" - utils-merge "1.0.1" - vary "~1.1.2" - extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -8841,19 +8707,6 @@ filter-obj@^1.1.0: resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== -finalhandler@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.4.0" - unpipe "~1.0.0" - finalhandler@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" @@ -9714,16 +9567,6 @@ http-deceiver@^1.2.7: resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= -http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - http-errors@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" @@ -9746,6 +9589,16 @@ http-errors@1.8.1: statuses ">= 1.5.0 < 2" toidentifier "1.0.1" +http-errors@~1.6.2, http-errors@~1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + http-parser-js@>=0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" @@ -9837,13 +9690,6 @@ hyperlinker@^1.0.0: resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== -iconv-lite@0.4.23: - version "0.4.23" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -11997,11 +11843,6 @@ mime-types@~2.1.34: dependencies: mime-db "1.52.0" -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== - mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -12356,16 +12197,16 @@ natural-orderby@^2.0.3: resolved "https://registry.yarnpkg.com/natural-orderby/-/natural-orderby-2.0.3.tgz#8623bc518ba162f8ff1cdb8941d74deb0fdcc016" integrity sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q== -negotiator@0.6.2, negotiator@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - negotiator@0.6.3, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + neo-async@^2.6.0, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -14300,7 +14141,7 @@ protocols@^2.0.1: resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86" integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q== -proxy-addr@~2.0.4, proxy-addr@~2.0.7: +proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -14372,16 +14213,6 @@ qqjs@^0.3.11: tmp "^0.1.0" write-json-file "^4.1.1" -qs@6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -qs@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== - qs@6.9.7: version "6.9.7" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" @@ -14453,31 +14284,11 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -range-parser@^1.2.1, range-parser@~1.2.0, range-parser@~1.2.1: +range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== - dependencies: - bytes "3.0.0" - http-errors "1.6.3" - iconv-lite "0.4.23" - unpipe "1.0.0" - -raw-body@2.4.2, raw-body@^2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" - integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== - dependencies: - bytes "3.1.1" - http-errors "1.8.1" - iconv-lite "0.4.24" - unpipe "1.0.0" - raw-body@2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" @@ -14488,6 +14299,16 @@ raw-body@2.4.3: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" + integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== + dependencies: + bytes "3.1.1" + http-errors "1.8.1" + iconv-lite "0.4.24" + unpipe "1.0.0" + rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -15420,25 +15241,6 @@ semver@^7.3.7: dependencies: lru-cache "^6.0.0" -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - send@0.17.2: version "0.17.2" resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" @@ -15492,16 +15294,6 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.13.2: - version "1.13.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" - serve-static@1.14.2: version "1.14.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" @@ -15970,11 +15762,6 @@ standard-as-callback@^2.1.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -statuses@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== - stdout-stderr@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/stdout-stderr/-/stdout-stderr-0.1.13.tgz#54e3450f3d4c54086a49c0c7f8786a44d1844b6f" @@ -16874,7 +16661,7 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.16, type-is@~1.6.18: +type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== From 6382325280e4d19de7593d02d0da64ae476f285d Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 22:19:00 +0100 Subject: [PATCH 37/64] feat(TestSubstep): put some space between info and test output --- packages/web/src/components/TestSubstep/index.tsx | 6 ++++-- packages/web/src/components/WebhookUrlInfo/index.tsx | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/web/src/components/TestSubstep/index.tsx b/packages/web/src/components/TestSubstep/index.tsx index 09a5f0c..b7c3c76 100644 --- a/packages/web/src/components/TestSubstep/index.tsx +++ b/packages/web/src/components/TestSubstep/index.tsx @@ -108,7 +108,7 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement { {!!error?.graphQLErrors?.length && ( {serializeErrors(error.graphQLErrors).map((error: any) => (
    {error.message}
    @@ -116,7 +116,9 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
    )} - {step.webhookUrl && } + {step.webhookUrl && ( + + )} {hasNoOutput && ( diff --git a/packages/web/src/components/WebhookUrlInfo/index.tsx b/packages/web/src/components/WebhookUrlInfo/index.tsx index cc5ca10..82a1a3c 100644 --- a/packages/web/src/components/WebhookUrlInfo/index.tsx +++ b/packages/web/src/components/WebhookUrlInfo/index.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import Typography from '@mui/material/Typography'; +import type { AlertProps } from '@mui/material/Alert'; import { generateExternalLink } from '../../helpers/translation-values'; import { WEBHOOK_DOCS } from '../../config/urls'; @@ -9,13 +10,13 @@ import { Alert } from './style'; type WebhookUrlInfoProps = { webhookUrl: string; -}; +} & AlertProps; function WebhookUrlInfo(props: WebhookUrlInfoProps): React.ReactElement { - const { webhookUrl } = props; + const { webhookUrl, ...alertProps } = props; return ( - + From 03368e2ccad2a4197a38dcb76dfe57b5d2944cbb Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 8 Dec 2022 22:19:45 +0100 Subject: [PATCH 38/64] fix(webhook): correct internal ID for GET requests --- packages/backend/src/controllers/webhooks/handler.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/controllers/webhooks/handler.ts b/packages/backend/src/controllers/webhooks/handler.ts index 4871769..ed8684d 100644 --- a/packages/backend/src/controllers/webhooks/handler.ts +++ b/packages/backend/src/controllers/webhooks/handler.ts @@ -45,6 +45,7 @@ export default async (request: IRequest, response: Response) => { // in case trigger type is 'webhook' let payload = request.body; + let rawInternalId: string | Buffer = request.rawBody; // in case it's our built-in generic webhook trigger if (isWebhookApp) { @@ -53,12 +54,14 @@ export default async (request: IRequest, response: Response) => { body: request.body, query: request.query, } + + rawInternalId = JSON.stringify(payload); } const triggerItem: ITriggerItem = { raw: payload, meta: { - internalId: await bcrypt.hash(request.rawBody, 1), + internalId: await bcrypt.hash(rawInternalId, 1), }, }; From 9cde6620921188a7a70b6b98319e6ee954073aa7 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sat, 10 Dec 2022 16:38:25 +0100 Subject: [PATCH 39/64] feat(grapql-schema): add type property in Trigger --- packages/backend/src/graphql/schema.graphql | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index 3f9714a..a33d6f0 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -381,6 +381,7 @@ type Trigger { key: String description: String pollInterval: Int + type: String substeps: [TriggerSubstep] } From e77580dd35f7e3c1736509ecbd6f46fcd2e16397 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sat, 10 Dec 2022 16:39:10 +0100 Subject: [PATCH 40/64] feat: show "instant" chip for webhook triggers --- .../ChooseAppAndEventSubstep/index.tsx | 63 +++++++++++++++++-- packages/web/src/graphql/queries/get-app.ts | 1 + packages/web/src/graphql/queries/get-apps.ts | 1 + packages/web/src/locales/en.json | 1 + 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx b/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx index fc964bb..080fb7e 100644 --- a/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx +++ b/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx @@ -7,6 +7,7 @@ import Collapse from '@mui/material/Collapse'; import ListItem from '@mui/material/ListItem'; import TextField from '@mui/material/TextField'; import Autocomplete from '@mui/material/Autocomplete'; +import Chip from '@mui/material/Chip'; import useFormatMessage from 'hooks/useFormatMessage'; import { EditorContext } from 'contexts/Editor'; @@ -38,8 +39,20 @@ const optionGenerator = (app: { value: app.key as string, }); -const getOption = (options: Record[], appKey?: IApp['key']) => - options.find((option) => option.value === (appKey as string)) || null; +const eventOptionGenerator = (app: { + name: string; + key: string; + type?: string; +}): { label: string; value: string; type: string } => ({ + label: app.name as string, + value: app.key as string, + type: app?.type as string, +}); + +const getOption = ( + options: T[], + selectedOptionValue?: string +) => options.find((option) => option.value === selectedOptionValue); function ChooseAppAndEventSubstep( props: ChooseAppAndEventSubstepProps @@ -72,14 +85,17 @@ function ChooseAppAndEventSubstep( ); const actionsOrTriggers: Array = (isTrigger ? app?.triggers : app?.actions) || []; - const actionOptions = React.useMemo( - () => actionsOrTriggers.map((trigger) => optionGenerator(trigger)), + const actionOrTriggerOptions = React.useMemo( + () => actionsOrTriggers.map((trigger) => eventOptionGenerator(trigger)), [app?.key] ); const selectedActionOrTrigger = actionsOrTriggers.find( (actionOrTrigger: IAction | ITrigger) => actionOrTrigger.key === step?.key ); + const isWebhook = + isTrigger && (selectedActionOrTrigger as ITrigger).type === 'webhook'; + const { name } = substep; const valid: boolean = !!step.key && !!step.appKey; @@ -177,14 +193,49 @@ function ChooseAppAndEventSubstep( disablePortal disableClearable disabled={editorContext.readOnly} - options={actionOptions} + options={actionOrTriggerOptions} renderInput={(params) => ( + {isWebhook && ( + + )} + + {params.InputProps.endAdornment} +
    + ), + }} /> )} - value={getOption(actionOptions, step.key)} + renderOption={(optionProps, option) => ( +
  • + {option.label} + + {option.type === 'webhook' && ( + + )} +
  • + )} + value={getOption(actionOrTriggerOptions, step.key)} onChange={onEventChange} data-test="choose-event-autocomplete" /> diff --git a/packages/web/src/graphql/queries/get-app.ts b/packages/web/src/graphql/queries/get-app.ts index b0f49df..f9009c7 100644 --- a/packages/web/src/graphql/queries/get-app.ts +++ b/packages/web/src/graphql/queries/get-app.ts @@ -59,6 +59,7 @@ export const GET_APP = gql` triggers { name key + type pollInterval description substeps { diff --git a/packages/web/src/graphql/queries/get-apps.ts b/packages/web/src/graphql/queries/get-apps.ts index e643845..c6d1968 100644 --- a/packages/web/src/graphql/queries/get-apps.ts +++ b/packages/web/src/graphql/queries/get-apps.ts @@ -66,6 +66,7 @@ export const GET_APPS = gql` triggers { name key + type pollInterval description substeps { diff --git a/packages/web/src/locales/en.json b/packages/web/src/locales/en.json index 1732120..4512cfb 100644 --- a/packages/web/src/locales/en.json +++ b/packages/web/src/locales/en.json @@ -57,6 +57,7 @@ "flowEditor.pollIntervalValue": "Every {minutes} minutes", "flowEditor.triggerEvent": "Trigger event", "flowEditor.actionEvent": "Action event", + "flowEditor.instantTriggerType": "Instant", "chooseConnectionSubstep.continue": "Continue", "chooseConnectionSubstep.addNewConnection": "Add new connection", "chooseConnectionSubstep.chooseConnection": "Choose connection", From 3aafaabda637099a08fd1a945d45564e921d310b Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Sun, 11 Dec 2022 15:55:16 +0300 Subject: [PATCH 41/64] docs: Add cta for github stars --- .../pages/.vitepress/theme/CustomLayout.vue | 64 +++++++++++++++++++ .../docs/pages/.vitepress/theme/custom.css | 12 ++++ packages/docs/pages/.vitepress/theme/index.js | 7 +- 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 packages/docs/pages/.vitepress/theme/CustomLayout.vue diff --git a/packages/docs/pages/.vitepress/theme/CustomLayout.vue b/packages/docs/pages/.vitepress/theme/CustomLayout.vue new file mode 100644 index 0000000..f0c94b8 --- /dev/null +++ b/packages/docs/pages/.vitepress/theme/CustomLayout.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/packages/docs/pages/.vitepress/theme/custom.css b/packages/docs/pages/.vitepress/theme/custom.css index 98e5409..b95f28c 100644 --- a/packages/docs/pages/.vitepress/theme/custom.css +++ b/packages/docs/pages/.vitepress/theme/custom.css @@ -123,3 +123,15 @@ top: 50%; transform: translateY(-50%); } + +header.VPNav { + margin-top: 50px; +} + +aside.VPSidebar { + margin-top: 50px; +} + +#VPContent { + margin-top: 50px; +} diff --git a/packages/docs/pages/.vitepress/theme/index.js b/packages/docs/pages/.vitepress/theme/index.js index d4dbe3d..75eaece 100644 --- a/packages/docs/pages/.vitepress/theme/index.js +++ b/packages/docs/pages/.vitepress/theme/index.js @@ -1,3 +1,8 @@ import DefaultTheme from 'vitepress/theme'; import './custom.css'; -export default DefaultTheme; +import CustomLayout from './CustomLayout.vue'; + +export default { + ...DefaultTheme, + Layout: CustomLayout, +}; From 16715129d1a03f1a88b4ef0c1fe931846127aa80 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Sun, 11 Dec 2022 16:05:46 +0100 Subject: [PATCH 42/64] docs: fix mobile nav for GH stars announcement --- .../docs/pages/.vitepress/theme/CustomLayout.vue | 13 ------------- packages/docs/pages/.vitepress/theme/custom.css | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/docs/pages/.vitepress/theme/CustomLayout.vue b/packages/docs/pages/.vitepress/theme/CustomLayout.vue index f0c94b8..a2d3914 100644 --- a/packages/docs/pages/.vitepress/theme/CustomLayout.vue +++ b/packages/docs/pages/.vitepress/theme/CustomLayout.vue @@ -4,27 +4,14 @@ color: #fff; border-bottom: 2px solid rgba(194, 194, 194, 0.2); text-align: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - -webkit-justify-content: center; justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; display: flex; position: fixed; padding: 4px 40px; z-index: 999999; font-size: 0.875rem; font-weight: 400; - text-align: center; width: 100%; height: 50px; } diff --git a/packages/docs/pages/.vitepress/theme/custom.css b/packages/docs/pages/.vitepress/theme/custom.css index b95f28c..8ac3296 100644 --- a/packages/docs/pages/.vitepress/theme/custom.css +++ b/packages/docs/pages/.vitepress/theme/custom.css @@ -117,6 +117,8 @@ :root { overflow-y: scroll; + + --announcement-bar-height: 50px; } .VPTeamMembersItem .avatar-img { @@ -128,10 +130,20 @@ header.VPNav { margin-top: 50px; } +.VPNavScreen.VPNavScreen { + top: calc(var(--announcement-bar-height) + var(--vp-nav-height-mobile)); +} + +.VPLocalNav.VPLocalNav { + top: 50px; +} + aside.VPSidebar { margin-top: 50px; } -#VPContent { - margin-top: 50px; +@media (min-width: 960px) { + #VPContent { + margin-top: 50px; + } } From f7e8cb24ee28e325bc1964e13489ec8bd3e66416 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 12 Dec 2022 12:29:36 +0300 Subject: [PATCH 43/64] feat: Add render.yaml for easy deployment to Render --- render.yaml | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 render.yaml diff --git a/render.yaml b/render.yaml new file mode 100644 index 0000000..ec7e421 --- /dev/null +++ b/render.yaml @@ -0,0 +1,113 @@ +services: + - type: web + name: automatisch-main + env: docker + dockerfilePath: ./docker/Dockerfile + dockerContext: ./docker + repo: https://github.com/automatisch/automatisch + autoDeploy: false + envVars: + - key: HOST + fromService: + name: automatisch-main + type: web + envVarKey: RENDER_EXTERNAL_HOSTNAME + - key: POSTGRES_HOST + fromDatabase: + name: automatisch-database + property: host + - key: POSTGRES_PORT + fromDatabase: + name: automatisch-database + property: port + - key: POSTGRES_DATABASE + fromDatabase: + name: automatisch-database + property: database + - key: POSTGRES_USERNAME + fromDatabase: + name: automatisch-database + property: user + - key: POSTGRES_PASSWORD + fromDatabase: + name: automatisch-database + property: password + - key: REDIS_HOST + fromService: + type: redis + name: automatisch-redis + property: host + - key: REDIS_PORT + fromService: + type: redis + name: automatisch-redis + property: port + - fromGroup: common-env-vars + - type: worker + name: automatisch-worker + env: docker + dockerfilePath: ./docker/Dockerfile + dockerContext: ./docker + repo: https://github.com/automatisch/automatisch + autoDeploy: false + envVars: + - key: WORKER + value: true + - key: HOST + fromService: + name: automatisch-main + type: web + envVarKey: RENDER_EXTERNAL_HOSTNAME + - key: POSTGRES_HOST + fromDatabase: + name: automatisch-database + property: host + - key: POSTGRES_PORT + fromDatabase: + name: automatisch-database + property: port + - key: POSTGRES_DATABASE + fromDatabase: + name: automatisch-database + property: database + - key: POSTGRES_USERNAME + fromDatabase: + name: automatisch-database + property: user + - key: POSTGRES_PASSWORD + fromDatabase: + name: automatisch-database + property: password + - key: REDIS_HOST + fromService: + type: redis + name: automatisch-redis + property: host + - key: REDIS_PORT + fromService: + type: redis + name: automatisch-redis + property: port + - fromGroup: common-env-vars + - type: redis + name: automatisch-redis + ipAllowList: [] # allow only internal connections + maxmemoryPolicy: noeviction +databases: + - name: automatisch-database + databaseName: automatisch +envVarGroups: + - name: common-env-vars + envVars: + - key: APP_ENV + value: production + - key: PROTOCOL + value: https + - key: PORT + value: 443 + - key: ENCRYPTION_KEY + generateValue: true + - key: WEBHOOK_SECRET_KEY + generateValue: true + - key: APP_SECRET_KEY + generateValue: true From dd9f69e4cdb2231e1045d88a1e31719832b58d8c Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 12 Dec 2022 13:43:04 +0300 Subject: [PATCH 44/64] docs: Add installation type for render --- packages/docs/pages/guide/installation.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/docs/pages/guide/installation.md b/packages/docs/pages/guide/installation.md index 7108e21..91fa423 100644 --- a/packages/docs/pages/guide/installation.md +++ b/packages/docs/pages/guide/installation.md @@ -74,6 +74,18 @@ REDIS_TLS= ::: +## Render + + + Deploy to Render + + +:::info + +We use default values of render plans with the `render.yaml` file, if you want to use the free plan or change the plan, you can change the `render.yaml` file in your fork and use your repository URL while creating a blueprint in Render. + +::: + ## Production setup If you need to change any other environment variables for your production setup, let's check out the [environment variables](/advanced/configuration#environment-variables) section of the configuration page. From ec3454291bd9bd22c5673bf3b3c4ce17c254f31e Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 12 Dec 2022 16:08:04 +0300 Subject: [PATCH 45/64] docs: Add webhooks to available apps --- packages/docs/pages/guide/available-apps.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md index e433054..e28bc1a 100644 --- a/packages/docs/pages/guide/available-apps.md +++ b/packages/docs/pages/guide/available-apps.md @@ -21,3 +21,4 @@ Following integrations are currently supported by Automatisch. - [Twilio](/apps/twilio/triggers) - [Twitter](/apps/twitter/triggers) - [Typeform](/apps/typeform/triggers) +- [Webhooks](/apps/webhooks/triggers) From f04597335fb48dcaac294017ca98e683c361a751 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Mon, 12 Dec 2022 15:54:36 +0100 Subject: [PATCH 46/64] fix: make type optional for webhook check --- packages/web/src/components/ChooseAppAndEventSubstep/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx b/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx index 080fb7e..534e2f1 100644 --- a/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx +++ b/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx @@ -94,7 +94,7 @@ function ChooseAppAndEventSubstep( ); const isWebhook = - isTrigger && (selectedActionOrTrigger as ITrigger).type === 'webhook'; + isTrigger && (selectedActionOrTrigger as ITrigger)?.type === 'webhook'; const { name } = substep; From 469050914bbf6ed95dfc0d8cc6696ee10de794a4 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 15 Dec 2022 01:01:30 +0300 Subject: [PATCH 47/64] feat: Add delay application along with delay for action --- .../src/apps/delay/actions/delay-for/index.ts | 56 +++++++++++++++++++ .../backend/src/apps/delay/actions/index.ts | 3 + .../backend/src/apps/delay/assets/favicon.svg | 7 +++ packages/backend/src/apps/delay/index.d.ts | 0 packages/backend/src/apps/delay/index.ts | 14 +++++ .../src/helpers/delay-as-milliseconds.ts | 21 +++++++ packages/backend/src/workers/action.ts | 22 +++++++- 7 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 packages/backend/src/apps/delay/actions/delay-for/index.ts create mode 100644 packages/backend/src/apps/delay/actions/index.ts create mode 100644 packages/backend/src/apps/delay/assets/favicon.svg create mode 100644 packages/backend/src/apps/delay/index.d.ts create mode 100644 packages/backend/src/apps/delay/index.ts create mode 100644 packages/backend/src/helpers/delay-as-milliseconds.ts diff --git a/packages/backend/src/apps/delay/actions/delay-for/index.ts b/packages/backend/src/apps/delay/actions/delay-for/index.ts new file mode 100644 index 0000000..2b7af61 --- /dev/null +++ b/packages/backend/src/apps/delay/actions/delay-for/index.ts @@ -0,0 +1,56 @@ +import defineAction from '../../../../helpers/define-action'; + +export default defineAction({ + name: 'Delay For', + key: 'delayFor', + description: + 'Delays the execution of the next action by a specified amount of time.', + arguments: [ + { + label: 'Delay for unit', + key: 'delayForUnit', + type: 'dropdown' as const, + required: true, + value: null, + description: 'Delay for unit, e.g. minutes, hours, days, weeks.', + variables: false, + options: [ + { + label: 'Minutes', + value: 'minutes', + }, + { + label: 'Hours', + value: 'hours', + }, + { + label: 'Days', + value: 'days', + }, + { + label: 'Weeks', + value: 'weeks', + }, + ], + }, + { + label: 'Delay for value', + key: 'delayForValue', + type: 'string' as const, + required: true, + description: 'Delay for value, use a number, e.g. 1, 2, 3.', + variables: true, + }, + ], + + async run($) { + const { delayForUnit, delayForValue } = $.step.parameters; + + const dataItem = { + delayForUnit, + delayForValue, + }; + + $.setActionItem({ raw: dataItem }); + }, +}); diff --git a/packages/backend/src/apps/delay/actions/index.ts b/packages/backend/src/apps/delay/actions/index.ts new file mode 100644 index 0000000..f1160de --- /dev/null +++ b/packages/backend/src/apps/delay/actions/index.ts @@ -0,0 +1,3 @@ +import delayFor from './delay-for'; + +export default [delayFor]; diff --git a/packages/backend/src/apps/delay/assets/favicon.svg b/packages/backend/src/apps/delay/assets/favicon.svg new file mode 100644 index 0000000..af5da4d --- /dev/null +++ b/packages/backend/src/apps/delay/assets/favicon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/backend/src/apps/delay/index.d.ts b/packages/backend/src/apps/delay/index.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/backend/src/apps/delay/index.ts b/packages/backend/src/apps/delay/index.ts new file mode 100644 index 0000000..7f25c1b --- /dev/null +++ b/packages/backend/src/apps/delay/index.ts @@ -0,0 +1,14 @@ +import defineApp from '../../helpers/define-app'; +import actions from './actions'; + +export default defineApp({ + name: 'Delay', + key: 'delay', + iconUrl: '{BASE_URL}/apps/delay/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/delay/connection', + supportsConnections: false, + baseUrl: '', + apiBaseUrl: '', + primaryColor: '001F52', + actions, +}); diff --git a/packages/backend/src/helpers/delay-as-milliseconds.ts b/packages/backend/src/helpers/delay-as-milliseconds.ts new file mode 100644 index 0000000..582d1b1 --- /dev/null +++ b/packages/backend/src/helpers/delay-as-milliseconds.ts @@ -0,0 +1,21 @@ +export type TDelayForUnit = 'minutes' | 'hours' | 'days' | 'weeks'; + +const delayAsMilliseconds = ( + delayForUnit: TDelayForUnit, + delayForValue: number +) => { + switch (delayForUnit) { + case 'minutes': + return delayForValue * 60 * 1000; + case 'hours': + return delayForValue * 60 * 60 * 1000; + case 'days': + return delayForValue * 24 * 60 * 60 * 1000; + case 'weeks': + return delayForValue * 7 * 24 * 60 * 60 * 1000; + default: + return 0; + } +}; + +export default delayAsMilliseconds; diff --git a/packages/backend/src/workers/action.ts b/packages/backend/src/workers/action.ts index 80dd284..2686993 100644 --- a/packages/backend/src/workers/action.ts +++ b/packages/backend/src/workers/action.ts @@ -4,7 +4,13 @@ import logger from '../helpers/logger'; import Step from '../models/step'; import actionQueue from '../queues/action'; import { processAction } from '../services/action'; -import { REMOVE_AFTER_30_DAYS_OR_150_JOBS, REMOVE_AFTER_7_DAYS_OR_50_JOBS } from '../helpers/remove-job-configuration'; +import { + REMOVE_AFTER_30_DAYS_OR_150_JOBS, + REMOVE_AFTER_7_DAYS_OR_50_JOBS, +} from '../helpers/remove-job-configuration'; +import delayAsMilliseconds, { + TDelayForUnit, +} from '../helpers/delay-as-milliseconds'; type JobData = { flowId: string; @@ -12,6 +18,8 @@ type JobData = { stepId: string; }; +const DEFAULT_DELAY_DURATION = 0; + export const worker = new Worker( 'action', async (job) => { @@ -35,6 +43,18 @@ export const worker = new Worker( const jobOptions = { removeOnComplete: REMOVE_AFTER_7_DAYS_OR_50_JOBS, removeOnFail: REMOVE_AFTER_30_DAYS_OR_150_JOBS, + delay: DEFAULT_DELAY_DURATION, + }; + + const stepApp = await step.getApp(); + + if (stepApp.key === 'delay') { + const { delayForUnit, delayForValue } = step.parameters; + + jobOptions.delay = delayAsMilliseconds( + delayForUnit as TDelayForUnit, + Number(delayForValue) + ); } await actionQueue.add(jobName, jobPayload, jobOptions); From 4839b100cbabe17363e1b51648255dd8212efbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C4=B1dvan=20Akca?= Date: Mon, 12 Dec 2022 17:45:15 +0300 Subject: [PATCH 48/64] feat: take search bar out of scroll in add app connection --- packages/web/src/components/AddNewAppConnection/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/web/src/components/AddNewAppConnection/index.tsx b/packages/web/src/components/AddNewAppConnection/index.tsx index 8b6cd30..bbd95d8 100644 --- a/packages/web/src/components/AddNewAppConnection/index.tsx +++ b/packages/web/src/components/AddNewAppConnection/index.tsx @@ -18,6 +18,7 @@ import ListItemText from '@mui/material/ListItemText'; import InputLabel from '@mui/material/InputLabel'; import OutlinedInput from '@mui/material/OutlinedInput'; import FormControl from '@mui/material/FormControl'; +import Box from '@mui/material/Box'; import type { IApp } from '@automatisch/types'; import * as URLS from 'config/urls'; @@ -76,7 +77,7 @@ export default function AddNewAppConnection( {formatMessage('apps.addNewAppConnection')} - + + + {loading && ( From 5b51cb30f5d5429e46be82cf7867ee7aa5ac4e0c Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Fri, 16 Dec 2022 19:54:55 +0100 Subject: [PATCH 49/64] refactor: use step.appKey to recognize delay --- packages/backend/src/workers/action.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/backend/src/workers/action.ts b/packages/backend/src/workers/action.ts index 2686993..e09f945 100644 --- a/packages/backend/src/workers/action.ts +++ b/packages/backend/src/workers/action.ts @@ -46,9 +46,7 @@ export const worker = new Worker( delay: DEFAULT_DELAY_DURATION, }; - const stepApp = await step.getApp(); - - if (stepApp.key === 'delay') { + if (step.appKey === 'delay') { const { delayForUnit, delayForValue } = step.parameters; jobOptions.delay = delayAsMilliseconds( From cb58ab5fb755a9655a44e367d8f7e20d3eba4b54 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Fri, 16 Dec 2022 03:15:30 +0300 Subject: [PATCH 50/64] feat: Add delay until action for delay app --- .../apps/delay/actions/delay-until/index.ts | 28 +++++++++++++++ .../backend/src/apps/delay/actions/index.ts | 3 +- .../src/helpers/delay-as-milliseconds.ts | 36 ++++++++++--------- .../src/helpers/delay-for-as-milliseconds.ts | 21 +++++++++++ .../helpers/delay-until-as-milliseconds.ts | 8 +++++ packages/backend/src/workers/action.ts | 11 ++---- 6 files changed, 81 insertions(+), 26 deletions(-) create mode 100644 packages/backend/src/apps/delay/actions/delay-until/index.ts create mode 100644 packages/backend/src/helpers/delay-for-as-milliseconds.ts create mode 100644 packages/backend/src/helpers/delay-until-as-milliseconds.ts diff --git a/packages/backend/src/apps/delay/actions/delay-until/index.ts b/packages/backend/src/apps/delay/actions/delay-until/index.ts new file mode 100644 index 0000000..4197704 --- /dev/null +++ b/packages/backend/src/apps/delay/actions/delay-until/index.ts @@ -0,0 +1,28 @@ +import defineAction from '../../../../helpers/define-action'; + +export default defineAction({ + name: 'Delay Until', + key: 'delayUntil', + description: + 'Delays the execution of the next action until a specified date.', + arguments: [ + { + label: 'Delay until (Date)', + key: 'delayUntil', + type: 'string' as const, + required: true, + description: 'Delay until the date. E.g. 2022-12-18', + variables: true, + }, + ], + + async run($) { + const { delayUntil } = $.step.parameters; + + const dataItem = { + delayUntil, + }; + + $.setActionItem({ raw: dataItem }); + }, +}); diff --git a/packages/backend/src/apps/delay/actions/index.ts b/packages/backend/src/apps/delay/actions/index.ts index f1160de..0779892 100644 --- a/packages/backend/src/apps/delay/actions/index.ts +++ b/packages/backend/src/apps/delay/actions/index.ts @@ -1,3 +1,4 @@ import delayFor from './delay-for'; +import delayUntil from './delay-until'; -export default [delayFor]; +export default [delayFor, delayUntil]; diff --git a/packages/backend/src/helpers/delay-as-milliseconds.ts b/packages/backend/src/helpers/delay-as-milliseconds.ts index 582d1b1..3b791a9 100644 --- a/packages/backend/src/helpers/delay-as-milliseconds.ts +++ b/packages/backend/src/helpers/delay-as-milliseconds.ts @@ -1,21 +1,25 @@ -export type TDelayForUnit = 'minutes' | 'hours' | 'days' | 'weeks'; +import Step from '../models/step'; +import delayForAsMilliseconds, { + TDelayForUnit, +} from './delay-for-as-milliseconds'; +import delayUntilAsMilliseconds from './delay-until-as-milliseconds'; -const delayAsMilliseconds = ( - delayForUnit: TDelayForUnit, - delayForValue: number -) => { - switch (delayForUnit) { - case 'minutes': - return delayForValue * 60 * 1000; - case 'hours': - return delayForValue * 60 * 60 * 1000; - case 'days': - return delayForValue * 24 * 60 * 60 * 1000; - case 'weeks': - return delayForValue * 7 * 24 * 60 * 60 * 1000; - default: - return 0; +const delayAsMilliseconds = (step: Step) => { + let delayDuration = 0; + + if (step.key === 'delayFor') { + const { delayForUnit, delayForValue } = step.parameters; + + delayDuration = delayForAsMilliseconds( + delayForUnit as TDelayForUnit, + Number(delayForValue) + ); + } else if (step.key === 'delayUntil') { + const { delayUntil } = step.parameters; + delayDuration = delayUntilAsMilliseconds(delayUntil as string); } + + return delayDuration; }; export default delayAsMilliseconds; diff --git a/packages/backend/src/helpers/delay-for-as-milliseconds.ts b/packages/backend/src/helpers/delay-for-as-milliseconds.ts new file mode 100644 index 0000000..582d1b1 --- /dev/null +++ b/packages/backend/src/helpers/delay-for-as-milliseconds.ts @@ -0,0 +1,21 @@ +export type TDelayForUnit = 'minutes' | 'hours' | 'days' | 'weeks'; + +const delayAsMilliseconds = ( + delayForUnit: TDelayForUnit, + delayForValue: number +) => { + switch (delayForUnit) { + case 'minutes': + return delayForValue * 60 * 1000; + case 'hours': + return delayForValue * 60 * 60 * 1000; + case 'days': + return delayForValue * 24 * 60 * 60 * 1000; + case 'weeks': + return delayForValue * 7 * 24 * 60 * 60 * 1000; + default: + return 0; + } +}; + +export default delayAsMilliseconds; diff --git a/packages/backend/src/helpers/delay-until-as-milliseconds.ts b/packages/backend/src/helpers/delay-until-as-milliseconds.ts new file mode 100644 index 0000000..4c1da96 --- /dev/null +++ b/packages/backend/src/helpers/delay-until-as-milliseconds.ts @@ -0,0 +1,8 @@ +const delayUntilAsMilliseconds = (delayUntil: string) => { + const delayUntilDate = new Date(delayUntil); + const now = new Date(); + + return delayUntilDate.getTime() - now.getTime(); +}; + +export default delayUntilAsMilliseconds; diff --git a/packages/backend/src/workers/action.ts b/packages/backend/src/workers/action.ts index e09f945..cf16d42 100644 --- a/packages/backend/src/workers/action.ts +++ b/packages/backend/src/workers/action.ts @@ -8,9 +8,7 @@ import { REMOVE_AFTER_30_DAYS_OR_150_JOBS, REMOVE_AFTER_7_DAYS_OR_50_JOBS, } from '../helpers/remove-job-configuration'; -import delayAsMilliseconds, { - TDelayForUnit, -} from '../helpers/delay-as-milliseconds'; +import delayAsMilliseconds from '../helpers/delay-as-milliseconds'; type JobData = { flowId: string; @@ -47,12 +45,7 @@ export const worker = new Worker( }; if (step.appKey === 'delay') { - const { delayForUnit, delayForValue } = step.parameters; - - jobOptions.delay = delayAsMilliseconds( - delayForUnit as TDelayForUnit, - Number(delayForValue) - ); + jobOptions.delay = delayAsMilliseconds(step); } await actionQueue.add(jobName, jobPayload, jobOptions); From 5d24216124198b9b97049aa8ebe434d92b085507 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Fri, 16 Dec 2022 20:34:25 +0100 Subject: [PATCH 51/64] feat: prioritize WEB_APP_URL --- packages/backend/src/config/app.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/config/app.ts b/packages/backend/src/config/app.ts index 6f81c2e..6e00727 100644 --- a/packages/backend/src/config/app.ts +++ b/packages/backend/src/config/app.ts @@ -1,3 +1,4 @@ +import { URL } from 'node:url'; import * as dotenv from 'dotenv'; dotenv.config(); @@ -38,14 +39,23 @@ const port = process.env.PORT || '3000'; const serveWebAppSeparately = process.env.SERVE_WEB_APP_SEPARATELY === 'true' ? true : false; -let webAppUrl = `${protocol}://${host}:${port}`; -const webhookUrl = process.env.WEBHOOK_URL || webAppUrl; +let apiUrl = (new URL(`${protocol}://${host}:${port}`)).toString(); +apiUrl = apiUrl.substring(0, apiUrl.length - 1); -if (serveWebAppSeparately) { - webAppUrl = process.env.WEB_APP_URL || 'http://localhost:3001'; +// use apiUrl by default, which has less priority over the following cases +let webAppUrl = apiUrl; + +if (process.env.WEB_APP_URL) { + // use env. var. if provided + webAppUrl = (new URL(process.env.WEB_APP_URL)).toString(); + webAppUrl = webAppUrl.substring(0, webAppUrl.length - 1); +} else if (serveWebAppSeparately) { + // no env. var. and serving separately, sign of development + webAppUrl = 'http://localhost:3001' } -const baseUrl = `${protocol}://${host}:${port}`; +let webhookUrl = (new URL(process.env.WEBHOOK_URL || apiUrl)).toString(); +webhookUrl = webhookUrl.substring(0, webhookUrl.length - 1); const appEnv = process.env.APP_ENV || 'development'; @@ -75,7 +85,7 @@ const appConfig: AppConfig = { enableBullMQDashboard: process.env.ENABLE_BULLMQ_DASHBOARD === 'true', bullMQDashboardUsername: process.env.BULLMQ_DASHBOARD_USERNAME, bullMQDashboardPassword: process.env.BULLMQ_DASHBOARD_PASSWORD, - baseUrl, + baseUrl: apiUrl, webAppUrl, webhookUrl, telemetryEnabled: process.env.TELEMETRY_ENABLED === 'false' ? false : true, From 0970db32959e631892a564111b89c55b29f9c971 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Wed, 14 Dec 2022 20:00:08 +0100 Subject: [PATCH 52/64] feat: add remoteWebhookId in Flow --- .../20221214184855_add_remote_webhook_id_in_flow.ts | 13 +++++++++++++ packages/backend/src/models/flow.ts | 2 ++ packages/types/index.d.ts | 3 +++ 3 files changed, 18 insertions(+) create mode 100644 packages/backend/src/db/migrations/20221214184855_add_remote_webhook_id_in_flow.ts diff --git a/packages/backend/src/db/migrations/20221214184855_add_remote_webhook_id_in_flow.ts b/packages/backend/src/db/migrations/20221214184855_add_remote_webhook_id_in_flow.ts new file mode 100644 index 0000000..67a086a --- /dev/null +++ b/packages/backend/src/db/migrations/20221214184855_add_remote_webhook_id_in_flow.ts @@ -0,0 +1,13 @@ +import { Knex } from 'knex'; + +export async function up(knex: Knex): Promise { + return knex.schema.table('flows', (table) => { + table.string('remote_webhook_id'); + }); +} + +export async function down(knex: Knex): Promise { + return knex.schema.table('flows', (table) => { + table.dropColumn('remote_webhook_id'); + }); +} diff --git a/packages/backend/src/models/flow.ts b/packages/backend/src/models/flow.ts index bb4015e..5577dd3 100644 --- a/packages/backend/src/models/flow.ts +++ b/packages/backend/src/models/flow.ts @@ -13,6 +13,7 @@ class Flow extends Base { active: boolean; steps: Step[]; published_at: string; + remoteWebhookId: string; executions?: Execution[]; static tableName = 'flows'; @@ -25,6 +26,7 @@ class Flow extends Base { id: { type: 'string', format: 'uuid' }, name: { type: 'string', minLength: 1 }, userId: { type: 'string', format: 'uuid' }, + remoteWebhookId: { type: 'string' }, active: { type: 'boolean' }, }, }; diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index 1386f96..7f56d0e 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -76,6 +76,7 @@ export interface IFlow { steps: IStep[]; createdAt: string; updatedAt: string; + remoteWebhookId: string; lastInternalId: () => Promise; } @@ -279,6 +280,8 @@ export type IGlobalVariable = { id: string; lastInternalId: string; isAlreadyProcessed?: (internalId: string) => boolean; + remoteWebhookId?: string; + setRemoteWebhookId?: (remoteWebhookId: string) => Promise; }; step?: { id: string; From f30ac466723a7411c90cf64a03ada48bc5816ae7 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Wed, 14 Dec 2022 20:50:33 +0100 Subject: [PATCH 53/64] feat($): add flow.setRemoteWebhookId --- packages/backend/src/helpers/global-variable.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/backend/src/helpers/global-variable.ts b/packages/backend/src/helpers/global-variable.ts index 6834b08..ed4dd96 100644 --- a/packages/backend/src/helpers/global-variable.ts +++ b/packages/backend/src/helpers/global-variable.ts @@ -37,6 +37,7 @@ const globalVariable = async ( testRun = false, } = options; + const isTrigger = step?.isTrigger; const lastInternalId = testRun ? undefined : await flow?.lastInternalId(); const nextStep = await step?.getNextStep(); @@ -123,6 +124,18 @@ const globalVariable = async ( $.webhookUrl = webhookUrl; } + if (isTrigger && (await step.getTriggerCommand()).type === 'webhook') { + $.flow.setRemoteWebhookId = async (remoteWebhookId) => { + await flow.$query().patchAndFetch({ + remoteWebhookId, + }); + + $.flow.remoteWebhookId = remoteWebhookId; + }; + + $.flow.remoteWebhookId = flow.remoteWebhookId; + } + const lastInternalIds = testRun || (flow && step.isAction) ? [] : await flow?.lastInternalIds(2000); From 7175d92eaf9a45fb7b7eaf0108147780129afacd Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 15 Dec 2022 00:46:42 +0100 Subject: [PATCH 54/64] feat(flowers-software): add app with authentication --- .../apps/flowers-software/assets/favicon.svg | 12 ++++++ .../src/apps/flowers-software/auth/index.ts | 43 +++++++++++++++++++ .../auth/is-still-verified.ts | 10 +++++ .../auth/verify-credentials.ts | 20 +++++++++ .../common/add-auth-header.ts | 18 ++++++++ .../flowers-software/common/get-webhooks.ts | 5 +++ .../src/apps/flowers-software/index.d.ts | 0 .../src/apps/flowers-software/index.ts | 16 +++++++ 8 files changed, 124 insertions(+) create mode 100644 packages/backend/src/apps/flowers-software/assets/favicon.svg create mode 100644 packages/backend/src/apps/flowers-software/auth/index.ts create mode 100644 packages/backend/src/apps/flowers-software/auth/is-still-verified.ts create mode 100644 packages/backend/src/apps/flowers-software/auth/verify-credentials.ts create mode 100644 packages/backend/src/apps/flowers-software/common/add-auth-header.ts create mode 100644 packages/backend/src/apps/flowers-software/common/get-webhooks.ts create mode 100644 packages/backend/src/apps/flowers-software/index.d.ts create mode 100644 packages/backend/src/apps/flowers-software/index.ts diff --git a/packages/backend/src/apps/flowers-software/assets/favicon.svg b/packages/backend/src/apps/flowers-software/assets/favicon.svg new file mode 100644 index 0000000..55b8ed6 --- /dev/null +++ b/packages/backend/src/apps/flowers-software/assets/favicon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/backend/src/apps/flowers-software/auth/index.ts b/packages/backend/src/apps/flowers-software/auth/index.ts new file mode 100644 index 0000000..6dd4071 --- /dev/null +++ b/packages/backend/src/apps/flowers-software/auth/index.ts @@ -0,0 +1,43 @@ +import verifyCredentials from './verify-credentials'; +import isStillVerified from './is-still-verified'; + +export default { + fields: [ + { + key: 'username', + label: 'Username', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: null, + clickToCopy: false, + }, + { + key: 'password', + label: 'Password', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: null, + clickToCopy: false, + }, + { + key: 'apiKey', + label: 'API Key', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: null, + clickToCopy: false, + }, + ], + + verifyCredentials, + isStillVerified, +}; diff --git a/packages/backend/src/apps/flowers-software/auth/is-still-verified.ts b/packages/backend/src/apps/flowers-software/auth/is-still-verified.ts new file mode 100644 index 0000000..5a2fe2a --- /dev/null +++ b/packages/backend/src/apps/flowers-software/auth/is-still-verified.ts @@ -0,0 +1,10 @@ +import { IGlobalVariable } from '@automatisch/types'; +import verifyCredentials from './verify-credentials'; + +const isStillVerified = async ($: IGlobalVariable) => { + await verifyCredentials($); + + return true; +}; + +export default isStillVerified; diff --git a/packages/backend/src/apps/flowers-software/auth/verify-credentials.ts b/packages/backend/src/apps/flowers-software/auth/verify-credentials.ts new file mode 100644 index 0000000..4e7a4f6 --- /dev/null +++ b/packages/backend/src/apps/flowers-software/auth/verify-credentials.ts @@ -0,0 +1,20 @@ +import { IGlobalVariable } from '@automatisch/types'; +import getWebhooks from '../common/get-webhooks'; + +const verifyCredentials = async ($: IGlobalVariable) => { + const response = await getWebhooks($); + const successful = Array.isArray(response.data); + + if (!successful) { + throw new Error('Failed while authorizing!'); + } + + await $.auth.set({ + screenName: $.auth.data.username, + username: $.auth.data.username, + password: $.auth.data.password, + apiKey: $.auth.data.apiKey, + }); +}; + +export default verifyCredentials; diff --git a/packages/backend/src/apps/flowers-software/common/add-auth-header.ts b/packages/backend/src/apps/flowers-software/common/add-auth-header.ts new file mode 100644 index 0000000..02f524f --- /dev/null +++ b/packages/backend/src/apps/flowers-software/common/add-auth-header.ts @@ -0,0 +1,18 @@ +import { TBeforeRequest } from '@automatisch/types'; + +const addAuthHeader: TBeforeRequest = ($, requestConfig) => { + const { data } = $.auth; + + if (data?.username && data.password && data.apiKey) { + requestConfig.headers['x-api-key'] = data.apiKey as string; + + requestConfig.auth = { + username: data.username as string, + password: data.password as string, + }; + } + + return requestConfig; +}; + +export default addAuthHeader; diff --git a/packages/backend/src/apps/flowers-software/common/get-webhooks.ts b/packages/backend/src/apps/flowers-software/common/get-webhooks.ts new file mode 100644 index 0000000..bb529c2 --- /dev/null +++ b/packages/backend/src/apps/flowers-software/common/get-webhooks.ts @@ -0,0 +1,5 @@ +import type { IGlobalVariable } from "@automatisch/types"; + +export default async function getWebhooks($: IGlobalVariable) { + return await $.http.get('/v2/public/api/webhooks'); +} diff --git a/packages/backend/src/apps/flowers-software/index.d.ts b/packages/backend/src/apps/flowers-software/index.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/backend/src/apps/flowers-software/index.ts b/packages/backend/src/apps/flowers-software/index.ts new file mode 100644 index 0000000..5206578 --- /dev/null +++ b/packages/backend/src/apps/flowers-software/index.ts @@ -0,0 +1,16 @@ +import defineApp from '../../helpers/define-app'; +import addAuthHeader from './common/add-auth-header'; +import auth from './auth'; + +export default defineApp({ + name: 'Flowers Software', + key: 'flowers-software', + iconUrl: '{BASE_URL}/apps/flowers-software/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/flowers-software/connection', + supportsConnections: true, + baseUrl: 'https://flowers-software.com', + apiBaseUrl: 'https://webapp.flowers-software.com/api', + primaryColor: '02AFC7', + beforeRequest: [addAuthHeader], + auth, +}); From bf1076b7d2cb64aebf9a4d447c372ae297662a3e Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Thu, 15 Dec 2022 00:48:21 +0100 Subject: [PATCH 55/64] fix(AddAppConnection): don't render empty error details --- packages/web/src/components/AddAppConnection/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/components/AddAppConnection/index.tsx b/packages/web/src/components/AddAppConnection/index.tsx index 38ba620..e1581b3 100644 --- a/packages/web/src/components/AddAppConnection/index.tsx +++ b/packages/web/src/components/AddAppConnection/index.tsx @@ -116,7 +116,7 @@ export default function AddAppConnection( sx={{ mt: 1, fontWeight: 500, wordBreak: 'break-all' }} > {error.message} -
    {JSON.stringify(error.details, null, 2)}
    + {error.details &&
    {JSON.stringify(error.details, null, 2)}
    } )} From 6d74f7c64d16f7769ccdd2d2dc385168c4a5a3e9 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Fri, 16 Dec 2022 16:27:49 +0100 Subject: [PATCH 56/64] feat(flowers-software): add new activity trigger --- .../common/webhook-filters.ts | 488 ++++++++++++++++++ .../src/apps/flowers-software/index.ts | 2 + .../apps/flowers-software/triggers/index.ts | 3 + .../triggers/new-activity/index.ts | 54 ++ 4 files changed, 547 insertions(+) create mode 100644 packages/backend/src/apps/flowers-software/common/webhook-filters.ts create mode 100644 packages/backend/src/apps/flowers-software/triggers/index.ts create mode 100644 packages/backend/src/apps/flowers-software/triggers/new-activity/index.ts diff --git a/packages/backend/src/apps/flowers-software/common/webhook-filters.ts b/packages/backend/src/apps/flowers-software/common/webhook-filters.ts new file mode 100644 index 0000000..d8a22d1 --- /dev/null +++ b/packages/backend/src/apps/flowers-software/common/webhook-filters.ts @@ -0,0 +1,488 @@ +const webhookFilters = [ + { + label: "Contact Company Created", + value: "CONTACT_COMPANY_CREATED" + }, + { + label: "Contact Company Deleted", + value: "CONTACT_COMPANY_DELETED" + }, + { + label: "Contact Company Updated", + value: "CONTACT_COMPANY_UPDATED" + }, + { + label: "Contact Created", + value: "CONTACT_CREATED" + }, + { + label: "Contact Deleted", + value: "CONTACT_DELETED" + }, + { + label: "Contact Updated", + value: "CONTACT_UPDATED" + }, + { + label: "Customer Created", + value: "CUSTOMER_CREATED" + }, + { + label: "Customer Updated", + value: "CUSTOMER_UPDATED" + }, + { + label: "Document Deleted", + value: "DOCUMENT_DELETED" + }, + { + label: "Document Downloaded", + value: "DOCUMENT_DOWNLOADED" + }, + { + label: "Document Saved", + value: "DOCUMENT_SAVED" + }, + { + label: "Document Updated", + value: "DOCUMENT_UPDATED" + }, + { + label: "Flow Archived", + value: "FLOW_ARCHIVED" + }, + { + label: "Flow Created", + value: "FLOW_CREATED" + }, + { + label: "Flow Object Automation Action Created", + value: "FLOW_OBJECT_AUTOMATION_ACTION_CREATED" + }, + { + label: "Flow Object Automation Action Deleted", + value: "FLOW_OBJECT_AUTOMATION_ACTION_DELETED" + }, + { + label: "Flow Object Automation Created", + value: "FLOW_OBJECT_AUTOMATION_CREATED" + }, + { + label: "Flow Object Automation Deleted", + value: "FLOW_OBJECT_AUTOMATION_DELETED" + }, + { + label: "Flow Object Automation Updated", + value: "FLOW_OBJECT_AUTOMATION_UPDATED" + }, + { + label: "Flow Object Automation Webdav Created", + value: "FLOW_OBJECT_AUTOMATION_WEBDAV_CREATED" + }, + { + label: "Flow Object Automation Webdav Deleted", + value: "FLOW_OBJECT_AUTOMATION_WEBDAV_DELETED" + }, + { + label: "Flow Object Automation Webdav Updated", + value: "FLOW_OBJECT_AUTOMATION_WEBDAV_UPDATED" + }, + { + label: "Flow Object Created", + value: "FLOW_OBJECT_CREATED" + }, + { + label: "Flow Object Deleted", + value: "FLOW_OBJECT_DELETED" + }, + { + label: "Flow Object Document Added", + value: "FLOW_OBJECT_DOCUMENT_ADDED" + }, + { + label: "Flow Object Document Removed", + value: "FLOW_OBJECT_DOCUMENT_REMOVED" + }, + { + label: "Flow Object Resource Created", + value: "FLOW_OBJECT_RESOURCE_CREATED" + }, + { + label: "Flow Object Resource Deleted", + value: "FLOW_OBJECT_RESOURCE_DELETED" + }, + { + label: "Flow Object Resource Updated", + value: "FLOW_OBJECT_RESOURCE_UPDATED" + }, + { + label: "Flow Object Task Condition Created", + value: "FLOW_OBJECT_TASK_CONDITION_CREATED" + }, + { + label: "Flow Object Task Condition Deleted", + value: "FLOW_OBJECT_TASK_CONDITION_DELETED" + }, + { + label: "Flow Object Task Condition Updated", + value: "FLOW_OBJECT_TASK_CONDITION_UPDATED" + }, + { + label: "Flow Object Task Created", + value: "FLOW_OBJECT_TASK_CREATED" + }, + { + label: "Flow Object Task Deleted", + value: "FLOW_OBJECT_TASK_DELETED" + }, + { + label: "Flow Object Task Updated", + value: "FLOW_OBJECT_TASK_UPDATED" + }, + { + label: "Flow Object Updated", + value: "FLOW_OBJECT_UPDATED" + }, + { + label: "Flow Objects Connection Created", + value: "FLOW_OBJECTS_CONNECTION_CREATED" + }, + { + label: "Flow Objects Connection Deleted", + value: "FLOW_OBJECTS_CONNECTION_DELETED" + }, + { + label: "Flow Objects Connection Updated", + value: "FLOW_OBJECTS_CONNECTION_UPDATED" + }, + { + label: "Flow Objects External Connection Created", + value: "FLOW_OBJECTS_EXTERNAL_CONNECTION_CREATED" + }, + { + label: "Flow Objects External Connection Deleted", + value: "FLOW_OBJECTS_EXTERNAL_CONNECTION_DELETED" + }, + { + label: "Flow Objects External Connection Updated", + value: "FLOW_OBJECTS_EXTERNAL_CONNECTION_UPDATED" + }, + { + label: "Flow Objects External Connections Group Created", + value: "FLOW_OBJECTS_EXTERNAL_CONNECTIONS_GROUP_CREATED" + }, + { + label: "Flow Objects External Connections Group Deleted", + value: "FLOW_OBJECTS_EXTERNAL_CONNECTIONS_GROUP_DELETED" + }, + { + label: "Flow Objects External Connections Group Updated", + value: "FLOW_OBJECTS_EXTERNAL_CONNECTIONS_GROUP_UPDATED" + }, + { + label: "Flow Unarchived", + value: "FLOW_UNARCHIVED" + }, + { + label: "Flow Updated", + value: "FLOW_UPDATED" + }, + { + label: "Note Created", + value: "NOTE_CREATED" + }, + { + label: "Note Deleted", + value: "NOTE_DELETED" + }, + { + label: "Note Updated", + value: "NOTE_UPDATED" + }, + { + label: "Team Created", + value: "TEAM_CREATED" + }, + { + label: "Team Deleted", + value: "TEAM_DELETED" + }, + { + label: "Team Updated", + value: "TEAM_UPDATED" + }, + { + label: "User Added To Team", + value: "USER_ADDED_TO_TEAM" + }, + { + label: "User Added To Teamleads", + value: "USER_ADDED_TO_TEAMLEADS" + }, + { + label: "User Archived", + value: "USER_ARCHIVED" + }, + { + label: "User Changed Password", + value: "USER_CHANGED_PASSWORD" + }, + { + label: "User Created", + value: "USER_CREATED" + }, + { + label: "User Forgot Password", + value: "USER_FORGOT_PASSWORD" + }, + { + label: "User Invited", + value: "USER_INVITED" + }, + { + label: "User Logged In", + value: "USER_LOGGED_IN" + }, + { + label: "User Notification Settings Changed", + value: "USER_NOTIFICATION_SETTINGS_CHANGED" + }, + { + label: "User Profile Updated", + value: "USER_PROFILE_UPDATED" + }, + { + label: "User Removed From Team", + value: "USER_REMOVED_FROM_TEAM" + }, + { + label: "User Removed From Teamleads", + value: "USER_REMOVED_FROM_TEAMLEADS" + }, + { + label: "User Unarchived", + value: "USER_UNARCHIVED" + }, + { + label: "Workflow Archived", + value: "WORKFLOW_ARCHIVED" + }, + { + label: "Workflow Completed", + value: "WORKFLOW_COMPLETED" + }, + { + label: "Workflow Created", + value: "WORKFLOW_CREATED" + }, + { + label: "Workflow Creation Failed", + value: "WORKFLOW_CREATION_FAILED" + }, + { + label: "Workflow Object Automation Api Get Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_API_GET_COMPLETED" + }, + { + label: "Workflow Object Automation Api Get Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_API_GET_FAILED" + }, + { + label: "Workflow Object Automation Api Post Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_API_POST_COMPLETED" + }, + { + label: "Workflow Object Automation Api Post Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_API_POST_FAILED" + }, + { + label: "Workflow Object Automation Datev Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_DATEV_COMPLETED" + }, + { + label: "Workflow Object Automation Datev Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_DATEV_FAILED" + }, + { + label: "Workflow Object Automation Email Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_EMAIL_COMPLETED" + }, + { + label: "Workflow Object Automation Email Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_EMAIL_FAILED" + }, + { + label: "Workflow Object Automation Lexoffice Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_LEXOFFICE_COMPLETED" + }, + { + label: "Workflow Object Automation Lexoffice Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_LEXOFFICE_FAILED" + }, + { + label: "Workflow Object Automation Rejected", + value: "WORKFLOW_OBJECT_AUTOMATION_REJECTED" + }, + { + label: "Workflow Object Automation Retried", + value: "WORKFLOW_OBJECT_AUTOMATION_RETRIED" + }, + { + label: "Workflow Object Automation Sevdesk Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_SEVDESK_COMPLETED" + }, + { + label: "Workflow Object Automation Sevdesk Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_SEVDESK_FAILED" + }, + { + label: "Workflow Object Automation Stamp Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_STAMP_COMPLETED" + }, + { + label: "Workflow Object Automation Stamp Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_STAMP_FAILED" + }, + { + label: "Workflow Object Automation Task Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_TASK_COMPLETED" + }, + { + label: "Workflow Object Automation Task Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_TASK_FAILED" + }, + { + label: "Workflow Object Automation Template Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_TEMPLATE_COMPLETED" + }, + { + label: "Workflow Object Automation Template Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_TEMPLATE_FAILED" + }, + { + label: "Workflow Object Automation Webdav Document Uploaded", + value: "WORKFLOW_OBJECT_AUTOMATION_WEBDAV_DOCUMENT_UPLOADED" + }, + { + label: "Workflow Object Automation Zapier Completed", + value: "WORKFLOW_OBJECT_AUTOMATION_ZAPIER_COMPLETED" + }, + { + label: "Workflow Object Automation Zapier Failed", + value: "WORKFLOW_OBJECT_AUTOMATION_ZAPIER_FAILED" + }, + { + label: "Workflow Object Combination Task Group Created", + value: "WORKFLOW_OBJECT_COMBINATION_TASK_GROUP_CREATED" + }, + { + label: "Workflow Object Combination Task Group Deleted", + value: "WORKFLOW_OBJECT_COMBINATION_TASK_GROUP_DELETED" + }, + { + label: "Workflow Object Completed Automations Finished", + value: "WORKFLOW_OBJECT_COMPLETED_AUTOMATIONS_FINISHED" + }, + { + label: "Workflow Object Completed", + value: "WORKFLOW_OBJECT_COMPLETED" + }, + { + label: "Workflow Object Created", + value: "WORKFLOW_OBJECT_CREATED" + }, + { + label: "Workflow Object Document Added", + value: "WORKFLOW_OBJECT_DOCUMENT_ADDED" + }, + { + label: "Workflow Object Document Lock Added", + value: "WORKFLOW_OBJECT_DOCUMENT_LOCK_ADDED" + }, + { + label: "Workflow Object Document Lock Deleted", + value: "WORKFLOW_OBJECT_DOCUMENT_LOCK_DELETED" + }, + { + label: "Workflow Object Document Removed", + value: "WORKFLOW_OBJECT_DOCUMENT_REMOVED" + }, + { + label: "Workflow Object Email Added", + value: "WORKFLOW_OBJECT_EMAIL_ADDED" + }, + { + label: "Workflow Object Email Removed", + value: "WORKFLOW_OBJECT_EMAIL_REMOVED" + }, + { + label: "Workflow Object External User Created", + value: "WORKFLOW_OBJECT_EXTERNAL_USER_CREATED" + }, + { + label: "Workflow Object External User Deleted", + value: "WORKFLOW_OBJECT_EXTERNAL_USER_DELETED" + }, + { + label: "Workflow Object Note Added", + value: "WORKFLOW_OBJECT_NOTE_ADDED" + }, + { + label: "Workflow Object Note Removed", + value: "WORKFLOW_OBJECT_NOTE_REMOVED" + }, + { + label: "Workflow Object Resource Created", + value: "WORKFLOW_OBJECT_RESOURCE_CREATED" + }, + { + label: "Workflow Object Snapshot Created", + value: "WORKFLOW_OBJECT_SNAPSHOT_CREATED" + }, + { + label: "Workflow Object Task Condition Created", + value: "WORKFLOW_OBJECT_TASK_CONDITION_CREATED" + }, + { + label: "Workflow Object Task Created", + value: "WORKFLOW_OBJECT_TASK_CREATED" + }, + { + label: "Workflow Object Task Deleted", + value: "WORKFLOW_OBJECT_TASK_DELETED" + }, + { + label: "Workflow Object Task Snapshot Created", + value: "WORKFLOW_OBJECT_TASK_SNAPSHOT_CREATED" + }, + { + label: "Workflow Object Task Updated", + value: "WORKFLOW_OBJECT_TASK_UPDATED" + }, + { + label: "Workflow Object Updated", + value: "WORKFLOW_OBJECT_UPDATED" + }, + { + label: "Workflow Objects Connection Created", + value: "WORKFLOW_OBJECTS_CONNECTION_CREATED" + }, + { + label: "Workflow Objects External Connection Created", + value: "WORKFLOW_OBJECTS_EXTERNAL_CONNECTION_CREATED" + }, + { + label: "Workflow Objects External Connection Group Created", + value: "WORKFLOW_OBJECTS_EXTERNAL_CONNECTION_GROUP_CREATED" + }, + { + label: "Workflow Unarchived", + value: "WORKFLOW_UNARCHIVED" + }, + { + label: "Workflow Updated", + value: "WORKFLOW_UPDATED" + } +]; + +export default webhookFilters; \ No newline at end of file diff --git a/packages/backend/src/apps/flowers-software/index.ts b/packages/backend/src/apps/flowers-software/index.ts index 5206578..a023486 100644 --- a/packages/backend/src/apps/flowers-software/index.ts +++ b/packages/backend/src/apps/flowers-software/index.ts @@ -1,6 +1,7 @@ import defineApp from '../../helpers/define-app'; import addAuthHeader from './common/add-auth-header'; import auth from './auth'; +import triggers from './triggers'; export default defineApp({ name: 'Flowers Software', @@ -13,4 +14,5 @@ export default defineApp({ primaryColor: '02AFC7', beforeRequest: [addAuthHeader], auth, + triggers, }); diff --git a/packages/backend/src/apps/flowers-software/triggers/index.ts b/packages/backend/src/apps/flowers-software/triggers/index.ts new file mode 100644 index 0000000..5599f29 --- /dev/null +++ b/packages/backend/src/apps/flowers-software/triggers/index.ts @@ -0,0 +1,3 @@ +import newActivity from './new-activity'; + +export default [newActivity]; diff --git a/packages/backend/src/apps/flowers-software/triggers/new-activity/index.ts b/packages/backend/src/apps/flowers-software/triggers/new-activity/index.ts new file mode 100644 index 0000000..3cd2997 --- /dev/null +++ b/packages/backend/src/apps/flowers-software/triggers/new-activity/index.ts @@ -0,0 +1,54 @@ +import isEmpty from 'lodash/isEmpty'; +import defineTrigger from '../../../../helpers/define-trigger'; +import webhookFilters from '../../common/webhook-filters'; + +export default defineTrigger({ + name: 'New activity', + key: 'newActivity', + type: 'webhook', + description: 'Triggers when a new activity occurs.', + arguments: [ + { + label: 'Activity type', + key: 'filters', + type: 'dropdown' as const, + required: true, + description: 'Pick an activity type to receive events for.', + variables: false, + options: webhookFilters, + }, + ], + + async testRun($) { + if (!isEmpty($.lastExecutionStep?.dataOut)) { + $.pushTriggerItem({ + raw: $.lastExecutionStep.dataOut, + meta: { + internalId: '', + } + }); + } + }, + + async registerHook($) { + const payload = { + name: $.flow.id, + type: 'POST', + url: $.webhookUrl, + filters: [$.step.parameters.filters] + }; + + const { data } = await $.http.post( + `/v2/public/api/webhooks`, + payload + ); + + await $.flow.setRemoteWebhookId(data.id); + }, + + async unregisterHook($) { + await $.http.delete( + `/v2/public/api/webhooks/${$.flow.remoteWebhookId}` + ); + }, +}); From 1f80f843ba92209444683bbe4b266a7382458044 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Sat, 17 Dec 2022 00:54:49 +0300 Subject: [PATCH 57/64] docs: Add WEB_APP_URL and WEBHOOK_URL to configuration --- packages/docs/pages/advanced/configuration.md | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/packages/docs/pages/advanced/configuration.md b/packages/docs/pages/advanced/configuration.md index cfcb25c..c861f7c 100644 --- a/packages/docs/pages/advanced/configuration.md +++ b/packages/docs/pages/advanced/configuration.md @@ -14,26 +14,28 @@ The default values for some environment variables might be different in our deve Please be careful with the `ENCRYPTION_KEY` and `WEBHOOK_SECRET_KEY` environment variables. They are used to encrypt your credentials from third-party services and verify webhook requests. If you change them, your existing connections and flows will not continue to work. ::: -| Variable Name | Type | Default Value | Description | -| --------------------------- | ------- | ------------------ | --------------------------------------------- | -| `HOST` | string | `localhost` | HTTP Host | -| `PROTOCOL` | string | `http` | HTTP Protocol | -| `PORT` | string | `3000` | HTTP Port | -| `APP_ENV` | string | `production` | Automatisch Environment | -| `POSTGRES_DATABASE` | string | `automatisch` | Database Name | -| `POSTGRES_PORT` | number | `5432` | Database Port | -| `POSTGRES_HOST` | string | `postgres` | Database Host | -| `POSTGRES_USERNAME` | string | `automatisch_user` | Database User | -| `POSTGRES_PASSWORD` | string | | Password of Database User | -| `ENCRYPTION_KEY` | string | | Encryption Key to store credentials | -| `WEBHOOK_SECRET_KEY` | string | | Webhook Secret Key to verify webhook requests | -| `APP_SECRET_KEY` | string | | Secret Key to authenticate the user | -| `REDIS_HOST` | string | `redis` | Redis Host | -| `REDIS_PORT` | number | `6379` | Redis Port | -| `REDIS_USERNAME` | string | `` | Redis Username | -| `REDIS_PASSWORD` | string | `` | Redis Password | -| `REDIS_TLS` | boolean | `false` | Redis TLS | -| `TELEMETRY_ENABLED` | boolean | `true` | Enable/Disable Telemetry | -| `ENABLE_BULLMQ_DASHBOARD` | boolean | `false` | Enable BullMQ Dashboard | -| `BULLMQ_DASHBOARD_USERNAME` | string | | Username to login BullMQ Dashboard | -| `BULLMQ_DASHBOARD_PASSWORD` | string | | Password to login BullMQ Dashboard | +| Variable Name | Type | Default Value | Description | +| --------------------------- | ------- | ------------------ | ---------------------------------------------------- | +| `HOST` | string | `localhost` | HTTP Host | +| `PROTOCOL` | string | `http` | HTTP Protocol | +| `PORT` | string | `3000` | HTTP Port | +| `APP_ENV` | string | `production` | Automatisch Environment | +| `WEB_APP_URL` | string | | Can be used to override connection URLs and CORS URL | +| `WEBHOOK_URL` | string | | Can be used to override webhook URL | +| `POSTGRES_DATABASE` | string | `automatisch` | Database Name | +| `POSTGRES_PORT` | number | `5432` | Database Port | +| `POSTGRES_HOST` | string | `postgres` | Database Host | +| `POSTGRES_USERNAME` | string | `automatisch_user` | Database User | +| `POSTGRES_PASSWORD` | string | | Password of Database User | +| `ENCRYPTION_KEY` | string | | Encryption Key to store credentials | +| `WEBHOOK_SECRET_KEY` | string | | Webhook Secret Key to verify webhook requests | +| `APP_SECRET_KEY` | string | | Secret Key to authenticate the user | +| `REDIS_HOST` | string | `redis` | Redis Host | +| `REDIS_PORT` | number | `6379` | Redis Port | +| `REDIS_USERNAME` | string | | Redis Username | +| `REDIS_PASSWORD` | string | | Redis Password | +| `REDIS_TLS` | boolean | `false` | Redis TLS | +| `TELEMETRY_ENABLED` | boolean | `true` | Enable/Disable Telemetry | +| `ENABLE_BULLMQ_DASHBOARD` | boolean | `false` | Enable BullMQ Dashboard | +| `BULLMQ_DASHBOARD_USERNAME` | string | | Username to login BullMQ Dashboard | +| `BULLMQ_DASHBOARD_PASSWORD` | string | | Password to login BullMQ Dashboard | From f3b1b2254f5d1d48e25a42d6fa5dc645a5a9a858 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Sat, 17 Dec 2022 01:04:03 +0300 Subject: [PATCH 58/64] docs: Add connection and actions pages for delay app --- packages/docs/pages/.vitepress/config.js | 9 +++++++++ packages/docs/pages/apps/delay/actions.md | 14 ++++++++++++++ packages/docs/pages/apps/delay/connection.md | 3 +++ packages/docs/pages/guide/available-apps.md | 1 + packages/docs/pages/public/favicons/delay.svg | 7 +++++++ 5 files changed, 34 insertions(+) create mode 100644 packages/docs/pages/apps/delay/actions.md create mode 100644 packages/docs/pages/apps/delay/connection.md create mode 100644 packages/docs/pages/public/favicons/delay.svg diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 4179c23..b736150 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -41,6 +41,15 @@ export default defineConfig({ { text: 'Connection', link: '/apps/deepl/connection' }, ], }, + { + text: 'Delay', + collapsible: true, + collapsed: true, + items: [ + { text: 'Actions', link: '/apps/delay/actions' }, + { text: 'Connection', link: '/apps/delay/connection' }, + ], + }, { text: 'Discord', collapsible: true, diff --git a/packages/docs/pages/apps/delay/actions.md b/packages/docs/pages/apps/delay/actions.md new file mode 100644 index 0000000..00e1495 --- /dev/null +++ b/packages/docs/pages/apps/delay/actions.md @@ -0,0 +1,14 @@ +--- +favicon: /favicons/delay.svg +items: + - name: Delay For + desc: Delays the execution of the next action by a specified amount of time. + - name: Delay Until + desc: Delays the execution of the next action until a specified date. +--- + + + + diff --git a/packages/docs/pages/apps/delay/connection.md b/packages/docs/pages/apps/delay/connection.md new file mode 100644 index 0000000..a2eec35 --- /dev/null +++ b/packages/docs/pages/apps/delay/connection.md @@ -0,0 +1,3 @@ +# Delay + +Delay is a built-in app shipped with Automatisch, and it doesn't need to talk with any other external service to run. So there are no additional steps to use the Delay app. It can be used only as an action and it delays the execution of the next action by a specified amount of time. diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md index e28bc1a..2edd2db 100644 --- a/packages/docs/pages/guide/available-apps.md +++ b/packages/docs/pages/guide/available-apps.md @@ -7,6 +7,7 @@ We just have a few available integrations at the moment and we also know that wo Following integrations are currently supported by Automatisch. - [DeepL](/apps/deepl/actions) +- [Delay](/apps/delay/actions) - [Discord](/apps/discord/actions) - [Flickr](/apps/flickr/triggers) - [Github](/apps/github/triggers) diff --git a/packages/docs/pages/public/favicons/delay.svg b/packages/docs/pages/public/favicons/delay.svg new file mode 100644 index 0000000..af5da4d --- /dev/null +++ b/packages/docs/pages/public/favicons/delay.svg @@ -0,0 +1,7 @@ + + + + + + + From 56dbe62cade57c2a64859235f91a9b34af8b9f0b Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Sat, 17 Dec 2022 01:37:59 +0300 Subject: [PATCH 59/64] docs: Update advantages section of Automatisch --- README.md | 2 +- packages/docs/pages/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e285f91..842c31c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ There are other existing solutions in the market, like Zapier and Integromat, so you might be wondering why you should use Automatisch. -✅ The most significant advantage of having Automatisch is keeping your data on your own servers. Not all companies want to use an automation service in the cloud, and the current open-source or self-hosted solutions mainly focus on developers rather than a user without a technical background. +✅ The most significant advantage of having Automatisch is keeping your data on your own servers, which is a critical requirement for companies with private user data that can't be shared with any other external cloud service. This is especially important for companies in some sectors like healthcare or financial and also European companies that must comply with GDPR. 🤓 Your contributions are vital to the development of Automatisch. As an open-source software, anyone can have an impact on how it is being developed. diff --git a/packages/docs/pages/index.md b/packages/docs/pages/index.md index 437ff62..a4b7214 100644 --- a/packages/docs/pages/index.md +++ b/packages/docs/pages/index.md @@ -28,7 +28,7 @@ You need to prepare the workflow once, and it will run continuously until you st There are other existing solutions in the market, like Zapier and Integromat, so you might be wondering why you should use Automatisch. -✅ The most significant advantage of having Automatisch is **keeping your data on your own servers**. Not all companies want to use an automation service in the cloud, and the current open-source or self-hosted solutions mainly focus on developers rather than a user without a technical background. +✅ The most significant advantage of having Automatisch is **keeping your data on your own servers**, which is a critical requirement for companies with private user data that can't be shared with any other external cloud service. This is especially important for companies in some sectors like healthcare or financial and also European companies that must comply with GDPR. 🤓 Your contributions are vital to the development of Automatisch. As an **open-source software**, anyone can have an impact on how it is being developed. From 2e542164691a7492839937ad8d8dcd429b05742d Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Sat, 17 Dec 2022 02:05:09 +0300 Subject: [PATCH 60/64] chore: Update readme to refer installation guide --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 842c31c..91e81df 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ docker compose up You can use `user@automatisch.io` email address and `sample` password to login to Automatisch. Please do not forget to change your email and password from the settings page. +For other installation types, you can check the [installation](https://automatisch.io/docs/guide/installation) guide. + ## Community Links - [Discord](https://discord.gg/dJSah9CVrC) From 5f76aa02dd90f288a91dcb3af91572d05fd5d4a3 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Sat, 17 Dec 2022 03:19:25 +0300 Subject: [PATCH 61/64] docs: Adjust advantages text of Automatisch --- README.md | 2 +- packages/docs/pages/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 91e81df..e87c7a6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ There are other existing solutions in the market, like Zapier and Integromat, so you might be wondering why you should use Automatisch. -✅ The most significant advantage of having Automatisch is keeping your data on your own servers, which is a critical requirement for companies with private user data that can't be shared with any other external cloud service. This is especially important for companies in some sectors like healthcare or financial and also European companies that must comply with GDPR. +✅ One of the main benefits of using Automatisch is that it allows you to store your data on your own servers, which is essential for businesses that handle sensitive user information and cannot risk sharing it with external cloud services. This is especially relevant for industries such as healthcare and finance, as well as for European companies that must adhere to the General Data Protection Regulation (GDPR). 🤓 Your contributions are vital to the development of Automatisch. As an open-source software, anyone can have an impact on how it is being developed. diff --git a/packages/docs/pages/index.md b/packages/docs/pages/index.md index a4b7214..864a34f 100644 --- a/packages/docs/pages/index.md +++ b/packages/docs/pages/index.md @@ -28,7 +28,7 @@ You need to prepare the workflow once, and it will run continuously until you st There are other existing solutions in the market, like Zapier and Integromat, so you might be wondering why you should use Automatisch. -✅ The most significant advantage of having Automatisch is **keeping your data on your own servers**, which is a critical requirement for companies with private user data that can't be shared with any other external cloud service. This is especially important for companies in some sectors like healthcare or financial and also European companies that must comply with GDPR. +✅ One of the main benefits of using Automatisch is that it allows you to **store your data on your own servers**, which is essential for businesses that handle sensitive user information and cannot risk sharing it with external cloud services. This is especially relevant for industries such as healthcare and finance, as well as for European companies that must adhere to the General Data Protection Regulation (GDPR). 🤓 Your contributions are vital to the development of Automatisch. As an **open-source software**, anyone can have an impact on how it is being developed. From a3348649800fc655d6bb7c798d7d026c4510cb85 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Sat, 17 Dec 2022 20:40:44 +0300 Subject: [PATCH 62/64] chore: Cover different architectures in Dockerfile --- .yarnrc | 1 + docker/Dockerfile | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 .yarnrc diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 0000000..568d245 --- /dev/null +++ b/.yarnrc @@ -0,0 +1 @@ +network-timeout 400000 diff --git a/docker/Dockerfile b/docker/Dockerfile index 2468dde..12683b6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,9 +2,13 @@ FROM node:16-alpine WORKDIR /automatisch +RUN apk --no-cache add --virtual build-dependencies python3 build-base + COPY ./entrypoint.sh /entrypoint.sh RUN yarn global add @automatisch/cli@0.3.0 +RUN apk del build-dependencies python3 build-base + EXPOSE 3000 ENTRYPOINT ["sh", "/entrypoint.sh"] From 74ebe492c584fd6894341f90dd3fd711e699565c Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 21 Dec 2022 23:07:40 +0300 Subject: [PATCH 63/64] docs: Add usage of ngrok for webhook-based trigger development --- packages/docs/pages/build-integrations/examples.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/docs/pages/build-integrations/examples.md b/packages/docs/pages/build-integrations/examples.md index 4a957a1..308be03 100644 --- a/packages/docs/pages/build-integrations/examples.md +++ b/packages/docs/pages/build-integrations/examples.md @@ -49,6 +49,10 @@ The build integrations section is best understood when read from beginning to en ### Webhook-based triggers +:::warning +If you are developing a webhook-based trigger, you need to ensure that the webhook is publicly accessible. You can use [ngrok](https://ngrok.com) for this purpose and override the webhook URL by setting the **WEBHOOK_URL** environment variable. +::: + - [New entry - Typeform](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/typeform/triggers/new-entry/index.ts) ### Pagination with descending order From faf151cd62d5ce26034d1e8b64f79aca46b60c44 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Fri, 23 Dec 2022 01:02:35 +0300 Subject: [PATCH 64/64] docs: Add the guide for how to create flows --- packages/docs/pages/guide/create-flow.md | 54 +++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/packages/docs/pages/guide/create-flow.md b/packages/docs/pages/guide/create-flow.md index a099036..4f7e849 100644 --- a/packages/docs/pages/guide/create-flow.md +++ b/packages/docs/pages/guide/create-flow.md @@ -1 +1,53 @@ -TBD +# Create Flow + +To understand how we can create a flow, it's better to start with a real use case. Let's say we want to create a flow that will fetch new submissions from Typeform and then send them to a Slack channel. To do that, we will use [Typeform](/apps/typeform/triggers) and [Slack](/apps/slack/actions) apps. Let's start with creating connections for these apps. + +## Typeform connection + +- Go to the **My Apps** page in Automatisch and click on **Add connection** button. +- Select the **Typeform** app from the list. +- It will ask you `Client ID` and `Client Secret` from Typeform and there is an information box above the fields. +- Click on **our documentation** link in the information box and follow the instructions to get the `Client ID` and `Client Secret` from Typeform. + +:::tip +Whenever you want to create a connection for an app, you can click on **our documentation** link in the information box to learn how to create a connection for that specific app. +::: + +- After you get the `Client ID` and `Client Secret` from Typeform, you can paste them to the fields in Automatisch and click on **Submit** button. + +## Slack connection + +- Go to the **My Apps** page in Automatisch and click on **Add connection** button. +- Select the **Slack** app from the list. +- It will ask you `API Key` and `API Secret` values from Slack and there is an information box above the fields. +- Click on **our documentation** link in the information box and follow the instructions to get the `API Key` and `API Secret` from Slack. +- After you get the `API Key` and `API Secret` from Slack, you can paste them into the fields in Automatisch and click on **Submit** button. + +## Build the flow + +### Trigger step + +- Go to the **Flows** page in Automatisch and click on **Create flow** button. +- It will give you empty trigger and action steps. +- For the trigger step (1st step), select the **Typeform** app from `Choose an app` dropdown. +- Select the **New entry** as the trigger event and click on the **Continue** button. +- It will ask you to select the connection you created for the Typeform app. Select the connection you have just created and click on the **Continue** button. +- Select the form you want to get the new entries from and click on the **Continue** button. +- Click on **Test & Continue** button to test the trigger step. If you see the data that reflects the recent submission in the form, you can continue to the next (action) step. + +### Action step + +- For the action step (2nd step), select the **Slack** app from `Choose an app` dropdown. +- Select the **Send a message to channel** as the action event and click on the **Continue** button. +- It will ask you to select the connection you created for the Slack app. Select the connection you have just created and click on the **Continue** button. +- Select the channel you want to send the message to. +- Write the message you want to send to the channel. You can use variables in the message from the trigger step. +- Select `Yes` for the `Send as a bot` option. +- Give a name for the bot and click on the **Continue** button. +- Click on **Test & Continue** button to test the action step. If you see the message in the Slack channel you selected, we can say that the flow is working as expected and is ready to be published. + +### Publish the flow + +- Click on the **Publish** button to publish the flow. +- Published flows will be executed automatically when the trigger event happens or at intervals of 15 minutes depending on the trigger type. +- You can not change the flow after it's published. If you want to change the flow, you need to unpublish it first and then make the changes.