Compare commits
	
		
			30 Commits
		
	
	
		
			AUT-802
			...
			replace-wi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | f4a2e1a84b | ||
|   | 788530be45 | ||
|   | 7ed392e854 | ||
|   | 3932e554da | ||
|   | 1a21624618 | ||
|   | 9f292ff018 | ||
|   | dbb24b3a9b | ||
|   | 35b2639837 | ||
|   | 35951199cd | ||
|   | 79af909c51 | ||
|   | 3482aa7b76 | ||
|   | 5dbc1f59ef | ||
|   | 2166a3220e | ||
|   | 24a7d1ef10 | ||
|   | 18ffbb7317 | ||
|   | 363874de6a | ||
|   | 68d1719b11 | ||
|   | 1a75d81268 | ||
|   | 2163be4227 | ||
|   | b54afcd922 | ||
|   | 0a86641a0f | ||
|   | 18464c746a | ||
|   | ba92cddae1 | ||
|   | 2a4f8ed45f | ||
|   | 135a0028be | ||
|   | 4da6e8372f | ||
|   | 6a7cdf2570 | ||
|   | 73c929f25e | ||
|   | 754c2d41c2 | ||
|   | 7201e48111 | 
| @@ -4,5 +4,9 @@ | ||||
| **/.devcontainer | ||||
| **/.github | ||||
| **/.vscode | ||||
| **/.env | ||||
| **/.env.test | ||||
| **/.env.production | ||||
| **/yarn-error.log | ||||
| packages/docs | ||||
| packages/e2e-test | ||||
|   | ||||
| @@ -1,14 +1,25 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM node:18-alpine | ||||
| WORKDIR /automatisch | ||||
|  | ||||
| ENV PORT 3000 | ||||
|  | ||||
| RUN \ | ||||
|   apk --no-cache add --virtual build-dependencies python3 build-base git | ||||
|  | ||||
| WORKDIR /automatisch | ||||
|  | ||||
| # copy the app, note .dockerignore | ||||
| COPY . /automatisch | ||||
|  | ||||
| RUN yarn | ||||
|  | ||||
| RUN cd packages/web && yarn build | ||||
|  | ||||
| RUN \ | ||||
|   apk --no-cache add --virtual build-dependencies python3 build-base && \ | ||||
|   yarn global add @automatisch/cli@0.10.0 --network-timeout 1000000 && \ | ||||
|   rm -rf /usr/local/share/.cache/ && \ | ||||
|   apk del build-dependencies | ||||
|  | ||||
| COPY ./entrypoint.sh /entrypoint.sh | ||||
| COPY ./docker/entrypoint.sh /entrypoint.sh | ||||
|  | ||||
| EXPOSE 3000 | ||||
| ENTRYPOINT ["sh", "/entrypoint.sh"] | ||||
|   | ||||
| @@ -2,8 +2,12 @@ | ||||
|  | ||||
| set -e | ||||
|  | ||||
| cd packages/backend | ||||
|  | ||||
| if [ -n "$WORKER" ]; then | ||||
|   automatisch start-worker | ||||
|   yarn start:worker | ||||
| else | ||||
|   automatisch start | ||||
|   yarn db:migrate | ||||
|   yarn db:seed:user | ||||
|   yarn start | ||||
| fi | ||||
|   | ||||
| @@ -31,7 +31,7 @@ | ||||
|     "accounting": "^0.4.1", | ||||
|     "ajv-formats": "^2.1.1", | ||||
|     "axios": "1.6.0", | ||||
|     "bcrypt": "^5.0.1", | ||||
|     "bcrypt": "^5.1.0", | ||||
|     "bullmq": "^3.0.0", | ||||
|     "cors": "^2.8.5", | ||||
|     "crypto-js": "^4.1.1", | ||||
| @@ -95,6 +95,7 @@ | ||||
|     "url": "https://github.com/automatisch/automatisch/issues" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "node-gyp": "^10.1.0", | ||||
|     "nodemon": "^2.0.13", | ||||
|     "supertest": "^6.3.3", | ||||
|     "vitest": "^1.1.3" | ||||
|   | ||||
| @@ -11,7 +11,7 @@ export default defineApp({ | ||||
|     'https://azure.microsoft.com/en-us/products/ai-services/openai-service', | ||||
|   apiBaseUrl: '', | ||||
|   iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/azure-openai/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/azure-openai/connection', | ||||
|   primaryColor: '000000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [setBaseUrl, addAuthHeader], | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Carbone', | ||||
|   key: 'carbone', | ||||
|   iconUrl: '{BASE_URL}/apps/carbone/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/carbone/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/carbone/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://carbone.io', | ||||
|   apiBaseUrl: 'https://api.carbone.io', | ||||
|   | ||||
| @@ -5,7 +5,7 @@ export default defineApp({ | ||||
|   name: 'Datastore', | ||||
|   key: 'datastore', | ||||
|   iconUrl: '{BASE_URL}/apps/datastore/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/datastore/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/datastore/connection', | ||||
|   supportsConnections: false, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'DeepL', | ||||
|   key: 'deepl', | ||||
|   iconUrl: '{BASE_URL}/apps/deepl/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/deepl/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/deepl/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://deepl.com', | ||||
|   apiBaseUrl: 'https://api.deepl.com', | ||||
|   | ||||
| @@ -5,7 +5,7 @@ export default defineApp({ | ||||
|   name: 'Delay', | ||||
|   key: 'delay', | ||||
|   iconUrl: '{BASE_URL}/apps/delay/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/delay/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/delay/connection', | ||||
|   supportsConnections: false, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   name: 'Discord', | ||||
|   key: 'discord', | ||||
|   iconUrl: '{BASE_URL}/apps/discord/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/discord/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/discord/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://discord.com', | ||||
|   apiBaseUrl: 'https://discord.com/api', | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Dropbox', | ||||
|   key: 'dropbox', | ||||
|   iconUrl: '{BASE_URL}/apps/dropbox/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/dropbox/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/dropbox/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://dropbox.com', | ||||
|   apiBaseUrl: 'https://api.dropboxapi.com', | ||||
|   | ||||
| @@ -5,7 +5,7 @@ export default defineApp({ | ||||
|   name: 'Filter', | ||||
|   key: 'filter', | ||||
|   iconUrl: '{BASE_URL}/apps/filter/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/filter/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/filter/connection', | ||||
|   supportsConnections: false, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -1,116 +0,0 @@ | ||||
| import defineAction from '../../../../helpers/define-action.js'; | ||||
|  | ||||
| export default defineAction({ | ||||
|   name: 'Create Cloud Firestore document', | ||||
|   key: 'createCloudFirestoreDocument', | ||||
|   description: 'Creates a new document within a Cloud Firestore collection.', | ||||
|   arguments: [ | ||||
|     { | ||||
|       label: 'Collection', | ||||
|       key: 'collectionId', | ||||
|       type: 'dropdown', | ||||
|       required: true, | ||||
|       description: '', | ||||
|       variables: true, | ||||
|       source: { | ||||
|         type: 'query', | ||||
|         name: 'getDynamicData', | ||||
|         arguments: [ | ||||
|           { | ||||
|             name: 'key', | ||||
|             value: 'listFirestoreCollections', | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       label: 'Convert Numerics', | ||||
|       key: 'convertNumerics', | ||||
|       type: 'dropdown', | ||||
|       required: false, | ||||
|       description: | ||||
|         "If any value represents a valid numerical value, whether it's an integer or a floating-point number, this field directs the database to store it as a numeric data type instead of a string.", | ||||
|       variables: true, | ||||
|       options: [ | ||||
|         { label: 'Yes', value: true }, | ||||
|         { label: 'No', value: false }, | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       label: 'Document ID', | ||||
|       key: 'documentId', | ||||
|       type: 'string', | ||||
|       required: false, | ||||
|       description: | ||||
|         'The document ID to use for this document. If not specified, an ID will be assigned.', | ||||
|       variables: true, | ||||
|     }, | ||||
|     { | ||||
|       label: 'Document Data', | ||||
|       key: 'documentData', | ||||
|       type: 'dynamic', | ||||
|       required: false, | ||||
|       description: '', | ||||
|       fields: [ | ||||
|         { | ||||
|           label: 'Key', | ||||
|           key: 'key', | ||||
|           type: 'string', | ||||
|           required: false, | ||||
|           variables: true, | ||||
|         }, | ||||
|         { | ||||
|           label: 'Value', | ||||
|           key: 'value', | ||||
|           type: 'string', | ||||
|           required: false, | ||||
|           variables: true, | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
|  | ||||
|   async run($) { | ||||
|     const projectId = $.auth.data.projectId; | ||||
|     const { collectionId, documentId, documentData, convertNumerics } = | ||||
|       $.step.parameters; | ||||
|  | ||||
|     const documentDataObject = documentData.reduce((result, entry) => { | ||||
|       const key = entry.key?.toLowerCase(); | ||||
|       const value = entry.value; | ||||
|       const isNumber = !isNaN(parseFloat(value)); | ||||
|  | ||||
|       if (key && value) { | ||||
|         const formattedValue = | ||||
|           convertNumerics && isNumber | ||||
|             ? { integerValue: parseFloat(value) } | ||||
|             : { stringValue: value }; | ||||
|  | ||||
|         return { | ||||
|           ...result, | ||||
|           [key]: formattedValue, | ||||
|         }; | ||||
|       } | ||||
|  | ||||
|       return result; | ||||
|     }, {}); | ||||
|  | ||||
|     const body = { | ||||
|       fields: documentDataObject, | ||||
|     }; | ||||
|  | ||||
|     const { data } = await $.http.post( | ||||
|       `/v1/projects/${projectId}/databases/(default)/documents/${collectionId}?documentId=${documentId}`, | ||||
|       body, | ||||
|       { | ||||
|         additionalProperties: { | ||||
|           setFirestoreBaseUrl: true, | ||||
|         }, | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     $.setActionItem({ | ||||
|       raw: data, | ||||
|     }); | ||||
|   }, | ||||
| }); | ||||
| @@ -1,53 +0,0 @@ | ||||
| import defineAction from '../../../../helpers/define-action.js'; | ||||
|  | ||||
| export default defineAction({ | ||||
|   name: 'Find Cloud Firestore document', | ||||
|   key: 'findCloudFirestoreDocument', | ||||
|   description: 'Finds a document within a collection.', | ||||
|   arguments: [ | ||||
|     { | ||||
|       label: 'Collection', | ||||
|       key: 'collectionId', | ||||
|       type: 'dropdown', | ||||
|       required: true, | ||||
|       description: '', | ||||
|       variables: true, | ||||
|       source: { | ||||
|         type: 'query', | ||||
|         name: 'getDynamicData', | ||||
|         arguments: [ | ||||
|           { | ||||
|             name: 'key', | ||||
|             value: 'listFirestoreCollections', | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       label: 'Document ID', | ||||
|       key: 'documentId', | ||||
|       type: 'string', | ||||
|       required: true, | ||||
|       description: '', | ||||
|       variables: true, | ||||
|     }, | ||||
|   ], | ||||
|  | ||||
|   async run($) { | ||||
|     const projectId = $.auth.data.projectId; | ||||
|     const { collectionId, documentId } = $.step.parameters; | ||||
|  | ||||
|     const { data } = await $.http.get( | ||||
|       `/v1/projects/${projectId}/databases/(default)/documents/${collectionId}/${documentId}`, | ||||
|       { | ||||
|         additionalProperties: { | ||||
|           setFirestoreBaseUrl: true, | ||||
|         }, | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     $.setActionItem({ | ||||
|       raw: data, | ||||
|     }); | ||||
|   }, | ||||
| }); | ||||
| @@ -1,4 +0,0 @@ | ||||
| import createCloudFirestoreDocument from './create-cloud-firestore-document/index.js'; | ||||
| import findCloudFirestoreDocument from './find-cloud-firestore-document/index.js'; | ||||
|  | ||||
| export default [createCloudFirestoreDocument, findCloudFirestoreDocument]; | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| Before Width: | Height: | Size: 21 KiB | 
| @@ -1,23 +0,0 @@ | ||||
| import { URLSearchParams } from 'url'; | ||||
| import authScope from '../common/auth-scope.js'; | ||||
|  | ||||
| export default async function generateAuthUrl($) { | ||||
|   const oauthRedirectUrlField = $.app.auth.fields.find( | ||||
|     (field) => field.key == 'oAuthRedirectUrl' | ||||
|   ); | ||||
|   const redirectUri = oauthRedirectUrlField.value; | ||||
|   const searchParams = new URLSearchParams({ | ||||
|     client_id: $.auth.data.clientId, | ||||
|     redirect_uri: redirectUri, | ||||
|     prompt: 'select_account', | ||||
|     scope: authScope.join(' '), | ||||
|     response_type: 'code', | ||||
|     access_type: 'offline', | ||||
|   }); | ||||
|  | ||||
|   const url = `https://accounts.google.com/o/oauth2/v2/auth?${searchParams.toString()}`; | ||||
|  | ||||
|   await $.auth.set({ | ||||
|     url, | ||||
|   }); | ||||
| } | ||||
| @@ -1,71 +0,0 @@ | ||||
| import generateAuthUrl from './generate-auth-url.js'; | ||||
| import verifyCredentials from './verify-credentials.js'; | ||||
| import refreshToken from './refresh-token.js'; | ||||
| import isStillVerified from './is-still-verified.js'; | ||||
|  | ||||
| export default { | ||||
|   fields: [ | ||||
|     { | ||||
|       key: 'oAuthRedirectUrl', | ||||
|       label: 'OAuth Redirect URL', | ||||
|       type: 'string', | ||||
|       required: true, | ||||
|       readOnly: true, | ||||
|       value: '{WEB_APP_URL}/app/firebase/connections/add', | ||||
|       placeholder: null, | ||||
|       description: | ||||
|         'When asked to input a redirect URL in Google Cloud, enter the URL above.', | ||||
|       clickToCopy: true, | ||||
|     }, | ||||
|     { | ||||
|       key: 'clientId', | ||||
|       label: 'Client ID', | ||||
|       type: 'string', | ||||
|       required: true, | ||||
|       readOnly: false, | ||||
|       value: null, | ||||
|       placeholder: null, | ||||
|       description: null, | ||||
|       clickToCopy: false, | ||||
|     }, | ||||
|     { | ||||
|       key: 'clientSecret', | ||||
|       label: 'Client Secret', | ||||
|       type: 'string', | ||||
|       required: true, | ||||
|       readOnly: false, | ||||
|       value: null, | ||||
|       placeholder: null, | ||||
|       description: null, | ||||
|       clickToCopy: false, | ||||
|     }, | ||||
|     { | ||||
|       key: 'projectId', | ||||
|       label: 'Project ID', | ||||
|       type: 'string', | ||||
|       required: true, | ||||
|       readOnly: false, | ||||
|       value: null, | ||||
|       placeholder: null, | ||||
|       description: 'The project id of your Firebase project', | ||||
|       clickToCopy: false, | ||||
|     }, | ||||
|     { | ||||
|       key: 'realtimeDatabaseId', | ||||
|       label: 'Realtime Database Domain', | ||||
|       type: 'string', | ||||
|       required: false, | ||||
|       readOnly: false, | ||||
|       value: null, | ||||
|       placeholder: null, | ||||
|       description: | ||||
|         'If you want to use Realtime Database, please provide the domain of your Realtime Database (https://{{domain}}.firebaseio.com)', | ||||
|       clickToCopy: false, | ||||
|     }, | ||||
|   ], | ||||
|  | ||||
|   generateAuthUrl, | ||||
|   verifyCredentials, | ||||
|   isStillVerified, | ||||
|   refreshToken, | ||||
| }; | ||||
| @@ -1,8 +0,0 @@ | ||||
| import getCurrentUser from '../common/get-current-user.js'; | ||||
|  | ||||
| const isStillVerified = async ($) => { | ||||
|   const currentUser = await getCurrentUser($); | ||||
|   return !!currentUser.resourceName; | ||||
| }; | ||||
|  | ||||
| export default isStillVerified; | ||||
| @@ -1,31 +0,0 @@ | ||||
| import { URLSearchParams } from 'node:url'; | ||||
|  | ||||
| import authScope from '../common/auth-scope.js'; | ||||
|  | ||||
| const refreshToken = async ($) => { | ||||
|   const params = new URLSearchParams({ | ||||
|     client_id: $.auth.data.clientId, | ||||
|     client_secret: $.auth.data.clientSecret, | ||||
|     grant_type: 'refresh_token', | ||||
|     refresh_token: $.auth.data.refreshToken, | ||||
|   }); | ||||
|  | ||||
|   const { data } = await $.http.post( | ||||
|     'https://oauth2.googleapis.com/token', | ||||
|     params.toString(), | ||||
|     { | ||||
|       additionalProperties: { | ||||
|         skipAddingAuthHeader: true, | ||||
|       }, | ||||
|     } | ||||
|   ); | ||||
|  | ||||
|   await $.auth.set({ | ||||
|     accessToken: data.access_token, | ||||
|     expiresIn: data.expires_in, | ||||
|     scope: authScope.join(' '), | ||||
|     tokenType: data.token_type, | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export default refreshToken; | ||||
| @@ -1,50 +0,0 @@ | ||||
| import getCurrentUser from '../common/get-current-user.js'; | ||||
|  | ||||
| const verifyCredentials = async ($) => { | ||||
|   const oauthRedirectUrlField = $.app.auth.fields.find( | ||||
|     (field) => field.key == 'oAuthRedirectUrl' | ||||
|   ); | ||||
|   const redirectUri = oauthRedirectUrlField.value; | ||||
|   const { data } = await $.http.post( | ||||
|     `https://oauth2.googleapis.com/token`, | ||||
|     { | ||||
|       client_id: $.auth.data.clientId, | ||||
|       client_secret: $.auth.data.clientSecret, | ||||
|       code: $.auth.data.code, | ||||
|       grant_type: 'authorization_code', | ||||
|       redirect_uri: redirectUri, | ||||
|     }, | ||||
|     { | ||||
|       additionalProperties: { | ||||
|         skipAddingAuthHeader: true, | ||||
|       }, | ||||
|     } | ||||
|   ); | ||||
|  | ||||
|   await $.auth.set({ | ||||
|     accessToken: data.access_token, | ||||
|     tokenType: data.token_type, | ||||
|   }); | ||||
|  | ||||
|   const currentUser = await getCurrentUser($); | ||||
|  | ||||
|   const { displayName } = currentUser.names.find( | ||||
|     (name) => name.metadata.primary | ||||
|   ); | ||||
|   const { value: email } = currentUser.emailAddresses.find( | ||||
|     (emailAddress) => emailAddress.metadata.primary | ||||
|   ); | ||||
|  | ||||
|   await $.auth.set({ | ||||
|     clientId: $.auth.data.clientId, | ||||
|     clientSecret: $.auth.data.clientSecret, | ||||
|     scope: $.auth.data.scope, | ||||
|     idToken: data.id_token, | ||||
|     expiresIn: data.expires_in, | ||||
|     refreshToken: data.refresh_token, | ||||
|     resourceName: currentUser.resourceName, | ||||
|     screenName: `${displayName} - ${email}`, | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export default verifyCredentials; | ||||
| @@ -1,9 +0,0 @@ | ||||
| const addAuthHeader = ($, requestConfig) => { | ||||
|   if ($.auth.data?.accessToken) { | ||||
|     requestConfig.headers.Authorization = `${$.auth.data.tokenType} ${$.auth.data.accessToken}`; | ||||
|   } | ||||
|  | ||||
|   return requestConfig; | ||||
| }; | ||||
|  | ||||
| export default addAuthHeader; | ||||
| @@ -1,9 +0,0 @@ | ||||
| const authScope = [ | ||||
|   'https://www.googleapis.com/auth/datastore', | ||||
|   'https://www.googleapis.com/auth/firebase.database', | ||||
|   'https://www.googleapis.com/auth/datastore', | ||||
|   'https://www.googleapis.com/auth/userinfo.email', | ||||
|   'https://www.googleapis.com/auth/userinfo.profile', | ||||
| ]; | ||||
|  | ||||
| export default authScope; | ||||
| @@ -1,13 +0,0 @@ | ||||
| const getCurrentUser = async ($) => { | ||||
|   const { data: currentUser } = await $.http.get( | ||||
|     'https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses', | ||||
|     { | ||||
|       additionalProperties: { | ||||
|         skipAddingAuthHeader: true, | ||||
|       }, | ||||
|     } | ||||
|   ); | ||||
|   return currentUser; | ||||
| }; | ||||
|  | ||||
| export default getCurrentUser; | ||||
| @@ -1,16 +0,0 @@ | ||||
| const setBaseUrl = ($, requestConfig) => { | ||||
|   const realtimeDatabaseId = $.auth.data.realtimeDatabaseId; | ||||
|  | ||||
|   if (requestConfig.additionalProperties?.skipAddingAuthHeader) | ||||
|     return requestConfig; | ||||
|  | ||||
|   if (requestConfig.additionalProperties?.setFirestoreBaseUrl) { | ||||
|     requestConfig.baseURL = 'https://firestore.googleapis.com'; | ||||
|   } else { | ||||
|     requestConfig.baseURL = `https://${realtimeDatabaseId}.firebaseio.com`; | ||||
|   } | ||||
|  | ||||
|   return requestConfig; | ||||
| }; | ||||
|  | ||||
| export default setBaseUrl; | ||||
| @@ -1,3 +0,0 @@ | ||||
| import listFirestoreCollections from './list-firestore-collections/index.js'; | ||||
|  | ||||
| export default [listFirestoreCollections]; | ||||
| @@ -1,32 +0,0 @@ | ||||
| export default { | ||||
|   name: 'List firestore collections', | ||||
|   key: 'listFirestoreCollections', | ||||
|  | ||||
|   async run($) { | ||||
|     const firestoreCollections = { | ||||
|       data: [], | ||||
|     }; | ||||
|     const projectId = $.auth.data.projectId; | ||||
|  | ||||
|     const { data } = await $.http.post( | ||||
|       `/v1/projects/${projectId}/databases/(default)/documents:listCollectionIds`, | ||||
|       null, | ||||
|       { | ||||
|         additionalProperties: { | ||||
|           setFirestoreBaseUrl: true, | ||||
|         }, | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     if (data.collectionIds?.length) { | ||||
|       for (const collectionId of data.collectionIds) { | ||||
|         firestoreCollections.data.push({ | ||||
|           value: collectionId, | ||||
|           name: collectionId, | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return firestoreCollections; | ||||
|   }, | ||||
| }; | ||||
| @@ -1,23 +0,0 @@ | ||||
| import defineApp from '../../helpers/define-app.js'; | ||||
| import addAuthHeader from './common/add-auth-header.js'; | ||||
| import auth from './auth/index.js'; | ||||
| import setBaseUrl from './common/set-base-url.js'; | ||||
| import triggers from './triggers/index.js'; | ||||
| import dynamicData from './dynamic-data/index.js'; | ||||
| import actions from './actions/index.js'; | ||||
|  | ||||
| export default defineApp({ | ||||
|   name: 'Firebase', | ||||
|   key: 'firebase', | ||||
|   baseUrl: 'https://firebase.google.com', | ||||
|   apiBaseUrl: '', | ||||
|   iconUrl: '{BASE_URL}/apps/firebase/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/firebase/connection', | ||||
|   primaryColor: 'FFA000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [setBaseUrl, addAuthHeader], | ||||
|   auth, | ||||
|   triggers, | ||||
|   dynamicData, | ||||
|   actions, | ||||
| }); | ||||
| @@ -1,7 +0,0 @@ | ||||
| import newChildObjectInFirebaseRealtimeDatabase from './new-child-object-in-a-firebase-realtime-database/index.js'; | ||||
| import newDocumentsWithinFirestoreCollection from './new-documents-within-firestore-collection/index.js'; | ||||
|  | ||||
| export default [ | ||||
|   newChildObjectInFirebaseRealtimeDatabase, | ||||
|   newDocumentsWithinFirestoreCollection, | ||||
| ]; | ||||
| @@ -1,75 +0,0 @@ | ||||
| import Crypto from 'crypto'; | ||||
| import defineTrigger from '../../../../helpers/define-trigger.js'; | ||||
|  | ||||
| export default defineTrigger({ | ||||
|   name: 'New child object in a firebase realtime database', | ||||
|   key: 'newChildObjectInFirebaseRealtimeDatabase', | ||||
|   pollInterval: 15, | ||||
|   description: | ||||
|     'Triggers when a new child object is generated within a specific path.', | ||||
|   arguments: [ | ||||
|     { | ||||
|       label: 'Path', | ||||
|       key: 'path', | ||||
|       type: 'string', | ||||
|       required: true, | ||||
|       description: | ||||
|         "Indicate the path to the key of the object where the child objects to be queried are located, for example, 'foo/bar/here.json'.", | ||||
|       variables: true, | ||||
|     }, | ||||
|     { | ||||
|       label: 'Order', | ||||
|       key: 'order', | ||||
|       type: 'string', | ||||
|       required: false, | ||||
|       description: | ||||
|         'The key or path of the child that should be utilized for comparing objects/records. If unspecified, the order of $key is used.', | ||||
|       variables: true, | ||||
|     }, | ||||
|     { | ||||
|       label: 'Location of newest objects', | ||||
|       key: 'locationOfNewestObjects', | ||||
|       type: 'dropdown', | ||||
|       required: false, | ||||
|       description: | ||||
|         'Specifies whether the new 100 records are positioned at the "top" or the "bottom" of the ordering. If left unspecified, the assumption is that the bottom/last result represents the "newest objects" (limitToLast).', | ||||
|       variables: true, | ||||
|       options: [ | ||||
|         { label: 'Top of results', value: 'limitToFirst' }, | ||||
|         { label: 'Bottom of results', value: 'limitToLast' }, | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
|  | ||||
|   async run($) { | ||||
|     const { path, order, locationOfNewestObjects } = $.step.parameters; | ||||
|  | ||||
|     const params = {}; | ||||
|  | ||||
|     if (order) { | ||||
|       params.orderBy = `"${order}"`; | ||||
|     } | ||||
|  | ||||
|     if (locationOfNewestObjects) { | ||||
|       params[`${locationOfNewestObjects}`] = 100; | ||||
|     } | ||||
|  | ||||
|     const { data } = await $.http.get(path, { | ||||
|       params, | ||||
|       additionalProperties: { | ||||
|         setFirestoreBaseUrl: false, | ||||
|       }, | ||||
|     }); | ||||
|  | ||||
|     if (!data) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     $.pushTriggerItem({ | ||||
|       raw: data, | ||||
|       meta: { | ||||
|         internalId: Crypto.randomUUID(), | ||||
|       }, | ||||
|     }); | ||||
|   }, | ||||
| }); | ||||
| @@ -1,66 +0,0 @@ | ||||
| import defineTrigger from '../../../../helpers/define-trigger.js'; | ||||
|  | ||||
| export default defineTrigger({ | ||||
|   name: 'New documents within a firestore collection', | ||||
|   key: 'newDocumentsWithinFirestoreCollection', | ||||
|   pollInterval: 15, | ||||
|   description: | ||||
|     'Triggers when a new document is added within a Cloud Firestore collection.', | ||||
|   arguments: [ | ||||
|     { | ||||
|       label: 'Collection', | ||||
|       key: 'collectionId', | ||||
|       type: 'dropdown', | ||||
|       required: true, | ||||
|       description: '', | ||||
|       variables: true, | ||||
|       source: { | ||||
|         type: 'query', | ||||
|         name: 'getDynamicData', | ||||
|         arguments: [ | ||||
|           { | ||||
|             name: 'key', | ||||
|             value: 'listFirestoreCollections', | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
|   ], | ||||
|  | ||||
|   async run($) { | ||||
|     const projectId = $.auth.data.projectId; | ||||
|     const collectionId = $.step.parameters.collectionId; | ||||
|     const params = { | ||||
|       pageSize: 100, | ||||
|       pageToken: undefined, | ||||
|     }; | ||||
|  | ||||
|     do { | ||||
|       const { data } = await $.http.get( | ||||
|         `/v1/projects/${projectId}/databases/(default)/documents/${collectionId}`, | ||||
|         { | ||||
|           params, | ||||
|           additionalProperties: { | ||||
|             setFirestoreBaseUrl: true, | ||||
|           }, | ||||
|         } | ||||
|       ); | ||||
|       params.pageToken = data.nextPageToken; | ||||
|  | ||||
|       if (!data?.documents?.length) { | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       for (const document of data.documents) { | ||||
|         const nameParts = document.name.split('/'); | ||||
|         const id = nameParts[nameParts.length - 1]; | ||||
|         $.pushTriggerItem({ | ||||
|           raw: document, | ||||
|           meta: { | ||||
|             internalId: id, | ||||
|           }, | ||||
|         }); | ||||
|       } | ||||
|     } while (params.pageToken); | ||||
|   }, | ||||
| }); | ||||
| @@ -8,7 +8,7 @@ export default defineApp({ | ||||
|   name: 'Flickr', | ||||
|   key: 'flickr', | ||||
|   iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/flickr/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/flickr/connection', | ||||
|   docUrl: 'https://automatisch.io/docs/flickr', | ||||
|   primaryColor: '000000', | ||||
|   supportsConnections: true, | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Flowers Software', | ||||
|   key: 'flowers-software', | ||||
|   iconUrl: '{BASE_URL}/apps/flowers-software/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/flowers-software/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/flowers-software/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://flowers-software.com', | ||||
|   apiBaseUrl: 'https://webapp.flowers-software.com/api', | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import htmlToMarkdown from './transformers/html-to-markdown.js'; | ||||
| import lowercase from './transformers/lowercase.js'; | ||||
| import markdownToHtml from './transformers/markdown-to-html.js'; | ||||
| import pluralize from './transformers/pluralize.js'; | ||||
| import replaceWithRegEx from './transformers/replace-with-regex.js'; | ||||
| import replace from './transformers/replace.js'; | ||||
| import stringToBase64 from './transformers/string-to-base64.js'; | ||||
| import trimWhitespace from './transformers/trim-whitespace.js'; | ||||
| @@ -22,6 +23,7 @@ const transformers = { | ||||
|   lowercase, | ||||
|   markdownToHtml, | ||||
|   pluralize, | ||||
|   replaceWithRegEx, | ||||
|   replace, | ||||
|   stringToBase64, | ||||
|   trimWhitespace, | ||||
| @@ -49,6 +51,7 @@ export default defineAction({ | ||||
|         { label: 'Extract Number', value: 'extractNumber' }, | ||||
|         { label: 'Lowercase', value: 'lowercase' }, | ||||
|         { label: 'Pluralize', value: 'pluralize' }, | ||||
|         { label: 'Replace with RegEx', value: 'replaceWithRegEx' }, | ||||
|         { label: 'Replace', value: 'replace' }, | ||||
|         { label: 'String to Base64', value: 'stringToBase64' }, | ||||
|         { label: 'Trim Whitespace', value: 'trimWhitespace' }, | ||||
|   | ||||
| @@ -0,0 +1,10 @@ | ||||
| const replaceWithRegEx = ($) => { | ||||
|   const input = $.step.parameters.input; | ||||
|  | ||||
|   const find = new RegExp($.step.parameters.find); | ||||
|   const replace = $.step.parameters.replace; | ||||
|  | ||||
|   return input.replace(find, replace); | ||||
| }; | ||||
|  | ||||
| export default replaceWithRegEx; | ||||
| @@ -6,6 +6,7 @@ import htmlToMarkdown from './text/html-to-markdown.js'; | ||||
| import lowercase from './text/lowercase.js'; | ||||
| import markdownToHtml from './text/markdown-to-html.js'; | ||||
| import pluralize from './text/pluralize.js'; | ||||
| import replaceWithRegEx from './text/replace-with-regex.js'; | ||||
| import replace from './text/replace.js'; | ||||
| import stringToBase64 from './text/string-to-base64.js'; | ||||
| import trimWhitespace from './text/trim-whitespace.js'; | ||||
| @@ -25,6 +26,7 @@ const options = { | ||||
|   lowercase, | ||||
|   markdownToHtml, | ||||
|   pluralize, | ||||
|   replaceWithRegEx, | ||||
|   replace, | ||||
|   stringToBase64, | ||||
|   trimWhitespace, | ||||
|   | ||||
| @@ -0,0 +1,29 @@ | ||||
| const replaceWithRegEx = [ | ||||
|   { | ||||
|     label: 'Input', | ||||
|     key: 'input', | ||||
|     type: 'string', | ||||
|     required: true, | ||||
|     description: | ||||
|       'Text that you want to search for and replace values with regex.', | ||||
|     variables: true, | ||||
|   }, | ||||
|   { | ||||
|     label: 'Find', | ||||
|     key: 'find', | ||||
|     type: 'string', | ||||
|     required: true, | ||||
|     description: 'RegEx that will be searched for.', | ||||
|     variables: true, | ||||
|   }, | ||||
|   { | ||||
|     label: 'Replace', | ||||
|     key: 'replace', | ||||
|     type: 'string', | ||||
|     required: false, | ||||
|     description: 'Text that will replace the found regex.', | ||||
|     variables: true, | ||||
|   }, | ||||
| ]; | ||||
|  | ||||
| export default replaceWithRegEx; | ||||
| @@ -6,7 +6,7 @@ export default defineApp({ | ||||
|   name: 'Formatter', | ||||
|   key: 'formatter', | ||||
|   iconUrl: '{BASE_URL}/apps/formatter/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/formatter/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/formatter/connection', | ||||
|   supportsConnections: false, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://ghost.org', | ||||
|   apiBaseUrl: '', | ||||
|   iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/ghost/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/ghost/connection', | ||||
|   primaryColor: '15171A', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [setBaseUrl, addAuthHeader], | ||||
|   | ||||
| @@ -11,7 +11,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://github.com', | ||||
|   apiBaseUrl: 'https://api.github.com', | ||||
|   iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/github/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/github/connection', | ||||
|   primaryColor: '000000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -11,7 +11,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://gitlab.com', | ||||
|   apiBaseUrl: 'https://gitlab.com', | ||||
|   iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/gitlab/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/gitlab/connection', | ||||
|   primaryColor: 'FC6D26', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [setBaseUrl, addAuthHeader], | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://calendar.google.com', | ||||
|   apiBaseUrl: 'https://www.googleapis.com/calendar', | ||||
|   iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/google-calendar/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/google-calendar/connection', | ||||
|   primaryColor: '448AFF', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://drive.google.com', | ||||
|   apiBaseUrl: 'https://www.googleapis.com/drive', | ||||
|   iconUrl: '{BASE_URL}/apps/google-drive/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/google-drive/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/google-drive/connection', | ||||
|   primaryColor: '1FA463', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://docs.google.com/forms', | ||||
|   apiBaseUrl: 'https://forms.googleapis.com', | ||||
|   iconUrl: '{BASE_URL}/apps/google-forms/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/google-forms/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/google-forms/connection', | ||||
|   primaryColor: '673AB7', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -12,7 +12,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://docs.google.com/spreadsheets', | ||||
|   apiBaseUrl: 'https://sheets.googleapis.com', | ||||
|   iconUrl: '{BASE_URL}/apps/google-sheets/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/google-sheets/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/google-sheets/connection', | ||||
|   primaryColor: '0F9D58', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://tryhelix.ai', | ||||
|   apiBaseUrl: 'https://app.tryhelix.ai', | ||||
|   iconUrl: '{BASE_URL}/apps/helix/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/helix/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/helix/connection', | ||||
|   primaryColor: '000000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [setBaseUrl, addAuthHeader], | ||||
|   | ||||
| @@ -5,7 +5,7 @@ export default defineApp({ | ||||
|   name: 'HTTP Request', | ||||
|   key: 'http-request', | ||||
|   iconUrl: '{BASE_URL}/apps/http-request/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/http-request/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/http-request/connection', | ||||
|   supportsConnections: false, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'HubSpot', | ||||
|   key: 'hubspot', | ||||
|   iconUrl: '{BASE_URL}/apps/hubspot/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/hubspot/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/hubspot/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://www.hubspot.com', | ||||
|   apiBaseUrl: 'https://api.hubapi.com', | ||||
|   | ||||
| @@ -12,7 +12,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://invoiceninja.com', | ||||
|   apiBaseUrl: 'https://invoicing.co/api', | ||||
|   iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/invoice-ninja/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/invoice-ninja/connection', | ||||
|   primaryColor: '000000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [setBaseUrl, addAuthHeader], | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   name: 'Mattermost', | ||||
|   key: 'mattermost', | ||||
|   iconUrl: '{BASE_URL}/apps/mattermost/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/mattermost/connection', | ||||
|   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', | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://miro.com', | ||||
|   apiBaseUrl: 'https://api.miro.com', | ||||
|   iconUrl: '{BASE_URL}/apps/miro/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/miro/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/miro/connection', | ||||
|   primaryColor: 'F2CA02', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -12,7 +12,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://notion.com', | ||||
|   apiBaseUrl: 'https://api.notion.com', | ||||
|   iconUrl: '{BASE_URL}/apps/notion/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/notion/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/notion/connection', | ||||
|   primaryColor: '000000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader, addNotionVersionHeader], | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Ntfy', | ||||
|   key: 'ntfy', | ||||
|   iconUrl: '{BASE_URL}/apps/ntfy/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/ntfy/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/ntfy/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://ntfy.sh', | ||||
|   apiBaseUrl: 'https://ntfy.sh', | ||||
|   | ||||
| @@ -6,7 +6,7 @@ export default defineApp({ | ||||
|   name: 'Odoo', | ||||
|   key: 'odoo', | ||||
|   iconUrl: '{BASE_URL}/apps/odoo/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/odoo/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/odoo/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://odoo.com', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://openai.com', | ||||
|   apiBaseUrl: 'https://api.openai.com', | ||||
|   iconUrl: '{BASE_URL}/apps/openai/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/openai/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/openai/connection', | ||||
|   primaryColor: '000000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -12,7 +12,7 @@ export default defineApp({ | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   iconUrl: '{BASE_URL}/apps/pipedrive/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/pipedrive/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/pipedrive/connection', | ||||
|   primaryColor: 'FFFFFF', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [setBaseUrl, addAuthHeader], | ||||
|   | ||||
| @@ -8,7 +8,7 @@ export default defineApp({ | ||||
|   name: 'Placetel', | ||||
|   key: 'placetel', | ||||
|   iconUrl: '{BASE_URL}/apps/placetel/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/placetel/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/placetel/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://placetel.de', | ||||
|   apiBaseUrl: 'https://api.placetel.de', | ||||
|   | ||||
| @@ -6,7 +6,7 @@ export default defineApp({ | ||||
|   name: 'PostgreSQL', | ||||
|   key: 'postgresql', | ||||
|   iconUrl: '{BASE_URL}/apps/postgresql/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/postgresql/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/postgresql/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://pushover.net', | ||||
|   apiBaseUrl: 'https://api.pushover.net', | ||||
|   iconUrl: '{BASE_URL}/apps/pushover/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/pushover/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/pushover/connection', | ||||
|   primaryColor: '249DF1', | ||||
|   supportsConnections: true, | ||||
|   auth, | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://www.reddit.com', | ||||
|   apiBaseUrl: 'https://oauth.reddit.com', | ||||
|   iconUrl: '{BASE_URL}/apps/reddit/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/reddit/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/reddit/connection', | ||||
|   primaryColor: 'FF4500', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Remove.bg', | ||||
|   key: 'removebg', | ||||
|   iconUrl: '{BASE_URL}/apps/removebg/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/removebg/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/removebg/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://www.remove.bg', | ||||
|   apiBaseUrl: 'https://api.remove.bg/v1.0', | ||||
|   | ||||
| @@ -5,7 +5,7 @@ export default defineApp({ | ||||
|   name: 'RSS', | ||||
|   key: 'rss', | ||||
|   iconUrl: '{BASE_URL}/apps/rss/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/rss/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/rss/connection', | ||||
|   supportsConnections: false, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export default defineApp({ | ||||
|   name: 'Salesforce', | ||||
|   key: 'salesforce', | ||||
|   iconUrl: '{BASE_URL}/apps/salesforce/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/connections/salesforce', | ||||
|   authDocUrl: '{DOCS_URL}/connections/salesforce', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://salesforce.com', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -6,7 +6,7 @@ export default defineApp({ | ||||
|   key: 'scheduler', | ||||
|   iconUrl: '{BASE_URL}/apps/scheduler/assets/favicon.svg', | ||||
|   docUrl: 'https://automatisch.io/docs/scheduler', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/scheduler/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/scheduler/connection', | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   primaryColor: '0059F7', | ||||
|   | ||||
| @@ -11,7 +11,7 @@ export default defineApp({ | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   iconUrl: '{BASE_URL}/apps/self-hosted-llm/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/self-hosted-llm/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/self-hosted-llm/connection', | ||||
|   primaryColor: '000000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [setBaseUrl, addAuthHeader], | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export default defineApp({ | ||||
|   name: 'SignalWire', | ||||
|   key: 'signalwire', | ||||
|   iconUrl: '{BASE_URL}/apps/signalwire/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/signalwire/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/signalwire/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://signalwire.com', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export default defineApp({ | ||||
|   name: 'Slack', | ||||
|   key: 'slack', | ||||
|   iconUrl: '{BASE_URL}/apps/slack/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/slack/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/slack/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://slack.com', | ||||
|   apiBaseUrl: 'https://slack.com/api', | ||||
|   | ||||
| @@ -6,7 +6,7 @@ export default defineApp({ | ||||
|   name: 'SMTP', | ||||
|   key: 'smtp', | ||||
|   iconUrl: '{BASE_URL}/apps/smtp/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/smtp/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/smtp/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Spotify', | ||||
|   key: 'spotify', | ||||
|   iconUrl: '{BASE_URL}/apps/spotify/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/spotify/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/spotify/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://spotify.com', | ||||
|   apiBaseUrl: 'https://api.spotify.com', | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Strava', | ||||
|   key: 'strava', | ||||
|   iconUrl: '{BASE_URL}/apps/strava/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/connections/strava', | ||||
|   authDocUrl: '{DOCS_URL}/connections/strava', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://www.strava.com', | ||||
|   apiBaseUrl: 'https://www.strava.com/api', | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Stripe', | ||||
|   key: 'stripe', | ||||
|   iconUrl: '{BASE_URL}/apps/stripe/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/stripe/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/stripe/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://stripe.com', | ||||
|   apiBaseUrl: 'https://api.stripe.com', | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export default defineApp({ | ||||
|   name: 'Telegram', | ||||
|   key: 'telegram-bot', | ||||
|   iconUrl: '{BASE_URL}/apps/telegram-bot/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/telegram-bot/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/telegram-bot/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://telegram.org', | ||||
|   apiBaseUrl: 'https://api.telegram.org', | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export default defineApp({ | ||||
|   name: 'Todoist', | ||||
|   key: 'todoist', | ||||
|   iconUrl: '{BASE_URL}/apps/todoist/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/todoist/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/todoist/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://todoist.com', | ||||
|   apiBaseUrl: 'https://api.todoist.com/rest/v2', | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://trello.com/', | ||||
|   apiBaseUrl: 'https://api.trello.com', | ||||
|   iconUrl: '{BASE_URL}/apps/trello/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/trello/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/trello/connection', | ||||
|   supportsConnections: true, | ||||
|   primaryColor: '0079bf', | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export default defineApp({ | ||||
|   name: 'Twilio', | ||||
|   key: 'twilio', | ||||
|   iconUrl: '{BASE_URL}/apps/twilio/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/twilio/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/twilio/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://twilio.com', | ||||
|   apiBaseUrl: 'https://api.twilio.com', | ||||
|   | ||||
| @@ -8,7 +8,7 @@ export default defineApp({ | ||||
|   name: 'Twitter', | ||||
|   key: 'twitter', | ||||
|   iconUrl: '{BASE_URL}/apps/twitter/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/twitter/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/twitter/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://twitter.com', | ||||
|   apiBaseUrl: 'https://api.twitter.com', | ||||
|   | ||||
| @@ -8,7 +8,7 @@ export default defineApp({ | ||||
|   name: 'Typeform', | ||||
|   key: 'typeform', | ||||
|   iconUrl: '{BASE_URL}/apps/typeform/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/typeform/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/typeform/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://typeform.com', | ||||
|   apiBaseUrl: 'https://api.typeform.com', | ||||
|   | ||||
| @@ -6,7 +6,7 @@ export default defineApp({ | ||||
|   name: 'Webhook', | ||||
|   key: 'webhook', | ||||
|   iconUrl: '{BASE_URL}/apps/webhook/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/webhook/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/webhook/connection', | ||||
|   supportsConnections: false, | ||||
|   baseUrl: '', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export default defineApp({ | ||||
|   name: 'WordPress', | ||||
|   key: 'wordpress', | ||||
|   iconUrl: '{BASE_URL}/apps/wordpress/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/wordpress/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/wordpress/connection', | ||||
|   supportsConnections: true, | ||||
|   baseUrl: 'https://wordpress.com', | ||||
|   apiBaseUrl: '', | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://go.xero.com', | ||||
|   apiBaseUrl: 'https://api.xero.com', | ||||
|   iconUrl: '{BASE_URL}/apps/xero/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/xero/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/xero/connection', | ||||
|   primaryColor: '13B5EA', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://www.youtube.com/', | ||||
|   apiBaseUrl: 'https://www.googleapis.com/youtube', | ||||
|   iconUrl: '{BASE_URL}/apps/youtube/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/youtube/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/youtube/connection', | ||||
|   primaryColor: 'FF0000', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -11,7 +11,7 @@ export default defineApp({ | ||||
|   baseUrl: 'https://zendesk.com/', | ||||
|   apiBaseUrl: '', | ||||
|   iconUrl: '{BASE_URL}/apps/zendesk/assets/favicon.svg', | ||||
|   authDocUrl: 'https://automatisch.io/docs/apps/zendesk/connection', | ||||
|   authDocUrl: '{DOCS_URL}/apps/zendesk/connection', | ||||
|   primaryColor: '17494d', | ||||
|   supportsConnections: true, | ||||
|   beforeRequest: [addAuthHeader], | ||||
|   | ||||
| @@ -38,6 +38,9 @@ if (process.env.WEB_APP_URL) { | ||||
| let webhookUrl = new URL(process.env.WEBHOOK_URL || apiUrl).toString(); | ||||
| webhookUrl = webhookUrl.substring(0, webhookUrl.length - 1); | ||||
|  | ||||
| const publicDocsUrl = 'https://automatisch.io/docs'; | ||||
| const docsUrl = process.env.DOCS_URL || publicDocsUrl; | ||||
|  | ||||
| const appEnv = process.env.APP_ENV || 'development'; | ||||
|  | ||||
| const appConfig = { | ||||
| @@ -73,6 +76,7 @@ const appConfig = { | ||||
|   baseUrl: apiUrl, | ||||
|   webAppUrl, | ||||
|   webhookUrl, | ||||
|   docsUrl, | ||||
|   telemetryEnabled: process.env.TELEMETRY_ENABLED === 'false' ? false : true, | ||||
|   requestBodySizeLimit: '1mb', | ||||
|   smtpHost: process.env.SMTP_HOST, | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import appConfig from './app.js'; | ||||
|  | ||||
| const corsOptions = { | ||||
|   origin: appConfig.webAppUrl, | ||||
|   methods: 'POST', | ||||
|   methods: 'GET,HEAD,POST,DELETE', | ||||
|   credentials: true, | ||||
|   optionsSuccessStatus: 200, | ||||
| }; | ||||
|   | ||||
| @@ -0,0 +1,15 @@ | ||||
| export default async (request, response) => { | ||||
|   const token = request.params.token; | ||||
|  | ||||
|   const accessToken = await request.currentUser | ||||
|     .$relatedQuery('accessTokens') | ||||
|     .findOne({ | ||||
|       token, | ||||
|       revoked_at: null, | ||||
|     }) | ||||
|     .throwIfNotFound(); | ||||
|  | ||||
|   await accessToken.revoke(); | ||||
|  | ||||
|   response.status(204).send(); | ||||
| }; | ||||
| @@ -0,0 +1,54 @@ | ||||
| import { expect, describe, it, beforeEach } from 'vitest'; | ||||
| import request from 'supertest'; | ||||
| import app from '../../../../app.js'; | ||||
| import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id'; | ||||
| import { createUser } from '../../../../../test/factories/user.js'; | ||||
| import AccessToken from '../../../../models/access-token.js'; | ||||
|  | ||||
| describe('DELETE /api/v1/access-tokens/:token', () => { | ||||
|   let token; | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     const currentUser = await createUser({ | ||||
|       email: 'user@automatisch.io', | ||||
|       password: 'password', | ||||
|     }); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should respond with HTTP 204 with correct token', async () => { | ||||
|     await request(app) | ||||
|       .delete(`/api/v1/access-tokens/${token}`) | ||||
|       .set('Authorization', token) | ||||
|       .expect(204); | ||||
|  | ||||
|     const revokedToken = await AccessToken.query().findOne({ token }); | ||||
|  | ||||
|     expect(revokedToken).toBeDefined(); | ||||
|     expect(revokedToken.revokedAt).not.toBeNull(); | ||||
|   }); | ||||
|  | ||||
|   it('should respond with HTTP 401 with incorrect credentials', async () => { | ||||
|     await request(app) | ||||
|       .delete(`/api/v1/access-tokens/${token}`) | ||||
|       .set('Authorization', 'wrong-token') | ||||
|       .expect(401); | ||||
|  | ||||
|     const unrevokedToken = await AccessToken.query().findOne({ token }); | ||||
|  | ||||
|     expect(unrevokedToken).toBeDefined(); | ||||
|     expect(unrevokedToken.revokedAt).toBeNull(); | ||||
|   }); | ||||
|  | ||||
|   it('should respond with HTTP 404 with correct credentials, but non-valid token', async () => { | ||||
|     await request(app) | ||||
|       .delete('/api/v1/access-tokens/wrong-token') | ||||
|       .set('Authorization', token) | ||||
|       .expect(404); | ||||
|  | ||||
|     const unrevokedToken = await AccessToken.query().findOne({ token }); | ||||
|  | ||||
|     expect(unrevokedToken).toBeDefined(); | ||||
|     expect(unrevokedToken.revokedAt).toBeNull(); | ||||
|   }); | ||||
| }); | ||||
| @@ -22,7 +22,7 @@ describe('GET /api/v1/admin/apps/:appKey/auth-clients/:appAuthClientId', () => { | ||||
|       appKey: 'deepl', | ||||
|     }); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return specified app auth client', async () => { | ||||
|   | ||||
| @@ -17,7 +17,7 @@ describe('GET /api/v1/admin/apps/:appKey/auth-clients', () => { | ||||
|     adminRole = await createRole({ key: 'admin' }); | ||||
|     currentUser = await createUser({ roleId: adminRole.id }); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return specified app auth client info', async () => { | ||||
|   | ||||
| @@ -14,7 +14,7 @@ describe('GET /api/v1/admin/permissions/catalog', () => { | ||||
|     role = await createRole({ key: 'admin' }); | ||||
|     currentUser = await createUser({ roleId: role.id }); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return roles', async () => { | ||||
|   | ||||
| @@ -18,7 +18,7 @@ describe('GET /api/v1/admin/roles/:roleId', () => { | ||||
|     permissionTwo = await createPermission({ roleId: role.id }); | ||||
|     currentUser = await createUser({ roleId: role.id }); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return role', async () => { | ||||
|   | ||||
| @@ -15,7 +15,7 @@ describe('GET /api/v1/admin/roles', () => { | ||||
|     roleTwo = await createRole({ key: 'user' }); | ||||
|     currentUser = await createUser({ roleId: roleOne.id }); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return roles', async () => { | ||||
|   | ||||
| @@ -28,7 +28,7 @@ describe('GET /api/v1/admin/saml-auth-providers/:samlAuthProviderId/role-mapping | ||||
|       remoteRoleName: 'User', | ||||
|     }); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return role mappings', async () => { | ||||
|   | ||||
| @@ -17,7 +17,7 @@ describe('GET /api/v1/admin/saml-auth-provider/:samlAuthProviderId', () => { | ||||
|     currentUser = await createUser({ roleId: role.id }); | ||||
|     samlAuthProvider = await createSamlAuthProvider(); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return saml auth provider with specified id', async () => { | ||||
|   | ||||
| @@ -18,7 +18,7 @@ describe('GET /api/v1/admin/saml-auth-providers', () => { | ||||
|     samlAuthProviderOne = await createSamlAuthProvider(); | ||||
|     samlAuthProviderTwo = await createSamlAuthProvider(); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return saml auth providers', async () => { | ||||
|   | ||||
| @@ -18,7 +18,7 @@ describe('GET /api/v1/admin/users/:userId', () => { | ||||
|     anotherUser = await createUser(); | ||||
|     anotherUserRole = await anotherUser.$relatedQuery('role'); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return specified user info', async () => { | ||||
|   | ||||
| @@ -28,7 +28,7 @@ describe('GET /api/v1/admin/users', () => { | ||||
|       fullName: 'Another User', | ||||
|     }); | ||||
|  | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return users data', async () => { | ||||
|   | ||||
| @@ -11,7 +11,7 @@ describe('GET /api/v1/apps/:appKey/actions/:actionKey/substeps', () => { | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     currentUser = await createUser(); | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|     exampleApp = await App.findOneByKey('github'); | ||||
|   }); | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,7 @@ describe('GET /api/v1/apps/:appKey/actions', () => { | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     currentUser = await createUser(); | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return the app actions', async () => { | ||||
|   | ||||
| @@ -11,7 +11,7 @@ describe('GET /api/v1/apps/:appKey', () => { | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     currentUser = await createUser(); | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|   }); | ||||
|  | ||||
|   it('should return the app info', async () => { | ||||
|   | ||||
| @@ -11,7 +11,7 @@ describe('GET /api/v1/apps', () => { | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     currentUser = await createUser(); | ||||
|     token = createAuthTokenByUserId(currentUser.id); | ||||
|     token = await createAuthTokenByUserId(currentUser.id); | ||||
|     apps = await App.findAll(); | ||||
|   }); | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user