@budibase/worker 2.4.41 → 2.4.42-alpha.0
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/package.json +5 -5
- package/scripts/test.sh +3 -3
- package/src/api/controllers/global/configs.ts +46 -0
- package/src/api/controllers/global/users.ts +2 -3
- package/src/api/routes/global/tests/configs.spec.ts +2 -0
- package/src/constants/index.ts +1 -0
- package/src/constants/templates/core.hbs +33 -0
- package/src/constants/templates/index.ts +1 -0
- package/src/index.ts +2 -0
- package/src/tests/TestConfiguration.ts +2 -0
- package/src/tests/jestEnv.ts +1 -0
- package/src/tests/jestSetup.ts +5 -1
- package/src/utilities/configs.ts +27 -0
- package/src/utilities/email.ts +13 -4
- package/src/utilities/templates.ts +9 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/worker",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "2.4.
|
|
4
|
+
"version": "2.4.42-alpha.0",
|
|
5
5
|
"description": "Budibase background service",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"author": "Budibase",
|
|
37
37
|
"license": "GPL-3.0",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@budibase/backend-core": "
|
|
39
|
+
"@budibase/backend-core": "2.4.42-alpha.0",
|
|
40
40
|
"@budibase/pro": "2.4.40",
|
|
41
|
-
"@budibase/string-templates": "
|
|
42
|
-
"@budibase/types": "
|
|
41
|
+
"@budibase/string-templates": "2.4.42-alpha.0",
|
|
42
|
+
"@budibase/types": "2.4.42-alpha.0",
|
|
43
43
|
"@koa/router": "8.0.8",
|
|
44
44
|
"@sentry/node": "6.17.7",
|
|
45
45
|
"@techpass/passport-openidconnect": "0.3.2",
|
|
@@ -101,5 +101,5 @@
|
|
|
101
101
|
"typescript": "4.7.3",
|
|
102
102
|
"update-dotenv": "1.1.1"
|
|
103
103
|
},
|
|
104
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "b31f1ba51b6d82958938a9acc7f8bf1ccef104ac"
|
|
105
105
|
}
|
package/scripts/test.sh
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
if [[ -n $CI ]]
|
|
4
4
|
then
|
|
5
5
|
# --runInBand performs better in ci where resources are limited
|
|
6
|
-
echo "jest --coverage --runInBand"
|
|
7
|
-
jest --coverage --runInBand
|
|
6
|
+
echo "jest --coverage --runInBand --forceExit"
|
|
7
|
+
jest --coverage --runInBand --forceExit
|
|
8
8
|
else
|
|
9
9
|
# --maxWorkers performs better in development
|
|
10
10
|
echo "jest --coverage --maxWorkers=2"
|
|
11
11
|
jest --coverage --maxWorkers=2
|
|
12
|
-
fi
|
|
12
|
+
fi
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
tenancy,
|
|
12
12
|
} from "@budibase/backend-core"
|
|
13
13
|
import { checkAnyUserExists } from "../../../utilities/users"
|
|
14
|
+
import { getLicensedConfig } from "../../../utilities/configs"
|
|
14
15
|
import {
|
|
15
16
|
Config,
|
|
16
17
|
ConfigType,
|
|
@@ -211,6 +212,38 @@ export async function save(ctx: UserCtx<Config>) {
|
|
|
211
212
|
ctx.throw(400, err)
|
|
212
213
|
}
|
|
213
214
|
|
|
215
|
+
// Ignore branding changes if the license does not permit it
|
|
216
|
+
// Favicon and Logo Url are excluded.
|
|
217
|
+
try {
|
|
218
|
+
const brandingEnabled = await pro.features.isBrandingEnabled()
|
|
219
|
+
if (existingConfig?.config && !brandingEnabled) {
|
|
220
|
+
const {
|
|
221
|
+
emailBrandingEnabled,
|
|
222
|
+
testimonialsEnabled,
|
|
223
|
+
platformTitle,
|
|
224
|
+
metaDescription,
|
|
225
|
+
loginHeading,
|
|
226
|
+
loginButton,
|
|
227
|
+
metaImageUrl,
|
|
228
|
+
metaTitle,
|
|
229
|
+
} = existingConfig.config
|
|
230
|
+
|
|
231
|
+
body.config = {
|
|
232
|
+
...body.config,
|
|
233
|
+
emailBrandingEnabled,
|
|
234
|
+
testimonialsEnabled,
|
|
235
|
+
platformTitle,
|
|
236
|
+
metaDescription,
|
|
237
|
+
loginHeading,
|
|
238
|
+
loginButton,
|
|
239
|
+
metaImageUrl,
|
|
240
|
+
metaTitle,
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
} catch (e) {
|
|
244
|
+
console.error("There was an issue retrieving the license", e)
|
|
245
|
+
}
|
|
246
|
+
|
|
214
247
|
try {
|
|
215
248
|
body._id = configs.generateConfigID(type)
|
|
216
249
|
const response = await configs.save(body)
|
|
@@ -276,6 +309,9 @@ export async function publicSettings(
|
|
|
276
309
|
// settings
|
|
277
310
|
const configDoc = await configs.getSettingsConfigDoc()
|
|
278
311
|
const config = configDoc.config
|
|
312
|
+
|
|
313
|
+
const branding = await pro.branding.getBrandingConfig(config)
|
|
314
|
+
|
|
279
315
|
// enrich the logo url - empty url means deleted
|
|
280
316
|
if (config.logoUrl && config.logoUrl !== "") {
|
|
281
317
|
config.logoUrl = objectStore.getGlobalFileUrl(
|
|
@@ -285,6 +321,15 @@ export async function publicSettings(
|
|
|
285
321
|
)
|
|
286
322
|
}
|
|
287
323
|
|
|
324
|
+
if (branding.faviconUrl && branding.faviconUrl !== "") {
|
|
325
|
+
// @ts-ignore
|
|
326
|
+
config.faviconUrl = objectStore.getGlobalFileUrl(
|
|
327
|
+
"settings",
|
|
328
|
+
"faviconUrl",
|
|
329
|
+
branding.faviconUrl
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
288
333
|
// google
|
|
289
334
|
const googleConfig = await configs.getGoogleConfig()
|
|
290
335
|
const preActivated = googleConfig && googleConfig.activated == null
|
|
@@ -305,6 +350,7 @@ export async function publicSettings(
|
|
|
305
350
|
_rev: configDoc._rev,
|
|
306
351
|
config: {
|
|
307
352
|
...config,
|
|
353
|
+
...branding,
|
|
308
354
|
google,
|
|
309
355
|
oidc,
|
|
310
356
|
isSSOEnforced,
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
getInviteCodes,
|
|
4
4
|
updateInviteCode,
|
|
5
5
|
} from "../../../utilities/redis"
|
|
6
|
-
// import sdk from "../../../sdk"
|
|
7
6
|
import * as userSdk from "../../../sdk/users"
|
|
8
7
|
import env from "../../../environment"
|
|
9
8
|
import {
|
|
@@ -26,11 +25,11 @@ import {
|
|
|
26
25
|
import {
|
|
27
26
|
accounts,
|
|
28
27
|
cache,
|
|
29
|
-
errors,
|
|
30
28
|
events,
|
|
31
29
|
migrations,
|
|
32
30
|
tenancy,
|
|
33
31
|
platform,
|
|
32
|
+
ErrorCode,
|
|
34
33
|
} from "@budibase/backend-core"
|
|
35
34
|
import { checkAnyUserExists } from "../../../utilities/users"
|
|
36
35
|
import { isEmailConfigured } from "../../../utilities/email"
|
|
@@ -421,7 +420,7 @@ export const inviteAccept = async (
|
|
|
421
420
|
email: user.email,
|
|
422
421
|
}
|
|
423
422
|
} catch (err: any) {
|
|
424
|
-
if (err.code ===
|
|
423
|
+
if (err.code === ErrorCode.USAGE_LIMIT_EXCEEDED) {
|
|
425
424
|
// explicitly re-throw limit exceeded errors
|
|
426
425
|
ctx.throw(400, err)
|
|
427
426
|
}
|
|
@@ -286,6 +286,7 @@ describe("configs", () => {
|
|
|
286
286
|
type: "settings",
|
|
287
287
|
config: {
|
|
288
288
|
company: "Budibase",
|
|
289
|
+
emailBrandingEnabled: true,
|
|
289
290
|
logoUrl: "",
|
|
290
291
|
analyticsEnabled: false,
|
|
291
292
|
google: false,
|
|
@@ -294,6 +295,7 @@ describe("configs", () => {
|
|
|
294
295
|
oidc: false,
|
|
295
296
|
oidcCallbackUrl: `http://localhost:10000/api/global/auth/${config.tenantId}/oidc/callback`,
|
|
296
297
|
platformUrl: "http://localhost:10000",
|
|
298
|
+
testimonialsEnabled: true,
|
|
297
299
|
},
|
|
298
300
|
}
|
|
299
301
|
delete body._rev
|
package/src/constants/index.ts
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{{#if enableEmailBranding}}
|
|
2
|
+
<tr>
|
|
3
|
+
<td cellpadding="0" cellspacing="0">
|
|
4
|
+
<table
|
|
5
|
+
align="center"
|
|
6
|
+
width="570"
|
|
7
|
+
cellpadding="0"
|
|
8
|
+
cellspacing="0"
|
|
9
|
+
role="presentation"
|
|
10
|
+
>
|
|
11
|
+
<tbody>
|
|
12
|
+
<tr>
|
|
13
|
+
<td
|
|
14
|
+
style="padding:0 35px; padding-top: 15px;"
|
|
15
|
+
cellpadding="0"
|
|
16
|
+
cellspacing="0"
|
|
17
|
+
>
|
|
18
|
+
<img
|
|
19
|
+
width="32px"
|
|
20
|
+
style="margin-right:16px; vertical-align: middle;"
|
|
21
|
+
alt="Budibase Logo"
|
|
22
|
+
src="https://i.imgur.com/Xhdt1YP.png"
|
|
23
|
+
/>
|
|
24
|
+
<strong style="vertical-align: middle; font-size: 1.1em">
|
|
25
|
+
Budibase
|
|
26
|
+
</strong>
|
|
27
|
+
</td>
|
|
28
|
+
</tr>
|
|
29
|
+
</tbody>
|
|
30
|
+
</table>
|
|
31
|
+
</td>
|
|
32
|
+
</tr>
|
|
33
|
+
{{/if}}
|
|
@@ -21,6 +21,7 @@ export const EmailTemplates = {
|
|
|
21
21
|
join(__dirname, "welcome.hbs")
|
|
22
22
|
),
|
|
23
23
|
[EmailTemplatePurpose.CUSTOM]: readStaticFile(join(__dirname, "custom.hbs")),
|
|
24
|
+
[EmailTemplatePurpose.CORE]: readStaticFile(join(__dirname, "core.hbs")),
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export function addBaseTemplates(templates: Template[], type?: string) {
|
package/src/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
middleware,
|
|
22
22
|
queue,
|
|
23
23
|
env as coreEnv,
|
|
24
|
+
timers,
|
|
24
25
|
} from "@budibase/backend-core"
|
|
25
26
|
db.init()
|
|
26
27
|
import Koa from "koa"
|
|
@@ -91,6 +92,7 @@ server.on("close", async () => {
|
|
|
91
92
|
}
|
|
92
93
|
shuttingDown = true
|
|
93
94
|
console.log("Server Closed")
|
|
95
|
+
timers.cleanup()
|
|
94
96
|
await redis.shutdown()
|
|
95
97
|
await events.shutdown()
|
|
96
98
|
await queue.shutdown()
|
package/src/tests/jestEnv.ts
CHANGED
package/src/tests/jestSetup.ts
CHANGED
|
@@ -2,7 +2,7 @@ import "./logging"
|
|
|
2
2
|
|
|
3
3
|
import { mocks, testContainerUtils } from "@budibase/backend-core/tests"
|
|
4
4
|
import env from "../environment"
|
|
5
|
-
import { env as coreEnv } from "@budibase/backend-core"
|
|
5
|
+
import { env as coreEnv, timers } from "@budibase/backend-core"
|
|
6
6
|
|
|
7
7
|
// must explicitly enable fetch mock
|
|
8
8
|
mocks.fetch.enable()
|
|
@@ -21,3 +21,7 @@ if (!process.env.CI) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
testContainerUtils.setupEnv(env, coreEnv)
|
|
24
|
+
|
|
25
|
+
afterAll(() => {
|
|
26
|
+
timers.cleanup()
|
|
27
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as pro from "@budibase/pro"
|
|
2
|
+
|
|
3
|
+
export async function getLicensedConfig() {
|
|
4
|
+
let licensedConfig: object = {}
|
|
5
|
+
const defaults = {
|
|
6
|
+
emailBrandingEnabled: true,
|
|
7
|
+
testimonialsEnabled: true,
|
|
8
|
+
platformTitle: undefined,
|
|
9
|
+
metaDescription: undefined,
|
|
10
|
+
loginHeading: undefined,
|
|
11
|
+
loginButton: undefined,
|
|
12
|
+
metaImageUrl: undefined,
|
|
13
|
+
metaTitle: undefined,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
// License/Feature Checks
|
|
18
|
+
const enabled = await pro.features.isBrandingEnabled()
|
|
19
|
+
if (!enabled) {
|
|
20
|
+
licensedConfig = { ...defaults }
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {
|
|
23
|
+
licensedConfig = { ...defaults }
|
|
24
|
+
console.info("Could not retrieve license", e)
|
|
25
|
+
}
|
|
26
|
+
return licensedConfig
|
|
27
|
+
}
|
package/src/utilities/email.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import env from "../environment"
|
|
2
2
|
import { EmailTemplatePurpose, TemplateType } from "../constants"
|
|
3
|
-
import { getTemplateByPurpose } from "../constants/templates"
|
|
3
|
+
import { getTemplateByPurpose, EmailTemplates } from "../constants/templates"
|
|
4
4
|
import { getSettingsTemplateContext } from "./templates"
|
|
5
5
|
import { processString } from "@budibase/string-templates"
|
|
6
6
|
import { getResetPasswordCode, getInviteCode } from "./redis"
|
|
@@ -109,11 +109,16 @@ async function buildEmail(
|
|
|
109
109
|
getTemplateByPurpose(TYPE, EmailTemplatePurpose.BASE),
|
|
110
110
|
getTemplateByPurpose(TYPE, purpose),
|
|
111
111
|
])
|
|
112
|
-
|
|
112
|
+
|
|
113
|
+
// Change from branding to core
|
|
114
|
+
let core = EmailTemplates[EmailTemplatePurpose.CORE]
|
|
115
|
+
|
|
116
|
+
if (!base || !body || !core) {
|
|
113
117
|
throw "Unable to build email, missing base components"
|
|
114
118
|
}
|
|
115
119
|
base = base.contents
|
|
116
120
|
body = body.contents
|
|
121
|
+
|
|
117
122
|
let name = user ? user.name : undefined
|
|
118
123
|
if (user && !name && user.firstName) {
|
|
119
124
|
name = user.lastName ? `${user.firstName} ${user.lastName}` : user.firstName
|
|
@@ -126,8 +131,12 @@ async function buildEmail(
|
|
|
126
131
|
user: user || {},
|
|
127
132
|
}
|
|
128
133
|
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
// Prepend the core template
|
|
135
|
+
const fullBody = core + body
|
|
136
|
+
|
|
137
|
+
body = await processString(fullBody, context)
|
|
138
|
+
|
|
139
|
+
// this should now be the core email HTML
|
|
131
140
|
return processString(base, {
|
|
132
141
|
...context,
|
|
133
142
|
body,
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { tenancy, configs } from "@budibase/backend-core"
|
|
2
|
+
import { SettingsInnerConfig } from "@budibase/types"
|
|
2
3
|
import {
|
|
3
4
|
InternalTemplateBinding,
|
|
4
5
|
LOGO_URL,
|
|
5
6
|
EmailTemplatePurpose,
|
|
6
7
|
} from "../constants"
|
|
7
8
|
import { checkSlashesInUrl } from "./index"
|
|
9
|
+
import { getLicensedConfig } from "./configs"
|
|
10
|
+
|
|
8
11
|
const BASE_COMPANY = "Budibase"
|
|
12
|
+
import * as pro from "@budibase/pro"
|
|
9
13
|
|
|
10
14
|
export async function getSettingsTemplateContext(
|
|
11
15
|
purpose: EmailTemplatePurpose,
|
|
12
16
|
code?: string | null
|
|
13
17
|
) {
|
|
14
|
-
|
|
18
|
+
const settings = await configs.getSettingsConfig()
|
|
19
|
+
const branding = await pro.branding.getBrandingConfig(settings)
|
|
15
20
|
const URL = settings.platformUrl
|
|
16
21
|
const context: any = {
|
|
17
22
|
[InternalTemplateBinding.LOGO_URL]:
|
|
@@ -25,6 +30,9 @@ export async function getSettingsTemplateContext(
|
|
|
25
30
|
[InternalTemplateBinding.CURRENT_DATE]: new Date().toISOString(),
|
|
26
31
|
[InternalTemplateBinding.CURRENT_YEAR]: new Date().getFullYear(),
|
|
27
32
|
}
|
|
33
|
+
|
|
34
|
+
context["enableEmailBranding"] = branding.emailBrandingEnabled === true
|
|
35
|
+
|
|
28
36
|
// attach purpose specific context
|
|
29
37
|
switch (purpose) {
|
|
30
38
|
case EmailTemplatePurpose.PASSWORD_RECOVERY:
|