@budibase/server 2.7.20-alpha.0 → 2.7.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builder/assets/{index.6b48215f.js → index.1066b334.js} +371 -371
- package/builder/assets/{index.2e9069f3.css → index.d9b46807.css} +1 -1
- package/builder/index.html +2 -2
- package/dist/automation.js +179 -405
- package/dist/automation.js.map +3 -3
- package/dist/index.js +284 -517
- package/dist/index.js.map +3 -3
- package/dist/query.js +141 -301
- package/dist/query.js.map +3 -3
- package/package.json +11 -11
- package/src/api/controllers/application.ts +24 -21
- package/src/api/controllers/backup.ts +8 -22
- package/src/api/controllers/datasource.ts +24 -41
- package/src/api/controllers/role.ts +5 -5
- package/src/api/controllers/routing.ts +3 -3
- package/src/api/routes/backup.ts +1 -1
- package/src/api/routes/tests/backup.spec.ts +2 -18
- package/src/automations/steps/sendSmtpEmail.ts +4 -55
- package/src/automations/tests/sendSmtpEmail.spec.js +71 -0
- package/src/events/docUpdates/syncUsers.ts +0 -4
- package/src/integrations/googlesheets.ts +18 -35
- package/src/integrations/mongodb.ts +2 -4
- package/src/integrations/postgres.ts +1 -2
- package/src/middleware/currentapp.ts +1 -1
- package/src/sdk/app/backups/exports.ts +5 -33
- package/src/sdk/app/backups/imports.ts +1 -21
- package/src/sdk/app/datasources/datasources.ts +0 -1
- package/src/utilities/workerRequests.ts +9 -20
- package/src/automations/tests/sendSmtpEmail.spec.ts +0 -74
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "2.7.20
|
|
4
|
+
"version": "2.7.20",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"license": "GPL-3.0",
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@apidevtools/swagger-parser": "10.0.3",
|
|
49
|
-
"@budibase/backend-core": "2.7.20
|
|
50
|
-
"@budibase/client": "2.7.20
|
|
51
|
-
"@budibase/pro": "2.7.20
|
|
52
|
-
"@budibase/shared-core": "2.7.20
|
|
53
|
-
"@budibase/string-templates": "2.7.20
|
|
54
|
-
"@budibase/types": "2.7.20
|
|
49
|
+
"@budibase/backend-core": "2.7.20",
|
|
50
|
+
"@budibase/client": "2.7.20",
|
|
51
|
+
"@budibase/pro": "2.7.20",
|
|
52
|
+
"@budibase/shared-core": "2.7.20",
|
|
53
|
+
"@budibase/string-templates": "2.7.20",
|
|
54
|
+
"@budibase/types": "2.7.20",
|
|
55
55
|
"@bull-board/api": "3.7.0",
|
|
56
56
|
"@bull-board/koa": "3.9.4",
|
|
57
57
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"koa2-ratelimit": "1.1.1",
|
|
98
98
|
"lodash": "4.17.21",
|
|
99
99
|
"memorystream": "0.3.1",
|
|
100
|
-
"mongodb": "
|
|
100
|
+
"mongodb": "4.9",
|
|
101
101
|
"mssql": "6.2.3",
|
|
102
102
|
"mysql2": "2.3.3",
|
|
103
103
|
"node-fetch": "2.6.7",
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"socket.io": "4.6.1",
|
|
118
118
|
"svelte": "3.49.0",
|
|
119
119
|
"swagger-parser": "10.0.3",
|
|
120
|
-
"tar": "6.1.
|
|
120
|
+
"tar": "6.1.11",
|
|
121
121
|
"to-json-schema": "0.2.5",
|
|
122
122
|
"uuid": "3.3.2",
|
|
123
123
|
"validate.js": "0.13.1",
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
"@types/redis": "4.0.11",
|
|
151
151
|
"@types/server-destroy": "1.0.1",
|
|
152
152
|
"@types/supertest": "2.0.12",
|
|
153
|
-
"@types/tar": "6.1.
|
|
153
|
+
"@types/tar": "6.1.3",
|
|
154
154
|
"@typescript-eslint/parser": "5.45.0",
|
|
155
155
|
"apidoc": "0.50.4",
|
|
156
156
|
"babel-jest": "29.5.0",
|
|
@@ -195,5 +195,5 @@
|
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
},
|
|
198
|
-
"gitHead": "
|
|
198
|
+
"gitHead": "d8b642d24f562d384c2fc760afda97d20b3478ff"
|
|
199
199
|
}
|
|
@@ -1,53 +1,54 @@
|
|
|
1
1
|
import env from "../../environment"
|
|
2
2
|
import {
|
|
3
|
+
createAllSearchIndex,
|
|
3
4
|
createLinkView,
|
|
4
5
|
createRoutingView,
|
|
5
|
-
createAllSearchIndex,
|
|
6
6
|
} from "../../db/views/staticViews"
|
|
7
|
-
import { createApp, deleteApp } from "../../utilities/fileSystem"
|
|
8
7
|
import {
|
|
8
|
+
backupClientLibrary,
|
|
9
|
+
createApp,
|
|
10
|
+
deleteApp,
|
|
11
|
+
revertClientLibrary,
|
|
12
|
+
updateClientLibrary,
|
|
13
|
+
} from "../../utilities/fileSystem"
|
|
14
|
+
import {
|
|
15
|
+
AppStatus,
|
|
16
|
+
DocumentType,
|
|
9
17
|
generateAppID,
|
|
18
|
+
generateDevAppID,
|
|
10
19
|
getLayoutParams,
|
|
11
20
|
getScreenParams,
|
|
12
|
-
generateDevAppID,
|
|
13
|
-
DocumentType,
|
|
14
|
-
AppStatus,
|
|
15
21
|
} from "../../db/utils"
|
|
16
22
|
import {
|
|
17
|
-
db as dbCore,
|
|
18
|
-
roles,
|
|
19
23
|
cache,
|
|
20
|
-
tenancy,
|
|
21
24
|
context,
|
|
25
|
+
db as dbCore,
|
|
26
|
+
env as envCore,
|
|
27
|
+
ErrorCode,
|
|
22
28
|
events,
|
|
23
29
|
migrations,
|
|
24
30
|
objectStore,
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
roles,
|
|
32
|
+
tenancy,
|
|
27
33
|
} from "@budibase/backend-core"
|
|
28
34
|
import { USERS_TABLE_SCHEMA } from "../../constants"
|
|
29
35
|
import {
|
|
30
|
-
DEFAULT_BB_DATASOURCE_ID,
|
|
31
36
|
buildDefaultDocs,
|
|
37
|
+
DEFAULT_BB_DATASOURCE_ID,
|
|
32
38
|
} from "../../db/defaultData/datasource_bb_default"
|
|
33
39
|
import { removeAppFromUserRoles } from "../../utilities/workerRequests"
|
|
34
|
-
import { stringToReadStream
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
updateClientLibrary,
|
|
38
|
-
backupClientLibrary,
|
|
39
|
-
revertClientLibrary,
|
|
40
|
-
} from "../../utilities/fileSystem"
|
|
40
|
+
import { stringToReadStream } from "../../utilities"
|
|
41
|
+
import { doesUserHaveLock, getLocksById } from "../../utilities/redis"
|
|
41
42
|
import { cleanupAutomations } from "../../automations/utils"
|
|
42
43
|
import { checkAppMetadata } from "../../automations/logging"
|
|
43
44
|
import { getUniqueRows } from "../../utilities/usageQuota/rows"
|
|
44
|
-
import {
|
|
45
|
+
import { groups, licensing, quotas } from "@budibase/pro"
|
|
45
46
|
import {
|
|
46
47
|
App,
|
|
47
48
|
Layout,
|
|
48
|
-
Screen,
|
|
49
49
|
MigrationType,
|
|
50
|
-
|
|
50
|
+
PlanType,
|
|
51
|
+
Screen,
|
|
51
52
|
UserCtx,
|
|
52
53
|
} from "@budibase/types"
|
|
53
54
|
import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts"
|
|
@@ -207,6 +208,7 @@ export async function fetchAppPackage(ctx: UserCtx) {
|
|
|
207
208
|
let application = await db.get(DocumentType.APP_METADATA)
|
|
208
209
|
const layouts = await getLayouts()
|
|
209
210
|
let screens = await getScreens()
|
|
211
|
+
const license = await licensing.getLicense()
|
|
210
212
|
|
|
211
213
|
// Enrich plugin URLs
|
|
212
214
|
application.usedPlugins = objectStore.enrichPluginURLs(
|
|
@@ -227,6 +229,7 @@ export async function fetchAppPackage(ctx: UserCtx) {
|
|
|
227
229
|
|
|
228
230
|
ctx.body = {
|
|
229
231
|
application: { ...application, upgradableVersion: envCore.VERSION },
|
|
232
|
+
licenseType: license?.plan.type || PlanType.FREE,
|
|
230
233
|
screens,
|
|
231
234
|
layouts,
|
|
232
235
|
clientLibPath,
|
|
@@ -1,31 +1,17 @@
|
|
|
1
1
|
import sdk from "../../sdk"
|
|
2
|
-
import { events, context
|
|
2
|
+
import { events, context } from "@budibase/backend-core"
|
|
3
3
|
import { DocumentType } from "../../db/utils"
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
interface ExportAppDumpRequest {
|
|
7
|
-
excludeRows: boolean
|
|
8
|
-
encryptPassword?: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function exportAppDump(ctx: Ctx<ExportAppDumpRequest>) {
|
|
12
|
-
const { appId } = ctx.query as any
|
|
13
|
-
const { excludeRows, encryptPassword } = ctx.request.body
|
|
14
|
-
|
|
15
|
-
const [app] = await db.getAppsByIDs([appId])
|
|
16
|
-
const appName = app.name
|
|
4
|
+
import { isQsTrue } from "../../utilities"
|
|
17
5
|
|
|
6
|
+
export async function exportAppDump(ctx: any) {
|
|
7
|
+
let { appId, excludeRows } = ctx.query
|
|
18
8
|
// remove the 120 second limit for the request
|
|
19
9
|
ctx.req.setTimeout(0)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const backupIdentifier = `${appName}-export-${new Date().getTime()}
|
|
10
|
+
const appName = decodeURI(ctx.query.appname)
|
|
11
|
+
excludeRows = isQsTrue(excludeRows)
|
|
12
|
+
const backupIdentifier = `${appName}-export-${new Date().getTime()}.tar.gz`
|
|
23
13
|
ctx.attachment(backupIdentifier)
|
|
24
|
-
ctx.body = await sdk.backups.streamExportApp(
|
|
25
|
-
appId,
|
|
26
|
-
excludeRows,
|
|
27
|
-
encryptPassword,
|
|
28
|
-
})
|
|
14
|
+
ctx.body = await sdk.backups.streamExportApp(appId, excludeRows)
|
|
29
15
|
|
|
30
16
|
await context.doInAppContext(appId, async () => {
|
|
31
17
|
const appDb = context.getAppDB()
|
|
@@ -11,7 +11,7 @@ import { BuildSchemaErrors, InvalidColumns } from "../../constants"
|
|
|
11
11
|
import { getIntegration } from "../../integrations"
|
|
12
12
|
import { getDatasourceAndQuery } from "./row/utils"
|
|
13
13
|
import { invalidateDynamicVariables } from "../../threads/utils"
|
|
14
|
-
import { db as dbCore, context, events
|
|
14
|
+
import { db as dbCore, context, events } from "@budibase/backend-core"
|
|
15
15
|
import {
|
|
16
16
|
UserCtx,
|
|
17
17
|
Datasource,
|
|
@@ -25,11 +25,9 @@ import {
|
|
|
25
25
|
FetchDatasourceInfoResponse,
|
|
26
26
|
IntegrationBase,
|
|
27
27
|
DatasourcePlus,
|
|
28
|
-
SourceName,
|
|
29
28
|
} from "@budibase/types"
|
|
30
29
|
import sdk from "../../sdk"
|
|
31
30
|
import { builderSocket } from "../../websockets"
|
|
32
|
-
import { setupCreationAuth as googleSetupCreationAuth } from "../../integrations/googlesheets"
|
|
33
31
|
|
|
34
32
|
function getErrorTables(errors: any, errorType: string) {
|
|
35
33
|
return Object.entries(errors)
|
|
@@ -103,22 +101,6 @@ async function buildSchemaHelper(datasource: Datasource) {
|
|
|
103
101
|
return { tables: connector.tables, error }
|
|
104
102
|
}
|
|
105
103
|
|
|
106
|
-
async function buildFilteredSchema(datasource: Datasource, filter?: string[]) {
|
|
107
|
-
let { tables, error } = await buildSchemaHelper(datasource)
|
|
108
|
-
let finalTables = tables
|
|
109
|
-
if (filter) {
|
|
110
|
-
finalTables = {}
|
|
111
|
-
for (let key in tables) {
|
|
112
|
-
if (
|
|
113
|
-
filter.some((filter: any) => filter.toLowerCase() === key.toLowerCase())
|
|
114
|
-
) {
|
|
115
|
-
finalTables[key] = tables[key]
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return { tables: finalTables, error }
|
|
120
|
-
}
|
|
121
|
-
|
|
122
104
|
export async function fetch(ctx: UserCtx) {
|
|
123
105
|
// Get internal tables
|
|
124
106
|
const db = context.getAppDB()
|
|
@@ -190,28 +172,43 @@ export async function information(
|
|
|
190
172
|
}
|
|
191
173
|
const tableNames = await connector.getTableNames()
|
|
192
174
|
ctx.body = {
|
|
193
|
-
tableNames
|
|
175
|
+
tableNames,
|
|
194
176
|
}
|
|
195
177
|
}
|
|
196
178
|
|
|
197
179
|
export async function buildSchemaFromDb(ctx: UserCtx) {
|
|
198
180
|
const db = context.getAppDB()
|
|
199
|
-
const tablesFilter = ctx.request.body.tablesFilter
|
|
200
181
|
const datasource = await sdk.datasources.get(ctx.params.datasourceId)
|
|
182
|
+
const tablesFilter = ctx.request.body.tablesFilter
|
|
201
183
|
|
|
202
|
-
|
|
203
|
-
|
|
184
|
+
let { tables, error } = await buildSchemaHelper(datasource)
|
|
185
|
+
if (tablesFilter) {
|
|
186
|
+
if (!datasource.entities) {
|
|
187
|
+
datasource.entities = {}
|
|
188
|
+
}
|
|
189
|
+
for (let key in tables) {
|
|
190
|
+
if (
|
|
191
|
+
tablesFilter.some(
|
|
192
|
+
(filter: any) => filter.toLowerCase() === key.toLowerCase()
|
|
193
|
+
)
|
|
194
|
+
) {
|
|
195
|
+
datasource.entities[key] = tables[key]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
datasource.entities = tables
|
|
200
|
+
}
|
|
204
201
|
|
|
205
202
|
setDefaultDisplayColumns(datasource)
|
|
206
203
|
const dbResp = await db.put(datasource)
|
|
207
204
|
datasource._rev = dbResp.rev
|
|
208
205
|
const cleanedDatasource = await sdk.datasources.removeSecretSingle(datasource)
|
|
209
206
|
|
|
210
|
-
const
|
|
207
|
+
const response: any = { datasource: cleanedDatasource }
|
|
211
208
|
if (error) {
|
|
212
|
-
|
|
209
|
+
response.error = error
|
|
213
210
|
}
|
|
214
|
-
ctx.body =
|
|
211
|
+
ctx.body = response
|
|
215
212
|
}
|
|
216
213
|
|
|
217
214
|
/**
|
|
@@ -309,19 +306,12 @@ export async function update(ctx: UserCtx<any, UpdateDatasourceResponse>) {
|
|
|
309
306
|
builderSocket?.emitDatasourceUpdate(ctx, datasource)
|
|
310
307
|
}
|
|
311
308
|
|
|
312
|
-
const preSaveAction: Partial<Record<SourceName, any>> = {
|
|
313
|
-
[SourceName.GOOGLE_SHEETS]: async (datasource: Datasource) => {
|
|
314
|
-
await googleSetupCreationAuth(datasource.config as any)
|
|
315
|
-
},
|
|
316
|
-
}
|
|
317
|
-
|
|
318
309
|
export async function save(
|
|
319
310
|
ctx: UserCtx<CreateDatasourceRequest, CreateDatasourceResponse>
|
|
320
311
|
) {
|
|
321
312
|
const db = context.getAppDB()
|
|
322
313
|
const plus = ctx.request.body.datasource.plus
|
|
323
314
|
const fetchSchema = ctx.request.body.fetchSchema
|
|
324
|
-
const tablesFilter = ctx.request.body.tablesFilter
|
|
325
315
|
|
|
326
316
|
const datasource = {
|
|
327
317
|
_id: generateDatasourceID({ plus }),
|
|
@@ -331,19 +321,12 @@ export async function save(
|
|
|
331
321
|
|
|
332
322
|
let schemaError = null
|
|
333
323
|
if (fetchSchema) {
|
|
334
|
-
const { tables, error } = await
|
|
335
|
-
datasource,
|
|
336
|
-
tablesFilter
|
|
337
|
-
)
|
|
324
|
+
const { tables, error } = await buildSchemaHelper(datasource)
|
|
338
325
|
schemaError = error
|
|
339
326
|
datasource.entities = tables
|
|
340
327
|
setDefaultDisplayColumns(datasource)
|
|
341
328
|
}
|
|
342
329
|
|
|
343
|
-
if (preSaveAction[datasource.source]) {
|
|
344
|
-
await preSaveAction[datasource.source](datasource)
|
|
345
|
-
}
|
|
346
|
-
|
|
347
330
|
const dbResp = await db.put(datasource)
|
|
348
331
|
await events.datasource.created(datasource)
|
|
349
332
|
datasource._rev = dbResp.rev
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getUserMetadataParams,
|
|
5
5
|
InternalTables,
|
|
6
6
|
} from "../../db/utils"
|
|
7
|
-
import {
|
|
7
|
+
import { BBContext, Database } from "@budibase/types"
|
|
8
8
|
|
|
9
9
|
const UpdateRolesOptions = {
|
|
10
10
|
CREATED: "created",
|
|
@@ -38,15 +38,15 @@ async function updateRolesOnUserTable(
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export async function fetch(ctx:
|
|
41
|
+
export async function fetch(ctx: BBContext) {
|
|
42
42
|
ctx.body = await roles.getAllRoles()
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export async function find(ctx:
|
|
45
|
+
export async function find(ctx: BBContext) {
|
|
46
46
|
ctx.body = await roles.getRole(ctx.params.roleId)
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export async function save(ctx:
|
|
49
|
+
export async function save(ctx: BBContext) {
|
|
50
50
|
const db = context.getAppDB()
|
|
51
51
|
let { _id, name, inherits, permissionId } = ctx.request.body
|
|
52
52
|
let isCreate = false
|
|
@@ -72,7 +72,7 @@ export async function save(ctx: UserCtx) {
|
|
|
72
72
|
ctx.message = `Role '${role.name}' created successfully.`
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
export async function destroy(ctx:
|
|
75
|
+
export async function destroy(ctx: BBContext) {
|
|
76
76
|
const db = context.getAppDB()
|
|
77
77
|
const roleId = ctx.params.roleId
|
|
78
78
|
const role = await db.get(roleId)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getRoutingInfo } from "../../utilities/routing"
|
|
2
2
|
import { roles } from "@budibase/backend-core"
|
|
3
|
-
import {
|
|
3
|
+
import { BBContext } from "@budibase/types"
|
|
4
4
|
|
|
5
5
|
const URL_SEPARATOR = "/"
|
|
6
6
|
|
|
@@ -56,11 +56,11 @@ async function getRoutingStructure() {
|
|
|
56
56
|
return { routes: routing.json }
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
export async function fetch(ctx:
|
|
59
|
+
export async function fetch(ctx: BBContext) {
|
|
60
60
|
ctx.body = await getRoutingStructure()
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
export async function clientFetch(ctx:
|
|
63
|
+
export async function clientFetch(ctx: BBContext) {
|
|
64
64
|
const routing = await getRoutingStructure()
|
|
65
65
|
let roleId = ctx.user?.role?._id
|
|
66
66
|
const roleIds = (await roles.getUserRoleHierarchy(roleId, {
|
package/src/api/routes/backup.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import tk from "timekeeper"
|
|
2
1
|
import * as setup from "./utilities"
|
|
3
2
|
import { events } from "@budibase/backend-core"
|
|
4
3
|
import sdk from "../../../sdk"
|
|
5
4
|
import { checkBuilderEndpoint } from "./utilities/TestFunctions"
|
|
6
|
-
import { mocks } from "@budibase/backend-core/tests"
|
|
7
5
|
|
|
8
6
|
describe("/backups", () => {
|
|
9
7
|
let request = setup.getRequest()
|
|
@@ -18,7 +16,7 @@ describe("/backups", () => {
|
|
|
18
16
|
describe("exportAppDump", () => {
|
|
19
17
|
it("should be able to export app", async () => {
|
|
20
18
|
const res = await request
|
|
21
|
-
.
|
|
19
|
+
.get(`/api/backups/export?appId=${config.getAppId()}&appname=test`)
|
|
22
20
|
.set(config.defaultHeaders())
|
|
23
21
|
.expect(200)
|
|
24
22
|
expect(res.headers["content-type"]).toEqual("application/gzip")
|
|
@@ -28,24 +26,10 @@ describe("/backups", () => {
|
|
|
28
26
|
it("should apply authorization to endpoint", async () => {
|
|
29
27
|
await checkBuilderEndpoint({
|
|
30
28
|
config,
|
|
31
|
-
method: "
|
|
29
|
+
method: "GET",
|
|
32
30
|
url: `/api/backups/export?appId=${config.getAppId()}`,
|
|
33
31
|
})
|
|
34
32
|
})
|
|
35
|
-
|
|
36
|
-
it("should infer the app name from the app", async () => {
|
|
37
|
-
tk.freeze(mocks.date.MOCK_DATE)
|
|
38
|
-
|
|
39
|
-
const res = await request
|
|
40
|
-
.post(`/api/backups/export?appId=${config.getAppId()}`)
|
|
41
|
-
.set(config.defaultHeaders())
|
|
42
|
-
|
|
43
|
-
expect(res.headers["content-disposition"]).toEqual(
|
|
44
|
-
`attachment; filename="${
|
|
45
|
-
config.getApp()!.name
|
|
46
|
-
}-export-${mocks.date.MOCK_DATE.getTime()}.tar.gz"`
|
|
47
|
-
)
|
|
48
|
-
})
|
|
49
33
|
})
|
|
50
34
|
|
|
51
35
|
describe("calculateBackupStats", () => {
|
|
@@ -48,35 +48,6 @@ export const definition: AutomationStepSchema = {
|
|
|
48
48
|
type: AutomationIOType.STRING,
|
|
49
49
|
title: "HTML Contents",
|
|
50
50
|
},
|
|
51
|
-
addInvite: {
|
|
52
|
-
type: AutomationIOType.BOOLEAN,
|
|
53
|
-
title: "Add calendar invite",
|
|
54
|
-
},
|
|
55
|
-
startTime: {
|
|
56
|
-
type: AutomationIOType.DATE,
|
|
57
|
-
title: "Start Time",
|
|
58
|
-
dependsOn: "addInvite",
|
|
59
|
-
},
|
|
60
|
-
endTime: {
|
|
61
|
-
type: AutomationIOType.DATE,
|
|
62
|
-
title: "End Time",
|
|
63
|
-
dependsOn: "addInvite",
|
|
64
|
-
},
|
|
65
|
-
summary: {
|
|
66
|
-
type: AutomationIOType.STRING,
|
|
67
|
-
title: "Meeting Summary",
|
|
68
|
-
dependsOn: "addInvite",
|
|
69
|
-
},
|
|
70
|
-
location: {
|
|
71
|
-
type: AutomationIOType.STRING,
|
|
72
|
-
title: "Location",
|
|
73
|
-
dependsOn: "addInvite",
|
|
74
|
-
},
|
|
75
|
-
url: {
|
|
76
|
-
type: AutomationIOType.STRING,
|
|
77
|
-
title: "URL",
|
|
78
|
-
dependsOn: "addInvite",
|
|
79
|
-
},
|
|
80
51
|
},
|
|
81
52
|
required: ["to", "from", "subject", "contents"],
|
|
82
53
|
},
|
|
@@ -97,43 +68,21 @@ export const definition: AutomationStepSchema = {
|
|
|
97
68
|
}
|
|
98
69
|
|
|
99
70
|
export async function run({ inputs }: AutomationStepInput) {
|
|
100
|
-
let {
|
|
101
|
-
to,
|
|
102
|
-
from,
|
|
103
|
-
subject,
|
|
104
|
-
contents,
|
|
105
|
-
cc,
|
|
106
|
-
bcc,
|
|
107
|
-
addInvite,
|
|
108
|
-
startTime,
|
|
109
|
-
endTime,
|
|
110
|
-
summary,
|
|
111
|
-
location,
|
|
112
|
-
url,
|
|
113
|
-
} = inputs
|
|
71
|
+
let { to, from, subject, contents, cc, bcc } = inputs
|
|
114
72
|
if (!contents) {
|
|
115
73
|
contents = "<h1>No content</h1>"
|
|
116
74
|
}
|
|
117
75
|
to = to || undefined
|
|
118
76
|
try {
|
|
119
|
-
let response = await sendSmtpEmail(
|
|
77
|
+
let response = await sendSmtpEmail(
|
|
120
78
|
to,
|
|
121
79
|
from,
|
|
122
80
|
subject,
|
|
123
81
|
contents,
|
|
124
82
|
cc,
|
|
125
83
|
bcc,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
? {
|
|
129
|
-
startTime,
|
|
130
|
-
endTime,
|
|
131
|
-
summary,
|
|
132
|
-
location,
|
|
133
|
-
url,
|
|
134
|
-
}
|
|
135
|
-
: undefined,
|
|
136
|
-
})
|
|
84
|
+
true
|
|
85
|
+
)
|
|
137
86
|
return {
|
|
138
87
|
success: true,
|
|
139
88
|
response,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
function generateResponse(to, from) {
|
|
3
|
+
return {
|
|
4
|
+
"success": true,
|
|
5
|
+
"response": {
|
|
6
|
+
"accepted": [
|
|
7
|
+
to
|
|
8
|
+
],
|
|
9
|
+
"envelope": {
|
|
10
|
+
"from": from,
|
|
11
|
+
"to": [
|
|
12
|
+
to
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"message": `Email sent to ${to}.`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const mockFetch = jest.fn(() => ({
|
|
22
|
+
headers: {
|
|
23
|
+
raw: () => {
|
|
24
|
+
return { "content-type": ["application/json"] }
|
|
25
|
+
},
|
|
26
|
+
get: () => ["application/json"],
|
|
27
|
+
},
|
|
28
|
+
json: jest.fn(() => response),
|
|
29
|
+
status: 200,
|
|
30
|
+
text: jest.fn(),
|
|
31
|
+
}))
|
|
32
|
+
jest.mock("node-fetch", () => mockFetch)
|
|
33
|
+
const setup = require("./utilities")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
describe("test the outgoing webhook action", () => {
|
|
37
|
+
let inputs
|
|
38
|
+
let config = setup.getConfig()
|
|
39
|
+
beforeAll(async () => {
|
|
40
|
+
await config.init()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
afterAll(setup.afterAll)
|
|
44
|
+
|
|
45
|
+
it("should be able to run the action", async () => {
|
|
46
|
+
inputs = {
|
|
47
|
+
to: "user1@test.com",
|
|
48
|
+
from: "admin@test.com",
|
|
49
|
+
subject: "hello",
|
|
50
|
+
contents: "testing",
|
|
51
|
+
}
|
|
52
|
+
let resp = generateResponse(inputs.to, inputs.from)
|
|
53
|
+
mockFetch.mockImplementationOnce(() => ({
|
|
54
|
+
headers: {
|
|
55
|
+
raw: () => {
|
|
56
|
+
return { "content-type": ["application/json"] }
|
|
57
|
+
},
|
|
58
|
+
get: () => ["application/json"],
|
|
59
|
+
},
|
|
60
|
+
json: jest.fn(() => resp),
|
|
61
|
+
status: 200,
|
|
62
|
+
text: jest.fn(),
|
|
63
|
+
}))
|
|
64
|
+
const res = await setup.runStep(setup.actions.SEND_EMAIL_SMTP.stepId, inputs)
|
|
65
|
+
expect(res.response).toEqual(resp)
|
|
66
|
+
expect(res.success).toEqual(true)
|
|
67
|
+
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
})
|
|
@@ -26,10 +26,6 @@ export default function process(updateCb?: UpdateCallback) {
|
|
|
26
26
|
// if something not found - no changes to perform
|
|
27
27
|
if (err?.status === 404) {
|
|
28
28
|
return
|
|
29
|
-
}
|
|
30
|
-
// The user has already been sync in another process
|
|
31
|
-
else if (err?.status === 409) {
|
|
32
|
-
return
|
|
33
29
|
} else {
|
|
34
30
|
logging.logAlert("Failed to perform user/group app sync", err)
|
|
35
31
|
}
|