Compare commits
117 Commits
dependabot
...
AUT-1324
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d31309a92d | ||
|
|
0234b4ad81 | ||
|
|
59ee9c21f3 | ||
|
|
00317fed24 | ||
|
|
42f6311ca8 | ||
|
|
0f77a1ec03 | ||
|
|
8268cd4d09 | ||
|
|
c868070337 | ||
|
|
623ec66a79 | ||
|
|
b51bae14ec | ||
|
|
9250456e7b | ||
|
|
163d6a7a28 | ||
|
|
4ce9976dbc | ||
|
|
f6490990de | ||
|
|
f24ff606ac | ||
|
|
3ff53744b5 | ||
|
|
0b33c10ed8 | ||
|
|
3fa87701ed | ||
|
|
e5e0c6fa2a | ||
|
|
0b38a0b6af | ||
|
|
44b228777a | ||
|
|
dd4f658d14 | ||
|
|
9c66f47bca | ||
|
|
138a34d6a4 | ||
|
|
8f2af2e863 | ||
|
|
c732fe16b3 | ||
|
|
9be75e56e7 | ||
|
|
e7d1f26034 | ||
|
|
c554fff048 | ||
|
|
0268521aaa | ||
|
|
89b1cb9353 | ||
|
|
8a17c5eaab | ||
|
|
f4a1ad6c8c | ||
|
|
93d76d8d79 | ||
|
|
0b956a71b9 | ||
|
|
26be72f76d | ||
|
|
737391c721 | ||
|
|
9c1d21fd1b | ||
|
|
ef4a4c8611 | ||
|
|
13c0a8ceaa | ||
|
|
c2976080f6 | ||
|
|
0a1b6931af | ||
|
|
5009319f91 | ||
|
|
4db8683bd6 | ||
|
|
d35cf8d31e | ||
|
|
5fef16131a | ||
|
|
8b2235ee26 | ||
|
|
2d8faf849e | ||
|
|
c9de9fa185 | ||
|
|
0618877d58 | ||
|
|
f6b4e7eef8 | ||
|
|
7abe44da19 | ||
|
|
9006a0c25f | ||
|
|
f8389ff8ab | ||
|
|
894afe8f92 | ||
|
|
115394ac8c | ||
|
|
de42eda65f | ||
|
|
0b7591edce | ||
|
|
a043a044ca | ||
|
|
b1f2727beb | ||
|
|
d6e78a48a0 | ||
|
|
589fe0f5f3 | ||
|
|
244eeeb816 | ||
|
|
4d5fc50f1a | ||
|
|
dc0273148c | ||
|
|
5e6f4bfb88 | ||
|
|
bc0e18d074 | ||
|
|
24d09fda4c | ||
|
|
5e20ac07d1 | ||
|
|
37c78e6bbd | ||
|
|
7dcfb1081b | ||
|
|
01407cf040 | ||
|
|
eb814c2fb0 | ||
|
|
d3caadf4af | ||
|
|
5769c82fca | ||
|
|
3754783ce2 | ||
|
|
55ebe2cc0b | ||
|
|
23c1a42163 | ||
|
|
c879ffa768 | ||
|
|
32f7bbfbab | ||
|
|
84d5b3b158 | ||
|
|
c8dae9ea9a | ||
|
|
cbfb5dd8a6 | ||
|
|
09b2b7350c | ||
|
|
e146793d32 | ||
|
|
0bad2ead10 | ||
|
|
25176884e7 | ||
|
|
266d4cddb0 | ||
|
|
6e529a4205 | ||
|
|
d2cce278bd | ||
|
|
b774a62f8c | ||
|
|
66c12e1a92 | ||
|
|
184d748890 | ||
|
|
8cc732c8d1 | ||
|
|
c688d67e4b | ||
|
|
3408be2840 | ||
|
|
e126066132 | ||
|
|
cfec447d8a | ||
|
|
805d1fdd52 | ||
|
|
9299948072 | ||
|
|
b02960a5ec | ||
|
|
8134b6db6a | ||
|
|
cd16a3cc15 | ||
|
|
074e7828f3 | ||
|
|
5f7d1f9219 | ||
|
|
b29c6105a1 | ||
|
|
1297f5d43c | ||
|
|
f94a5385d7 | ||
|
|
8ef2000e45 | ||
|
|
30d496076b | ||
|
|
5de06d4482 | ||
|
|
97fa983305 | ||
|
|
dccc3c5bc1 | ||
|
|
ed12465975 | ||
|
|
b78be222d7 | ||
|
|
342990e1bf | ||
|
|
2e5dfdbb0d |
4
.github/workflows/playwright.yml
vendored
4
.github/workflows/playwright.yml
vendored
@@ -12,6 +12,9 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
BULLMQ_DASHBOARD_USERNAME: root
|
||||||
|
BULLMQ_DASHBOARD_PASSWORD: sample
|
||||||
|
ENABLE_BULLMQ_DASHBOARD: true
|
||||||
ENCRYPTION_KEY: sample_encryption_key
|
ENCRYPTION_KEY: sample_encryption_key
|
||||||
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
||||||
APP_SECRET_KEY: sample_app_secret_key
|
APP_SECRET_KEY: sample_app_secret_key
|
||||||
@@ -22,6 +25,7 @@ env:
|
|||||||
POSTGRES_PASSWORD: automatisch_password
|
POSTGRES_PASSWORD: automatisch_password
|
||||||
REDIS_HOST: localhost
|
REDIS_HOST: localhost
|
||||||
APP_ENV: production
|
APP_ENV: production
|
||||||
|
PORT: 3000
|
||||||
LICENSE_KEY: dummy_license_key
|
LICENSE_KEY: dummy_license_key
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -23,8 +23,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bull-board/express": "^3.10.1",
|
"@bull-board/express": "^3.10.1",
|
||||||
"@casl/ability": "^6.5.0",
|
"@casl/ability": "^6.5.0",
|
||||||
"@graphql-tools/graphql-file-loader": "^7.3.4",
|
|
||||||
"@graphql-tools/load": "^7.5.2",
|
|
||||||
"@node-saml/passport-saml": "^4.0.4",
|
"@node-saml/passport-saml": "^4.0.4",
|
||||||
"@rudderstack/rudder-sdk-node": "^1.1.2",
|
"@rudderstack/rudder-sdk-node": "^1.1.2",
|
||||||
"@sentry/node": "^7.42.0",
|
"@sentry/node": "^7.42.0",
|
||||||
@@ -41,11 +39,7 @@
|
|||||||
"express": "~4.18.2",
|
"express": "~4.18.2",
|
||||||
"express-async-errors": "^3.1.1",
|
"express-async-errors": "^3.1.1",
|
||||||
"express-basic-auth": "^1.2.1",
|
"express-basic-auth": "^1.2.1",
|
||||||
"express-graphql": "^0.12.0",
|
|
||||||
"fast-xml-parser": "^4.0.11",
|
"fast-xml-parser": "^4.0.11",
|
||||||
"graphql-middleware": "^6.1.15",
|
|
||||||
"graphql-shield": "^7.5.0",
|
|
||||||
"graphql-tools": "^8.2.0",
|
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
"http-errors": "~1.6.3",
|
"http-errors": "~1.6.3",
|
||||||
"http-proxy-agent": "^7.0.0",
|
"http-proxy-agent": "^7.0.0",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.airtable.com',
|
apiBaseUrl: 'https://api.airtable.com',
|
||||||
iconUrl: '{BASE_URL}/apps/airtable/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/airtable/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/airtable/connection',
|
authDocUrl: '{DOCS_URL}/apps/airtable/connection',
|
||||||
primaryColor: 'FFBF00',
|
primaryColor: '#FFBF00',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://cloud.appwrite.io',
|
apiBaseUrl: 'https://cloud.appwrite.io',
|
||||||
iconUrl: '{BASE_URL}/apps/appwrite/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/appwrite/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/appwrite/connection',
|
authDocUrl: '{DOCS_URL}/apps/appwrite/connection',
|
||||||
primaryColor: 'FD366E',
|
primaryColor: '#FD366E',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/azure-openai/connection',
|
authDocUrl: '{DOCS_URL}/apps/azure-openai/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://carbone.io',
|
baseUrl: 'https://carbone.io',
|
||||||
apiBaseUrl: 'https://api.carbone.io',
|
apiBaseUrl: 'https://api.carbone.io',
|
||||||
primaryColor: '6f42c1',
|
primaryColor: '#6f42c1',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ export default defineApp({
|
|||||||
baseUrl: 'https://clickup.com',
|
baseUrl: 'https://clickup.com',
|
||||||
apiBaseUrl: 'https://api.clickup.com/api',
|
apiBaseUrl: 'https://api.clickup.com/api',
|
||||||
iconUrl: '{BASE_URL}/apps/clickup/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/clickup/assets/favicon.svg',
|
||||||
authDocUrl: 'https://automatisch.io/docs/apps/clickup/connection',
|
authDocUrl: '{DOCS_URL}/apps/clickup/connection',
|
||||||
primaryColor: 'FD71AF',
|
primaryColor: '#FD71AF',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/code/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/code/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/code/connection',
|
authDocUrl: '{DOCS_URL}/apps/code/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://deepl.com',
|
baseUrl: 'https://deepl.com',
|
||||||
apiBaseUrl: 'https://api.deepl.com',
|
apiBaseUrl: 'https://api.deepl.com',
|
||||||
primaryColor: '0d2d45',
|
primaryColor: '#0d2d45',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://discord.com',
|
baseUrl: 'https://discord.com',
|
||||||
apiBaseUrl: 'https://discord.com/api',
|
apiBaseUrl: 'https://discord.com/api',
|
||||||
primaryColor: '5865f2',
|
primaryColor: '#5865f2',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
dynamicData,
|
dynamicData,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://disqus.com/api',
|
apiBaseUrl: 'https://disqus.com/api',
|
||||||
iconUrl: '{BASE_URL}/apps/disqus/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/disqus/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/disqus/connection',
|
authDocUrl: '{DOCS_URL}/apps/disqus/connection',
|
||||||
primaryColor: '2E9FFF',
|
primaryColor: '#2E9FFF',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://dropbox.com',
|
baseUrl: 'https://dropbox.com',
|
||||||
apiBaseUrl: 'https://api.dropboxapi.com',
|
apiBaseUrl: 'https://api.dropboxapi.com',
|
||||||
primaryColor: '0061ff',
|
primaryColor: '#0061ff',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/flickr/connection',
|
authDocUrl: '{DOCS_URL}/apps/flickr/connection',
|
||||||
docUrl: 'https://automatisch.io/docs/flickr',
|
docUrl: 'https://automatisch.io/docs/flickr',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://www.flickr.com/',
|
baseUrl: 'https://www.flickr.com/',
|
||||||
apiBaseUrl: 'https://www.flickr.com/services',
|
apiBaseUrl: 'https://www.flickr.com/services',
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://flowers-software.com',
|
baseUrl: 'https://flowers-software.com',
|
||||||
apiBaseUrl: 'https://webapp.flowers-software.com/api',
|
apiBaseUrl: 'https://webapp.flowers-software.com/api',
|
||||||
primaryColor: '02AFC7',
|
primaryColor: '#02AFC7',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
dynamicFields,
|
dynamicFields,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/ghost/connection',
|
authDocUrl: '{DOCS_URL}/apps/ghost/connection',
|
||||||
primaryColor: '15171A',
|
primaryColor: '#15171A',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.github.com',
|
apiBaseUrl: 'https://api.github.com',
|
||||||
iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/github/connection',
|
authDocUrl: '{DOCS_URL}/apps/github/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://gitlab.com',
|
apiBaseUrl: 'https://gitlab.com',
|
||||||
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/gitlab/connection',
|
authDocUrl: '{DOCS_URL}/apps/gitlab/connection',
|
||||||
primaryColor: 'FC6D26',
|
primaryColor: '#FC6D26',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://www.googleapis.com/calendar',
|
apiBaseUrl: 'https://www.googleapis.com/calendar',
|
||||||
iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-calendar/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-calendar/connection',
|
||||||
primaryColor: '448AFF',
|
primaryColor: '#448AFF',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://www.googleapis.com/drive',
|
apiBaseUrl: 'https://www.googleapis.com/drive',
|
||||||
iconUrl: '{BASE_URL}/apps/google-drive/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-drive/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-drive/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-drive/connection',
|
||||||
primaryColor: '1FA463',
|
primaryColor: '#1FA463',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://forms.googleapis.com',
|
apiBaseUrl: 'https://forms.googleapis.com',
|
||||||
iconUrl: '{BASE_URL}/apps/google-forms/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-forms/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-forms/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-forms/connection',
|
||||||
primaryColor: '673AB7',
|
primaryColor: '#673AB7',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://sheets.googleapis.com',
|
apiBaseUrl: 'https://sheets.googleapis.com',
|
||||||
iconUrl: '{BASE_URL}/apps/google-sheets/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-sheets/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-sheets/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-sheets/connection',
|
||||||
primaryColor: '0F9D58',
|
primaryColor: '#0F9D58',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://tasks.googleapis.com',
|
apiBaseUrl: 'https://tasks.googleapis.com',
|
||||||
iconUrl: '{BASE_URL}/apps/google-tasks/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-tasks/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-tasks/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-tasks/connection',
|
||||||
primaryColor: '0066DA',
|
primaryColor: '#0066DA',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://app.tryhelix.ai',
|
apiBaseUrl: 'https://app.tryhelix.ai',
|
||||||
iconUrl: '{BASE_URL}/apps/helix/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/helix/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/helix/connection',
|
authDocUrl: '{DOCS_URL}/apps/helix/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://www.hubspot.com',
|
baseUrl: 'https://www.hubspot.com',
|
||||||
apiBaseUrl: 'https://api.hubapi.com',
|
apiBaseUrl: 'https://api.hubapi.com',
|
||||||
primaryColor: 'F95C35',
|
primaryColor: '#F95C35',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://invoicing.co/api',
|
apiBaseUrl: 'https://invoicing.co/api',
|
||||||
iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/invoice-ninja/connection',
|
authDocUrl: '{DOCS_URL}/apps/invoice-ninja/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ export default defineApp({
|
|||||||
name: 'Jotform',
|
name: 'Jotform',
|
||||||
key: 'jotform',
|
key: 'jotform',
|
||||||
iconUrl: '{BASE_URL}/apps/jotform/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/jotform/assets/favicon.svg',
|
||||||
authDocUrl: 'https://automatisch.io/docs/apps/jotform/connection',
|
authDocUrl: '{DOCS_URL}/apps/jotform/connection',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://www.jotform.com',
|
baseUrl: 'https://www.jotform.com',
|
||||||
apiBaseUrl: 'https://api.jotform.com',
|
apiBaseUrl: 'https://api.jotform.com',
|
||||||
primaryColor: 'FF6100',
|
primaryColor: '#FF6100',
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ export default defineApp({
|
|||||||
baseUrl: 'https://mailchimp.com',
|
baseUrl: 'https://mailchimp.com',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/mailchimp/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/mailchimp/assets/favicon.svg',
|
||||||
authDocUrl: 'https://automatisch.io/docs/apps/mailchimp/connection',
|
authDocUrl: '{DOCS_URL}/apps/mailchimp/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ export default defineApp({
|
|||||||
name: 'MailerLite',
|
name: 'MailerLite',
|
||||||
key: 'mailerlite',
|
key: 'mailerlite',
|
||||||
iconUrl: '{BASE_URL}/apps/mailerlite/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/mailerlite/assets/favicon.svg',
|
||||||
authDocUrl: 'https://automatisch.io/docs/apps/mailerlite/connection',
|
authDocUrl: '{DOCS_URL}/apps/mailerlite/connection',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://www.mailerlite.com',
|
baseUrl: 'https://www.mailerlite.com',
|
||||||
apiBaseUrl: 'https://connect.mailerlite.com/api',
|
apiBaseUrl: 'https://connect.mailerlite.com/api',
|
||||||
primaryColor: '09C269',
|
primaryColor: '#09C269',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
authDocUrl: '{DOCS_URL}/apps/mattermost/connection',
|
authDocUrl: '{DOCS_URL}/apps/mattermost/connection',
|
||||||
baseUrl: 'https://mattermost.com',
|
baseUrl: 'https://mattermost.com',
|
||||||
apiBaseUrl: '', // there is no cloud version of this app, user always need to provide address of own instance when creating connection
|
apiBaseUrl: '', // there is no cloud version of this app, user always need to provide address of own instance when creating connection
|
||||||
primaryColor: '4a154b',
|
primaryColor: '#4a154b',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addXRequestedWithHeader, addAuthHeader],
|
beforeRequest: [setBaseUrl, addXRequestedWithHeader, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.miro.com',
|
apiBaseUrl: 'https://api.miro.com',
|
||||||
iconUrl: '{BASE_URL}/apps/miro/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/miro/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/miro/connection',
|
authDocUrl: '{DOCS_URL}/apps/miro/connection',
|
||||||
primaryColor: 'F2CA02',
|
primaryColor: '#F2CA02',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.notion.com',
|
apiBaseUrl: 'https://api.notion.com',
|
||||||
iconUrl: '{BASE_URL}/apps/notion/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/notion/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/notion/connection',
|
authDocUrl: '{DOCS_URL}/apps/notion/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader, addNotionVersionHeader],
|
beforeRequest: [addAuthHeader, addNotionVersionHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://ntfy.sh',
|
baseUrl: 'https://ntfy.sh',
|
||||||
apiBaseUrl: 'https://ntfy.sh',
|
apiBaseUrl: 'https://ntfy.sh',
|
||||||
primaryColor: '56bda8',
|
primaryColor: '#56bda8',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://odoo.com',
|
baseUrl: 'https://odoo.com',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '9c5789',
|
primaryColor: '#9c5789',
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.openai.com',
|
apiBaseUrl: 'https://api.openai.com',
|
||||||
iconUrl: '{BASE_URL}/apps/openai/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/openai/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/openai/connection',
|
authDocUrl: '{DOCS_URL}/apps/openai/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/pipedrive/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/pipedrive/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/pipedrive/connection',
|
authDocUrl: '{DOCS_URL}/apps/pipedrive/connection',
|
||||||
primaryColor: 'FFFFFF',
|
primaryColor: '#FFFFFF',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://placetel.de',
|
baseUrl: 'https://placetel.de',
|
||||||
apiBaseUrl: 'https://api.placetel.de',
|
apiBaseUrl: 'https://api.placetel.de',
|
||||||
primaryColor: '069dd9',
|
primaryColor: '#069dd9',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '336791',
|
primaryColor: '#336791',
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.pushover.net',
|
apiBaseUrl: 'https://api.pushover.net',
|
||||||
iconUrl: '{BASE_URL}/apps/pushover/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/pushover/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/pushover/connection',
|
authDocUrl: '{DOCS_URL}/apps/pushover/connection',
|
||||||
primaryColor: '249DF1',
|
primaryColor: '#249DF1',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://oauth.reddit.com',
|
apiBaseUrl: 'https://oauth.reddit.com',
|
||||||
iconUrl: '{BASE_URL}/apps/reddit/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/reddit/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/reddit/connection',
|
authDocUrl: '{DOCS_URL}/apps/reddit/connection',
|
||||||
primaryColor: 'FF4500',
|
primaryColor: '#FF4500',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://www.remove.bg',
|
baseUrl: 'https://www.remove.bg',
|
||||||
apiBaseUrl: 'https://api.remove.bg/v1.0',
|
apiBaseUrl: 'https://api.remove.bg/v1.0',
|
||||||
primaryColor: '55636c',
|
primaryColor: '#55636c',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: 'ff8800',
|
primaryColor: '#ff8800',
|
||||||
triggers,
|
triggers,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://salesforce.com',
|
baseUrl: 'https://salesforce.com',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '00A1E0',
|
primaryColor: '#00A1E0',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default defineApp({
|
|||||||
authDocUrl: '{DOCS_URL}/apps/scheduler/connection',
|
authDocUrl: '{DOCS_URL}/apps/scheduler/connection',
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '0059F7',
|
primaryColor: '#0059F7',
|
||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
triggers,
|
triggers,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/self-hosted-llm/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/self-hosted-llm/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/self-hosted-llm/connection',
|
authDocUrl: '{DOCS_URL}/apps/self-hosted-llm/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://signalwire.com',
|
baseUrl: 'https://signalwire.com',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '044cf6',
|
primaryColor: '#044cf6',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://slack.com',
|
baseUrl: 'https://slack.com',
|
||||||
apiBaseUrl: 'https://slack.com/api',
|
apiBaseUrl: 'https://slack.com/api',
|
||||||
primaryColor: '4a154b',
|
primaryColor: '#4a154b',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '2DAAE1',
|
primaryColor: '#2DAAE1',
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://spotify.com',
|
baseUrl: 'https://spotify.com',
|
||||||
apiBaseUrl: 'https://api.spotify.com',
|
apiBaseUrl: 'https://api.spotify.com',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://www.strava.com',
|
baseUrl: 'https://www.strava.com',
|
||||||
apiBaseUrl: 'https://www.strava.com/api',
|
apiBaseUrl: 'https://www.strava.com/api',
|
||||||
primaryColor: 'fc4c01',
|
primaryColor: '#fc4c01',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://stripe.com',
|
baseUrl: 'https://stripe.com',
|
||||||
apiBaseUrl: 'https://api.stripe.com',
|
apiBaseUrl: 'https://api.stripe.com',
|
||||||
primaryColor: '635bff',
|
primaryColor: '#635bff',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://telegram.org',
|
baseUrl: 'https://telegram.org',
|
||||||
apiBaseUrl: 'https://api.telegram.org',
|
apiBaseUrl: 'https://api.telegram.org',
|
||||||
primaryColor: '2AABEE',
|
primaryColor: '#2AABEE',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://todoist.com',
|
baseUrl: 'https://todoist.com',
|
||||||
apiBaseUrl: 'https://api.todoist.com/rest/v2',
|
apiBaseUrl: 'https://api.todoist.com/rest/v2',
|
||||||
primaryColor: 'e44332',
|
primaryColor: '#e44332',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
iconUrl: '{BASE_URL}/apps/trello/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/trello/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/trello/connection',
|
authDocUrl: '{DOCS_URL}/apps/trello/connection',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
primaryColor: '0079bf',
|
primaryColor: '#0079bf',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://twilio.com',
|
baseUrl: 'https://twilio.com',
|
||||||
apiBaseUrl: 'https://api.twilio.com',
|
apiBaseUrl: 'https://api.twilio.com',
|
||||||
primaryColor: 'e1000f',
|
primaryColor: '#e1000f',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://twitter.com',
|
baseUrl: 'https://twitter.com',
|
||||||
apiBaseUrl: 'https://api.twitter.com',
|
apiBaseUrl: 'https://api.twitter.com',
|
||||||
primaryColor: '1da1f2',
|
primaryColor: '#1da1f2',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://typeform.com',
|
baseUrl: 'https://typeform.com',
|
||||||
apiBaseUrl: 'https://api.typeform.com',
|
apiBaseUrl: 'https://api.typeform.com',
|
||||||
primaryColor: '262627',
|
primaryColor: '#262627',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '39a86d',
|
primaryColor: '#39a86d',
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '0059F7',
|
primaryColor: '#0059F7',
|
||||||
actions,
|
actions,
|
||||||
triggers,
|
triggers,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://wordpress.com',
|
baseUrl: 'https://wordpress.com',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '464342',
|
primaryColor: '#464342',
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.xero.com',
|
apiBaseUrl: 'https://api.xero.com',
|
||||||
iconUrl: '{BASE_URL}/apps/xero/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/xero/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/xero/connection',
|
authDocUrl: '{DOCS_URL}/apps/xero/connection',
|
||||||
primaryColor: '13B5EA',
|
primaryColor: '#13B5EA',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.ynab.com/v1',
|
apiBaseUrl: 'https://api.ynab.com/v1',
|
||||||
iconUrl: '{BASE_URL}/apps/you-need-a-budget/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/you-need-a-budget/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/you-need-a-budget/connection',
|
authDocUrl: '{DOCS_URL}/apps/you-need-a-budget/connection',
|
||||||
primaryColor: '19223C',
|
primaryColor: '#19223C',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://www.googleapis.com/youtube',
|
apiBaseUrl: 'https://www.googleapis.com/youtube',
|
||||||
iconUrl: '{BASE_URL}/apps/youtube/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/youtube/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/youtube/connection',
|
authDocUrl: '{DOCS_URL}/apps/youtube/connection',
|
||||||
primaryColor: 'FF0000',
|
primaryColor: '#FF0000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/zendesk/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/zendesk/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/zendesk/connection',
|
authDocUrl: '{DOCS_URL}/apps/zendesk/connection',
|
||||||
primaryColor: '17494d',
|
primaryColor: '#17494d',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
|||||||
@@ -1,23 +1,28 @@
|
|||||||
import pick from 'lodash/pick.js';
|
|
||||||
import { renderObject } from '../../../../../helpers/renderer.js';
|
import { renderObject } from '../../../../../helpers/renderer.js';
|
||||||
import Config from '../../../../../models/config.js';
|
import Config from '../../../../../models/config.js';
|
||||||
|
|
||||||
export default async (request, response) => {
|
export default async (request, response) => {
|
||||||
const config = configParams(request);
|
const config = await Config.query().updateFirstOrInsert(
|
||||||
|
configParams(request)
|
||||||
await Config.batchUpdate(config);
|
);
|
||||||
|
|
||||||
renderObject(response, config);
|
renderObject(response, config);
|
||||||
};
|
};
|
||||||
|
|
||||||
const configParams = (request) => {
|
const configParams = (request) => {
|
||||||
const updatableConfigurationKeys = [
|
const {
|
||||||
'logo.svgData',
|
logoSvgData,
|
||||||
'palette.primary.dark',
|
palettePrimaryDark,
|
||||||
'palette.primary.light',
|
palettePrimaryLight,
|
||||||
'palette.primary.main',
|
palettePrimaryMain,
|
||||||
'title',
|
title,
|
||||||
];
|
} = request.body;
|
||||||
|
|
||||||
return pick(request.body, updatableConfigurationKeys);
|
return {
|
||||||
|
logoSvgData,
|
||||||
|
palettePrimaryDark,
|
||||||
|
palettePrimaryLight,
|
||||||
|
palettePrimaryMain,
|
||||||
|
title,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import app from '../../../../../app.js';
|
|||||||
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
|
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
|
||||||
import { createUser } from '../../../../../../test/factories/user.js';
|
import { createUser } from '../../../../../../test/factories/user.js';
|
||||||
import { createRole } from '../../../../../../test/factories/role.js';
|
import { createRole } from '../../../../../../test/factories/role.js';
|
||||||
import { createBulkConfig } from '../../../../../../test/factories/config.js';
|
import { updateConfig } from '../../../../../../test/factories/config.js';
|
||||||
import * as license from '../../../../../helpers/license.ee.js';
|
import * as license from '../../../../../helpers/license.ee.js';
|
||||||
|
|
||||||
describe('PATCH /api/v1/admin/config', () => {
|
describe('PATCH /api/v1/admin/config', () => {
|
||||||
@@ -30,13 +30,13 @@ describe('PATCH /api/v1/admin/config', () => {
|
|||||||
|
|
||||||
const appConfig = {
|
const appConfig = {
|
||||||
title,
|
title,
|
||||||
'palette.primary.main': palettePrimaryMain,
|
palettePrimaryMain: palettePrimaryMain,
|
||||||
'palette.primary.dark': palettePrimaryDark,
|
palettePrimaryDark: palettePrimaryDark,
|
||||||
'palette.primary.light': palettePrimaryLight,
|
palettePrimaryLight: palettePrimaryLight,
|
||||||
'logo.svgData': logoSvgData,
|
logoSvgData: logoSvgData,
|
||||||
};
|
};
|
||||||
|
|
||||||
await createBulkConfig(appConfig);
|
await updateConfig(appConfig);
|
||||||
|
|
||||||
const newTitle = 'Updated title';
|
const newTitle = 'Updated title';
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ describe('PATCH /api/v1/admin/config', () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
expect(response.body.data.title).toEqual(newTitle);
|
expect(response.body.data.title).toEqual(newTitle);
|
||||||
expect(response.body.meta.type).toEqual('Object');
|
expect(response.body.meta.type).toEqual('Config');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return created config for unexisting config', async () => {
|
it('should return created config for unexisting config', async () => {
|
||||||
@@ -68,7 +68,7 @@ describe('PATCH /api/v1/admin/config', () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
expect(response.body.data.title).toEqual(newTitle);
|
expect(response.body.data.title).toEqual(newTitle);
|
||||||
expect(response.body.meta.type).toEqual('Object');
|
expect(response.body.meta.type).toEqual('Config');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return null for deleted config entry', async () => {
|
it('should return null for deleted config entry', async () => {
|
||||||
@@ -83,6 +83,6 @@ describe('PATCH /api/v1/admin/config', () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
expect(response.body.data.title).toBeNull();
|
expect(response.body.data.title).toBeNull();
|
||||||
expect(response.body.meta.type).toEqual('Object');
|
expect(response.body.meta.type).toEqual('Config');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default async (request, response) => {
|
|||||||
const user = await User.query().insertAndFetch(await userParams(request));
|
const user = await User.query().insertAndFetch(await userParams(request));
|
||||||
await user.sendInvitationEmail();
|
await user.sendInvitationEmail();
|
||||||
|
|
||||||
renderObject(response, user, { status: 201 });
|
renderObject(response, user, { status: 201, serializer: 'AdminUser' });
|
||||||
};
|
};
|
||||||
|
|
||||||
const userParams = async (request) => {
|
const userParams = async (request) => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import User from '../../../../../models/user.js';
|
|||||||
import Role from '../../../../../models/role.js';
|
import Role from '../../../../../models/role.js';
|
||||||
import { createUser } from '../../../../../../test/factories/user.js';
|
import { createUser } from '../../../../../../test/factories/user.js';
|
||||||
import { createRole } from '../../../../../../test/factories/role.js';
|
import { createRole } from '../../../../../../test/factories/role.js';
|
||||||
import createUserMock from '../../../../../../test/mocks/rest/api/v1/users/create-user.js';
|
import createUserMock from '../../../../../../test/mocks/rest/api/v1/admin/users/create-user.js';
|
||||||
|
|
||||||
describe('POST /api/v1/admin/users', () => {
|
describe('POST /api/v1/admin/users', () => {
|
||||||
let currentUser, adminRole, token;
|
let currentUser, adminRole, token;
|
||||||
|
|||||||
@@ -1,25 +1,8 @@
|
|||||||
import appConfig from '../../../../config/app.js';
|
|
||||||
import Config from '../../../../models/config.js';
|
import Config from '../../../../models/config.js';
|
||||||
import { renderObject } from '../../../../helpers/renderer.js';
|
import { renderObject } from '../../../../helpers/renderer.js';
|
||||||
|
|
||||||
export default async (request, response) => {
|
export default async (request, response) => {
|
||||||
const defaultConfig = {
|
const config = await Config.get();
|
||||||
disableNotificationsPage: appConfig.disableNotificationsPage,
|
|
||||||
disableFavicon: appConfig.disableFavicon,
|
|
||||||
additionalDrawerLink: appConfig.additionalDrawerLink,
|
|
||||||
additionalDrawerLinkIcon: appConfig.additionalDrawerLinkIcon,
|
|
||||||
additionalDrawerLinkText: appConfig.additionalDrawerLinkText,
|
|
||||||
};
|
|
||||||
|
|
||||||
let config = await Config.query().orderBy('key', 'asc');
|
|
||||||
|
|
||||||
config = config.reduce((computedConfig, configEntry) => {
|
|
||||||
const { key, value } = configEntry;
|
|
||||||
|
|
||||||
computedConfig[key] = value?.data;
|
|
||||||
|
|
||||||
return computedConfig;
|
|
||||||
}, defaultConfig);
|
|
||||||
|
|
||||||
renderObject(response, config);
|
renderObject(response, config);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,66 +1,47 @@
|
|||||||
import { vi, expect, describe, it } from 'vitest';
|
import { vi, expect, describe, it } from 'vitest';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
import { createConfig } from '../../../../../test/factories/config.js';
|
import { updateConfig } from '../../../../../test/factories/config.js';
|
||||||
import app from '../../../../app.js';
|
import app from '../../../../app.js';
|
||||||
import configMock from '../../../../../test/mocks/rest/api/v1/automatisch/config.js';
|
import configMock from '../../../../../test/mocks/rest/api/v1/automatisch/config.js';
|
||||||
import * as license from '../../../../helpers/license.ee.js';
|
import * as license from '../../../../helpers/license.ee.js';
|
||||||
import appConfig from '../../../../config/app.js';
|
import appConfig from '../../../../config/app.js';
|
||||||
|
|
||||||
describe('GET /api/v1/automatisch/config', () => {
|
describe('GET /api/v1/automatisch/config', () => {
|
||||||
it('should return Automatisch config', async () => {
|
it('should return Automatisch config along with static config', async () => {
|
||||||
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
|
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
|
||||||
|
vi.spyOn(appConfig, 'disableNotificationsPage', 'get').mockReturnValue(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
vi.spyOn(appConfig, 'disableFavicon', 'get').mockReturnValue(true);
|
||||||
|
vi.spyOn(appConfig, 'additionalDrawerLink', 'get').mockReturnValue('link');
|
||||||
|
vi.spyOn(appConfig, 'additionalDrawerLinkIcon', 'get').mockReturnValue(
|
||||||
|
'icon'
|
||||||
|
);
|
||||||
|
vi.spyOn(appConfig, 'additionalDrawerLinkText', 'get').mockReturnValue(
|
||||||
|
'text'
|
||||||
|
);
|
||||||
|
|
||||||
const logoConfig = await createConfig({
|
const config = await updateConfig({
|
||||||
key: 'logo.svgData',
|
logoSvgData: '<svg>Sample</svg>',
|
||||||
value: { data: '<svg>Sample</svg>' },
|
palettePrimaryDark: '#001f52',
|
||||||
});
|
palettePrimaryLight: '#4286FF',
|
||||||
|
palettePrimaryMain: '#0059F7',
|
||||||
const primaryDarkConfig = await createConfig({
|
title: 'Sample Title',
|
||||||
key: 'palette.primary.dark',
|
|
||||||
value: { data: '#001F52' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const primaryLightConfig = await createConfig({
|
|
||||||
key: 'palette.primary.light',
|
|
||||||
value: { data: '#4286FF' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const primaryMainConfig = await createConfig({
|
|
||||||
key: 'palette.primary.main',
|
|
||||||
value: { data: '#0059F7' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const titleConfig = await createConfig({
|
|
||||||
key: 'title',
|
|
||||||
value: { data: 'Sample Title' },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await request(app)
|
const response = await request(app)
|
||||||
.get('/api/v1/automatisch/config')
|
.get('/api/v1/automatisch/config')
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const expectedPayload = configMock(
|
const expectedPayload = configMock({
|
||||||
logoConfig,
|
...config,
|
||||||
primaryDarkConfig,
|
disableNotificationsPage: true,
|
||||||
primaryLightConfig,
|
disableFavicon: true,
|
||||||
primaryMainConfig,
|
additionalDrawerLink: 'link',
|
||||||
titleConfig
|
additionalDrawerLinkIcon: 'icon',
|
||||||
);
|
additionalDrawerLinkText: 'text',
|
||||||
|
});
|
||||||
|
|
||||||
expect(response.body).toEqual(expectedPayload);
|
expect(response.body).toStrictEqual(expectedPayload);
|
||||||
});
|
|
||||||
|
|
||||||
it('should return additional environment variables', async () => {
|
|
||||||
vi.spyOn(appConfig, 'disableNotificationsPage', 'get').mockReturnValue(true);
|
|
||||||
vi.spyOn(appConfig, 'disableFavicon', 'get').mockReturnValue(true);
|
|
||||||
vi.spyOn(appConfig, 'additionalDrawerLink', 'get').mockReturnValue('link');
|
|
||||||
vi.spyOn(appConfig, 'additionalDrawerLinkIcon', 'get').mockReturnValue('icon');
|
|
||||||
vi.spyOn(appConfig, 'additionalDrawerLinkText', 'get').mockReturnValue('text');
|
|
||||||
|
|
||||||
expect(appConfig.disableNotificationsPage).toEqual(true);
|
|
||||||
expect(appConfig.disableFavicon).toEqual(true);
|
|
||||||
expect(appConfig.additionalDrawerLink).toEqual('link');
|
|
||||||
expect(appConfig.additionalDrawerLinkIcon).toEqual('icon');
|
|
||||||
expect(appConfig.additionalDrawerLinkText).toEqual('text');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Config from '../../../../../models/config.js';
|
|||||||
import User from '../../../../../models/user.js';
|
import User from '../../../../../models/user.js';
|
||||||
import { createRole } from '../../../../../../test/factories/role';
|
import { createRole } from '../../../../../../test/factories/role';
|
||||||
import { createUser } from '../../../../../../test/factories/user';
|
import { createUser } from '../../../../../../test/factories/user';
|
||||||
import { createInstallationCompletedConfig } from '../../../../../../test/factories/config';
|
import { markInstallationCompleted } from '../../../../../../test/factories/config';
|
||||||
|
|
||||||
describe('POST /api/v1/installation/users', () => {
|
describe('POST /api/v1/installation/users', () => {
|
||||||
let adminRole;
|
let adminRole;
|
||||||
@@ -59,7 +59,7 @@ describe('POST /api/v1/installation/users', () => {
|
|||||||
|
|
||||||
describe('for completed installations', () => {
|
describe('for completed installations', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await createInstallationCompletedConfig();
|
await markInstallationCompleted();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should respond with HTTP 403 when installation completed', async () => {
|
it('should respond with HTTP 403 when installation completed', async () => {
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ describe('POST /api/v1/steps/:stepId/dynamic-data', () => {
|
|||||||
dynamicDataKey: 'listRepos',
|
dynamicDataKey: 'listRepos',
|
||||||
parameters: {},
|
parameters: {},
|
||||||
})
|
})
|
||||||
.expect(200);
|
.expect(422);
|
||||||
|
|
||||||
expect(response.body.errors).toEqual(errors);
|
expect(response.body.errors).toEqual(errors);
|
||||||
});
|
});
|
||||||
|
|||||||
22
packages/backend/src/controllers/api/v1/steps/update-step.js
Normal file
22
packages/backend/src/controllers/api/v1/steps/update-step.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { renderObject } from '../../../../helpers/renderer.js';
|
||||||
|
|
||||||
|
export default async (request, response) => {
|
||||||
|
let step = await request.currentUser.authorizedSteps
|
||||||
|
.findById(request.params.stepId)
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
step = await step.updateFor(request.currentUser, stepParams(request));
|
||||||
|
|
||||||
|
renderObject(response, step);
|
||||||
|
};
|
||||||
|
|
||||||
|
const stepParams = (request) => {
|
||||||
|
const { connectionId, appKey, key, parameters } = request.body;
|
||||||
|
|
||||||
|
return {
|
||||||
|
connectionId,
|
||||||
|
appKey,
|
||||||
|
key,
|
||||||
|
parameters,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
import { describe, it, beforeEach, expect } from 'vitest';
|
||||||
|
import request from 'supertest';
|
||||||
|
import Crypto from 'crypto';
|
||||||
|
import app from '../../../../app.js';
|
||||||
|
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id.js';
|
||||||
|
import { createUser } from '../../../../../test/factories/user.js';
|
||||||
|
import { createConnection } from '../../../../../test/factories/connection.js';
|
||||||
|
import { createFlow } from '../../../../../test/factories/flow.js';
|
||||||
|
import { createStep } from '../../../../../test/factories/step.js';
|
||||||
|
import { createPermission } from '../../../../../test/factories/permission.js';
|
||||||
|
import updateStepMock from '../../../../../test/mocks/rest/api/v1/steps/update-step.js';
|
||||||
|
|
||||||
|
describe('PATCH /api/v1/steps/:stepId', () => {
|
||||||
|
let currentUser, token;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
currentUser = await createUser();
|
||||||
|
|
||||||
|
token = await createAuthTokenByUserId(currentUser.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the step of the current user', async () => {
|
||||||
|
const currentUserFlow = await createFlow({ userId: currentUser.id });
|
||||||
|
const currentUserConnection = await createConnection({
|
||||||
|
key: 'deepl',
|
||||||
|
});
|
||||||
|
|
||||||
|
await createStep({
|
||||||
|
flowId: currentUserFlow.id,
|
||||||
|
connectionId: currentUserConnection.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const actionStep = await createStep({
|
||||||
|
flowId: currentUserFlow.id,
|
||||||
|
connectionId: currentUserConnection.id,
|
||||||
|
appKey: 'deepl',
|
||||||
|
key: 'translateText',
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'read',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: ['isCreator'],
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'update',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: ['isCreator'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await request(app)
|
||||||
|
.patch(`/api/v1/steps/${actionStep.id}`)
|
||||||
|
.set('Authorization', token)
|
||||||
|
.send({
|
||||||
|
parameters: {
|
||||||
|
text: 'Hello world!',
|
||||||
|
targetLanguage: 'de',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const refetchedStep = await actionStep.$query();
|
||||||
|
|
||||||
|
const expectedResponse = updateStepMock(refetchedStep);
|
||||||
|
|
||||||
|
expect(response.body).toStrictEqual(expectedResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the step of the another user', async () => {
|
||||||
|
const anotherUser = await createUser();
|
||||||
|
const anotherUserFlow = await createFlow({ userId: anotherUser.id });
|
||||||
|
const anotherUserConnection = await createConnection({
|
||||||
|
key: 'deepl',
|
||||||
|
});
|
||||||
|
|
||||||
|
await createStep({
|
||||||
|
flowId: anotherUserFlow.id,
|
||||||
|
connectionId: anotherUserConnection.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const actionStep = await createStep({
|
||||||
|
flowId: anotherUserFlow.id,
|
||||||
|
connectionId: anotherUserConnection.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'read',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'update',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await request(app)
|
||||||
|
.patch(`/api/v1/steps/${actionStep.id}`)
|
||||||
|
.set('Authorization', token)
|
||||||
|
.send({
|
||||||
|
parameters: {
|
||||||
|
text: 'Hello world!',
|
||||||
|
targetLanguage: 'de',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const refetchedStep = await actionStep.$query();
|
||||||
|
|
||||||
|
const expectedResponse = updateStepMock(refetchedStep);
|
||||||
|
|
||||||
|
expect(response.body).toStrictEqual(expectedResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return not found response for inaccessible connection', async () => {
|
||||||
|
const currentUserFlow = await createFlow({ userId: currentUser.id });
|
||||||
|
|
||||||
|
const anotherUser = await createUser();
|
||||||
|
const anotherUserConnection = await createConnection({
|
||||||
|
key: 'deepl',
|
||||||
|
userId: anotherUser.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await createStep({
|
||||||
|
flowId: currentUserFlow.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const actionStep = await createStep({
|
||||||
|
flowId: currentUserFlow.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'read',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: ['isCreator'],
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'update',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: ['isCreator'],
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'read',
|
||||||
|
subject: 'Connection',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: ['isCreator'],
|
||||||
|
});
|
||||||
|
|
||||||
|
await request(app)
|
||||||
|
.patch(`/api/v1/steps/${actionStep.id}`)
|
||||||
|
.set('Authorization', token)
|
||||||
|
.send({
|
||||||
|
connectionId: anotherUserConnection.id,
|
||||||
|
})
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return not found response for not existing step UUID', async () => {
|
||||||
|
await createPermission({
|
||||||
|
action: 'update',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'read',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const notExistingStepUUID = Crypto.randomUUID();
|
||||||
|
|
||||||
|
await request(app)
|
||||||
|
.patch(`/api/v1/steps/${notExistingStepUUID}`)
|
||||||
|
.set('Authorization', token)
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return bad request response for invalid step UUID', async () => {
|
||||||
|
await createPermission({
|
||||||
|
action: 'update',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
await createPermission({
|
||||||
|
action: 'read',
|
||||||
|
subject: 'Flow',
|
||||||
|
roleId: currentUser.roleId,
|
||||||
|
conditions: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
await request(app)
|
||||||
|
.patch('/api/v1/steps/invalidStepUUID')
|
||||||
|
.set('Authorization', token)
|
||||||
|
.expect(400);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
export async function up(knex) {
|
||||||
|
await knex.schema.alterTable('config', (table) => {
|
||||||
|
table.dropUnique('key');
|
||||||
|
|
||||||
|
table.string('key').nullable().alter();
|
||||||
|
table.boolean('installation_completed').defaultTo(false);
|
||||||
|
table.text('logo_svg_data');
|
||||||
|
table.text('palette_primary_dark');
|
||||||
|
table.text('palette_primary_light');
|
||||||
|
table.text('palette_primary_main');
|
||||||
|
table.string('title');
|
||||||
|
});
|
||||||
|
|
||||||
|
const config = await knex('config').select('key', 'value');
|
||||||
|
|
||||||
|
const newConfigData = {
|
||||||
|
logo_svg_data: getValueForKey(config, 'logo.svgData'),
|
||||||
|
palette_primary_dark: getValueForKey(config, 'palette.primary.dark'),
|
||||||
|
palette_primary_light: getValueForKey(config, 'palette.primary.light'),
|
||||||
|
palette_primary_main: getValueForKey(config, 'palette.primary.main'),
|
||||||
|
title: getValueForKey(config, 'title'),
|
||||||
|
installation_completed: getValueForKey(config, 'installation.completed'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const [configEntry] = await knex('config')
|
||||||
|
.insert(newConfigData)
|
||||||
|
.select('id')
|
||||||
|
.returning('id');
|
||||||
|
|
||||||
|
await knex('config').where('id', '!=', configEntry.id).delete();
|
||||||
|
|
||||||
|
await knex.schema.alterTable('config', (table) => {
|
||||||
|
table.dropColumn('key');
|
||||||
|
table.dropColumn('value');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex) {
|
||||||
|
await knex.schema.alterTable('config', (table) => {
|
||||||
|
table.string('key');
|
||||||
|
table.jsonb('value').notNullable().defaultTo({});
|
||||||
|
});
|
||||||
|
|
||||||
|
const configRow = await knex('config').first();
|
||||||
|
|
||||||
|
const config = [
|
||||||
|
{
|
||||||
|
key: 'logo.svgData',
|
||||||
|
value: {
|
||||||
|
data: configRow.logo_svg_data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'palette.primary.dark',
|
||||||
|
value: {
|
||||||
|
data: configRow.palette_primary_dark,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'palette.primary.light',
|
||||||
|
value: {
|
||||||
|
data: configRow.palette_primary_light,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'palette.primary.main',
|
||||||
|
value: {
|
||||||
|
data: configRow.palette_primary_main,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
value: {
|
||||||
|
data: configRow.title,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'installation.completed',
|
||||||
|
value: {
|
||||||
|
data: configRow.installation_completed,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await knex('config').insert(config).returning('id');
|
||||||
|
|
||||||
|
await knex('config').where('id', '=', configRow.id).delete();
|
||||||
|
|
||||||
|
await knex.schema.alterTable('config', (table) => {
|
||||||
|
table.dropColumn('installation_completed');
|
||||||
|
table.dropColumn('logo_svg_data');
|
||||||
|
table.dropColumn('palette_primary_dark');
|
||||||
|
table.dropColumn('palette_primary_light');
|
||||||
|
table.dropColumn('palette_primary_main');
|
||||||
|
table.dropColumn('title');
|
||||||
|
|
||||||
|
table.string('key').unique().notNullable().alter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getValueForKey(rows, key) {
|
||||||
|
const row = rows.find((row) => row.key === key);
|
||||||
|
|
||||||
|
return row?.value?.data || null;
|
||||||
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import updateStep from './mutations/update-step.js';
|
|
||||||
|
|
||||||
// Converted mutations
|
|
||||||
import executeFlow from './mutations/execute-flow.js';
|
|
||||||
import updateUser from './mutations/update-user.ee.js';
|
|
||||||
import deleteStep from './mutations/delete-step.js';
|
|
||||||
import verifyConnection from './mutations/verify-connection.js';
|
|
||||||
import createFlow from './mutations/create-flow.js';
|
|
||||||
import deleteCurrentUser from './mutations/delete-current-user.ee.js';
|
|
||||||
import updateCurrentUser from './mutations/update-current-user.js';
|
|
||||||
import generateAuthUrl from './mutations/generate-auth-url.js';
|
|
||||||
import createConnection from './mutations/create-connection.js';
|
|
||||||
import deleteFlow from './mutations/delete-flow.js';
|
|
||||||
import resetConnection from './mutations/reset-connection.js';
|
|
||||||
import updateConnection from './mutations/update-connection.js';
|
|
||||||
import createUser from './mutations/create-user.ee.js';
|
|
||||||
import updateFlowStatus from './mutations/update-flow-status.js';
|
|
||||||
|
|
||||||
const mutationResolvers = {
|
|
||||||
createConnection,
|
|
||||||
createFlow,
|
|
||||||
createUser,
|
|
||||||
deleteCurrentUser,
|
|
||||||
deleteFlow,
|
|
||||||
deleteStep,
|
|
||||||
executeFlow,
|
|
||||||
generateAuthUrl,
|
|
||||||
resetConnection,
|
|
||||||
updateConnection,
|
|
||||||
updateCurrentUser,
|
|
||||||
updateFlowStatus,
|
|
||||||
updateStep,
|
|
||||||
updateUser,
|
|
||||||
verifyConnection,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default mutationResolvers;
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import App from '../../models/app.js';
|
|
||||||
import AppConfig from '../../models/app-config.js';
|
|
||||||
|
|
||||||
const createConnection = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('create', 'Connection');
|
|
||||||
|
|
||||||
const { key, appAuthClientId } = params.input;
|
|
||||||
|
|
||||||
const app = await App.findOneByKey(key);
|
|
||||||
|
|
||||||
const appConfig = await AppConfig.query().findOne({ key });
|
|
||||||
|
|
||||||
let formattedData = params.input.formattedData;
|
|
||||||
if (appConfig) {
|
|
||||||
if (appConfig.disabled)
|
|
||||||
throw new Error(
|
|
||||||
'This application has been disabled for new connections!'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!appConfig.allowCustomConnection && formattedData)
|
|
||||||
throw new Error(`Custom connections cannot be created for ${app.name}!`);
|
|
||||||
|
|
||||||
if (appConfig.shared && !formattedData) {
|
|
||||||
const authClient = await appConfig
|
|
||||||
.$relatedQuery('appAuthClients')
|
|
||||||
.findById(appAuthClientId)
|
|
||||||
.where({
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
formattedData = authClient.formattedAuthDefaults;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const createdConnection = await context.currentUser
|
|
||||||
.$relatedQuery('connections')
|
|
||||||
.insert({
|
|
||||||
key,
|
|
||||||
appAuthClientId,
|
|
||||||
formattedData,
|
|
||||||
verified: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
return createdConnection;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default createConnection;
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import App from '../../models/app.js';
|
|
||||||
import Step from '../../models/step.js';
|
|
||||||
|
|
||||||
const createFlow = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('create', 'Flow');
|
|
||||||
|
|
||||||
const connectionId = params?.input?.connectionId;
|
|
||||||
const appKey = params?.input?.triggerAppKey;
|
|
||||||
|
|
||||||
if (appKey) {
|
|
||||||
await App.findOneByKey(appKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
const flow = await context.currentUser.$relatedQuery('flows').insert({
|
|
||||||
name: 'Name your flow',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (connectionId) {
|
|
||||||
const hasConnection = await context.currentUser
|
|
||||||
.$relatedQuery('connections')
|
|
||||||
.findById(connectionId);
|
|
||||||
|
|
||||||
if (!hasConnection) {
|
|
||||||
throw new Error('The connection does not exist!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Step.query().insert({
|
|
||||||
flowId: flow.id,
|
|
||||||
type: 'trigger',
|
|
||||||
position: 1,
|
|
||||||
appKey,
|
|
||||||
connectionId,
|
|
||||||
});
|
|
||||||
|
|
||||||
await Step.query().insert({
|
|
||||||
flowId: flow.id,
|
|
||||||
type: 'action',
|
|
||||||
position: 2,
|
|
||||||
});
|
|
||||||
|
|
||||||
return flow;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default createFlow;
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import appConfig from '../../config/app.js';
|
|
||||||
import User from '../../models/user.js';
|
|
||||||
import Role from '../../models/role.js';
|
|
||||||
import emailQueue from '../../queues/email.js';
|
|
||||||
import {
|
|
||||||
REMOVE_AFTER_30_DAYS_OR_150_JOBS,
|
|
||||||
REMOVE_AFTER_7_DAYS_OR_50_JOBS,
|
|
||||||
} from '../../helpers/remove-job-configuration.js';
|
|
||||||
|
|
||||||
const createUser = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('create', 'User');
|
|
||||||
|
|
||||||
const { fullName, email } = params.input;
|
|
||||||
|
|
||||||
const existingUser = await User.query().findOne({
|
|
||||||
email: email.toLowerCase(),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (existingUser) {
|
|
||||||
throw new Error('User already exists!');
|
|
||||||
}
|
|
||||||
|
|
||||||
const userPayload = {
|
|
||||||
fullName,
|
|
||||||
email,
|
|
||||||
status: 'invited',
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
context.currentUser.can('update', 'Role');
|
|
||||||
|
|
||||||
userPayload.roleId = params.input.role.id;
|
|
||||||
} catch {
|
|
||||||
// void
|
|
||||||
const role = await Role.findAdmin();
|
|
||||||
userPayload.roleId = role.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await User.query().insert(userPayload);
|
|
||||||
|
|
||||||
await user.generateInvitationToken();
|
|
||||||
|
|
||||||
const jobName = `Invitation Email - ${user.id}`;
|
|
||||||
const acceptInvitationUrl = `${appConfig.webAppUrl}/accept-invitation?token=${user.invitationToken}`;
|
|
||||||
|
|
||||||
const jobPayload = {
|
|
||||||
email: user.email,
|
|
||||||
subject: 'You are invited!',
|
|
||||||
template: 'invitation-instructions',
|
|
||||||
params: {
|
|
||||||
fullName: user.fullName,
|
|
||||||
acceptInvitationUrl,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const jobOptions = {
|
|
||||||
removeOnComplete: REMOVE_AFTER_7_DAYS_OR_50_JOBS,
|
|
||||||
removeOnFail: REMOVE_AFTER_30_DAYS_OR_150_JOBS,
|
|
||||||
};
|
|
||||||
|
|
||||||
await emailQueue.add(jobName, jobPayload, jobOptions);
|
|
||||||
|
|
||||||
return { user, acceptInvitationUrl };
|
|
||||||
};
|
|
||||||
|
|
||||||
export default createUser;
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import AppAuthClient from '../../models/app-auth-client';
|
|
||||||
|
|
||||||
const deleteAppAuthClient = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('delete', 'App');
|
|
||||||
|
|
||||||
await AppAuthClient.query()
|
|
||||||
.delete()
|
|
||||||
.findOne({
|
|
||||||
id: params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default deleteAppAuthClient;
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import { Duration } from 'luxon';
|
|
||||||
import deleteUserQueue from '../../queues/delete-user.ee.js';
|
|
||||||
import flowQueue from '../../queues/flow.js';
|
|
||||||
import Flow from '../../models/flow.js';
|
|
||||||
import ExecutionStep from '../../models/execution-step.js';
|
|
||||||
import appConfig from '../../config/app.js';
|
|
||||||
|
|
||||||
const deleteCurrentUser = async (_parent, params, context) => {
|
|
||||||
const id = context.currentUser.id;
|
|
||||||
|
|
||||||
const flows = await context.currentUser.$relatedQuery('flows').where({
|
|
||||||
active: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const repeatableJobs = await flowQueue.getRepeatableJobs();
|
|
||||||
|
|
||||||
for (const flow of flows) {
|
|
||||||
const job = repeatableJobs.find((job) => job.id === flow.id);
|
|
||||||
|
|
||||||
if (job) {
|
|
||||||
await flowQueue.removeRepeatableByKey(job.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const executionIds = (
|
|
||||||
await context.currentUser
|
|
||||||
.$relatedQuery('executions')
|
|
||||||
.select('executions.id')
|
|
||||||
).map((execution) => execution.id);
|
|
||||||
const flowIds = flows.map((flow) => flow.id);
|
|
||||||
|
|
||||||
await ExecutionStep.query().delete().whereIn('execution_id', executionIds);
|
|
||||||
await context.currentUser.$relatedQuery('executions').delete();
|
|
||||||
await context.currentUser.$relatedQuery('steps').delete();
|
|
||||||
await Flow.query().whereIn('id', flowIds).delete();
|
|
||||||
await context.currentUser.$relatedQuery('connections').delete();
|
|
||||||
await context.currentUser.$relatedQuery('identities').delete();
|
|
||||||
|
|
||||||
if (appConfig.isCloud) {
|
|
||||||
await context.currentUser.$relatedQuery('subscriptions').delete();
|
|
||||||
await context.currentUser.$relatedQuery('usageData').delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
await context.currentUser.$query().delete();
|
|
||||||
|
|
||||||
const jobName = `Delete user - ${id}`;
|
|
||||||
const jobPayload = { id };
|
|
||||||
const millisecondsFor30Days = Duration.fromObject({ days: 30 }).toMillis();
|
|
||||||
const jobOptions = {
|
|
||||||
delay: millisecondsFor30Days,
|
|
||||||
};
|
|
||||||
|
|
||||||
await deleteUserQueue.add(jobName, jobPayload, jobOptions);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default deleteCurrentUser;
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import Flow from '../../models/flow.js';
|
|
||||||
import ExecutionStep from '../../models/execution-step.js';
|
|
||||||
import globalVariable from '../../helpers/global-variable.js';
|
|
||||||
import logger from '../../helpers/logger.js';
|
|
||||||
|
|
||||||
const deleteFlow = async (_parent, params, context) => {
|
|
||||||
const conditions = context.currentUser.can('delete', 'Flow');
|
|
||||||
const isCreator = conditions.isCreator;
|
|
||||||
const allFlows = Flow.query();
|
|
||||||
const userFlows = context.currentUser.$relatedQuery('flows');
|
|
||||||
const baseQuery = isCreator ? userFlows : allFlows;
|
|
||||||
|
|
||||||
const flow = await baseQuery
|
|
||||||
.findOne({
|
|
||||||
id: params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
const triggerStep = await flow.getTriggerStep();
|
|
||||||
const trigger = await triggerStep?.getTriggerCommand();
|
|
||||||
|
|
||||||
if (trigger?.type === 'webhook' && trigger.unregisterHook) {
|
|
||||||
const $ = await globalVariable({
|
|
||||||
flow,
|
|
||||||
connection: await triggerStep.$relatedQuery('connection'),
|
|
||||||
app: await triggerStep.getApp(),
|
|
||||||
step: triggerStep,
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
await trigger.unregisterHook($);
|
|
||||||
} catch (error) {
|
|
||||||
// suppress error as the remote resource might have been already deleted
|
|
||||||
logger.debug(
|
|
||||||
`Failed to unregister webhook for flow ${flow.id}: ${error.message}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const executionIds = (
|
|
||||||
await flow.$relatedQuery('executions').select('executions.id')
|
|
||||||
).map((execution) => execution.id);
|
|
||||||
|
|
||||||
await ExecutionStep.query().delete().whereIn('execution_id', executionIds);
|
|
||||||
|
|
||||||
await flow.$relatedQuery('executions').delete();
|
|
||||||
await flow.$relatedQuery('steps').delete();
|
|
||||||
await flow.$query().delete();
|
|
||||||
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default deleteFlow;
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import Step from '../../models/step.js';
|
|
||||||
|
|
||||||
const deleteStep = async (_parent, params, context) => {
|
|
||||||
const conditions = context.currentUser.can('update', 'Flow');
|
|
||||||
const isCreator = conditions.isCreator;
|
|
||||||
const allSteps = Step.query();
|
|
||||||
const userSteps = context.currentUser.$relatedQuery('steps');
|
|
||||||
const baseQuery = isCreator ? userSteps : allSteps;
|
|
||||||
|
|
||||||
const step = await baseQuery
|
|
||||||
.withGraphFetched('flow')
|
|
||||||
.findOne({
|
|
||||||
'steps.id': params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
await step.$relatedQuery('executionSteps').delete();
|
|
||||||
await step.$query().delete();
|
|
||||||
|
|
||||||
const nextSteps = await step.flow
|
|
||||||
.$relatedQuery('steps')
|
|
||||||
.where('position', '>', step.position);
|
|
||||||
|
|
||||||
const nextStepQueries = nextSteps.map(async (nextStep) => {
|
|
||||||
await nextStep.$query().patch({
|
|
||||||
position: nextStep.position - 1,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.all(nextStepQueries);
|
|
||||||
|
|
||||||
step.flow = await step.flow
|
|
||||||
.$query()
|
|
||||||
.withGraphJoined('steps')
|
|
||||||
.orderBy('steps.position', 'asc');
|
|
||||||
|
|
||||||
return step;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default deleteStep;
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import testRun from '../../services/test-run.js';
|
|
||||||
import Step from '../../models/step.js';
|
|
||||||
|
|
||||||
const executeFlow = async (_parent, params, context) => {
|
|
||||||
const conditions = context.currentUser.can('update', 'Flow');
|
|
||||||
const isCreator = conditions.isCreator;
|
|
||||||
const allSteps = Step.query();
|
|
||||||
const userSteps = context.currentUser.$relatedQuery('steps');
|
|
||||||
const baseQuery = isCreator ? userSteps : allSteps;
|
|
||||||
|
|
||||||
const { stepId } = params.input;
|
|
||||||
|
|
||||||
const untilStep = await baseQuery.clone().findById(stepId).throwIfNotFound();
|
|
||||||
|
|
||||||
const { executionStep } = await testRun({ stepId });
|
|
||||||
|
|
||||||
if (executionStep.isFailed) {
|
|
||||||
throw new Error(JSON.stringify(executionStep.errorDetails));
|
|
||||||
}
|
|
||||||
|
|
||||||
await untilStep.$query().patch({
|
|
||||||
status: 'completed',
|
|
||||||
});
|
|
||||||
|
|
||||||
return { data: executionStep.dataOut, step: untilStep };
|
|
||||||
};
|
|
||||||
|
|
||||||
export default executeFlow;
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import globalVariable from '../../helpers/global-variable.js';
|
|
||||||
import App from '../../models/app.js';
|
|
||||||
|
|
||||||
const generateAuthUrl = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('create', 'Connection');
|
|
||||||
|
|
||||||
const connection = await context.currentUser
|
|
||||||
.$relatedQuery('connections')
|
|
||||||
.findOne({
|
|
||||||
id: params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
if (!connection.formattedData) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const authInstance = (
|
|
||||||
await import(`../../apps/${connection.key}/auth/index.js`)
|
|
||||||
).default;
|
|
||||||
|
|
||||||
const app = await App.findOneByKey(connection.key);
|
|
||||||
|
|
||||||
const $ = await globalVariable({ connection, app });
|
|
||||||
await authInstance.generateAuthUrl($);
|
|
||||||
|
|
||||||
return connection.formattedData;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default generateAuthUrl;
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
const resetConnection = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('create', 'Connection');
|
|
||||||
|
|
||||||
let connection = await context.currentUser
|
|
||||||
.$relatedQuery('connections')
|
|
||||||
.findOne({
|
|
||||||
id: params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
if (!connection.formattedData) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
connection = await connection.$query().patchAndFetch({
|
|
||||||
formattedData: { screenName: connection.formattedData.screenName },
|
|
||||||
});
|
|
||||||
|
|
||||||
return connection;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default resetConnection;
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import AppAuthClient from '../../models/app-auth-client.js';
|
|
||||||
|
|
||||||
const updateConnection = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('create', 'Connection');
|
|
||||||
|
|
||||||
let connection = await context.currentUser
|
|
||||||
.$relatedQuery('connections')
|
|
||||||
.findOne({
|
|
||||||
id: params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
let formattedData = params.input.formattedData;
|
|
||||||
|
|
||||||
if (params.input.appAuthClientId) {
|
|
||||||
const appAuthClient = await AppAuthClient.query()
|
|
||||||
.findById(params.input.appAuthClientId)
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
formattedData = appAuthClient.formattedAuthDefaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
connection = await connection.$query().patchAndFetch({
|
|
||||||
formattedData: {
|
|
||||||
...connection.formattedData,
|
|
||||||
...formattedData,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return connection;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default updateConnection;
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
const updateCurrentUser = async (_parent, params, context) => {
|
|
||||||
const user = await context.currentUser.$query().patchAndFetch({
|
|
||||||
email: params.input.email,
|
|
||||||
password: params.input.password,
|
|
||||||
fullName: params.input.fullName,
|
|
||||||
});
|
|
||||||
|
|
||||||
return user;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default updateCurrentUser;
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
import Flow from '../../models/flow.js';
|
|
||||||
import flowQueue from '../../queues/flow.js';
|
|
||||||
import {
|
|
||||||
REMOVE_AFTER_30_DAYS_OR_150_JOBS,
|
|
||||||
REMOVE_AFTER_7_DAYS_OR_50_JOBS,
|
|
||||||
} from '../../helpers/remove-job-configuration.js';
|
|
||||||
import globalVariable from '../../helpers/global-variable.js';
|
|
||||||
|
|
||||||
const JOB_NAME = 'flow';
|
|
||||||
const EVERY_15_MINUTES_CRON = '*/15 * * * *';
|
|
||||||
|
|
||||||
const updateFlowStatus = async (_parent, params, context) => {
|
|
||||||
const conditions = context.currentUser.can('publish', 'Flow');
|
|
||||||
const isCreator = conditions.isCreator;
|
|
||||||
const allFlows = Flow.query();
|
|
||||||
const userFlows = context.currentUser.$relatedQuery('flows');
|
|
||||||
const baseQuery = isCreator ? userFlows : allFlows;
|
|
||||||
|
|
||||||
let flow = await baseQuery
|
|
||||||
.clone()
|
|
||||||
.findOne({
|
|
||||||
id: params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
const newActiveValue = params.input.active;
|
|
||||||
|
|
||||||
if (flow.active === newActiveValue) {
|
|
||||||
return flow;
|
|
||||||
}
|
|
||||||
|
|
||||||
const triggerStep = await flow.getTriggerStep();
|
|
||||||
|
|
||||||
if (triggerStep.status === 'incomplete') {
|
|
||||||
throw flow.IncompleteStepsError;
|
|
||||||
}
|
|
||||||
|
|
||||||
const trigger = await triggerStep.getTriggerCommand();
|
|
||||||
const interval = trigger.getInterval?.(triggerStep.parameters);
|
|
||||||
const repeatOptions = {
|
|
||||||
pattern: interval || EVERY_15_MINUTES_CRON,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (trigger.type === 'webhook') {
|
|
||||||
const $ = await globalVariable({
|
|
||||||
flow,
|
|
||||||
connection: await triggerStep.$relatedQuery('connection'),
|
|
||||||
app: await triggerStep.getApp(),
|
|
||||||
step: triggerStep,
|
|
||||||
testRun: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (newActiveValue && trigger.registerHook) {
|
|
||||||
await trigger.registerHook($);
|
|
||||||
} else if (!newActiveValue && trigger.unregisterHook) {
|
|
||||||
await trigger.unregisterHook($);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (newActiveValue) {
|
|
||||||
flow = await flow.$query().patchAndFetch({
|
|
||||||
publishedAt: new Date().toISOString(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const jobName = `${JOB_NAME}-${flow.id}`;
|
|
||||||
|
|
||||||
await flowQueue.add(
|
|
||||||
jobName,
|
|
||||||
{ flowId: flow.id },
|
|
||||||
{
|
|
||||||
repeat: repeatOptions,
|
|
||||||
jobId: flow.id,
|
|
||||||
removeOnComplete: REMOVE_AFTER_7_DAYS_OR_50_JOBS,
|
|
||||||
removeOnFail: REMOVE_AFTER_30_DAYS_OR_150_JOBS,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const repeatableJobs = await flowQueue.getRepeatableJobs();
|
|
||||||
const job = repeatableJobs.find((job) => job.id === flow.id);
|
|
||||||
|
|
||||||
await flowQueue.removeRepeatableByKey(job.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flow = await flow.$query().withGraphFetched('steps').patchAndFetch({
|
|
||||||
active: newActiveValue,
|
|
||||||
});
|
|
||||||
|
|
||||||
return flow;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default updateFlowStatus;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
const updateFlow = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('update', 'Flow');
|
|
||||||
|
|
||||||
let flow = await context.currentUser
|
|
||||||
.$relatedQuery('flows')
|
|
||||||
.findOne({
|
|
||||||
id: params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
flow = await flow.$query().patchAndFetch({
|
|
||||||
name: params.input.name,
|
|
||||||
});
|
|
||||||
|
|
||||||
return flow;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default updateFlow;
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import Role from '../../models/role.js';
|
|
||||||
import Permission from '../../models/permission.js';
|
|
||||||
import permissionCatalog from '../../helpers/permission-catalog.ee.js';
|
|
||||||
|
|
||||||
const updateRole = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('update', 'Role');
|
|
||||||
|
|
||||||
const { id, name, description, permissions } = params.input;
|
|
||||||
|
|
||||||
const role = await Role.query().findById(id).throwIfNotFound();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const updatedRole = await Role.transaction(async (trx) => {
|
|
||||||
await role.$relatedQuery('permissions', trx).delete();
|
|
||||||
|
|
||||||
if (permissions?.length) {
|
|
||||||
const sanitizedPermissions = permissions
|
|
||||||
.filter((permission) => {
|
|
||||||
const { action, subject, conditions } = permission;
|
|
||||||
|
|
||||||
const relevantAction = permissionCatalog.actions.find(
|
|
||||||
(actionCatalogItem) => actionCatalogItem.key === action
|
|
||||||
);
|
|
||||||
const validSubject = relevantAction.subjects.includes(subject);
|
|
||||||
const validConditions = conditions.every((condition) => {
|
|
||||||
return !!permissionCatalog.conditions.find(
|
|
||||||
(conditionCatalogItem) => conditionCatalogItem.key === condition
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return validSubject && validConditions;
|
|
||||||
})
|
|
||||||
.map((permission) => ({
|
|
||||||
...permission,
|
|
||||||
roleId: role.id,
|
|
||||||
}));
|
|
||||||
|
|
||||||
await Permission.query().insert(sanitizedPermissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
await role.$query(trx).patch({
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
});
|
|
||||||
|
|
||||||
return await Role.query(trx)
|
|
||||||
.leftJoinRelated({
|
|
||||||
permissions: true,
|
|
||||||
})
|
|
||||||
.withGraphFetched({
|
|
||||||
permissions: true,
|
|
||||||
})
|
|
||||||
.findById(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
return updatedRole;
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error('The role could not be updated!');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default updateRole;
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import App from '../../models/app.js';
|
|
||||||
import Step from '../../models/step.js';
|
|
||||||
import Connection from '../../models/connection.js';
|
|
||||||
|
|
||||||
const updateStep = async (_parent, params, context) => {
|
|
||||||
const { isCreator } = context.currentUser.can('update', 'Flow');
|
|
||||||
const userSteps = context.currentUser.$relatedQuery('steps');
|
|
||||||
const allSteps = Step.query();
|
|
||||||
const baseQuery = isCreator ? userSteps : allSteps;
|
|
||||||
|
|
||||||
const { input } = params;
|
|
||||||
|
|
||||||
let step = await baseQuery
|
|
||||||
.findOne({
|
|
||||||
'steps.id': input.id,
|
|
||||||
flow_id: input.flow.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
if (input.connection.id) {
|
|
||||||
let canSeeAllConnections = false;
|
|
||||||
try {
|
|
||||||
const conditions = context.currentUser.can('read', 'Connection');
|
|
||||||
|
|
||||||
canSeeAllConnections = !conditions.isCreator;
|
|
||||||
} catch {
|
|
||||||
// void
|
|
||||||
}
|
|
||||||
|
|
||||||
const userConnections = context.currentUser.$relatedQuery('connections');
|
|
||||||
const allConnections = Connection.query();
|
|
||||||
const baseConnectionsQuery = canSeeAllConnections
|
|
||||||
? allConnections
|
|
||||||
: userConnections;
|
|
||||||
|
|
||||||
const connection = await baseConnectionsQuery
|
|
||||||
.clone()
|
|
||||||
.findById(input.connection?.id);
|
|
||||||
|
|
||||||
if (!connection) {
|
|
||||||
throw new Error('The connection does not exist!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (step.isTrigger) {
|
|
||||||
await App.checkAppAndTrigger(input.appKey, input.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (step.isAction) {
|
|
||||||
await App.checkAppAndAction(input.appKey, input.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
step = await Step.query()
|
|
||||||
.patchAndFetchById(input.id, {
|
|
||||||
key: input.key,
|
|
||||||
appKey: input.appKey,
|
|
||||||
connectionId: input.connection.id,
|
|
||||||
parameters: input.parameters,
|
|
||||||
status: 'incomplete'
|
|
||||||
})
|
|
||||||
.withGraphFetched('connection');
|
|
||||||
|
|
||||||
await step.updateWebhookUrl();
|
|
||||||
|
|
||||||
return step;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default updateStep;
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import User from '../../models/user.js';
|
|
||||||
|
|
||||||
const updateUser = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('update', 'User');
|
|
||||||
|
|
||||||
const userPayload = {
|
|
||||||
email: params.input.email,
|
|
||||||
fullName: params.input.fullName,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
context.currentUser.can('update', 'Role');
|
|
||||||
|
|
||||||
userPayload.roleId = params.input.role.id;
|
|
||||||
} catch {
|
|
||||||
// void
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await User.query().patchAndFetchById(
|
|
||||||
params.input.id,
|
|
||||||
userPayload
|
|
||||||
);
|
|
||||||
|
|
||||||
return user;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default updateUser;
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import App from '../../models/app.js';
|
|
||||||
import globalVariable from '../../helpers/global-variable.js';
|
|
||||||
|
|
||||||
const verifyConnection = async (_parent, params, context) => {
|
|
||||||
context.currentUser.can('create', 'Connection');
|
|
||||||
|
|
||||||
let connection = await context.currentUser
|
|
||||||
.$relatedQuery('connections')
|
|
||||||
.findOne({
|
|
||||||
id: params.input.id,
|
|
||||||
})
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
const app = await App.findOneByKey(connection.key);
|
|
||||||
const $ = await globalVariable({ connection, app });
|
|
||||||
await app.auth.verifyCredentials($);
|
|
||||||
|
|
||||||
connection = await connection.$query().patchAndFetch({
|
|
||||||
verified: true,
|
|
||||||
draft: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...connection,
|
|
||||||
app,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default verifyConnection;
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import mutationResolvers from './mutation-resolvers.js';
|
|
||||||
|
|
||||||
const resolvers = {
|
|
||||||
Mutation: mutationResolvers,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default resolvers;
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user