Compare commits

..

130 Commits

Author SHA1 Message Date
dependabot[bot]
015d65ac98 chore(deps): bump http-proxy-middleware from 2.0.1 to 2.0.7
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.1 to 2.0.7.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.1...v2.0.7)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-25 03:27:15 +00:00
Ömer Faruk Aydın
47510e24d5 Merge pull request #2110 from automatisch/aut-1293
test(app-config): write model tests
2024-10-25 01:18:26 +02:00
Faruk AYDIN
91c9ef3068 fix: Pass app config parameters to be used for hooks 2024-10-25 01:07:44 +02:00
Faruk AYDIN
240854e4ac fix: Use uuid for down migration of app config id removal 2024-10-25 00:59:00 +02:00
Jakub P.
0e4fc7efbc fix: use key instead of id in appConfig 2024-10-24 19:42:54 +02:00
Faruk AYDIN
b47e859225 test: Add additional cases for triggerAppConfigUpdate method 2024-10-24 17:10:47 +02:00
Faruk AYDIN
62a1072682 fix: Use triggerAppConfigUpdate spy instead of 2024-10-24 17:07:23 +02:00
Faruk AYDIN
c6f2a97591 test: Add missing associations test for app auth client 2024-10-24 17:04:45 +02:00
Faruk AYDIN
d66be231b3 refactor: Remove redundant updateConnectionAllowedProperty 2024-10-24 17:00:47 +02:00
Faruk AYDIN
f73ffc8711 test: Add idColumn test to app config model 2024-10-24 16:59:17 +02:00
Faruk AYDIN
e4c17c1bc7 refactor: Use belongsTo relation for app config association 2024-10-24 16:59:17 +02:00
Faruk AYDIN
997e729535 refactor: Use hooks with refetched record for app config 2024-10-24 16:59:17 +02:00
Faruk AYDIN
e0e313b8d1 refactor: Remove id from app config factory 2024-10-24 16:59:17 +02:00
Faruk AYDIN
f0bd763e72 feat: Remove id field from app config model 2024-10-24 16:59:17 +02:00
Faruk AYDIN
6a7a90536b feat: Make key field primary key for app config model 2024-10-24 16:59:17 +02:00
Ali BARIN
ac8ddedfb5 test(connection): use new properties from app-config 2024-10-24 16:59:17 +02:00
Ali BARIN
6fcd126ff8 test(app-auth-client): cover lifecycle hooks and triggerAppConfigUpdate method 2024-10-24 16:59:17 +02:00
Faruk AYDIN
55d0966d48 fix: Pass app key while triggering app config update 2024-10-24 16:59:17 +02:00
Faruk AYDIN
2583e08f7a fix: Don't compute connectionAllowed column twice 2024-10-24 16:59:17 +02:00
Faruk AYDIN
de72e62470 fix: Pass app config key to fix associations 2024-10-24 16:59:17 +02:00
Faruk AYDIN
91993dbb07 refactor: AppConfig model and corresponding tests 2024-10-24 16:59:17 +02:00
Faruk AYDIN
d87ee4daa3 refactor: Move and adjust getApp tests for app config model 2024-10-24 16:59:17 +02:00
Ali BARIN
6791e002ff test(app-config): remove redundant virtual attributes test case 2024-10-24 16:59:17 +02:00
Ali BARIN
4ca84aa515 refactor(app-auth-client): remove redundant column selection 2024-10-24 16:59:17 +02:00
Ali BARIN
8189cbc171 fix(app-config): use correct case in connection_allowed 2024-10-24 16:59:17 +02:00
Ali BARIN
73edb45ff7 refactor(app-config): rename allowCustomConnection as customConnectionAllowed 2024-10-24 16:59:17 +02:00
Ali BARIN
0bbe362660 refactor(app-config): rename allow_custom_connection as custom_connection_allowed 2024-10-24 16:59:17 +02:00
Ali BARIN
a76bee51fc refactor(app-config): remove canCustomConnect virtual attribute 2024-10-24 16:59:17 +02:00
Ali BARIN
6e42b52414 refactor(app-config): rename canConnect as connectionAllowed 2024-10-24 16:59:17 +02:00
Ali BARIN
aed61209fa feat(app-config): update canConnect upon dependent changes 2024-10-24 16:59:17 +02:00
Ali BARIN
f5d796ea77 feat(app-config): persist relational virtual attrs 2024-10-24 16:59:17 +02:00
Ali BARIN
ecb04b4ba9 test(app-config): write model tests 2024-10-24 16:59:17 +02:00
Ali BARIN
dabb01e237 Merge pull request #2127 from automatisch/AUT-1231
feat: add error snackbar when creating or updating saml auth provider
2024-10-22 12:13:05 +02:00
Ali BARIN
c2d27d0fd4 Merge pull request #2136 from automatisch/aut-1322
test(connection): write remaining model tests
2024-10-21 17:41:31 +02:00
Ali BARIN
e62bd75fdf Merge pull request #2122 from automatisch/AUT-1239
feat: add error snackbar for updating role mappings
2024-10-21 16:44:24 +02:00
Ali BARIN
2e917bd62b Merge pull request #2120 from automatisch/AUT-1097
feat: allow both number and string values as sampleValue
2024-10-21 16:41:58 +02:00
Ali BARIN
e0492c4264 Merge pull request #2129 from automatisch/AUT-1253
feat: add error snackbar for errors originating from registerUser function
2024-10-21 16:41:31 +02:00
Ali BARIN
7db68e2f96 test(connection): write remaining model tests 2024-10-21 13:10:29 +00:00
Ömer Faruk Aydın
e9b05a37d1 Merge pull request #2135 from automatisch/aut-1322-2
test(connection): cover model lifecycle hooks
2024-10-21 12:49:49 +02:00
Ali BARIN
5613259536 test(connection): cover model lifecycle hooks 2024-10-21 12:41:57 +02:00
Ömer Faruk Aydın
3209ff16ac Merge pull request #2130 from automatisch/aut-1322
test(connection): write model tests
2024-10-21 12:41:04 +02:00
Faruk AYDIN
a49c8602d1 refactor: Remove redundant test cases for connection model 2024-10-21 12:32:46 +02:00
Ali BARIN
7caa055e00 test(connection): write model tests 2024-10-21 10:27:43 +02:00
Ömer Faruk Aydın
0d62bc6c78 Merge pull request #2134 from automatisch/permission-tests
Permission tests
2024-10-18 17:33:57 +02:00
Faruk AYDIN
bc0861fd9e test: Implement tests for permission model 2024-10-18 15:34:06 +02:00
Faruk AYDIN
f280052d93 refactor: Permission model sanitize method 2024-10-18 15:33:47 +02:00
kasia.oczkowska
21da49f79d feat: add error snackbar for errors originating from registerUser function 2024-10-18 13:41:57 +01:00
kasia.oczkowska
19a5ccf942 feat: add error snackbar when creating or updating saml auth provider 2024-10-16 14:31:05 +01:00
Ali BARIN
0234b4ad81 Merge pull request #2125 from automatisch/aut-1322
test(connection): write model tests
2024-10-16 13:23:17 +02:00
Ömer Faruk Aydın
59ee9c21f3 Merge pull request #2111 from automatisch/aut-1301
test(app): write model tests
2024-10-16 13:17:35 +02:00
Faruk AYDIN
00317fed24 refactor: Use endsWith for app folder path test 2024-10-16 12:56:17 +02:00
Ali BARIN
42f6311ca8 test(app): write model tests 2024-10-16 12:56:17 +02:00
Ali BARIN
0f77a1ec03 test(connection): write model tests 2024-10-16 09:38:48 +00:00
Ali BARIN
8268cd4d09 Merge pull request #2123 from automatisch/aut-1319
test(config): write model tests
2024-10-14 13:28:09 +02:00
Ali BARIN
c868070337 test(config): write model tests 2024-10-14 11:19:29 +00:00
kasia.oczkowska
2981fa5946 feat: add error snackbar for updating role mappings 2024-10-10 13:34:40 +01:00
Ömer Faruk Aydın
623ec66a79 Merge pull request #2121 from automatisch/usage-data-tests
test: Implement UsageData model tests
2024-10-10 13:03:09 +02:00
Faruk AYDIN
b51bae14ec test: Implement UsageData model tests 2024-10-10 12:08:41 +02:00
kasia.oczkowska
05a3016557 feat: allow both number and string values as sampleValue 2024-10-10 09:21:03 +01:00
Ömer Faruk Aydın
9250456e7b Merge pull request #2119 from automatisch/execution-step-test
tests: Implement tests for ExecutionStep model
2024-10-09 16:27:39 +02:00
Faruk AYDIN
163d6a7a28 refactor: Do not use persisted instance for execution step is failed 2024-10-09 15:43:33 +02:00
Faruk AYDIN
4ce9976dbc refactor: Use isSucceededNonTestRun naming for execution steps 2024-10-09 15:43:33 +02:00
Faruk AYDIN
f6490990de tests: Implement tests for ExecutionStep model 2024-10-09 15:43:33 +02:00
Ali BARIN
f24ff606ac Merge pull request #2113 from automatisch/AUT-1196
fix: use env var for authDocUrl
2024-10-09 15:15:09 +02:00
Jakub P.
3ff53744b5 fix: use env var for authDocUrl 2024-10-09 15:02:59 +02:00
Ali BARIN
0b33c10ed8 Merge pull request #2029 from automatisch/AUT-1190
fix: limit resetting form on defaultValues change
2024-10-09 14:54:05 +02:00
Ömer Faruk Aydın
3fa87701ed Merge pull request #2114 from automatisch/AUT-929
feat: fix primary app color value and how it is displayed in the app
2024-10-09 11:02:03 +02:00
Ali BARIN
e5e0c6fa2a Merge pull request #2117 from automatisch/aut-1191-2
fix: bring back missing custom logo
2024-10-08 21:54:12 +02:00
Jakub P.
0b38a0b6af fix: bring back missing custom logo 2024-10-08 17:56:13 +00:00
Ömer Faruk Aydın
44b228777a Merge pull request #2093 from automatisch/aut-1191
feat(config): make data structure horizontal
2024-10-08 18:15:33 +02:00
Ali BARIN
dd4f658d14 test: cover static config in config controller test 2024-10-08 14:41:02 +00:00
Ali BARIN
9c66f47bca test: write config serializer cases 2024-10-08 14:34:14 +00:00
Ali BARIN
138a34d6a4 feat(config): incorporate static config as virtual attributes 2024-10-08 14:19:17 +00:00
Ali BARIN
8f2af2e863 chore: rename horizontal config migration as make_config_single_record 2024-10-08 14:18:38 +00:00
Ali BARIN
c732fe16b3 refactor(update-config): introduce updateFirstOrInsert via query builder 2024-10-08 13:18:42 +00:00
Ali BARIN
9be75e56e7 refactor(migration): simplify make_config_horizontal_scale script 2024-10-08 13:18:42 +00:00
Ali BARIN
e7d1f26034 feat(serializers): add config serializer 2024-10-08 13:18:42 +00:00
Ali BARIN
c554fff048 feat(config): add missing schema properties 2024-10-08 13:18:42 +00:00
Ali BARIN
0268521aaa test(config): fix typo in palette primary light 2024-10-08 13:18:42 +00:00
Ali BARIN
89b1cb9353 feat(web): adapt to horizontal config structure 2024-10-08 13:18:42 +00:00
Ali BARIN
8a17c5eaab feat(config): make data structure horizontal 2024-10-08 13:18:42 +00:00
Ömer Faruk Aydın
f4a1ad6c8c Merge pull request #2109 from automatisch/aut-1292
test(app-auth-client): write model tests
2024-10-08 15:09:41 +02:00
Jakub P.
93d76d8d79 feat: add hash in color to the examples in docs 2024-10-07 16:39:51 +02:00
Ali BARIN
0b956a71b9 test(models/app-auth-client): improve decrypt data test cases 2024-10-07 13:25:04 +00:00
Faruk AYDIN
26be72f76d test: Improve encrypt data tests for AppAuthClient model 2024-10-07 14:21:14 +02:00
Ali BARIN
737391c721 test(app-auth-client): write model tests 2024-10-07 09:14:18 +00:00
kasia.oczkowska
9c1d21fd1b feat: fix primary app color value and how it is displayed in the app 2024-10-04 12:34:50 +01:00
kasia.oczkowska
ef4a4c8611 fix: limit resetting form on defaultValues change 2024-10-04 11:46:12 +01:00
Ömer Faruk Aydın
13c0a8ceaa Merge pull request #2112 from automatisch/test-subscription
test: Implement subscription model tests
2024-10-02 13:53:46 +03:00
Faruk AYDIN
c2976080f6 test: Implement subscription model tests 2024-10-02 13:44:21 +03:00
Faruk AYDIN
0a1b6931af test: Add tests for Identity model 2024-10-02 10:52:05 +03:00
Ömer Faruk Aydın
5009319f91 Merge pull request #2108 from automatisch/aut-1282
test(access-token): write model tests
2024-10-02 10:16:49 +03:00
Ali BARIN
4db8683bd6 test(access-token): write model tests 2024-10-01 10:37:43 +00:00
Ali BARIN
d35cf8d31e test: add access token factory 2024-10-01 09:55:36 +00:00
Ali BARIN
5fef16131a test: add identity factory 2024-10-01 09:55:26 +00:00
Ömer Faruk Aydın
8b2235ee26 Merge pull request #2107 from automatisch/execution-tests
test: Implement execution model tests
2024-09-30 17:33:28 +03:00
Faruk AYDIN
2d8faf849e test: Implement execution model tests 2024-09-30 17:25:15 +03:00
Ali BARIN
c9de9fa185 Merge pull request #2096 from automatisch/aut-1276
test(SamlAuthProvidersRoleMapping): assert model properties
2024-09-30 16:24:46 +02:00
Ali BARIN
0618877d58 test(models/saml-auth-providers-role-mapping): assert model properties 2024-09-30 14:14:02 +00:00
Ömer Faruk Aydın
f6b4e7eef8 Merge pull request #2095 from automatisch/datastore-tests
feat: Implement datastore model tests
2024-09-30 17:12:11 +03:00
Faruk AYDIN
7abe44da19 refactor: Use matchsnapshot for datastore tests 2024-09-30 16:43:06 +03:00
Faruk AYDIN
9006a0c25f refactor: Update required validations with custom assertion 2024-09-30 16:39:06 +03:00
Faruk AYDIN
f8389ff8ab feat: Implement datastore model tests 2024-09-30 16:39:06 +03:00
Ömer Faruk Aydın
894afe8f92 Merge pull request #2104 from automatisch/remove-gql
refactor: remove whole graphql implementation
2024-09-30 15:14:14 +03:00
Ali BARIN
115394ac8c test(helpers/authentication): bring back applicable tests 2024-09-30 12:04:58 +00:00
Ali BARIN
de42eda65f refactor(helpers/authentication): remove obsolete arguments in isAuthenticated 2024-09-30 12:04:37 +00:00
Ali BARIN
0b7591edce refactor: remove whole graphql implementation 2024-09-30 12:02:25 +00:00
Ömer Faruk Aydın
a043a044ca Merge pull request #2099 from automatisch/aut-1262
feat: use REST API endpoints to create and reconnect connections
2024-09-30 13:33:52 +03:00
Ali BARIN
b1f2727beb test(create-dynamic-data): use 422 for error response 2024-09-30 08:25:56 +00:00
Ali BARIN
d6e78a48a0 feat(AddAppConnection): show meaningful error messages only 2024-09-30 08:25:56 +00:00
Ali BARIN
589fe0f5f3 feat(useAuthenticateApp): remove redundant graphql implementation 2024-09-30 08:25:56 +00:00
Ali BARIN
244eeeb816 feat(useAuthenticateApp): centralize invalidating queries 2024-09-30 08:25:56 +00:00
kasia.oczkowska
4d5fc50f1a feat: refactor verify connection mutation with the REST API endpoint 2024-09-30 08:25:54 +00:00
Ali BARIN
dc0273148c chore: remove redundant reset connection mutation 2024-09-30 08:25:09 +00:00
Ali BARIN
5e6f4bfb88 feat(useAuthenticateApp): use REST API endpoint to reset connection 2024-09-30 08:24:03 +00:00
Ali BARIN
bc0e18d074 chore: remove redundant update connection mutation 2024-09-30 08:24:02 +00:00
Ali BARIN
24d09fda4c feat(useAuthenticateApp): use REST API endpoint to update connection 2024-09-30 08:23:29 +00:00
Ali BARIN
5e20ac07d1 chore(add-authentication-steps): remove unnecessary id arguments 2024-09-30 08:23:29 +00:00
Ali BARIN
37c78e6bbd chore: remove redundant generate auth url mutation 2024-09-30 08:23:26 +00:00
Ali BARIN
7dcfb1081b feat(useAuthenticateApp): use REST API endpoint to create auth url 2024-09-30 08:23:00 +00:00
Ali BARIN
01407cf040 Merge pull request #2106 from automatisch/AUT-1265
feat: refactor update-current-user mutation with the REST API endpoint
2024-09-30 10:11:22 +02:00
Jakub P.
eb814c2fb0 test: add reset password tests 2024-09-27 23:16:16 +02:00
kasia.oczkowska
d3caadf4af feat: refactor update-current-user mutation with the REST API endpoint 2024-09-27 13:42:58 +01:00
Ali BARIN
5769c82fca Merge pull request #2098 from automatisch/aut-1258
feat(useAuthenticateApp): use REST API endpoint to create connection
2024-09-25 10:03:57 +02:00
Ali BARIN
3754783ce2 Merge pull request #2103 from automatisch/AUT-1279
test: add change own user data test
2024-09-24 21:25:41 +02:00
Jakub P.
55ebe2cc0b test: add change own user data test 2024-09-24 18:42:30 +02:00
Ali BARIN
23c1a42163 chore: remove redundant create connection mutation 2024-09-24 08:31:26 +00:00
Ali BARIN
c879ffa768 feat(useAuthenticateApp): use REST API endpoint to create connection 2024-09-24 08:30:53 +00:00
Ali BARIN
32f7bbfbab chore: remove redundant execute flow mutation 2024-09-24 10:23:33 +02:00
Ali BARIN
84d5b3b158 feat: use REST API endpoint to test step 2024-09-24 10:23:33 +02:00
239 changed files with 4649 additions and 2338 deletions

