@budibase/worker 2.8.29-alpha.1 → 2.8.29-alpha.11
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/jest.config.ts +0 -2
- package/package.json +12 -13
- package/src/api/controllers/global/auth.ts +5 -5
- package/src/api/controllers/global/roles.ts +6 -6
- package/src/api/controllers/global/self.ts +3 -3
- package/src/api/controllers/global/users.ts +13 -13
- package/src/api/routes/global/tests/appBuilder.spec.ts +62 -0
- package/src/api/routes/global/tests/auth.spec.ts +3 -3
- package/src/api/routes/global/tests/scim.spec.ts +2 -2
- package/src/api/routes/global/tests/self.spec.ts +2 -2
- package/src/api/routes/global/tests/users.spec.ts +2 -2
- package/src/api/routes/index.ts +1 -0
- package/src/api/routes/system/tests/status.spec.ts +7 -4
- package/src/environment.ts +5 -1
- package/src/initPro.ts +1 -8
- package/src/migrations/functions/globalInfoSyncUsers.ts +1 -1
- package/src/sdk/auth/auth.ts +8 -9
- package/src/sdk/users/index.ts +5 -0
- package/src/sdk/users/tests/users.spec.ts +8 -8
- package/src/sdk/users/users.ts +7 -590
- package/src/tests/TestConfiguration.ts +4 -4
- package/src/tests/api/users.ts +20 -0
- package/src/tests/mocks/index.ts +1 -1
- package/tsconfig.json +2 -4
- package/src/sdk/users/events.ts +0 -176
package/jest.config.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Config } from "@jest/types"
|
|
2
2
|
import * as fs from "fs"
|
|
3
|
-
const preset = require("ts-jest/jest-preset")
|
|
4
3
|
|
|
5
4
|
const config: Config.InitialOptions = {
|
|
6
|
-
...preset,
|
|
7
5
|
preset: "@trendyol/jest-testcontainers",
|
|
8
6
|
setupFiles: ["./src/tests/jestEnv.ts"],
|
|
9
7
|
setupFilesAfterEnv: ["./src/tests/jestSetup.ts"],
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/worker",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "2.8.29-alpha.
|
|
4
|
+
"version": "2.8.29-alpha.11",
|
|
5
5
|
"description": "Budibase background service",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"prebuild": "rimraf dist/",
|
|
16
16
|
"build": "node ../../scripts/build.js",
|
|
17
|
-
"check:types": "tsc -p tsconfig.
|
|
17
|
+
"check:types": "tsc -p tsconfig.json --noEmit --paths null",
|
|
18
18
|
"build:dev": "yarn prebuild && tsc --build --watch --preserveWatchOutput",
|
|
19
19
|
"run:docker": "node dist/index.js",
|
|
20
20
|
"debug": "yarn build && node --expose-gc --inspect=9223 dist/index.js",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"author": "Budibase",
|
|
39
39
|
"license": "GPL-3.0",
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@budibase/backend-core": "2.8.29-alpha.
|
|
42
|
-
"@budibase/pro": "2.8.29-alpha.
|
|
43
|
-
"@budibase/string-templates": "2.8.29-alpha.
|
|
44
|
-
"@budibase/types": "2.8.29-alpha.
|
|
41
|
+
"@budibase/backend-core": "2.8.29-alpha.11",
|
|
42
|
+
"@budibase/pro": "2.8.29-alpha.11",
|
|
43
|
+
"@budibase/string-templates": "2.8.29-alpha.11",
|
|
44
|
+
"@budibase/types": "2.8.29-alpha.11",
|
|
45
45
|
"@koa/router": "8.0.8",
|
|
46
46
|
"@sentry/node": "6.17.7",
|
|
47
47
|
"@techpass/passport-openidconnect": "0.3.2",
|
|
@@ -74,10 +74,10 @@
|
|
|
74
74
|
"server-destroy": "1.0.1"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@swc/core": "
|
|
78
|
-
"@swc/jest": "
|
|
79
|
-
"@trendyol/jest-testcontainers": "
|
|
80
|
-
"@types/jest": "
|
|
77
|
+
"@swc/core": "1.3.71",
|
|
78
|
+
"@swc/jest": "0.2.27",
|
|
79
|
+
"@trendyol/jest-testcontainers": "2.1.1",
|
|
80
|
+
"@types/jest": "29.5.3",
|
|
81
81
|
"@types/jsonwebtoken": "8.5.1",
|
|
82
82
|
"@types/koa": "2.13.4",
|
|
83
83
|
"@types/koa__router": "8.0.8",
|
|
@@ -91,14 +91,13 @@
|
|
|
91
91
|
"@typescript-eslint/parser": "5.45.0",
|
|
92
92
|
"copyfiles": "2.4.1",
|
|
93
93
|
"eslint": "6.8.0",
|
|
94
|
-
"jest": "
|
|
94
|
+
"jest": "29.6.2",
|
|
95
95
|
"lodash": "4.17.21",
|
|
96
96
|
"nodemon": "2.0.15",
|
|
97
97
|
"pouchdb-adapter-memory": "7.2.2",
|
|
98
98
|
"rimraf": "3.0.2",
|
|
99
99
|
"supertest": "6.2.2",
|
|
100
100
|
"timekeeper": "2.2.0",
|
|
101
|
-
"ts-jest": "28.0.4",
|
|
102
101
|
"ts-node": "10.8.1",
|
|
103
102
|
"tsconfig-paths": "4.0.0",
|
|
104
103
|
"typescript": "4.7.3",
|
|
@@ -118,5 +117,5 @@
|
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
119
|
},
|
|
121
|
-
"gitHead": "
|
|
120
|
+
"gitHead": "30ebf0d274c93fd68ee316ce7a7b514609d69205"
|
|
122
121
|
}
|
|
@@ -55,8 +55,8 @@ async function passportCallback(
|
|
|
55
55
|
export const login = async (ctx: Ctx<LoginRequest>, next: any) => {
|
|
56
56
|
const email = ctx.request.body.username
|
|
57
57
|
|
|
58
|
-
const user = await userSdk.getUserByEmail(email)
|
|
59
|
-
if (user && (await userSdk.isPreventPasswordActions(user))) {
|
|
58
|
+
const user = await userSdk.db.getUserByEmail(email)
|
|
59
|
+
if (user && (await userSdk.db.isPreventPasswordActions(user))) {
|
|
60
60
|
ctx.throw(403, "Invalid credentials")
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -174,7 +174,7 @@ export const googlePreAuth = async (ctx: any, next: any) => {
|
|
|
174
174
|
const strategy = await google.strategyFactory(
|
|
175
175
|
config,
|
|
176
176
|
callbackUrl,
|
|
177
|
-
userSdk.save
|
|
177
|
+
userSdk.db.save
|
|
178
178
|
)
|
|
179
179
|
|
|
180
180
|
return passport.authenticate(strategy, {
|
|
@@ -193,7 +193,7 @@ export const googleCallback = async (ctx: any, next: any) => {
|
|
|
193
193
|
const strategy = await google.strategyFactory(
|
|
194
194
|
config,
|
|
195
195
|
callbackUrl,
|
|
196
|
-
userSdk.save
|
|
196
|
+
userSdk.db.save
|
|
197
197
|
)
|
|
198
198
|
|
|
199
199
|
return passport.authenticate(
|
|
@@ -228,7 +228,7 @@ export const oidcStrategyFactory = async (ctx: any, configId: any) => {
|
|
|
228
228
|
|
|
229
229
|
//Remote Config
|
|
230
230
|
const enrichedConfig = await oidc.fetchStrategyConfig(config, callbackUrl)
|
|
231
|
-
return oidc.strategyFactory(enrichedConfig, userSdk.save)
|
|
231
|
+
return oidc.strategyFactory(enrichedConfig, userSdk.db.save)
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
/**
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
cache,
|
|
6
6
|
tenancy,
|
|
7
7
|
} from "@budibase/backend-core"
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
8
|
+
import sdk from "../../../sdk"
|
|
9
|
+
import { Ctx, App } from "@budibase/types"
|
|
10
10
|
|
|
11
|
-
export async function fetch(ctx:
|
|
11
|
+
export async function fetch(ctx: Ctx) {
|
|
12
12
|
const tenantId = ctx.user!.tenantId
|
|
13
13
|
// always use the dev apps as they'll be most up to date (true)
|
|
14
14
|
const apps = (await dbCore.getAllApps({ tenantId, all: true })) as App[]
|
|
@@ -31,7 +31,7 @@ export async function fetch(ctx: BBContext) {
|
|
|
31
31
|
ctx.body = response
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export async function find(ctx:
|
|
34
|
+
export async function find(ctx: Ctx) {
|
|
35
35
|
const appId = ctx.params.appId
|
|
36
36
|
await context.doInAppContext(dbCore.getDevAppID(appId), async () => {
|
|
37
37
|
const db = context.getAppDB()
|
|
@@ -45,10 +45,10 @@ export async function find(ctx: BBContext) {
|
|
|
45
45
|
})
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export async function removeAppRole(ctx:
|
|
48
|
+
export async function removeAppRole(ctx: Ctx) {
|
|
49
49
|
const { appId } = ctx.params
|
|
50
50
|
const db = tenancy.getGlobalDB()
|
|
51
|
-
const users = await allUsers()
|
|
51
|
+
const users = await sdk.users.db.allUsers()
|
|
52
52
|
const bulk = []
|
|
53
53
|
const cacheInvalidations = []
|
|
54
54
|
for (let user of users) {
|
|
@@ -91,7 +91,7 @@ export async function getSelf(ctx: any) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// get the main body of the user
|
|
94
|
-
const user = await userSdk.getUser(userId)
|
|
94
|
+
const user = await userSdk.db.getUser(userId)
|
|
95
95
|
ctx.body = await groups.enrichUserRolesFromGroups(user)
|
|
96
96
|
|
|
97
97
|
// add the feature flags for this tenant
|
|
@@ -106,12 +106,12 @@ export async function updateSelf(
|
|
|
106
106
|
) {
|
|
107
107
|
const update = ctx.request.body
|
|
108
108
|
|
|
109
|
-
let user = await userSdk.getUser(ctx.user._id!)
|
|
109
|
+
let user = await userSdk.db.getUser(ctx.user._id!)
|
|
110
110
|
user = {
|
|
111
111
|
...user,
|
|
112
112
|
...update,
|
|
113
113
|
}
|
|
114
|
-
user = await userSdk.save(user, { requirePassword: false })
|
|
114
|
+
user = await userSdk.db.save(user, { requirePassword: false })
|
|
115
115
|
|
|
116
116
|
if (update.password) {
|
|
117
117
|
// Log all other sessions out apart from the current one
|
|
@@ -41,7 +41,7 @@ export const save = async (ctx: UserCtx<User, SaveUserResponse>) => {
|
|
|
41
41
|
const currentUserId = ctx.user?._id
|
|
42
42
|
const requestUser = ctx.request.body
|
|
43
43
|
|
|
44
|
-
const user = await userSdk.save(requestUser, { currentUserId })
|
|
44
|
+
const user = await userSdk.db.save(requestUser, { currentUserId })
|
|
45
45
|
|
|
46
46
|
ctx.body = {
|
|
47
47
|
_id: user._id!,
|
|
@@ -57,7 +57,7 @@ const bulkDelete = async (userIds: string[], currentUserId: string) => {
|
|
|
57
57
|
if (userIds?.indexOf(currentUserId) !== -1) {
|
|
58
58
|
throw new Error("Unable to delete self.")
|
|
59
59
|
}
|
|
60
|
-
return await userSdk.bulkDelete(userIds)
|
|
60
|
+
return await userSdk.db.bulkDelete(userIds)
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const bulkCreate = async (users: User[], groupIds: string[]) => {
|
|
@@ -66,7 +66,7 @@ const bulkCreate = async (users: User[], groupIds: string[]) => {
|
|
|
66
66
|
"Max limit for upload is 1000 users. Please reduce file size and try again."
|
|
67
67
|
)
|
|
68
68
|
}
|
|
69
|
-
return await userSdk.bulkCreate(users, groupIds)
|
|
69
|
+
return await userSdk.db.bulkCreate(users, groupIds)
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export const bulkUpdate = async (
|
|
@@ -141,7 +141,7 @@ export const adminUser = async (
|
|
|
141
141
|
// always bust checklist beforehand, if an error occurs but can proceed, don't get
|
|
142
142
|
// stuck in a cycle
|
|
143
143
|
await cache.bustCache(cache.CacheKey.CHECKLIST)
|
|
144
|
-
const finalUser = await userSdk.save(user, {
|
|
144
|
+
const finalUser = await userSdk.db.save(user, {
|
|
145
145
|
hashPassword,
|
|
146
146
|
requirePassword,
|
|
147
147
|
})
|
|
@@ -167,7 +167,7 @@ export const adminUser = async (
|
|
|
167
167
|
export const countByApp = async (ctx: any) => {
|
|
168
168
|
const appId = ctx.params.appId
|
|
169
169
|
try {
|
|
170
|
-
ctx.body = await userSdk.countUsersByApp(appId)
|
|
170
|
+
ctx.body = await userSdk.db.countUsersByApp(appId)
|
|
171
171
|
} catch (err: any) {
|
|
172
172
|
ctx.throw(err.status || 400, err)
|
|
173
173
|
}
|
|
@@ -179,7 +179,7 @@ export const destroy = async (ctx: any) => {
|
|
|
179
179
|
ctx.throw(400, "Unable to delete self.")
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
await userSdk.destroy(id)
|
|
182
|
+
await userSdk.db.destroy(id)
|
|
183
183
|
|
|
184
184
|
ctx.body = {
|
|
185
185
|
message: `User ${id} deleted.`,
|
|
@@ -188,7 +188,7 @@ export const destroy = async (ctx: any) => {
|
|
|
188
188
|
|
|
189
189
|
export const getAppUsers = async (ctx: Ctx<SearchUsersRequest>) => {
|
|
190
190
|
const body = ctx.request.body
|
|
191
|
-
const users = await userSdk.getUsersByAppAccess(body?.appId)
|
|
191
|
+
const users = await userSdk.db.getUsersByAppAccess(body?.appId)
|
|
192
192
|
|
|
193
193
|
ctx.body = { data: users }
|
|
194
194
|
}
|
|
@@ -212,7 +212,7 @@ export const search = async (ctx: Ctx<SearchUsersRequest>) => {
|
|
|
212
212
|
|
|
213
213
|
// called internally by app server user fetch
|
|
214
214
|
export const fetch = async (ctx: any) => {
|
|
215
|
-
const all = await userSdk.allUsers()
|
|
215
|
+
const all = await userSdk.db.allUsers()
|
|
216
216
|
// user hashed password shouldn't ever be returned
|
|
217
217
|
for (let user of all) {
|
|
218
218
|
if (user) {
|
|
@@ -224,12 +224,12 @@ export const fetch = async (ctx: any) => {
|
|
|
224
224
|
|
|
225
225
|
// called internally by app server user find
|
|
226
226
|
export const find = async (ctx: any) => {
|
|
227
|
-
ctx.body = await userSdk.getUser(ctx.params.id)
|
|
227
|
+
ctx.body = await userSdk.db.getUser(ctx.params.id)
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
export const tenantUserLookup = async (ctx: any) => {
|
|
231
231
|
const id = ctx.params.id
|
|
232
|
-
const user = await userSdk.getPlatformUser(id)
|
|
232
|
+
const user = await userSdk.core.getPlatformUser(id)
|
|
233
233
|
if (user) {
|
|
234
234
|
ctx.body = user
|
|
235
235
|
} else {
|
|
@@ -252,7 +252,7 @@ export const onboardUsers = async (ctx: Ctx<InviteUsersRequest>) => {
|
|
|
252
252
|
// @ts-ignore
|
|
253
253
|
const { users, groups, roles } = request.create
|
|
254
254
|
const assignUsers = users.map((user: User) => (user.roles = roles))
|
|
255
|
-
onboardingResponse = await userSdk.bulkCreate(assignUsers, groups)
|
|
255
|
+
onboardingResponse = await userSdk.db.bulkCreate(assignUsers, groups)
|
|
256
256
|
ctx.body = onboardingResponse
|
|
257
257
|
} else if (emailConfigured) {
|
|
258
258
|
onboardingResponse = await inviteMultiple(ctx)
|
|
@@ -277,7 +277,7 @@ export const onboardUsers = async (ctx: Ctx<InviteUsersRequest>) => {
|
|
|
277
277
|
tenantId: tenancy.getTenantId(),
|
|
278
278
|
}
|
|
279
279
|
})
|
|
280
|
-
let bulkCreateReponse = await userSdk.bulkCreate(users, [])
|
|
280
|
+
let bulkCreateReponse = await userSdk.db.bulkCreate(users, [])
|
|
281
281
|
|
|
282
282
|
// Apply temporary credentials
|
|
283
283
|
let createWithCredentials = {
|
|
@@ -410,7 +410,7 @@ export const inviteAccept = async (
|
|
|
410
410
|
...info,
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
const saved = await userSdk.save(request)
|
|
413
|
+
const saved = await userSdk.db.save(request)
|
|
414
414
|
const db = tenancy.getGlobalDB()
|
|
415
415
|
const user = await db.get<User>(saved._id)
|
|
416
416
|
await events.user.inviteAccepted(user)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { TestConfiguration, structures } from "../../../../tests"
|
|
2
|
+
import { mocks } from "@budibase/backend-core/tests"
|
|
3
|
+
import { User } from "@budibase/types"
|
|
4
|
+
|
|
5
|
+
const MOCK_APP_ID = "app_a"
|
|
6
|
+
|
|
7
|
+
describe("/api/global/users/:userId/app/builder", () => {
|
|
8
|
+
const config = new TestConfiguration()
|
|
9
|
+
|
|
10
|
+
beforeAll(async () => {
|
|
11
|
+
await config.beforeAll()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
afterAll(async () => {
|
|
15
|
+
await config.afterAll()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
async function newUser() {
|
|
19
|
+
const base = structures.users.user()
|
|
20
|
+
return await config.createUser(base)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function getUser(userId: string) {
|
|
24
|
+
const response = await config.api.users.getUser(userId)
|
|
25
|
+
return response.body as User
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe("Confirm pro license", () => {
|
|
29
|
+
it("should 400 with licensing", async () => {
|
|
30
|
+
const user = await newUser()
|
|
31
|
+
const resp = await config.api.users.grantBuilderToApp(
|
|
32
|
+
user._id!,
|
|
33
|
+
MOCK_APP_ID,
|
|
34
|
+
400
|
|
35
|
+
)
|
|
36
|
+
expect(resp.body.message).toContain("Feature not enabled")
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
describe("PATCH /api/global/users/:userId/app/:appId/builder", () => {
|
|
41
|
+
it("should be able to grant a user access to a particular app", async () => {
|
|
42
|
+
mocks.licenses.useAppBuilders()
|
|
43
|
+
const user = await newUser()
|
|
44
|
+
await config.api.users.grantBuilderToApp(user._id!, MOCK_APP_ID)
|
|
45
|
+
const updated = await getUser(user._id!)
|
|
46
|
+
expect(updated.builder?.apps![0]).toBe(MOCK_APP_ID)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
describe("DELETE /api/global/users/:userId/app/:appId/builder", () => {
|
|
51
|
+
it("should allow revoking access", async () => {
|
|
52
|
+
mocks.licenses.useAppBuilders()
|
|
53
|
+
const user = await newUser()
|
|
54
|
+
await config.api.users.grantBuilderToApp(user._id!, MOCK_APP_ID)
|
|
55
|
+
let updated = await getUser(user._id!)
|
|
56
|
+
expect(updated.builder?.apps![0]).toBe(MOCK_APP_ID)
|
|
57
|
+
await config.api.users.revokeBuilderFromApp(user._id!, MOCK_APP_ID)
|
|
58
|
+
updated = await getUser(user._id!)
|
|
59
|
+
expect(updated.builder?.apps!.length).toBe(0)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
})
|
|
@@ -41,7 +41,7 @@ describe("/api/global/auth", () => {
|
|
|
41
41
|
|
|
42
42
|
async function createSSOUser() {
|
|
43
43
|
return config.doInTenant(async () => {
|
|
44
|
-
return userSdk.save(structures.users.ssoUser(), {
|
|
44
|
+
return userSdk.db.save(structures.users.ssoUser(), {
|
|
45
45
|
requirePassword: false,
|
|
46
46
|
})
|
|
47
47
|
})
|
|
@@ -206,7 +206,7 @@ describe("/api/global/auth", () => {
|
|
|
206
206
|
const newPassword = "newpassword"
|
|
207
207
|
const res = await config.api.auth.updatePassword(code!, newPassword)
|
|
208
208
|
|
|
209
|
-
user = await config.getUser(user.email)
|
|
209
|
+
user = (await config.getUser(user.email))!
|
|
210
210
|
delete user.password
|
|
211
211
|
|
|
212
212
|
expect(res.body).toEqual({ message: "password reset successfully." })
|
|
@@ -245,7 +245,7 @@ describe("/api/global/auth", () => {
|
|
|
245
245
|
const ssoUser = user as SSOUser
|
|
246
246
|
ssoUser.providerType = structures.sso.providerType()
|
|
247
247
|
delete ssoUser.password
|
|
248
|
-
await config.doInTenant(() => userSdk.save(ssoUser))
|
|
248
|
+
await config.doInTenant(() => userSdk.db.save(ssoUser))
|
|
249
249
|
|
|
250
250
|
await testSSOUser(code!)
|
|
251
251
|
})
|
|
@@ -314,7 +314,7 @@ describe("scim", () => {
|
|
|
314
314
|
|
|
315
315
|
const user = await config.getUser(email)
|
|
316
316
|
expect(user).toBeDefined()
|
|
317
|
-
expect(user
|
|
317
|
+
expect(user!.email).toEqual(email)
|
|
318
318
|
})
|
|
319
319
|
|
|
320
320
|
it("if multiple emails are provided, the first primary one is used as email", async () => {
|
|
@@ -345,7 +345,7 @@ describe("scim", () => {
|
|
|
345
345
|
|
|
346
346
|
const user = await config.getUser(email)
|
|
347
347
|
expect(user).toBeDefined()
|
|
348
|
-
expect(user
|
|
348
|
+
expect(user!.email).toEqual(email)
|
|
349
349
|
})
|
|
350
350
|
|
|
351
351
|
it("if no email is provided and the user name is not an email, an exception is thrown", async () => {
|
|
@@ -36,7 +36,7 @@ describe("/api/global/self", () => {
|
|
|
36
36
|
})
|
|
37
37
|
.expect(200)
|
|
38
38
|
|
|
39
|
-
const dbUser = await config.getUser(user.email)
|
|
39
|
+
const dbUser = (await config.getUser(user.email))!
|
|
40
40
|
|
|
41
41
|
user._rev = dbUser._rev
|
|
42
42
|
user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString()
|
|
@@ -58,7 +58,7 @@ describe("/api/global/self", () => {
|
|
|
58
58
|
})
|
|
59
59
|
.expect(200)
|
|
60
60
|
|
|
61
|
-
const dbUser = await config.getUser(user.email)
|
|
61
|
+
const dbUser = (await config.getUser(user.email))!
|
|
62
62
|
|
|
63
63
|
user._rev = dbUser._rev
|
|
64
64
|
user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString()
|
|
@@ -66,7 +66,7 @@ describe("/api/global/users", () => {
|
|
|
66
66
|
expect(res.body._id).toBeDefined()
|
|
67
67
|
const user = await config.getUser(email)
|
|
68
68
|
expect(user).toBeDefined()
|
|
69
|
-
expect(user
|
|
69
|
+
expect(user!._id).toEqual(res.body._id)
|
|
70
70
|
expect(events.user.inviteAccepted).toBeCalledTimes(1)
|
|
71
71
|
expect(events.user.inviteAccepted).toBeCalledWith(user)
|
|
72
72
|
})
|
|
@@ -480,7 +480,7 @@ describe("/api/global/users", () => {
|
|
|
480
480
|
function createSSOUser() {
|
|
481
481
|
return config.doInTenant(() => {
|
|
482
482
|
const user = structures.users.ssoUser()
|
|
483
|
-
return userSdk.save(user, { requirePassword: false })
|
|
483
|
+
return userSdk.db.save(user, { requirePassword: false })
|
|
484
484
|
})
|
|
485
485
|
}
|
|
486
486
|
|
package/src/api/routes/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HealthStatusResponse } from "@budibase/types"
|
|
1
2
|
import { TestConfiguration } from "../../../../tests"
|
|
2
3
|
import { accounts as _accounts } from "@budibase/backend-core"
|
|
3
4
|
const accounts = jest.mocked(_accounts)
|
|
@@ -31,13 +32,15 @@ describe("/api/system/status", () => {
|
|
|
31
32
|
})
|
|
32
33
|
|
|
33
34
|
it("returns status in cloud", async () => {
|
|
34
|
-
const value = {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const value: HealthStatusResponse = {
|
|
36
|
+
passing: false,
|
|
37
|
+
checks: {
|
|
38
|
+
login: false,
|
|
39
|
+
search: false,
|
|
37
40
|
},
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
accounts.getStatus.
|
|
43
|
+
accounts.getStatus.mockResolvedValue(value)
|
|
41
44
|
|
|
42
45
|
const res = await config.api.status.getStatus()
|
|
43
46
|
|
package/src/environment.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { env as coreEnv } from "@budibase/backend-core"
|
|
2
|
+
import { ServiceType } from "@budibase/types"
|
|
3
|
+
import { join } from "path"
|
|
4
|
+
|
|
5
|
+
coreEnv._set("SERVICE_TYPE", ServiceType.WORKER)
|
|
2
6
|
|
|
3
7
|
function isDev() {
|
|
4
8
|
return process.env.NODE_ENV !== "production"
|
package/src/initPro.ts
CHANGED
|
@@ -2,12 +2,5 @@ import { sdk as proSdk } from "@budibase/pro"
|
|
|
2
2
|
import * as userSdk from "./sdk/users"
|
|
3
3
|
|
|
4
4
|
export const initPro = async () => {
|
|
5
|
-
await proSdk.init({
|
|
6
|
-
scimUserServiceConfig: {
|
|
7
|
-
functions: {
|
|
8
|
-
saveUser: userSdk.save,
|
|
9
|
-
removeUser: (id: string) => userSdk.destroy(id),
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
})
|
|
5
|
+
await proSdk.init({})
|
|
13
6
|
}
|
|
@@ -10,7 +10,7 @@ import { platform } from "@budibase/backend-core"
|
|
|
10
10
|
* Re-sync the global-db users to the global-info db users
|
|
11
11
|
*/
|
|
12
12
|
export const run = async (globalDb: any) => {
|
|
13
|
-
const users = (await usersSdk.allUsers()) as User[]
|
|
13
|
+
const users = (await usersSdk.db.allUsers()) as User[]
|
|
14
14
|
const promises = []
|
|
15
15
|
for (let user of users) {
|
|
16
16
|
promises.push(
|
package/src/sdk/auth/auth.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
auth as authCore,
|
|
3
|
-
|
|
4
|
-
utils as coreUtils,
|
|
5
|
-
sessions,
|
|
3
|
+
env as coreEnv,
|
|
6
4
|
events,
|
|
7
5
|
HTTPError,
|
|
8
|
-
|
|
6
|
+
sessions,
|
|
7
|
+
tenancy,
|
|
8
|
+
utils as coreUtils,
|
|
9
9
|
} from "@budibase/backend-core"
|
|
10
10
|
import { PlatformLogoutOpts, User } from "@budibase/types"
|
|
11
11
|
import jwt from "jsonwebtoken"
|
|
@@ -20,7 +20,7 @@ export async function loginUser(user: User) {
|
|
|
20
20
|
const sessionId = coreUtils.newid()
|
|
21
21
|
const tenantId = tenancy.getTenantId()
|
|
22
22
|
await sessions.createASession(user._id!, { sessionId, tenantId })
|
|
23
|
-
|
|
23
|
+
return jwt.sign(
|
|
24
24
|
{
|
|
25
25
|
userId: user._id,
|
|
26
26
|
sessionId,
|
|
@@ -28,7 +28,6 @@ export async function loginUser(user: User) {
|
|
|
28
28
|
},
|
|
29
29
|
coreEnv.JWT_SECRET!
|
|
30
30
|
)
|
|
31
|
-
return token
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export async function logout(opts: PlatformLogoutOpts) {
|
|
@@ -58,7 +57,7 @@ export const reset = async (email: string) => {
|
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
// exit if user has sso
|
|
61
|
-
if (await userSdk.isPreventPasswordActions(user)) {
|
|
60
|
+
if (await userSdk.db.isPreventPasswordActions(user)) {
|
|
62
61
|
return
|
|
63
62
|
}
|
|
64
63
|
|
|
@@ -76,9 +75,9 @@ export const reset = async (email: string) => {
|
|
|
76
75
|
export const resetUpdate = async (resetCode: string, password: string) => {
|
|
77
76
|
const { userId } = await redis.checkResetPasswordCode(resetCode)
|
|
78
77
|
|
|
79
|
-
let user = await userSdk.getUser(userId)
|
|
78
|
+
let user = await userSdk.db.getUser(userId)
|
|
80
79
|
user.password = password
|
|
81
|
-
user = await userSdk.save(user)
|
|
80
|
+
user = await userSdk.db.save(user)
|
|
82
81
|
|
|
83
82
|
// remove password from the user before sending events
|
|
84
83
|
delete user.password
|
package/src/sdk/users/index.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export * from "./users"
|
|
2
|
+
import { users } from "@budibase/backend-core"
|
|
3
|
+
import * as pro from "@budibase/pro"
|
|
4
|
+
// pass in the components which are specific to the worker/the parts of pro which backend-core cannot access
|
|
5
|
+
users.UserDB.init(pro.quotas, pro.groups, pro.features)
|
|
6
|
+
export const db = users.UserDB
|
|
2
7
|
export { users as core } from "@budibase/backend-core"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { structures, mocks } from "../../../tests"
|
|
2
2
|
import { env, context } from "@budibase/backend-core"
|
|
3
3
|
import * as users from "../users"
|
|
4
|
+
import { db as userDb } from "../"
|
|
4
5
|
import { CloudAccount } from "@budibase/types"
|
|
5
|
-
import { isPreventPasswordActions } from "../users"
|
|
6
6
|
|
|
7
7
|
describe("users", () => {
|
|
8
8
|
beforeEach(() => {
|
|
@@ -13,7 +13,7 @@ describe("users", () => {
|
|
|
13
13
|
it("returns false for non sso user", async () => {
|
|
14
14
|
await context.doInTenant(structures.tenant.id(), async () => {
|
|
15
15
|
const user = structures.users.user()
|
|
16
|
-
const result = await
|
|
16
|
+
const result = await userDb.isPreventPasswordActions(user)
|
|
17
17
|
expect(result).toBe(false)
|
|
18
18
|
})
|
|
19
19
|
})
|
|
@@ -24,7 +24,7 @@ describe("users", () => {
|
|
|
24
24
|
const account = structures.accounts.ssoAccount() as CloudAccount
|
|
25
25
|
account.email = user.email
|
|
26
26
|
mocks.accounts.getAccountByTenantId.mockResolvedValueOnce(account)
|
|
27
|
-
const result = await
|
|
27
|
+
const result = await userDb.isPreventPasswordActions(user)
|
|
28
28
|
expect(result).toBe(true)
|
|
29
29
|
})
|
|
30
30
|
})
|
|
@@ -34,7 +34,7 @@ describe("users", () => {
|
|
|
34
34
|
const user = structures.users.user()
|
|
35
35
|
const account = structures.accounts.ssoAccount() as CloudAccount
|
|
36
36
|
mocks.accounts.getAccountByTenantId.mockResolvedValueOnce(account)
|
|
37
|
-
const result = await
|
|
37
|
+
const result = await userDb.isPreventPasswordActions(user)
|
|
38
38
|
expect(result).toBe(false)
|
|
39
39
|
})
|
|
40
40
|
})
|
|
@@ -42,7 +42,7 @@ describe("users", () => {
|
|
|
42
42
|
it("returns true for sso user", async () => {
|
|
43
43
|
await context.doInTenant(structures.tenant.id(), async () => {
|
|
44
44
|
const user = structures.users.ssoUser()
|
|
45
|
-
const result = await
|
|
45
|
+
const result = await userDb.isPreventPasswordActions(user)
|
|
46
46
|
expect(result).toBe(true)
|
|
47
47
|
})
|
|
48
48
|
})
|
|
@@ -52,7 +52,7 @@ describe("users", () => {
|
|
|
52
52
|
await context.doInTenant(structures.tenant.id(), async () => {
|
|
53
53
|
const user = structures.users.user()
|
|
54
54
|
mocks.pro.features.isSSOEnforced.mockResolvedValueOnce(true)
|
|
55
|
-
const result = await
|
|
55
|
+
const result = await userDb.isPreventPasswordActions(user)
|
|
56
56
|
expect(result).toBe(true)
|
|
57
57
|
})
|
|
58
58
|
})
|
|
@@ -70,7 +70,7 @@ describe("users", () => {
|
|
|
70
70
|
describe("non-admin user", () => {
|
|
71
71
|
it("returns true", async () => {
|
|
72
72
|
const user = structures.users.ssoUser()
|
|
73
|
-
const result = await
|
|
73
|
+
const result = await userDb.isPreventPasswordActions(user)
|
|
74
74
|
expect(result).toBe(true)
|
|
75
75
|
})
|
|
76
76
|
})
|
|
@@ -80,7 +80,7 @@ describe("users", () => {
|
|
|
80
80
|
const user = structures.users.ssoUser({
|
|
81
81
|
user: structures.users.adminUser(),
|
|
82
82
|
})
|
|
83
|
-
const result = await
|
|
83
|
+
const result = await userDb.isPreventPasswordActions(user)
|
|
84
84
|
expect(result).toBe(false)
|
|
85
85
|
})
|
|
86
86
|
})
|