@budibase/worker 2.1.43-alpha.2 → 2.1.43
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 +24 -14
- package/{src/tests/jestSetup.ts → scripts/jestSetup.js} +3 -12
- package/scripts/localdomain.js +7 -33
- package/src/api/controllers/global/auth.ts +43 -51
- package/src/api/controllers/global/{configs.ts → configs.js} +114 -119
- package/src/api/controllers/global/{email.ts → email.js} +5 -6
- package/src/api/controllers/global/roles.js +68 -0
- package/src/api/controllers/global/self.ts +2 -2
- package/src/api/controllers/global/users.ts +2 -4
- package/src/api/controllers/global/{workspaces.ts → workspaces.js} +18 -15
- package/src/api/controllers/system/{environment.ts → environment.js} +2 -3
- package/src/api/controllers/system/restore.ts +1 -1
- package/src/api/controllers/system/{status.ts → status.js} +3 -4
- package/src/api/controllers/system/tenants.ts +51 -8
- package/src/api/index.ts +8 -31
- package/src/api/routes/global/{auth.ts → auth.js} +48 -31
- package/src/api/routes/global/{configs.ts → configs.js} +23 -22
- package/src/api/routes/global/{email.ts → email.js} +10 -9
- package/src/api/routes/global/license.ts +1 -1
- package/src/api/routes/global/roles.js +12 -0
- package/src/api/routes/global/self.ts +2 -2
- package/src/api/routes/global/templates.ts +4 -4
- package/src/api/routes/global/tests/auth.spec.ts +64 -134
- package/src/api/routes/global/tests/configs.spec.ts +35 -34
- package/src/api/routes/global/tests/email.spec.ts +3 -4
- package/src/api/routes/global/tests/realEmail.spec.ts +3 -2
- package/src/api/routes/global/tests/self.spec.ts +4 -3
- package/src/api/routes/global/tests/users.spec.ts +45 -61
- package/src/api/routes/global/{users.ts → users.js} +26 -28
- package/src/api/routes/global/{workspaces.ts → workspaces.js} +10 -9
- package/src/api/routes/index.ts +1 -2
- package/src/api/routes/system/accounts.ts +1 -1
- package/src/api/routes/system/environment.js +8 -0
- package/src/api/routes/system/migrations.ts +1 -1
- package/src/api/routes/system/restore.ts +1 -1
- package/src/api/routes/system/status.js +8 -0
- package/src/api/routes/system/tenants.js +12 -0
- package/src/api/routes/system/tests/accounts.spec.ts +6 -5
- package/src/api/routes/validation/users.ts +3 -3
- package/src/constants/{index.ts → index.js} +64 -57
- package/src/constants/templates/{index.ts → index.js} +19 -23
- package/src/db/index.js +11 -0
- package/src/environment.ts +7 -9
- package/src/index.ts +16 -15
- package/src/middleware/{cloudRestricted.ts → cloudRestricted.js} +4 -5
- package/src/tests/TestConfiguration.ts +50 -99
- package/src/tests/api/accounts.ts +8 -5
- package/src/tests/api/auth.ts +6 -3
- package/src/tests/api/configs.ts +8 -15
- package/src/tests/api/email.ts +6 -3
- package/src/tests/api/index.ts +0 -15
- package/src/tests/api/self.ts +6 -11
- package/src/tests/api/users.ts +6 -38
- package/src/tests/controllers.js +7 -0
- package/src/tests/index.ts +1 -5
- package/src/tests/structures/accounts.ts +24 -0
- package/src/tests/structures/{configs.ts → configs.js} +11 -11
- package/src/tests/structures/index.ts +3 -5
- package/src/tests/structures/users.ts +0 -1
- package/src/utilities/appService.js +33 -0
- package/src/utilities/{email.ts → email.js} +45 -78
- package/src/utilities/fileSystem.js +5 -0
- package/src/utilities/{index.ts → index.js} +1 -1
- package/src/utilities/{redis.ts → redis.js} +24 -29
- package/src/utilities/templates.js +49 -0
- package/src/utilities/users.js +17 -0
- package/tsconfig.build.json +3 -2
- package/tsconfig.json +1 -3
- package/__mocks__/aws-sdk.ts +0 -15
- package/__mocks__/oauth.ts +0 -57
- package/coverage/clover.xml +0 -2157
- package/coverage/coverage-final.json +0 -78
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -431
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/src/api/controllers/global/auth.ts.html +0 -925
- package/coverage/lcov-report/src/api/controllers/global/configs.ts.html +0 -1405
- package/coverage/lcov-report/src/api/controllers/global/email.ts.html +0 -196
- package/coverage/lcov-report/src/api/controllers/global/index.html +0 -236
- package/coverage/lcov-report/src/api/controllers/global/license.ts.html +0 -187
- package/coverage/lcov-report/src/api/controllers/global/roles.ts.html +0 -283
- package/coverage/lcov-report/src/api/controllers/global/self.ts.html +0 -577
- package/coverage/lcov-report/src/api/controllers/global/templates.ts.html +0 -316
- package/coverage/lcov-report/src/api/controllers/global/users.ts.html +0 -796
- package/coverage/lcov-report/src/api/controllers/global/workspaces.ts.html +0 -244
- package/coverage/lcov-report/src/api/controllers/system/accounts.ts.html +0 -148
- package/coverage/lcov-report/src/api/controllers/system/environment.ts.html +0 -124
- package/coverage/lcov-report/src/api/controllers/system/index.html +0 -191
- package/coverage/lcov-report/src/api/controllers/system/migrations.ts.html +0 -124
- package/coverage/lcov-report/src/api/controllers/system/restore.ts.html +0 -124
- package/coverage/lcov-report/src/api/controllers/system/status.ts.html +0 -133
- package/coverage/lcov-report/src/api/controllers/system/tenants.ts.html +0 -154
- package/coverage/lcov-report/src/api/index.html +0 -116
- package/coverage/lcov-report/src/api/index.ts.html +0 -583
- package/coverage/lcov-report/src/api/routes/global/auth.ts.html +0 -349
- package/coverage/lcov-report/src/api/routes/global/configs.ts.html +0 -457
- package/coverage/lcov-report/src/api/routes/global/email.ts.html +0 -193
- package/coverage/lcov-report/src/api/routes/global/index.html +0 -236
- package/coverage/lcov-report/src/api/routes/global/license.ts.html +0 -124
- package/coverage/lcov-report/src/api/routes/global/roles.ts.html +0 -133
- package/coverage/lcov-report/src/api/routes/global/self.ts.html +0 -139
- package/coverage/lcov-report/src/api/routes/global/templates.ts.html +0 -196
- package/coverage/lcov-report/src/api/routes/global/users.ts.html +0 -433
- package/coverage/lcov-report/src/api/routes/global/workspaces.ts.html +0 -196
- package/coverage/lcov-report/src/api/routes/index.html +0 -116
- package/coverage/lcov-report/src/api/routes/index.ts.html +0 -196
- package/coverage/lcov-report/src/api/routes/system/accounts.ts.html +0 -142
- package/coverage/lcov-report/src/api/routes/system/environment.ts.html +0 -109
- package/coverage/lcov-report/src/api/routes/system/index.html +0 -191
- package/coverage/lcov-report/src/api/routes/system/migrations.ts.html +0 -142
- package/coverage/lcov-report/src/api/routes/system/restore.ts.html +0 -109
- package/coverage/lcov-report/src/api/routes/system/status.ts.html +0 -109
- package/coverage/lcov-report/src/api/routes/system/tenants.ts.html +0 -124
- package/coverage/lcov-report/src/api/routes/validation/index.html +0 -131
- package/coverage/lcov-report/src/api/routes/validation/index.ts.html +0 -88
- package/coverage/lcov-report/src/api/routes/validation/users.ts.html +0 -235
- package/coverage/lcov-report/src/constants/index.html +0 -116
- package/coverage/lcov-report/src/constants/index.ts.html +0 -613
- package/coverage/lcov-report/src/constants/templates/index.html +0 -116
- package/coverage/lcov-report/src/constants/templates/index.ts.html +0 -316
- package/coverage/lcov-report/src/db/index.html +0 -116
- package/coverage/lcov-report/src/db/index.ts.html +0 -115
- package/coverage/lcov-report/src/environment.ts.html +0 -373
- package/coverage/lcov-report/src/index.html +0 -131
- package/coverage/lcov-report/src/index.ts.html +0 -394
- package/coverage/lcov-report/src/middleware/cloudRestricted.ts.html +0 -139
- package/coverage/lcov-report/src/middleware/index.html +0 -116
- package/coverage/lcov-report/src/migrations/functions/globalInfoSyncUsers.ts.html +0 -145
- package/coverage/lcov-report/src/migrations/functions/index.html +0 -116
- package/coverage/lcov-report/src/migrations/index.html +0 -116
- package/coverage/lcov-report/src/migrations/index.ts.html +0 -271
- package/coverage/lcov-report/src/sdk/accounts/accounts.ts.html +0 -262
- package/coverage/lcov-report/src/sdk/accounts/index.html +0 -131
- package/coverage/lcov-report/src/sdk/accounts/index.ts.html +0 -88
- package/coverage/lcov-report/src/sdk/index.html +0 -116
- package/coverage/lcov-report/src/sdk/index.ts.html +0 -106
- package/coverage/lcov-report/src/sdk/users/events.ts.html +0 -577
- package/coverage/lcov-report/src/sdk/users/index.html +0 -146
- package/coverage/lcov-report/src/sdk/users/index.ts.html +0 -88
- package/coverage/lcov-report/src/sdk/users/users.ts.html +0 -1903
- package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +0 -1051
- package/coverage/lcov-report/src/tests/api/accounts.ts.html +0 -160
- package/coverage/lcov-report/src/tests/api/auth.ts.html +0 -220
- package/coverage/lcov-report/src/tests/api/base.ts.html +0 -133
- package/coverage/lcov-report/src/tests/api/configs.ts.html +0 -226
- package/coverage/lcov-report/src/tests/api/email.ts.html +0 -148
- package/coverage/lcov-report/src/tests/api/environment.ts.html +0 -130
- package/coverage/lcov-report/src/tests/api/index.html +0 -296
- package/coverage/lcov-report/src/tests/api/index.ts.html +0 -205
- package/coverage/lcov-report/src/tests/api/migrations.ts.html +0 -151
- package/coverage/lcov-report/src/tests/api/restore.ts.html +0 -127
- package/coverage/lcov-report/src/tests/api/self.ts.html +0 -163
- package/coverage/lcov-report/src/tests/api/status.ts.html +0 -121
- package/coverage/lcov-report/src/tests/api/tenants.ts.html +0 -130
- package/coverage/lcov-report/src/tests/api/users.ts.html +0 -511
- package/coverage/lcov-report/src/tests/controllers.ts.html +0 -100
- package/coverage/lcov-report/src/tests/index.html +0 -146
- package/coverage/lcov-report/src/tests/index.ts.html +0 -139
- package/coverage/lcov-report/src/tests/mocks/email.js.html +0 -115
- package/coverage/lcov-report/src/tests/mocks/index.html +0 -131
- package/coverage/lcov-report/src/tests/mocks/index.ts.html +0 -106
- package/coverage/lcov-report/src/tests/structures/configs.ts.html +0 -313
- package/coverage/lcov-report/src/tests/structures/groups.ts.html +0 -118
- package/coverage/lcov-report/src/tests/structures/index.html +0 -161
- package/coverage/lcov-report/src/tests/structures/index.ts.html +0 -151
- package/coverage/lcov-report/src/tests/structures/users.ts.html +0 -196
- package/coverage/lcov-report/src/utilities/appService.ts.html +0 -181
- package/coverage/lcov-report/src/utilities/email.ts.html +0 -850
- package/coverage/lcov-report/src/utilities/fileSystem.ts.html +0 -100
- package/coverage/lcov-report/src/utilities/index.html +0 -206
- package/coverage/lcov-report/src/utilities/index.ts.html +0 -112
- package/coverage/lcov-report/src/utilities/redis.ts.html +0 -424
- package/coverage/lcov-report/src/utilities/templates.ts.html +0 -232
- package/coverage/lcov-report/src/utilities/users.ts.html +0 -133
- package/coverage/lcov.info +0 -3970
- package/jest.config.ts +0 -29
- package/src/api/controllers/global/roles.ts +0 -66
- package/src/api/routes/global/roles.ts +0 -16
- package/src/api/routes/global/tests/license.spec.ts +0 -31
- package/src/api/routes/global/tests/roles.spec.ts +0 -27
- package/src/api/routes/global/tests/templates.spec.ts +0 -35
- package/src/api/routes/global/tests/workspaces.spec.ts +0 -29
- package/src/api/routes/system/environment.ts +0 -8
- package/src/api/routes/system/status.ts +0 -8
- package/src/api/routes/system/tenants.ts +0 -13
- package/src/api/routes/system/tests/environment.spec.ts +0 -29
- package/src/api/routes/system/tests/migrations.spec.ts +0 -63
- package/src/api/routes/system/tests/restore.spec.ts +0 -36
- package/src/api/routes/system/tests/status.spec.ts +0 -48
- package/src/api/routes/system/tests/tenants.spec.ts +0 -61
- package/src/db/index.ts +0 -10
- package/src/middleware/tests/tenancy.spec.ts +0 -73
- package/src/tests/api/base.ts +0 -16
- package/src/tests/api/environment.ts +0 -15
- package/src/tests/api/migrations.ts +0 -22
- package/src/tests/api/restore.ts +0 -14
- package/src/tests/api/status.ts +0 -12
- package/src/tests/api/tenants.ts +0 -15
- package/src/tests/controllers.ts +0 -5
- package/src/utilities/appService.ts +0 -32
- package/src/utilities/fileSystem.ts +0 -5
- package/src/utilities/templates.ts +0 -49
- package/src/utilities/users.ts +0 -16
|
@@ -1,33 +1,15 @@
|
|
|
1
|
-
import env from "../environment"
|
|
2
|
-
import { EmailTemplatePurpose, TemplateType, Config } from "../constants"
|
|
3
|
-
import { getTemplateByPurpose } from "../constants/templates"
|
|
4
|
-
import { getSettingsTemplateContext } from "./templates"
|
|
5
|
-
import { processString } from "@budibase/string-templates"
|
|
6
|
-
import { getResetPasswordCode, getInviteCode } from "./redis"
|
|
7
|
-
import { User, Database } from "@budibase/types"
|
|
8
|
-
import { tenancy, db as dbCore } from "@budibase/backend-core"
|
|
9
1
|
const nodemailer = require("nodemailer")
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
// contents If sending a custom email then can supply contents which will be added to it.
|
|
19
|
-
contents?: string
|
|
20
|
-
// subject A custom subject can be specified if the config one is not desired.
|
|
21
|
-
subject?: string
|
|
22
|
-
// info Pass in a structure of information to be stored alongside the invitation.
|
|
23
|
-
info?: any
|
|
24
|
-
cc?: boolean
|
|
25
|
-
bcc?: boolean
|
|
26
|
-
automation?: boolean
|
|
27
|
-
}
|
|
2
|
+
const env = require("../environment")
|
|
3
|
+
const { getScopedConfig } = require("@budibase/backend-core/db")
|
|
4
|
+
const { EmailTemplatePurpose, TemplateTypes, Configs } = require("../constants")
|
|
5
|
+
const { getTemplateByPurpose } = require("../constants/templates")
|
|
6
|
+
const { getSettingsTemplateContext } = require("./templates")
|
|
7
|
+
const { processString } = require("@budibase/string-templates")
|
|
8
|
+
const { getResetPasswordCode, getInviteCode } = require("../utilities/redis")
|
|
9
|
+
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
28
10
|
|
|
29
11
|
const TEST_MODE = false
|
|
30
|
-
const TYPE =
|
|
12
|
+
const TYPE = TemplateTypes.EMAIL
|
|
31
13
|
|
|
32
14
|
const FULL_EMAIL_PURPOSES = [
|
|
33
15
|
EmailTemplatePurpose.INVITATION,
|
|
@@ -36,8 +18,8 @@ const FULL_EMAIL_PURPOSES = [
|
|
|
36
18
|
EmailTemplatePurpose.CUSTOM,
|
|
37
19
|
]
|
|
38
20
|
|
|
39
|
-
function createSMTPTransport(config
|
|
40
|
-
let options
|
|
21
|
+
function createSMTPTransport(config) {
|
|
22
|
+
let options
|
|
41
23
|
let secure = config.secure
|
|
42
24
|
// default it if not specified
|
|
43
25
|
if (secure == null) {
|
|
@@ -70,15 +52,10 @@ function createSMTPTransport(config: any) {
|
|
|
70
52
|
return nodemailer.createTransport(options)
|
|
71
53
|
}
|
|
72
54
|
|
|
73
|
-
async function getLinkCode(
|
|
74
|
-
purpose: EmailTemplatePurpose,
|
|
75
|
-
email: string,
|
|
76
|
-
user: User,
|
|
77
|
-
info: any = null
|
|
78
|
-
) {
|
|
55
|
+
async function getLinkCode(purpose, email, user, info = null) {
|
|
79
56
|
switch (purpose) {
|
|
80
57
|
case EmailTemplatePurpose.PASSWORD_RECOVERY:
|
|
81
|
-
return getResetPasswordCode(user._id
|
|
58
|
+
return getResetPasswordCode(user._id, info)
|
|
82
59
|
case EmailTemplatePurpose.INVITATION:
|
|
83
60
|
return getInviteCode(email, info)
|
|
84
61
|
default:
|
|
@@ -95,12 +72,7 @@ async function getLinkCode(
|
|
|
95
72
|
* @param {string|null} contents if using a custom template can supply contents for context.
|
|
96
73
|
* @return {Promise<string>} returns the built email HTML if all provided parameters were valid.
|
|
97
74
|
*/
|
|
98
|
-
async function buildEmail(
|
|
99
|
-
purpose: EmailTemplatePurpose,
|
|
100
|
-
email: string,
|
|
101
|
-
context: any,
|
|
102
|
-
{ user, contents }: any = {}
|
|
103
|
-
) {
|
|
75
|
+
async function buildEmail(purpose, email, context, { user, contents } = {}) {
|
|
104
76
|
// this isn't a full email
|
|
105
77
|
if (FULL_EMAIL_PURPOSES.indexOf(purpose) === -1) {
|
|
106
78
|
throw `Unable to build an email of type ${purpose}`
|
|
@@ -141,19 +113,15 @@ async function buildEmail(
|
|
|
141
113
|
* @param {boolean|null} automation Whether or not the configuration is being fetched for an email automation.
|
|
142
114
|
* @return {Promise<object|null>} returns the SMTP configuration if it exists
|
|
143
115
|
*/
|
|
144
|
-
async function getSmtpConfiguration(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
automation?: boolean
|
|
148
|
-
) {
|
|
149
|
-
const params: any = {
|
|
150
|
-
type: Config.SMTP,
|
|
116
|
+
async function getSmtpConfiguration(db, workspaceId = null, automation) {
|
|
117
|
+
const params = {
|
|
118
|
+
type: Configs.SMTP,
|
|
151
119
|
}
|
|
152
120
|
if (workspaceId) {
|
|
153
121
|
params.workspace = workspaceId
|
|
154
122
|
}
|
|
155
123
|
|
|
156
|
-
const customConfig = await
|
|
124
|
+
const customConfig = await getScopedConfig(db, params)
|
|
157
125
|
|
|
158
126
|
if (customConfig) {
|
|
159
127
|
return customConfig
|
|
@@ -178,12 +146,12 @@ async function getSmtpConfiguration(
|
|
|
178
146
|
* Checks if a SMTP config exists based on passed in parameters.
|
|
179
147
|
* @return {Promise<boolean>} returns true if there is a configuration that can be used.
|
|
180
148
|
*/
|
|
181
|
-
|
|
149
|
+
exports.isEmailConfigured = async (workspaceId = null) => {
|
|
182
150
|
// when "testing" or smtp fallback is enabled simply return true
|
|
183
151
|
if (TEST_MODE || env.SMTP_FALLBACK_ENABLED) {
|
|
184
152
|
return true
|
|
185
153
|
}
|
|
186
|
-
const db =
|
|
154
|
+
const db = getGlobalDB()
|
|
187
155
|
const config = await getSmtpConfiguration(db, workspaceId)
|
|
188
156
|
return config != null
|
|
189
157
|
}
|
|
@@ -193,49 +161,48 @@ export async function isEmailConfigured(workspaceId?: string) {
|
|
|
193
161
|
* send an email using it.
|
|
194
162
|
* @param {string} email The email address to send to.
|
|
195
163
|
* @param {string} purpose The purpose of the email being sent (e.g. reset password).
|
|
196
|
-
* @param {
|
|
164
|
+
* @param {string|undefined} workspaceId If finer grain controls being used then this will lookup config for workspace.
|
|
165
|
+
* @param {object|undefined} user If sending to an existing user the object can be provided, this is used in the context.
|
|
166
|
+
* @param {string|undefined} from If sending from an address that is not what is configured in the SMTP config.
|
|
167
|
+
* @param {string|undefined} contents If sending a custom email then can supply contents which will be added to it.
|
|
168
|
+
* @param {string|undefined} subject A custom subject can be specified if the config one is not desired.
|
|
169
|
+
* @param {object|undefined} info Pass in a structure of information to be stored alongside the invitation.
|
|
170
|
+
* @param {boolean|undefined} disableFallback Prevent email being sent from SMTP fallback to avoid spam.
|
|
197
171
|
* @return {Promise<object>} returns details about the attempt to send email, e.g. if it is successful; based on
|
|
198
172
|
* nodemailer response.
|
|
199
173
|
*/
|
|
200
|
-
|
|
201
|
-
email
|
|
202
|
-
purpose
|
|
203
|
-
|
|
204
|
-
) {
|
|
205
|
-
const db =
|
|
206
|
-
let config =
|
|
207
|
-
(await getSmtpConfiguration(db, opts?.workspaceId, opts?.automation)) || {}
|
|
174
|
+
exports.sendEmail = async (
|
|
175
|
+
email,
|
|
176
|
+
purpose,
|
|
177
|
+
{ workspaceId, user, from, contents, subject, info, cc, bcc, automation } = {}
|
|
178
|
+
) => {
|
|
179
|
+
const db = getGlobalDB()
|
|
180
|
+
let config = (await getSmtpConfiguration(db, workspaceId, automation)) || {}
|
|
208
181
|
if (Object.keys(config).length === 0 && !TEST_MODE) {
|
|
209
182
|
throw "Unable to find SMTP configuration."
|
|
210
183
|
}
|
|
211
184
|
const transport = createSMTPTransport(config)
|
|
212
185
|
// if there is a link code needed this will retrieve it
|
|
213
|
-
const code = await getLinkCode(purpose, email,
|
|
214
|
-
|
|
215
|
-
if (code) {
|
|
216
|
-
context = await getSettingsTemplateContext(purpose, code)
|
|
217
|
-
}
|
|
186
|
+
const code = await getLinkCode(purpose, email, user, info)
|
|
187
|
+
const context = await getSettingsTemplateContext(purpose, code)
|
|
218
188
|
|
|
219
|
-
let message
|
|
220
|
-
from:
|
|
189
|
+
let message = {
|
|
190
|
+
from: from || config.from,
|
|
221
191
|
html: await buildEmail(purpose, email, context, {
|
|
222
|
-
user
|
|
223
|
-
contents
|
|
192
|
+
user,
|
|
193
|
+
contents,
|
|
224
194
|
}),
|
|
225
195
|
}
|
|
226
196
|
|
|
227
197
|
message = {
|
|
228
198
|
...message,
|
|
229
199
|
to: email,
|
|
230
|
-
cc:
|
|
231
|
-
bcc:
|
|
200
|
+
cc: cc,
|
|
201
|
+
bcc: bcc,
|
|
232
202
|
}
|
|
233
203
|
|
|
234
|
-
if (
|
|
235
|
-
message.subject = await processString(
|
|
236
|
-
opts?.subject || config.subject,
|
|
237
|
-
context
|
|
238
|
-
)
|
|
204
|
+
if (subject || config.subject) {
|
|
205
|
+
message.subject = await processString(subject || config.subject, context)
|
|
239
206
|
}
|
|
240
207
|
const response = await transport.sendMail(message)
|
|
241
208
|
if (TEST_MODE) {
|
|
@@ -249,7 +216,7 @@ export async function sendEmail(
|
|
|
249
216
|
* @param {object} config an SMTP configuration - this is based on the nodemailer API.
|
|
250
217
|
* @return {Promise<boolean>} returns true if the configuration is valid.
|
|
251
218
|
*/
|
|
252
|
-
|
|
219
|
+
exports.verifyConfig = async config => {
|
|
253
220
|
const transport = createSMTPTransport(config)
|
|
254
221
|
await transport.verify()
|
|
255
222
|
}
|
|
@@ -1,35 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
const { Client, utils } = require("@budibase/backend-core/redis")
|
|
2
|
+
const { newid } = require("@budibase/backend-core/utils")
|
|
2
3
|
|
|
3
|
-
function getExpirySecondsForDB(db
|
|
4
|
+
function getExpirySecondsForDB(db) {
|
|
4
5
|
switch (db) {
|
|
5
|
-
case
|
|
6
|
+
case utils.Databases.PW_RESETS:
|
|
6
7
|
// a hour
|
|
7
8
|
return 3600
|
|
8
|
-
case
|
|
9
|
+
case utils.Databases.INVITATIONS:
|
|
9
10
|
// a day
|
|
10
11
|
return 86400
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
let pwResetClient
|
|
15
|
+
let pwResetClient, invitationClient
|
|
15
16
|
|
|
16
|
-
function getClient(db
|
|
17
|
+
function getClient(db) {
|
|
17
18
|
switch (db) {
|
|
18
|
-
case
|
|
19
|
+
case utils.Databases.PW_RESETS:
|
|
19
20
|
return pwResetClient
|
|
20
|
-
case
|
|
21
|
+
case utils.Databases.INVITATIONS:
|
|
21
22
|
return invitationClient
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
async function writeACode(db
|
|
26
|
+
async function writeACode(db, value) {
|
|
26
27
|
const client = await getClient(db)
|
|
27
|
-
const code =
|
|
28
|
+
const code = newid()
|
|
28
29
|
await client.store(code, value, getExpirySecondsForDB(db))
|
|
29
30
|
return code
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
async function getACode(db
|
|
33
|
+
async function getACode(db, code, deleteCode = true) {
|
|
33
34
|
const client = await getClient(db)
|
|
34
35
|
const value = await client.get(code)
|
|
35
36
|
if (!value) {
|
|
@@ -41,9 +42,9 @@ async function getACode(db: string, code: string, deleteCode = true) {
|
|
|
41
42
|
return value
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
pwResetClient = new
|
|
46
|
-
invitationClient = new
|
|
45
|
+
exports.init = async () => {
|
|
46
|
+
pwResetClient = new Client(utils.Databases.PW_RESETS)
|
|
47
|
+
invitationClient = new Client(utils.Databases.INVITATIONS)
|
|
47
48
|
await pwResetClient.init()
|
|
48
49
|
await invitationClient.init()
|
|
49
50
|
}
|
|
@@ -51,7 +52,7 @@ export async function init() {
|
|
|
51
52
|
/**
|
|
52
53
|
* make sure redis connection is closed.
|
|
53
54
|
*/
|
|
54
|
-
|
|
55
|
+
exports.shutdown = async () => {
|
|
55
56
|
if (pwResetClient) await pwResetClient.finish()
|
|
56
57
|
if (invitationClient) await invitationClient.finish()
|
|
57
58
|
console.log("Redis shutdown")
|
|
@@ -64,8 +65,8 @@ export async function shutdown() {
|
|
|
64
65
|
* @param {object} info Info about the user/the reset process.
|
|
65
66
|
* @return {Promise<string>} returns the code that was stored to redis.
|
|
66
67
|
*/
|
|
67
|
-
|
|
68
|
-
return writeACode(
|
|
68
|
+
exports.getResetPasswordCode = async (userId, info) => {
|
|
69
|
+
return writeACode(utils.Databases.PW_RESETS, { userId, info })
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
/**
|
|
@@ -74,12 +75,9 @@ export async function getResetPasswordCode(userId: string, info: any) {
|
|
|
74
75
|
* @param {boolean} deleteCode If the code is used/finished with this will delete it - defaults to true.
|
|
75
76
|
* @return {Promise<string>} returns the user ID if it is found
|
|
76
77
|
*/
|
|
77
|
-
|
|
78
|
-
resetCode: string,
|
|
79
|
-
deleteCode = true
|
|
80
|
-
) {
|
|
78
|
+
exports.checkResetPasswordCode = async (resetCode, deleteCode = true) => {
|
|
81
79
|
try {
|
|
82
|
-
return getACode(
|
|
80
|
+
return getACode(utils.Databases.PW_RESETS, resetCode, deleteCode)
|
|
83
81
|
} catch (err) {
|
|
84
82
|
throw "Provided information is not valid, cannot reset password - please try again."
|
|
85
83
|
}
|
|
@@ -91,8 +89,8 @@ export async function checkResetPasswordCode(
|
|
|
91
89
|
* @param {object|null} info Information to be carried along with the invitation.
|
|
92
90
|
* @return {Promise<string>} returns the code that was stored to redis.
|
|
93
91
|
*/
|
|
94
|
-
|
|
95
|
-
return writeACode(
|
|
92
|
+
exports.getInviteCode = async (email, info) => {
|
|
93
|
+
return writeACode(utils.Databases.INVITATIONS, { email, info })
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
/**
|
|
@@ -101,12 +99,9 @@ export async function getInviteCode(email: string, info: any) {
|
|
|
101
99
|
* @param {boolean} deleteCode whether or not the code should be deleted after retrieval - defaults to true.
|
|
102
100
|
* @return {Promise<object>} If the code is valid then an email address will be returned.
|
|
103
101
|
*/
|
|
104
|
-
|
|
105
|
-
inviteCode: string,
|
|
106
|
-
deleteCode: boolean = true
|
|
107
|
-
) {
|
|
102
|
+
exports.checkInviteCode = async (inviteCode, deleteCode = true) => {
|
|
108
103
|
try {
|
|
109
|
-
return getACode(
|
|
104
|
+
return getACode(utils.Databases.INVITATIONS, inviteCode, deleteCode)
|
|
110
105
|
} catch (err) {
|
|
111
106
|
throw "Invitation is not valid or has expired, please request a new one."
|
|
112
107
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const { getScopedConfig } = require("@budibase/backend-core/db")
|
|
2
|
+
const {
|
|
3
|
+
Configs,
|
|
4
|
+
InternalTemplateBindings,
|
|
5
|
+
LOGO_URL,
|
|
6
|
+
EmailTemplatePurpose,
|
|
7
|
+
} = require("../constants")
|
|
8
|
+
const { checkSlashesInUrl } = require("./index")
|
|
9
|
+
const {
|
|
10
|
+
getGlobalDB,
|
|
11
|
+
addTenantToUrl,
|
|
12
|
+
} = require("@budibase/backend-core/tenancy")
|
|
13
|
+
const BASE_COMPANY = "Budibase"
|
|
14
|
+
|
|
15
|
+
exports.getSettingsTemplateContext = async (purpose, code = null) => {
|
|
16
|
+
const db = getGlobalDB()
|
|
17
|
+
// TODO: use more granular settings in the future if required
|
|
18
|
+
let settings = (await getScopedConfig(db, { type: Configs.SETTINGS })) || {}
|
|
19
|
+
const URL = settings.platformUrl
|
|
20
|
+
const context = {
|
|
21
|
+
[InternalTemplateBindings.LOGO_URL]:
|
|
22
|
+
checkSlashesInUrl(`${URL}/${settings.logoUrl}`) || LOGO_URL,
|
|
23
|
+
[InternalTemplateBindings.PLATFORM_URL]: URL,
|
|
24
|
+
[InternalTemplateBindings.COMPANY]: settings.company || BASE_COMPANY,
|
|
25
|
+
[InternalTemplateBindings.DOCS_URL]:
|
|
26
|
+
settings.docsUrl || "https://docs.budibase.com/",
|
|
27
|
+
[InternalTemplateBindings.LOGIN_URL]: checkSlashesInUrl(
|
|
28
|
+
addTenantToUrl(`${URL}/login`)
|
|
29
|
+
),
|
|
30
|
+
[InternalTemplateBindings.CURRENT_DATE]: new Date().toISOString(),
|
|
31
|
+
[InternalTemplateBindings.CURRENT_YEAR]: new Date().getFullYear(),
|
|
32
|
+
}
|
|
33
|
+
// attach purpose specific context
|
|
34
|
+
switch (purpose) {
|
|
35
|
+
case EmailTemplatePurpose.PASSWORD_RECOVERY:
|
|
36
|
+
context[InternalTemplateBindings.RESET_CODE] = code
|
|
37
|
+
context[InternalTemplateBindings.RESET_URL] = checkSlashesInUrl(
|
|
38
|
+
addTenantToUrl(`${URL}/builder/auth/reset?code=${code}`)
|
|
39
|
+
)
|
|
40
|
+
break
|
|
41
|
+
case EmailTemplatePurpose.INVITATION:
|
|
42
|
+
context[InternalTemplateBindings.INVITE_CODE] = code
|
|
43
|
+
context[InternalTemplateBindings.INVITE_URL] = checkSlashesInUrl(
|
|
44
|
+
addTenantToUrl(`${URL}/builder/invite?code=${code}`)
|
|
45
|
+
)
|
|
46
|
+
break
|
|
47
|
+
}
|
|
48
|
+
return context
|
|
49
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
2
|
+
const { getGlobalUserParams } = require("@budibase/backend-core/db")
|
|
3
|
+
|
|
4
|
+
exports.checkAnyUserExists = async () => {
|
|
5
|
+
try {
|
|
6
|
+
const db = getGlobalDB()
|
|
7
|
+
const users = await db.allDocs(
|
|
8
|
+
getGlobalUserParams(null, {
|
|
9
|
+
include_docs: true,
|
|
10
|
+
limit: 1,
|
|
11
|
+
})
|
|
12
|
+
)
|
|
13
|
+
return users && users.rows.length >= 1
|
|
14
|
+
} catch (err) {
|
|
15
|
+
throw new Error("Unable to retrieve user list")
|
|
16
|
+
}
|
|
17
|
+
}
|
package/tsconfig.build.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"target": "es6",
|
|
4
4
|
"module": "commonjs",
|
|
5
5
|
"lib": ["es2020"],
|
|
6
|
+
"allowJs": true,
|
|
6
7
|
"strict": true,
|
|
7
8
|
"noImplicitAny": true,
|
|
8
9
|
"esModuleInterop": true,
|
|
@@ -19,7 +20,7 @@
|
|
|
19
20
|
"node_modules",
|
|
20
21
|
"dist",
|
|
21
22
|
"src/tests",
|
|
22
|
-
"**/*.spec.
|
|
23
|
-
"**/*.spec.
|
|
23
|
+
"**/*.spec.ts",
|
|
24
|
+
"**/*.spec.js"
|
|
24
25
|
]
|
|
25
26
|
}
|
package/tsconfig.json
CHANGED
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
"paths": {
|
|
9
9
|
"@budibase/types": ["../types/src"],
|
|
10
10
|
"@budibase/backend-core": ["../backend-core/src"],
|
|
11
|
-
"@budibase/backend-core/*": ["../backend-core/*"]
|
|
12
|
-
"@budibase/pro": ["../../../budibase-pro/packages/pro/src"]
|
|
11
|
+
"@budibase/backend-core/*": ["../backend-core/*"]
|
|
13
12
|
}
|
|
14
13
|
},
|
|
15
14
|
"ts-node": {
|
|
@@ -18,7 +17,6 @@
|
|
|
18
17
|
"references": [
|
|
19
18
|
{ "path": "../types" },
|
|
20
19
|
{ "path": "../backend-core" },
|
|
21
|
-
{ "path": "../../../budibase-pro/packages/pro" }
|
|
22
20
|
],
|
|
23
21
|
"include": [
|
|
24
22
|
"src/**/*",
|
package/__mocks__/aws-sdk.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const mockS3 = {
|
|
2
|
-
headBucket: jest.fn().mockReturnThis(),
|
|
3
|
-
deleteObject: jest.fn().mockReturnThis(),
|
|
4
|
-
deleteObjects: jest.fn().mockReturnThis(),
|
|
5
|
-
createBucket: jest.fn().mockReturnThis(),
|
|
6
|
-
listObjects: jest.fn().mockReturnThis(),
|
|
7
|
-
promise: jest.fn().mockReturnThis(),
|
|
8
|
-
catch: jest.fn(),
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const AWS = {
|
|
12
|
-
S3: jest.fn(() => mockS3),
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default AWS
|
package/__mocks__/oauth.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import * as jwt from "jsonwebtoken"
|
|
2
|
-
|
|
3
|
-
const mockOAuth2 = {
|
|
4
|
-
getOAuthAccessToken: (code: string, p: any, cb: any) => {
|
|
5
|
-
const err = null
|
|
6
|
-
const accessToken = "access_token"
|
|
7
|
-
const refreshToken = "refresh_token"
|
|
8
|
-
|
|
9
|
-
const exp = new Date()
|
|
10
|
-
exp.setDate(exp.getDate() + 1)
|
|
11
|
-
|
|
12
|
-
const iat = new Date()
|
|
13
|
-
iat.setDate(iat.getDate() - 1)
|
|
14
|
-
|
|
15
|
-
const claims = {
|
|
16
|
-
iss: "test",
|
|
17
|
-
sub: "sub",
|
|
18
|
-
aud: "clientId",
|
|
19
|
-
exp: exp.getTime() / 1000,
|
|
20
|
-
iat: iat.getTime() / 1000,
|
|
21
|
-
email: "oauth@example.com",
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const idToken = jwt.sign(claims, "secret")
|
|
25
|
-
|
|
26
|
-
const params = {
|
|
27
|
-
id_token: idToken,
|
|
28
|
-
}
|
|
29
|
-
return cb(err, accessToken, refreshToken, params)
|
|
30
|
-
},
|
|
31
|
-
_request: (
|
|
32
|
-
method: string,
|
|
33
|
-
url: string,
|
|
34
|
-
headers: any,
|
|
35
|
-
postBody: any,
|
|
36
|
-
accessToken: string,
|
|
37
|
-
cb: any
|
|
38
|
-
) => {
|
|
39
|
-
const err = null
|
|
40
|
-
const body = {
|
|
41
|
-
sub: "sub",
|
|
42
|
-
user_id: "userId",
|
|
43
|
-
name: "OAuth",
|
|
44
|
-
family_name: "2",
|
|
45
|
-
given_name: "OAuth",
|
|
46
|
-
middle_name: "",
|
|
47
|
-
}
|
|
48
|
-
const res = {}
|
|
49
|
-
return cb(err, JSON.stringify(body), res)
|
|
50
|
-
},
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const oauth = {
|
|
54
|
-
OAuth2: jest.fn(() => mockOAuth2),
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export = oauth
|