View File

@@ -23,7 +23,6 @@ env:
REDIS_HOST: localhost
APP_ENV: production
LICENSE_KEY: dummy_license_key
BACKEND_APP_URL: http://localhost:3000
jobs:
test:

View File

@@ -23,8 +23,6 @@
"dependencies": {
"@bull-board/express": "^3.10.1",
"@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",
"@rudderstack/rudder-sdk-node": "^1.1.2",
"@sentry/node": "^7.42.0",
@@ -41,11 +39,7 @@
"express": "~4.18.2",
"express-async-errors": "^3.1.1",
"express-basic-auth": "^1.2.1",
"express-graphql": "^0.12.0",
"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",
"http-errors": "~1.6.3",
"http-proxy-agent": "^7.0.0",

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://api.airtable.com',
iconUrl: '{BASE_URL}/apps/airtable/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/airtable/connection',
primaryColor: 'FFBF00',
primaryColor: '#FFBF00',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://cloud.appwrite.io',
iconUrl: '{BASE_URL}/apps/appwrite/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/appwrite/connection',
primaryColor: 'FD366E',
primaryColor: '#FD366E',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/azure-openai/connection',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://carbone.io',
apiBaseUrl: 'https://api.carbone.io',
primaryColor: '6f42c1',
primaryColor: '#6f42c1',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -12,8 +12,8 @@ export default defineApp({
baseUrl: 'https://clickup.com',
apiBaseUrl: 'https://api.clickup.com/api',
iconUrl: '{BASE_URL}/apps/clickup/assets/favicon.svg',
authDocUrl: 'https://automatisch.io/docs/apps/clickup/connection',
primaryColor: 'FD71AF',
authDocUrl: '{DOCS_URL}/apps/clickup/connection',
primaryColor: '#FD71AF',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -8,7 +8,7 @@ export default defineApp({
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/code/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/code/connection',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: false,
actions,
});

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '001F52',
primaryColor: '#001F52',
actions,
});

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '001F52',
primaryColor: '#001F52',
actions,
});

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://deepl.com',
apiBaseUrl: 'https://api.deepl.com',
primaryColor: '0d2d45',
primaryColor: '#0d2d45',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '001F52',
primaryColor: '#001F52',
actions,
});

