@budibase/worker 1.3.19-alpha.7 → 1.3.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/package.json +6 -6
- package/scripts/localdomain.js +1 -3
- package/src/api/controllers/global/self.js +17 -36
- package/src/api/controllers/global/users.ts +1 -4
- package/src/api/routes/global/tests/self.spec.ts +1 -7
- package/src/environment.ts +0 -1
- package/src/sdk/users/events.ts +1 -5
- package/src/sdk/users/users.ts +46 -21
- package/src/tests/api/users.ts +2 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/worker",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.20",
|
|
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": "1.3.
|
|
40
|
-
"@budibase/pro": "1.3.19
|
|
41
|
-
"@budibase/string-templates": "1.3.
|
|
42
|
-
"@budibase/types": "1.3.
|
|
39
|
+
"@budibase/backend-core": "^1.3.20",
|
|
40
|
+
"@budibase/pro": "1.3.19",
|
|
41
|
+
"@budibase/string-templates": "^1.3.20",
|
|
42
|
+
"@budibase/types": "^1.3.20",
|
|
43
43
|
"@koa/router": "8.0.8",
|
|
44
44
|
"@sentry/node": "6.17.7",
|
|
45
45
|
"@techpass/passport-openidconnect": "0.3.2",
|
|
@@ -104,5 +104,5 @@
|
|
|
104
104
|
"./scripts/jestSetup.js"
|
|
105
105
|
]
|
|
106
106
|
},
|
|
107
|
-
"gitHead": "
|
|
107
|
+
"gitHead": "463d6238d270324638761183110f61dd0e448508"
|
|
108
108
|
}
|
package/scripts/localdomain.js
CHANGED
|
@@ -17,9 +17,7 @@ const arg = process.argv.slice(2)[0]
|
|
|
17
17
|
*/
|
|
18
18
|
updateDotEnv({
|
|
19
19
|
ACCOUNT_PORTAL_URL:
|
|
20
|
-
arg === "enable"
|
|
21
|
-
? "http://account.local.com:10001"
|
|
22
|
-
: "http://localhost:10001",
|
|
20
|
+
arg === "enable" ? "http://local.com:10001" : "http://localhost:10001",
|
|
23
21
|
COOKIE_DOMAIN: arg === "enable" ? ".local.com" : "",
|
|
24
22
|
PLATFORM_URL:
|
|
25
23
|
arg === "enable" ? "http://local.com:10000" : "http://localhost:10000",
|
|
@@ -16,11 +16,6 @@ const { newid } = require("@budibase/backend-core/utils")
|
|
|
16
16
|
const { users } = require("../../../sdk")
|
|
17
17
|
const { Cookies } = require("@budibase/backend-core/constants")
|
|
18
18
|
const { events, featureFlags } = require("@budibase/backend-core")
|
|
19
|
-
const env = require("../../../environment")
|
|
20
|
-
|
|
21
|
-
function newTestApiKey() {
|
|
22
|
-
return env.ENCRYPTED_TEST_PUBLIC_API_KEY
|
|
23
|
-
}
|
|
24
19
|
|
|
25
20
|
function newApiKey() {
|
|
26
21
|
return encrypt(`${getTenantId()}${SEPARATOR}${newid()}`)
|
|
@@ -34,25 +29,15 @@ function cleanupDevInfo(info) {
|
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
exports.generateAPIKey = async ctx => {
|
|
37
|
-
let userId
|
|
38
|
-
let apiKey
|
|
39
|
-
if (env.isTest() && ctx.request.body.userId) {
|
|
40
|
-
userId = ctx.request.body.userId
|
|
41
|
-
apiKey = newTestApiKey()
|
|
42
|
-
} else {
|
|
43
|
-
userId = ctx.user._id
|
|
44
|
-
apiKey = newApiKey()
|
|
45
|
-
}
|
|
46
|
-
|
|
47
32
|
const db = getGlobalDB()
|
|
48
|
-
const id = generateDevInfoID(
|
|
33
|
+
const id = generateDevInfoID(ctx.user._id)
|
|
49
34
|
let devInfo
|
|
50
35
|
try {
|
|
51
36
|
devInfo = await db.get(id)
|
|
52
37
|
} catch (err) {
|
|
53
|
-
devInfo = { _id: id, userId }
|
|
38
|
+
devInfo = { _id: id, userId: ctx.user._id }
|
|
54
39
|
}
|
|
55
|
-
devInfo.apiKey = await
|
|
40
|
+
devInfo.apiKey = await newApiKey()
|
|
56
41
|
await db.put(devInfo)
|
|
57
42
|
ctx.body = cleanupDevInfo(devInfo)
|
|
58
43
|
}
|
|
@@ -95,16 +80,15 @@ const addSessionAttributesToUser = ctx => {
|
|
|
95
80
|
ctx.body.csrfToken = ctx.user.csrfToken
|
|
96
81
|
}
|
|
97
82
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
delete ctx.request.body.license
|
|
83
|
+
const sanitiseUserUpdate = ctx => {
|
|
84
|
+
const allowed = ["firstName", "lastName", "password", "forceResetPassword"]
|
|
85
|
+
const resp = {}
|
|
86
|
+
for (let [key, value] of Object.entries(ctx.request.body)) {
|
|
87
|
+
if (allowed.includes(key)) {
|
|
88
|
+
resp[key] = value
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return resp
|
|
108
92
|
}
|
|
109
93
|
|
|
110
94
|
exports.getSelf = async ctx => {
|
|
@@ -132,10 +116,12 @@ exports.updateSelf = async ctx => {
|
|
|
132
116
|
const db = getGlobalDB()
|
|
133
117
|
const user = await db.get(ctx.user._id)
|
|
134
118
|
let passwordChange = false
|
|
135
|
-
|
|
119
|
+
|
|
120
|
+
const userUpdateObj = sanitiseUserUpdate(ctx)
|
|
121
|
+
if (userUpdateObj.password) {
|
|
136
122
|
// changing password
|
|
137
123
|
passwordChange = true
|
|
138
|
-
|
|
124
|
+
userUpdateObj.password = await hash(userUpdateObj.password)
|
|
139
125
|
// Log all other sessions out apart from the current one
|
|
140
126
|
await platformLogout({
|
|
141
127
|
ctx,
|
|
@@ -143,14 +129,10 @@ exports.updateSelf = async ctx => {
|
|
|
143
129
|
keepActiveSession: true,
|
|
144
130
|
})
|
|
145
131
|
}
|
|
146
|
-
// don't allow sending up an ID/Rev, always use the existing one
|
|
147
|
-
delete ctx.request.body._id
|
|
148
|
-
delete ctx.request.body._rev
|
|
149
|
-
removeSessionAttributesFromUser(ctx)
|
|
150
132
|
|
|
151
133
|
const response = await db.put({
|
|
152
134
|
...user,
|
|
153
|
-
...
|
|
135
|
+
...userUpdateObj,
|
|
154
136
|
})
|
|
155
137
|
await userCache.invalidateUser(user._id)
|
|
156
138
|
ctx.body = {
|
|
@@ -159,7 +141,6 @@ exports.updateSelf = async ctx => {
|
|
|
159
141
|
}
|
|
160
142
|
|
|
161
143
|
// remove the old password from the user before sending events
|
|
162
|
-
user._rev = response.rev
|
|
163
144
|
delete user.password
|
|
164
145
|
await events.user.updated(user)
|
|
165
146
|
if (passwordChange) {
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
errors,
|
|
15
15
|
events,
|
|
16
16
|
tenancy,
|
|
17
|
-
users as usersCore,
|
|
18
17
|
} from "@budibase/backend-core"
|
|
19
18
|
import { checkAnyUserExists } from "../../../utilities/users"
|
|
20
19
|
import { groups as groupUtils } from "@budibase/pro"
|
|
@@ -148,9 +147,7 @@ export const bulkDelete = async (ctx: any) => {
|
|
|
148
147
|
}
|
|
149
148
|
|
|
150
149
|
try {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
ctx.body = response
|
|
150
|
+
ctx.body = await users.bulkDelete(userIds)
|
|
154
151
|
} catch (err) {
|
|
155
152
|
ctx.throw(err)
|
|
156
153
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
jest.mock("nodemailer")
|
|
2
|
-
import { TestConfiguration, API
|
|
2
|
+
import { TestConfiguration, API } from "../../../../tests"
|
|
3
3
|
import { events } from "@budibase/backend-core"
|
|
4
4
|
|
|
5
5
|
describe("/api/global/self", () => {
|
|
@@ -26,9 +26,6 @@ describe("/api/global/self", () => {
|
|
|
26
26
|
delete user.password
|
|
27
27
|
const res = await api.self.updateSelf(user)
|
|
28
28
|
|
|
29
|
-
const dbUser = await config.getUser(user.email)
|
|
30
|
-
user._rev = dbUser._rev
|
|
31
|
-
user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString()
|
|
32
29
|
expect(res.body._id).toBe(user._id)
|
|
33
30
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
34
31
|
expect(events.user.updated).toBeCalledWith(user)
|
|
@@ -42,9 +39,6 @@ describe("/api/global/self", () => {
|
|
|
42
39
|
user.password = "newPassword"
|
|
43
40
|
const res = await api.self.updateSelf(user)
|
|
44
41
|
|
|
45
|
-
const dbUser = await config.getUser(user.email)
|
|
46
|
-
user._rev = dbUser._rev
|
|
47
|
-
user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString()
|
|
48
42
|
delete user.password
|
|
49
43
|
expect(res.body._id).toBe(user._id)
|
|
50
44
|
expect(events.user.updated).toBeCalledTimes(1)
|
package/src/environment.ts
CHANGED
|
@@ -63,7 +63,6 @@ const env = {
|
|
|
63
63
|
// other
|
|
64
64
|
CHECKLIST_CACHE_TTL: parseIntSafe(process.env.CHECKLIST_CACHE_TTL) || 3600,
|
|
65
65
|
SESSION_UPDATE_PERIOD: process.env.SESSION_UPDATE_PERIOD,
|
|
66
|
-
ENCRYPTED_TEST_PUBLIC_API_KEY: process.env.ENCRYPTED_TEST_PUBLIC_API_KEY,
|
|
67
66
|
_set(key: any, value: any) {
|
|
68
67
|
process.env[key] = value
|
|
69
68
|
module.exports[key] = value
|
package/src/sdk/users/events.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import env from "../../environment"
|
|
2
2
|
import { events, accounts, tenancy } from "@budibase/backend-core"
|
|
3
3
|
import { User, UserRoles, CloudAccount } from "@budibase/types"
|
|
4
|
-
import { users as pro } from "@budibase/pro"
|
|
5
4
|
|
|
6
5
|
export const handleDeleteEvents = async (user: any) => {
|
|
7
6
|
await events.user.deleted(user)
|
|
@@ -52,10 +51,7 @@ const handleAppRoleEvents = async (user: any, existingUser: any) => {
|
|
|
52
51
|
await unassignAppRoleEvents(user, roles, existingRoles)
|
|
53
52
|
}
|
|
54
53
|
|
|
55
|
-
export const handleSaveEvents = async (
|
|
56
|
-
user: User,
|
|
57
|
-
existingUser: User | undefined
|
|
58
|
-
) => {
|
|
54
|
+
export const handleSaveEvents = async (user: any, existingUser: any) => {
|
|
59
55
|
const tenantId = tenancy.getTenantId()
|
|
60
56
|
let tenantAccount: CloudAccount | undefined
|
|
61
57
|
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
|
package/src/sdk/users/users.ts
CHANGED
|
@@ -1,35 +1,37 @@
|
|
|
1
1
|
import env from "../../environment"
|
|
2
|
+
import { quotas } from "@budibase/pro"
|
|
2
3
|
import * as apps from "../../utilities/appService"
|
|
3
4
|
import * as eventHelpers from "./events"
|
|
4
5
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
constants,
|
|
6
|
+
tenancy,
|
|
7
|
+
utils,
|
|
8
8
|
db as dbUtils,
|
|
9
|
+
constants,
|
|
10
|
+
cache,
|
|
11
|
+
users as usersCore,
|
|
9
12
|
deprovisioning,
|
|
10
|
-
|
|
13
|
+
sessions,
|
|
11
14
|
HTTPError,
|
|
15
|
+
accounts,
|
|
12
16
|
migrations,
|
|
13
|
-
|
|
14
|
-
tenancy,
|
|
15
|
-
users as usersCore,
|
|
16
|
-
utils,
|
|
17
|
+
StaticDatabases,
|
|
17
18
|
ViewName,
|
|
19
|
+
events,
|
|
18
20
|
} from "@budibase/backend-core"
|
|
19
21
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
MigrationType,
|
|
23
|
+
PlatformUserByEmail,
|
|
24
|
+
User,
|
|
22
25
|
BulkCreateUsersResponse,
|
|
26
|
+
CreateUserResponse,
|
|
23
27
|
BulkDeleteUsersResponse,
|
|
24
|
-
BulkDocsResponse,
|
|
25
28
|
CloudAccount,
|
|
26
|
-
|
|
29
|
+
AllDocsResponse,
|
|
30
|
+
RowResponse,
|
|
31
|
+
BulkDocsResponse,
|
|
32
|
+
AccountMetadata,
|
|
27
33
|
InviteUsersRequest,
|
|
28
34
|
InviteUsersResponse,
|
|
29
|
-
MigrationType,
|
|
30
|
-
PlatformUserByEmail,
|
|
31
|
-
RowResponse,
|
|
32
|
-
User,
|
|
33
35
|
} from "@budibase/types"
|
|
34
36
|
import { groups as groupUtils } from "@budibase/pro"
|
|
35
37
|
import { sendEmail } from "../../utilities/email"
|
|
@@ -118,7 +120,7 @@ interface SaveUserOpts {
|
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
const buildUser = async (
|
|
121
|
-
user:
|
|
123
|
+
user: any,
|
|
122
124
|
opts: SaveUserOpts = {
|
|
123
125
|
hashPassword: true,
|
|
124
126
|
requirePassword: true,
|
|
@@ -228,7 +230,16 @@ export const save = async (
|
|
|
228
230
|
|
|
229
231
|
try {
|
|
230
232
|
// save the user to db
|
|
231
|
-
let response
|
|
233
|
+
let response
|
|
234
|
+
const putUserFn = () => {
|
|
235
|
+
return db.put(builtUser)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (eventHelpers.isAddingBuilder(builtUser, dbUser)) {
|
|
239
|
+
response = await quotas.addDeveloper(putUserFn)
|
|
240
|
+
} else {
|
|
241
|
+
response = await putUserFn()
|
|
242
|
+
}
|
|
232
243
|
builtUser._rev = response.rev
|
|
233
244
|
|
|
234
245
|
await eventHelpers.handleSaveEvents(builtUser, dbUser)
|
|
@@ -377,8 +388,13 @@ export const bulkCreate = async (
|
|
|
377
388
|
newUsers.push(newUser)
|
|
378
389
|
}
|
|
379
390
|
|
|
380
|
-
//
|
|
391
|
+
// Figure out how many builders we are adding and create the promises
|
|
392
|
+
// array that will be called by bulkDocs
|
|
393
|
+
let builderCount = 0
|
|
381
394
|
newUsers.forEach((user: any) => {
|
|
395
|
+
if (eventHelpers.isAddingBuilder(user, null)) {
|
|
396
|
+
builderCount++
|
|
397
|
+
}
|
|
382
398
|
usersToSave.push(
|
|
383
399
|
buildUser(
|
|
384
400
|
user,
|
|
@@ -392,14 +408,14 @@ export const bulkCreate = async (
|
|
|
392
408
|
})
|
|
393
409
|
|
|
394
410
|
const usersToBulkSave = await Promise.all(usersToSave)
|
|
395
|
-
await db.bulkDocs(usersToBulkSave)
|
|
411
|
+
await quotas.addDevelopers(() => db.bulkDocs(usersToBulkSave), builderCount)
|
|
396
412
|
|
|
397
413
|
// Post processing of bulk added users, i.e events and cache operations
|
|
398
414
|
for (const user of usersToBulkSave) {
|
|
399
415
|
// TODO: Refactor to bulk insert users into the info db
|
|
400
416
|
// instead of relying on looping tenant creation
|
|
401
417
|
await addTenant(tenantId, user._id, user.email)
|
|
402
|
-
await eventHelpers.handleSaveEvents(user,
|
|
418
|
+
await eventHelpers.handleSaveEvents(user, null)
|
|
403
419
|
await apps.syncUserInApps(user._id)
|
|
404
420
|
}
|
|
405
421
|
|
|
@@ -459,6 +475,8 @@ export const bulkDelete = async (
|
|
|
459
475
|
}
|
|
460
476
|
|
|
461
477
|
let groupsToModify: any = {}
|
|
478
|
+
let builderCount = 0
|
|
479
|
+
|
|
462
480
|
// Get users and delete
|
|
463
481
|
const allDocsResponse: AllDocsResponse<User> = await db.allDocs({
|
|
464
482
|
include_docs: true,
|
|
@@ -479,6 +497,11 @@ export const bulkDelete = async (
|
|
|
479
497
|
}
|
|
480
498
|
}
|
|
481
499
|
|
|
500
|
+
// Also figure out how many builders are being deleted
|
|
501
|
+
if (eventHelpers.isAddingBuilder(user.doc, null)) {
|
|
502
|
+
builderCount++
|
|
503
|
+
}
|
|
504
|
+
|
|
482
505
|
return user.doc
|
|
483
506
|
}
|
|
484
507
|
)
|
|
@@ -496,6 +519,7 @@ export const bulkDelete = async (
|
|
|
496
519
|
for (let user of usersToDelete) {
|
|
497
520
|
await bulkDeleteProcessing(user)
|
|
498
521
|
}
|
|
522
|
+
await quotas.removeDevelopers(builderCount)
|
|
499
523
|
|
|
500
524
|
// Build Response
|
|
501
525
|
// index users by id
|
|
@@ -550,6 +574,7 @@ export const destroy = async (id: string, currentUser: any) => {
|
|
|
550
574
|
}
|
|
551
575
|
|
|
552
576
|
await eventHelpers.handleDeleteEvents(dbUser)
|
|
577
|
+
await quotas.removeUser(dbUser)
|
|
553
578
|
await cache.user.invalidateUser(userId)
|
|
554
579
|
await sessions.invalidateSessions(userId, { reason: "deletion" })
|
|
555
580
|
// let server know to sync user
|
package/src/tests/api/users.ts
CHANGED
|
@@ -2,9 +2,10 @@ import {
|
|
|
2
2
|
BulkCreateUsersRequest,
|
|
3
3
|
BulkCreateUsersResponse,
|
|
4
4
|
BulkDeleteUsersRequest,
|
|
5
|
-
|
|
5
|
+
CreateUserResponse,
|
|
6
6
|
InviteUsersRequest,
|
|
7
7
|
User,
|
|
8
|
+
UserDetails,
|
|
8
9
|
} from "@budibase/types"
|
|
9
10
|
import TestConfiguration from "../TestConfiguration"
|
|
10
11
|
|