View File

@@ -14,7 +14,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://discord.com',
apiBaseUrl: 'https://discord.com/api',
primaryColor: '5865f2',
primaryColor: '#5865f2',
beforeRequest: [addAuthHeader],
auth,
dynamicData,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://disqus.com/api',
iconUrl: '{BASE_URL}/apps/disqus/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/disqus/connection',
primaryColor: '2E9FFF',
primaryColor: '#2E9FFF',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://dropbox.com',
apiBaseUrl: 'https://api.dropboxapi.com',
primaryColor: '0061ff',
primaryColor: '#0061ff',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '001F52',
primaryColor: '#001F52',
actions,
});

View File

@@ -10,7 +10,7 @@ export default defineApp({
iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/flickr/connection',
docUrl: 'https://automatisch.io/docs/flickr',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: true,
baseUrl: 'https://www.flickr.com/',
apiBaseUrl: 'https://www.flickr.com/services',

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://flowers-software.com',
apiBaseUrl: 'https://webapp.flowers-software.com/api',
primaryColor: '02AFC7',
primaryColor: '#02AFC7',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -10,7 +10,7 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '001F52',
primaryColor: '#001F52',
actions,
dynamicFields,
});

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/ghost/connection',
primaryColor: '15171A',
primaryColor: '#15171A',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://api.github.com',
iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/github/connection',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://gitlab.com',
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/gitlab/connection',
primaryColor: 'FC6D26',
primaryColor: '#FC6D26',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://www.googleapis.com/calendar',
iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-calendar/connection',
primaryColor: '448AFF',
primaryColor: '#448AFF',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://www.googleapis.com/drive',
iconUrl: '{BASE_URL}/apps/google-drive/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-drive/connection',
primaryColor: '1FA463',
primaryColor: '#1FA463',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://forms.googleapis.com',
iconUrl: '{BASE_URL}/apps/google-forms/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-forms/connection',
primaryColor: '673AB7',
primaryColor: '#673AB7',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -13,7 +13,7 @@ export default defineApp({
apiBaseUrl: 'https://sheets.googleapis.com',
iconUrl: '{BASE_URL}/apps/google-sheets/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-sheets/connection',
primaryColor: '0F9D58',
primaryColor: '#0F9D58',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://tasks.googleapis.com',
iconUrl: '{BASE_URL}/apps/google-tasks/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-tasks/connection',
primaryColor: '0066DA',
primaryColor: '#0066DA',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://app.tryhelix.ai',
iconUrl: '{BASE_URL}/apps/helix/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/helix/connection',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '000000',
primaryColor: '#000000',
actions,
});

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://www.hubspot.com',
apiBaseUrl: 'https://api.hubapi.com',
primaryColor: 'F95C35',
primaryColor: '#F95C35',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -13,7 +13,7 @@ export default defineApp({
apiBaseUrl: 'https://invoicing.co/api',
iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/invoice-ninja/connection',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -9,11 +9,11 @@ export default defineApp({
name: 'Jotform',
key: 'jotform',
iconUrl: '{BASE_URL}/apps/jotform/assets/favicon.svg',
authDocUrl: 'https://automatisch.io/docs/apps/jotform/connection',
authDocUrl: '{DOCS_URL}/apps/jotform/connection',
supportsConnections: true,
baseUrl: 'https://www.jotform.com',
apiBaseUrl: 'https://api.jotform.com',
primaryColor: 'FF6100',
primaryColor: '#FF6100',
beforeRequest: [setBaseUrl, addAuthHeader],
auth,
triggers,

View File

@@ -12,8 +12,8 @@ export default defineApp({
baseUrl: 'https://mailchimp.com',
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/mailchimp/assets/favicon.svg',
authDocUrl: 'https://automatisch.io/docs/apps/mailchimp/connection',
primaryColor: '000000',
authDocUrl: '{DOCS_URL}/apps/mailchimp/connection',
primaryColor: '#000000',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -7,11 +7,11 @@ export default defineApp({
name: 'MailerLite',
key: 'mailerlite',
iconUrl: '{BASE_URL}/apps/mailerlite/assets/favicon.svg',
authDocUrl: 'https://automatisch.io/docs/apps/mailerlite/connection',
authDocUrl: '{DOCS_URL}/apps/mailerlite/connection',
supportsConnections: true,
baseUrl: 'https://www.mailerlite.com',
apiBaseUrl: 'https://connect.mailerlite.com/api',
primaryColor: '09C269',
primaryColor: '#09C269',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -13,7 +13,7 @@ export default defineApp({
authDocUrl: '{DOCS_URL}/apps/mattermost/connection',
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
primaryColor: '4a154b',
primaryColor: '#4a154b',
supportsConnections: true,
beforeRequest: [setBaseUrl, addXRequestedWithHeader, addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://api.miro.com',
iconUrl: '{BASE_URL}/apps/miro/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/miro/connection',
primaryColor: 'F2CA02',
primaryColor: '#F2CA02',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -13,7 +13,7 @@ export default defineApp({
apiBaseUrl: 'https://api.notion.com',
iconUrl: '{BASE_URL}/apps/notion/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/notion/connection',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: true,
beforeRequest: [addAuthHeader, addNotionVersionHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://ntfy.sh',
apiBaseUrl: 'https://ntfy.sh',
primaryColor: '56bda8',
primaryColor: '#56bda8',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -10,7 +10,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://odoo.com',
apiBaseUrl: '',
primaryColor: '9c5789',
primaryColor: '#9c5789',
auth,
actions,
});

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://api.openai.com',
iconUrl: '{BASE_URL}/apps/openai/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/openai/connection',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -13,7 +13,7 @@ export default defineApp({
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/pipedrive/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/pipedrive/connection',
primaryColor: 'FFFFFF',
primaryColor: '#FFFFFF',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://placetel.de',
apiBaseUrl: 'https://api.placetel.de',
primaryColor: '069dd9',
primaryColor: '#069dd9',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -10,7 +10,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '336791',
primaryColor: '#336791',
auth,
actions,
});

View File

@@ -10,7 +10,7 @@ export default defineApp({
apiBaseUrl: 'https://api.pushover.net',
iconUrl: '{BASE_URL}/apps/pushover/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/pushover/connection',
primaryColor: '249DF1',
primaryColor: '#249DF1',
supportsConnections: true,
auth,
actions,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://oauth.reddit.com',
iconUrl: '{BASE_URL}/apps/reddit/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/reddit/connection',
primaryColor: 'FF4500',
primaryColor: '#FF4500',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://www.remove.bg',
apiBaseUrl: 'https://api.remove.bg/v1.0',
primaryColor: '55636c',
primaryColor: '#55636c',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: 'ff8800',
primaryColor: '#ff8800',
triggers,
});

View File

@@ -13,7 +13,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://salesforce.com',
apiBaseUrl: '',
primaryColor: '00A1E0',
primaryColor: '#00A1E0',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -9,7 +9,7 @@ export default defineApp({
authDocUrl: '{DOCS_URL}/apps/scheduler/connection',
baseUrl: '',
apiBaseUrl: '',
primaryColor: '0059F7',
primaryColor: '#0059F7',
supportsConnections: false,
triggers,
});

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/self-hosted-llm/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/self-hosted-llm/connection',
primaryColor: '000000',
primaryColor: '#000000',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -13,7 +13,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://signalwire.com',
apiBaseUrl: '',
primaryColor: '044cf6',
primaryColor: '#044cf6',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -13,7 +13,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://slack.com',
apiBaseUrl: 'https://slack.com/api',
primaryColor: '4a154b',
primaryColor: '#4a154b',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -10,7 +10,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '2DAAE1',
primaryColor: '#2DAAE1',
auth,
actions,
});

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://spotify.com',
apiBaseUrl: 'https://api.spotify.com',
primaryColor: '000000',
primaryColor: '#000000',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://www.strava.com',
apiBaseUrl: 'https://www.strava.com/api',
primaryColor: 'fc4c01',
primaryColor: '#fc4c01',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://stripe.com',
apiBaseUrl: 'https://api.stripe.com',
primaryColor: '635bff',
primaryColor: '#635bff',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://telegram.org',
apiBaseUrl: 'https://api.telegram.org',
primaryColor: '2AABEE',
primaryColor: '#2AABEE',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -13,7 +13,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://todoist.com',
apiBaseUrl: 'https://api.todoist.com/rest/v2',
primaryColor: 'e44332',
primaryColor: '#e44332',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -12,7 +12,7 @@ export default defineApp({
iconUrl: '{BASE_URL}/apps/trello/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/trello/connection',
supportsConnections: true,
primaryColor: '0079bf',
primaryColor: '#0079bf',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -13,7 +13,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://twilio.com',
apiBaseUrl: 'https://api.twilio.com',
primaryColor: 'e1000f',
primaryColor: '#e1000f',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -12,7 +12,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://twitter.com',
apiBaseUrl: 'https://api.twitter.com',
primaryColor: '1da1f2',
primaryColor: '#1da1f2',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -12,7 +12,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://typeform.com',
apiBaseUrl: 'https://api.typeform.com',
primaryColor: '262627',
primaryColor: '#262627',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -14,7 +14,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '39a86d',
primaryColor: '#39a86d',
beforeRequest: [setBaseUrl, addAuthHeader],
auth,
triggers,

View File

@@ -10,7 +10,7 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '0059F7',
primaryColor: '#0059F7',
actions,
triggers,
});

View File

@@ -13,7 +13,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://wordpress.com',
apiBaseUrl: '',
primaryColor: '464342',
primaryColor: '#464342',
beforeRequest: [setBaseUrl, addAuthHeader],
auth,
triggers,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://api.xero.com',
iconUrl: '{BASE_URL}/apps/xero/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/xero/connection',
primaryColor: '13B5EA',
primaryColor: '#13B5EA',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -10,7 +10,7 @@ export default defineApp({
apiBaseUrl: 'https://api.ynab.com/v1',
iconUrl: '{BASE_URL}/apps/you-need-a-budget/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/you-need-a-budget/connection',
primaryColor: '19223C',
primaryColor: '#19223C',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -10,7 +10,7 @@ export default defineApp({
apiBaseUrl: 'https://www.googleapis.com/youtube',
iconUrl: '{BASE_URL}/apps/youtube/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/youtube/connection',
primaryColor: 'FF0000',
primaryColor: '#FF0000',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/zendesk/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/zendesk/connection',
primaryColor: '17494d',
primaryColor: '#17494d',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -10,11 +10,11 @@ export default async (request, response) => {
};
const appConfigParams = (request) => {
const { allowCustomConnection, shared, disabled } = request.body;
const { customConnectionAllowed, shared, disabled } = request.body;
return {
key: request.params.appKey,
allowCustomConnection,
customConnectionAllowed,
shared,
disabled,
};

View File

@@ -23,7 +23,7 @@ describe('POST /api/v1/admin/apps/:appKey/config', () => {
it('should return created app config', async () => {
const appConfig = {
allowCustomConnection: true,
customConnectionAllowed: true,
shared: true,
disabled: false,
};
@@ -44,7 +44,7 @@ describe('POST /api/v1/admin/apps/:appKey/config', () => {
it('should return HTTP 422 for already existing app config', async () => {
const appConfig = {
key: 'gitlab',
allowCustomConnection: true,
customConnectionAllowed: true,
shared: true,
disabled: false,
};

View File

@@ -8,16 +8,19 @@ export default async (request, response) => {
})
.throwIfNotFound();
await appConfig.$query().patchAndFetch(appConfigParams(request));
await appConfig.$query().patchAndFetch({
...appConfigParams(request),
key: request.params.appKey,
});
renderObject(response, appConfig);
};
const appConfigParams = (request) => {
const { allowCustomConnection, shared, disabled } = request.body;
const { customConnectionAllowed, shared, disabled } = request.body;
return {
allowCustomConnection,
customConnectionAllowed,
shared,
disabled,
};

View File

@@ -24,7 +24,7 @@ describe('PATCH /api/v1/admin/apps/:appKey/config', () => {
it('should return updated app config', async () => {
const appConfig = {
key: 'gitlab',
allowCustomConnection: true,
customConnectionAllowed: true,
shared: true,
disabled: false,
};
@@ -34,7 +34,7 @@ describe('PATCH /api/v1/admin/apps/:appKey/config', () => {
const newAppConfigValues = {
shared: false,
disabled: true,
allowCustomConnection: false,
customConnectionAllowed: false,
};
const response = await request(app)
@@ -55,7 +55,7 @@ describe('PATCH /api/v1/admin/apps/:appKey/config', () => {
const appConfig = {
shared: false,
disabled: true,
allowCustomConnection: false,
customConnectionAllowed: false,
};
await request(app)
@@ -68,7 +68,7 @@ describe('PATCH /api/v1/admin/apps/:appKey/config', () => {
it('should return HTTP 422 for invalid app config data', async () => {
const appConfig = {
key: 'gitlab',
allowCustomConnection: true,
customConnectionAllowed: true,
shared: true,
disabled: false,
};

View File

@@ -1,23 +1,28 @@
import pick from 'lodash/pick.js';
import { renderObject } from '../../../../../helpers/renderer.js';
import Config from '../../../../../models/config.js';
export default async (request, response) => {
const config = configParams(request);
await Config.batchUpdate(config);
const config = await Config.query().updateFirstOrInsert(
configParams(request)
);
renderObject(response, config);
};
const configParams = (request) => {
const updatableConfigurationKeys = [
'logo.svgData',
'palette.primary.dark',
'palette.primary.light',
'palette.primary.main',
'title',
];
const {
logoSvgData,
palettePrimaryDark,
palettePrimaryLight,
palettePrimaryMain,
title,
} = request.body;
return pick(request.body, updatableConfigurationKeys);
return {
logoSvgData,
palettePrimaryDark,
palettePrimaryLight,
palettePrimaryMain,
title,
};
};

View File

@@ -5,7 +5,7 @@ import app from '../../../../../app.js';
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
import { createUser } from '../../../../../../test/factories/user.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';
describe('PATCH /api/v1/admin/config', () => {
@@ -30,13 +30,13 @@ describe('PATCH /api/v1/admin/config', () => {
const appConfig = {
title,
'palette.primary.main': palettePrimaryMain,
'palette.primary.dark': palettePrimaryDark,
'palette.primary.light': palettePrimaryLight,
'logo.svgData': logoSvgData,
palettePrimaryMain: palettePrimaryMain,
palettePrimaryDark: palettePrimaryDark,
palettePrimaryLight: palettePrimaryLight,
logoSvgData: logoSvgData,
};
await createBulkConfig(appConfig);
await updateConfig(appConfig);
const newTitle = 'Updated title';
@@ -51,7 +51,7 @@ describe('PATCH /api/v1/admin/config', () => {
.expect(200);
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 () => {
@@ -68,7 +68,7 @@ describe('PATCH /api/v1/admin/config', () => {
.expect(200);
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 () => {
@@ -83,6 +83,6 @@ describe('PATCH /api/v1/admin/config', () => {
.expect(200);
expect(response.body.data.title).toBeNull();
expect(response.body.meta.type).toEqual('Object');
expect(response.body.meta.type).toEqual('Config');
});
});

View File

@@ -155,7 +155,7 @@ describe('POST /api/v1/apps/:appKey/connections', () => {
await createAppConfig({
key: 'gitlab',
disabled: false,
allowCustomConnection: true,
customConnectionAllowed: true,
});
});
@@ -218,7 +218,7 @@ describe('POST /api/v1/apps/:appKey/connections', () => {
await createAppConfig({
key: 'gitlab',
disabled: false,
allowCustomConnection: false,
customConnectionAllowed: false,
});
});

View File

@@ -17,7 +17,7 @@ describe('GET /api/v1/apps/:appKey/config', () => {
appConfig = await createAppConfig({
key: 'deepl',
allowCustomConnection: true,
customConnectionAllowed: true,
shared: true,
disabled: false,
});

View File

@@ -1,25 +1,8 @@
import appConfig from '../../../../config/app.js';
import Config from '../../../../models/config.js';
import { renderObject } from '../../../../helpers/renderer.js';
export default async (request, response) => {
const defaultConfig = {
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);
const config = await Config.get();
renderObject(response, config);
};

View File

@@ -1,66 +1,47 @@
import { vi, expect, describe, it } from 'vitest';
import request from 'supertest';
import { createConfig } from '../../../../../test/factories/config.js';
import { updateConfig } from '../../../../../test/factories/config.js';
import app from '../../../../app.js';
import configMock from '../../../../../test/mocks/rest/api/v1/automatisch/config.js';
import * as license from '../../../../helpers/license.ee.js';
import appConfig from '../../../../config/app.js';
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(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({
key: 'logo.svgData',
value: { data: '<svg>Sample</svg>' },
});
const primaryDarkConfig = await createConfig({
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 config = await updateConfig({
logoSvgData: '<svg>Sample</svg>',
palettePrimaryDark: '#001f52',
palettePrimaryLight: '#4286FF',
palettePrimaryMain: '#0059F7',
title: 'Sample Title',
});
const response = await request(app)
.get('/api/v1/automatisch/config')
.expect(200);
const expectedPayload = configMock(
logoConfig,
primaryDarkConfig,
primaryLightConfig,
primaryMainConfig,
titleConfig
);
const expectedPayload = configMock({
...config,
disableNotificationsPage: true,
disableFavicon: true,
additionalDrawerLink: 'link',
additionalDrawerLinkIcon: 'icon',
additionalDrawerLinkText: 'text',
});
expect(response.body).toEqual(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');
expect(response.body).toStrictEqual(expectedPayload);
});
});

View File

@@ -8,7 +8,7 @@ export default async (request, response) => {
})
.throwIfNotFound();
connection = await connection.update(connectionParams(request));
connection = await connection.updateFormattedData(connectionParams(request));
renderObject(response, connection);
};

View File

@@ -5,7 +5,7 @@ import Config from '../../../../../models/config.js';
import User from '../../../../../models/user.js';
import { createRole } from '../../../../../../test/factories/role';
import { createUser } from '../../../../../../test/factories/user';
import { createInstallationCompletedConfig } from '../../../../../../test/factories/config';
import { markInstallationCompleted } from '../../../../../../test/factories/config';
describe('POST /api/v1/installation/users', () => {
let adminRole;
@@ -59,7 +59,7 @@ describe('POST /api/v1/installation/users', () => {
describe('for completed installations', () => {
beforeEach(async () => {
await createInstallationCompletedConfig();
await markInstallationCompleted();
});
it('should respond with HTTP 403 when installation completed', async () => {

View File

@@ -169,7 +169,7 @@ describe('POST /api/v1/steps/:stepId/dynamic-data', () => {
dynamicDataKey: 'listRepos',
parameters: {},
})
.expect(200);
.expect(422);
expect(response.body.errors).toEqual(errors);
});

View File

@@ -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;
}

View File

@@ -0,0 +1,37 @@
export async function up(knex) {
await knex.schema.alterTable('app_configs', (table) => {
table.boolean('connection_allowed').defaultTo(false);
});
const appConfigs = await knex('app_configs').select('*');
for (const appConfig of appConfigs) {
const appAuthClients = await knex('app_auth_clients').where(
'app_key',
appConfig.key
);
const hasSomeActiveAppAuthClients = !!appAuthClients?.some(
(appAuthClient) => appAuthClient.active
);
const shared = appConfig.shared;
const active = appConfig.disabled === false;
const connectionAllowedConditions = [
hasSomeActiveAppAuthClients,
shared,
active,
];
const connectionAllowed = connectionAllowedConditions.every(Boolean);
await knex('app_configs')
.where('id', appConfig.id)
.update({ connection_allowed: connectionAllowed });
}
}
export async function down(knex) {
await knex.schema.alterTable('app_configs', (table) => {
table.dropColumn('connection_allowed');
});
}

View File

@@ -0,0 +1,11 @@
export async function up(knex) {
return knex.schema.alterTable('app_configs', (table) => {
table.renameColumn('allow_custom_connection', 'custom_connection_allowed');
});
}
export async function down(knex) {
return knex.schema.alterTable('app_configs', (table) => {
table.renameColumn('custom_connection_allowed', 'allow_custom_connection');
});
}

View File

@@ -0,0 +1,13 @@
export async function up(knex) {
return knex.schema.alterTable('app_configs', function (table) {
table.dropPrimary();
table.primary('key');
});
}
export async function down(knex) {
return knex.schema.alterTable('app_configs', function (table) {
table.dropPrimary();
table.primary('id');
});
}

View File

@@ -0,0 +1,11 @@
export async function up(knex) {
return knex.schema.alterTable('app_configs', function (table) {
table.dropColumn('id');
});
}
export async function down(knex) {
return knex.schema.alterTable('app_configs', function (table) {
table.uuid('id').defaultTo(knex.raw('gen_random_uuid()'));
});
}

View File

@@ -1,20 +0,0 @@
// Converted mutations
import executeFlow from './mutations/execute-flow.js';
import verifyConnection from './mutations/verify-connection.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 resetConnection from './mutations/reset-connection.js';
import updateConnection from './mutations/update-connection.js';
const mutationResolvers = {
createConnection,
executeFlow,
generateAuthUrl,
resetConnection,
updateConnection,
updateCurrentUser,
verifyConnection,
};
export default mutationResolvers;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -1,7 +0,0 @@
import mutationResolvers from './mutation-resolvers.js';
const resolvers = {
Mutation: mutationResolvers,
};
export default resolvers;

View File

@@ -1,382 +0,0 @@
type Query {
placeholderQuery(name: String): Boolean
}
type Mutation {
createConnection(input: CreateConnectionInput): Connection
executeFlow(input: ExecuteFlowInput): executeFlowType
generateAuthUrl(input: GenerateAuthUrlInput): AuthLink
resetConnection(input: ResetConnectionInput): Connection
updateConnection(input: UpdateConnectionInput): Connection
updateCurrentUser(input: UpdateCurrentUserInput): User
verifyConnection(input: VerifyConnectionInput): Connection
}
"""
Exposes a URL that specifies the behaviour of this scalar.
"""
directive @specifiedBy(
"""
The URL that specifies the behaviour of this scalar.
"""
url: String!
) on SCALAR
type Trigger {
name: String
key: String
description: String
showWebhookUrl: Boolean
pollInterval: Int
type: String
substeps: [Substep]
}
type Action {
name: String
key: String
description: String
substeps: [Substep]
}
type Substep {
key: String
name: String
arguments: [SubstepArgument]
}
type SubstepArgument {
label: String
key: String
type: String
description: String
required: Boolean
variables: Boolean
options: [SubstepArgumentOption]
source: SubstepArgumentSource
additionalFields: SubstepArgumentAdditionalFields
dependsOn: [String]
fields: [SubstepArgument]
value: JSONObject
}
type SubstepArgumentOption {
label: String
value: JSONObject
}
type SubstepArgumentSource {
type: String
name: String
arguments: [SubstepArgumentSourceArgument]
}
type SubstepArgumentSourceArgument {
name: String
value: String
}
type SubstepArgumentAdditionalFields {
type: String
name: String
arguments: [SubstepArgumentAdditionalFieldsArgument]
}
type SubstepArgumentAdditionalFieldsArgument {
name: String
value: String
}
type App {
name: String
key: String
connectionCount: Int
flowCount: Int
iconUrl: String
docUrl: String
authDocUrl: String
primaryColor: String
supportsConnections: Boolean
auth: AppAuth
triggers: [Trigger]
actions: [Action]
connections: [Connection]
}
type AppAuth {
fields: [Field]
authenticationSteps: [AuthenticationStep]
sharedAuthenticationSteps: [AuthenticationStep]
reconnectionSteps: [ReconnectionStep]
sharedReconnectionSteps: [ReconnectionStep]
}
enum ArgumentEnumType {
integer
string
}
type AuthenticationStep {
type: String
name: String
arguments: [AuthenticationStepArgument]
}
type AuthenticationStepArgument {
name: String
value: String
type: ArgumentEnumType
properties: [AuthenticationStepProperty]
}
type AuthenticationStepProperty {
name: String
value: String
}
type AuthLink {
url: String
}
type Connection {
id: String
key: String
reconnectable: Boolean
appAuthClientId: String
formattedData: ConnectionData
verified: Boolean
app: App
createdAt: String
flowCount: Int
}
type ConnectionData {
screenName: String
}
type executeFlowType {
data: JSONObject
step: Step
}
type ExecutionStep {
id: String
executionId: String
stepId: String
step: Step
status: String
dataIn: JSONObject
dataOut: JSONObject
errorDetails: JSONObject
createdAt: String
updatedAt: String
}
type Field {
key: String
label: String
type: String
required: Boolean
readOnly: Boolean
value: String
placeholder: String
description: String
docUrl: String
clickToCopy: Boolean
options: [SubstepArgumentOption]
}
enum FlowStatus {
paused
published
draft
}
type Flow {
id: String
name: String
active: Boolean
steps: [Step]
createdAt: String
updatedAt: String
status: FlowStatus
}
type SamlAuthProvidersRoleMapping {
id: String
samlAuthProviderId: String
roleId: String
remoteRoleName: String
}
input CreateConnectionInput {
key: String!
appAuthClientId: String
formattedData: JSONObject
}
input GenerateAuthUrlInput {
id: String!
}
input UpdateConnectionInput {
id: String!
formattedData: JSONObject
appAuthClientId: String
}
input ResetConnectionInput {
id: String!
}
input VerifyConnectionInput {
id: String!
}
input ExecuteFlowInput {
stepId: String!
}
input UserRoleInput {
id: String
}
input UpdateCurrentUserInput {
email: String
password: String
fullName: String
}
"""
The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
"""
scalar JSONObject
input PreviousStepInput {
id: String
}
type ReconnectionStep {
type: String
name: String
arguments: [ReconnectionStepArgument]
}
type ReconnectionStepArgument {
name: String
value: String
type: ArgumentEnumType
properties: [ReconnectionStepProperty]
}
type ReconnectionStepProperty {
name: String
value: String
}
type Step {
id: String
previousStepId: String
key: String
appKey: String
iconUrl: String
webhookUrl: String
type: StepEnumType
parameters: JSONObject
connection: Connection
flow: Flow
position: Int
status: String
executionSteps: [ExecutionStep]
}
input StepConnectionInput {
id: String
}
enum StepEnumType {
trigger
action
}
input StepFlowInput {
id: String
}
input StepInput {
id: String
previousStepId: String
key: String
appKey: String
connection: StepConnectionInput
flow: StepFlowInput
parameters: JSONObject
previousStep: PreviousStepInput
}
type User {
id: String
fullName: String
email: String
role: Role
permissions: [Permission]
createdAt: String
updatedAt: String
}
type Role {
id: String
name: String
key: String
description: String
isAdmin: Boolean
permissions: [Permission]
}
type PageInfo {
currentPage: Int!
totalPages: Int!
}
type ExecutionStepEdge {
node: ExecutionStep
}
type ExecutionStepConnection {
edges: [ExecutionStepEdge]
pageInfo: PageInfo
}
type License {
id: String
name: String
expireAt: String
verified: Boolean
}
type Permission {
id: String
action: String
subject: String
conditions: [String]
}
type Action {
label: String
key: String
subjects: [String]
}
type Condition {
key: String
label: String
}
type Subject {
label: String
key: String
}
schema {
query: Query
mutation: Mutation
}

Some files were not shown because too many files have changed in this diff Show More