@budibase/worker 2.22.12 → 2.22.14
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 +1 -1
- package/package.json +6 -7
- package/src/api/controllers/global/users.ts +22 -1
- package/src/api/index.ts +9 -0
- package/src/api/routes/global/tests/users.spec.ts +41 -0
- package/src/api/routes/global/users.ts +8 -1
- package/src/api/routes/validation/users.ts +9 -0
- package/src/tests/api/users.ts +14 -0
- package/src/tests/jestEnv.ts +2 -0
- package/.vscode/launch.json +0 -142
- package/jest-testcontainers-config.js +0 -8
package/jest.config.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Config } from "@jest/types"
|
|
|
2
2
|
import * as fs from "fs"
|
|
3
3
|
|
|
4
4
|
const config: Config.InitialOptions = {
|
|
5
|
-
|
|
5
|
+
globalSetup: "./../../globalSetup.ts",
|
|
6
6
|
setupFiles: ["./src/tests/jestEnv.ts"],
|
|
7
7
|
setupFilesAfterEnv: ["./src/tests/jestSetup.ts"],
|
|
8
8
|
collectCoverageFrom: ["src/**/*.{js,ts}", "../backend-core/src/**/*.{js,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.22.
|
|
4
|
+
"version": "2.22.14",
|
|
5
5
|
"description": "Budibase background service",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"author": "Budibase",
|
|
38
38
|
"license": "GPL-3.0",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@budibase/backend-core": "2.22.
|
|
41
|
-
"@budibase/pro": "2.22.
|
|
42
|
-
"@budibase/string-templates": "2.22.
|
|
43
|
-
"@budibase/types": "2.22.
|
|
40
|
+
"@budibase/backend-core": "2.22.14",
|
|
41
|
+
"@budibase/pro": "2.22.14",
|
|
42
|
+
"@budibase/string-templates": "2.22.14",
|
|
43
|
+
"@budibase/types": "2.22.14",
|
|
44
44
|
"@koa/router": "8.0.8",
|
|
45
45
|
"@techpass/passport-openidconnect": "0.3.2",
|
|
46
46
|
"@types/global-agent": "2.1.1",
|
|
@@ -75,7 +75,6 @@
|
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@swc/core": "1.3.71",
|
|
77
77
|
"@swc/jest": "0.2.27",
|
|
78
|
-
"@trendyol/jest-testcontainers": "2.1.1",
|
|
79
78
|
"@types/jest": "29.5.5",
|
|
80
79
|
"@types/jsonwebtoken": "9.0.3",
|
|
81
80
|
"@types/koa": "2.13.4",
|
|
@@ -109,5 +108,5 @@
|
|
|
109
108
|
}
|
|
110
109
|
}
|
|
111
110
|
},
|
|
112
|
-
"gitHead": "
|
|
111
|
+
"gitHead": "ed44967cf2d47b2f6dad178938af28b68d4124ee"
|
|
113
112
|
}
|
|
@@ -3,6 +3,7 @@ import env from "../../../environment"
|
|
|
3
3
|
import {
|
|
4
4
|
AcceptUserInviteRequest,
|
|
5
5
|
AcceptUserInviteResponse,
|
|
6
|
+
AddSSoUserRequest,
|
|
6
7
|
BulkUserRequest,
|
|
7
8
|
BulkUserResponse,
|
|
8
9
|
CloudAccount,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
LockName,
|
|
16
17
|
LockType,
|
|
17
18
|
MigrationType,
|
|
19
|
+
PlatformUserByEmail,
|
|
18
20
|
SaveUserResponse,
|
|
19
21
|
SearchUsersRequest,
|
|
20
22
|
User,
|
|
@@ -53,6 +55,25 @@ export const save = async (ctx: UserCtx<User, SaveUserResponse>) => {
|
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
export const addSsoSupport = async (ctx: Ctx<AddSSoUserRequest>) => {
|
|
59
|
+
const { email, ssoId } = ctx.request.body
|
|
60
|
+
try {
|
|
61
|
+
// Status is changed to 404 from getUserDoc if user is not found
|
|
62
|
+
let userByEmail = (await platform.users.getUserDoc(
|
|
63
|
+
email
|
|
64
|
+
)) as PlatformUserByEmail
|
|
65
|
+
await platform.users.addSsoUser(
|
|
66
|
+
ssoId,
|
|
67
|
+
email,
|
|
68
|
+
userByEmail.userId,
|
|
69
|
+
userByEmail.tenantId
|
|
70
|
+
)
|
|
71
|
+
ctx.status = 200
|
|
72
|
+
} catch (err: any) {
|
|
73
|
+
ctx.throw(err.status || 400, err)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
56
77
|
const bulkDelete = async (userIds: string[], currentUserId: string) => {
|
|
57
78
|
if (userIds?.indexOf(currentUserId) !== -1) {
|
|
58
79
|
throw new Error("Unable to delete self.")
|
|
@@ -127,8 +148,8 @@ export const adminUser = async (
|
|
|
127
148
|
try {
|
|
128
149
|
const finalUser = await userSdk.db.createAdminUser(
|
|
129
150
|
email,
|
|
130
|
-
password,
|
|
131
151
|
tenantId,
|
|
152
|
+
password,
|
|
132
153
|
{
|
|
133
154
|
ssoId,
|
|
134
155
|
hashPassword,
|
package/src/api/index.ts
CHANGED
|
@@ -41,6 +41,10 @@ const PUBLIC_ENDPOINTS = [
|
|
|
41
41
|
route: "/api/global/users/init",
|
|
42
42
|
method: "POST",
|
|
43
43
|
},
|
|
44
|
+
{
|
|
45
|
+
route: "/api/global/users/sso",
|
|
46
|
+
method: "POST",
|
|
47
|
+
},
|
|
44
48
|
{
|
|
45
49
|
route: "/api/global/users/invite/accept",
|
|
46
50
|
method: "POST",
|
|
@@ -81,6 +85,11 @@ const NO_TENANCY_ENDPOINTS = [
|
|
|
81
85
|
route: "/api/global/users/init",
|
|
82
86
|
method: "POST",
|
|
83
87
|
},
|
|
88
|
+
// tenant is retrieved from the user found by the requested email
|
|
89
|
+
{
|
|
90
|
+
route: "/api/global/users/sso",
|
|
91
|
+
method: "POST",
|
|
92
|
+
},
|
|
84
93
|
// deprecated single tenant sso callback
|
|
85
94
|
{
|
|
86
95
|
route: "/api/admin/auth/google/callback",
|
|
@@ -520,10 +520,51 @@ describe("/api/global/users", () => {
|
|
|
520
520
|
})
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
+
function createPasswordUser() {
|
|
524
|
+
return config.doInTenant(() => {
|
|
525
|
+
const user = structures.users.user()
|
|
526
|
+
return userSdk.db.save(user)
|
|
527
|
+
})
|
|
528
|
+
}
|
|
529
|
+
|
|
523
530
|
it("should be able to update an sso user that has no password", async () => {
|
|
524
531
|
const user = await createSSOUser()
|
|
525
532
|
await config.api.users.saveUser(user)
|
|
526
533
|
})
|
|
534
|
+
|
|
535
|
+
it("sso support couldn't be used by admin. It is cloud restricted and needs internal key", async () => {
|
|
536
|
+
const user = await config.createUser()
|
|
537
|
+
const ssoId = "fake-ssoId"
|
|
538
|
+
await config.api.users
|
|
539
|
+
.addSsoSupportDefaultAuth(ssoId, user.email)
|
|
540
|
+
.expect("Content-Type", /json/)
|
|
541
|
+
.expect(403)
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
it("if user email doesn't exist, SSO support couldn't be added. Not found error returned", async () => {
|
|
545
|
+
const ssoId = "fake-ssoId"
|
|
546
|
+
const email = "fake-email@budibase.com"
|
|
547
|
+
await config.api.users
|
|
548
|
+
.addSsoSupportInternalAPIAuth(ssoId, email)
|
|
549
|
+
.expect("Content-Type", /json/)
|
|
550
|
+
.expect(404)
|
|
551
|
+
})
|
|
552
|
+
|
|
553
|
+
it("if user email exist, SSO support is added", async () => {
|
|
554
|
+
const user = await createPasswordUser()
|
|
555
|
+
const ssoId = "fakessoId"
|
|
556
|
+
await config.api.users
|
|
557
|
+
.addSsoSupportInternalAPIAuth(ssoId, user.email)
|
|
558
|
+
.expect(200)
|
|
559
|
+
})
|
|
560
|
+
|
|
561
|
+
it("if user ssoId is already assigned, no change will be applied", async () => {
|
|
562
|
+
const user = await createSSOUser()
|
|
563
|
+
user.ssoId = "testssoId"
|
|
564
|
+
await config.api.users
|
|
565
|
+
.addSsoSupportInternalAPIAuth(user.ssoId, user.email)
|
|
566
|
+
.expect(200)
|
|
567
|
+
})
|
|
527
568
|
})
|
|
528
569
|
})
|
|
529
570
|
|
|
@@ -7,12 +7,13 @@ import { users } from "../validation"
|
|
|
7
7
|
import * as selfController from "../../controllers/global/self"
|
|
8
8
|
|
|
9
9
|
const router: Router = new Router()
|
|
10
|
+
const OPTIONAL_STRING = Joi.string().optional().allow(null).allow("")
|
|
10
11
|
|
|
11
12
|
function buildAdminInitValidation() {
|
|
12
13
|
return auth.joiValidator.body(
|
|
13
14
|
Joi.object({
|
|
14
15
|
email: Joi.string().required(),
|
|
15
|
-
password:
|
|
16
|
+
password: OPTIONAL_STRING,
|
|
16
17
|
tenantId: Joi.string().required(),
|
|
17
18
|
ssoId: Joi.string(),
|
|
18
19
|
})
|
|
@@ -64,6 +65,12 @@ router
|
|
|
64
65
|
users.buildUserSaveValidation(),
|
|
65
66
|
controller.save
|
|
66
67
|
)
|
|
68
|
+
.post(
|
|
69
|
+
"/api/global/users/sso",
|
|
70
|
+
cloudRestricted,
|
|
71
|
+
users.buildAddSsoSupport(),
|
|
72
|
+
controller.addSsoSupport
|
|
73
|
+
)
|
|
67
74
|
.post(
|
|
68
75
|
"/api/global/users/bulk",
|
|
69
76
|
auth.adminOnly,
|
|
@@ -41,6 +41,15 @@ export const buildUserSaveValidation = () => {
|
|
|
41
41
|
return auth.joiValidator.body(Joi.object(schema).required().unknown(true))
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
export const buildAddSsoSupport = () => {
|
|
45
|
+
return auth.joiValidator.body(
|
|
46
|
+
Joi.object({
|
|
47
|
+
ssoId: Joi.string().required(),
|
|
48
|
+
email: Joi.string().required(),
|
|
49
|
+
}).required()
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
44
53
|
export const buildUserBulkUserValidation = (isSelf = false) => {
|
|
45
54
|
if (!isSelf) {
|
|
46
55
|
schema = {
|
package/src/tests/api/users.ts
CHANGED
|
@@ -127,6 +127,20 @@ export class UserAPI extends TestAPI {
|
|
|
127
127
|
.expect(status ? status : 200)
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
addSsoSupportInternalAPIAuth = (ssoId: string, email: string) => {
|
|
131
|
+
return this.request
|
|
132
|
+
.post(`/api/global/users/sso`)
|
|
133
|
+
.send({ ssoId, email })
|
|
134
|
+
.set(this.config.internalAPIHeaders())
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
addSsoSupportDefaultAuth = (ssoId: string, email: string) => {
|
|
138
|
+
return this.request
|
|
139
|
+
.post(`/api/global/users/sso`)
|
|
140
|
+
.send({ ssoId, email })
|
|
141
|
+
.set(this.config.defaultHeaders())
|
|
142
|
+
}
|
|
143
|
+
|
|
130
144
|
deleteUser = (userId: string, status?: number) => {
|
|
131
145
|
return this.request
|
|
132
146
|
.delete(`/api/global/users/${userId}`)
|
package/src/tests/jestEnv.ts
CHANGED
package/.vscode/launch.json
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Use IntelliSense to learn about possible attributes.
|
|
3
|
-
// Hover to view descriptions of existing attributes.
|
|
4
|
-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
-
"version": "0.2.0",
|
|
6
|
-
"configurations": [
|
|
7
|
-
{
|
|
8
|
-
"name": "Start Server",
|
|
9
|
-
"type": "node",
|
|
10
|
-
"request": "launch",
|
|
11
|
-
"runtimeExecutable": "node",
|
|
12
|
-
"runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
|
|
13
|
-
"args": ["src/index.ts"],
|
|
14
|
-
"cwd": "${workspaceRoot}",
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"type": "node",
|
|
18
|
-
"request": "launch",
|
|
19
|
-
"name": "Jest - All",
|
|
20
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
21
|
-
"args": [],
|
|
22
|
-
"console": "integratedTerminal",
|
|
23
|
-
"internalConsoleOptions": "neverOpen",
|
|
24
|
-
"disableOptimisticBPs": true,
|
|
25
|
-
"windows": {
|
|
26
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"type": "node",
|
|
31
|
-
"request": "launch",
|
|
32
|
-
"name": "Jest - Users",
|
|
33
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
34
|
-
"args": ["user.spec", "--runInBand"],
|
|
35
|
-
"console": "integratedTerminal",
|
|
36
|
-
"internalConsoleOptions": "neverOpen",
|
|
37
|
-
"disableOptimisticBPs": true,
|
|
38
|
-
"windows": {
|
|
39
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"type": "node",
|
|
44
|
-
"request": "launch",
|
|
45
|
-
"name": "Jest - Instances",
|
|
46
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
47
|
-
"args": ["instance.spec", "--runInBand"],
|
|
48
|
-
"console": "integratedTerminal",
|
|
49
|
-
"internalConsoleOptions": "neverOpen",
|
|
50
|
-
"disableOptimisticBPs": true,
|
|
51
|
-
"windows": {
|
|
52
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"type": "node",
|
|
57
|
-
"request": "launch",
|
|
58
|
-
"name": "Jest - Roles",
|
|
59
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
60
|
-
"args": ["role.spec", "--runInBand"],
|
|
61
|
-
"console": "integratedTerminal",
|
|
62
|
-
"internalConsoleOptions": "neverOpen",
|
|
63
|
-
"disableOptimisticBPs": true,
|
|
64
|
-
"windows": {
|
|
65
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
"type": "node",
|
|
70
|
-
"request": "launch",
|
|
71
|
-
"name": "Jest - Records",
|
|
72
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
73
|
-
"args": ["record.spec", "--runInBand"],
|
|
74
|
-
"console": "integratedTerminal",
|
|
75
|
-
"internalConsoleOptions": "neverOpen",
|
|
76
|
-
"disableOptimisticBPs": true,
|
|
77
|
-
"windows": {
|
|
78
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
"type": "node",
|
|
83
|
-
"request": "launch",
|
|
84
|
-
"name": "Jest - Models",
|
|
85
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
86
|
-
"args": ["table.spec", "--runInBand"],
|
|
87
|
-
"console": "integratedTerminal",
|
|
88
|
-
"internalConsoleOptions": "neverOpen",
|
|
89
|
-
"disableOptimisticBPs": true,
|
|
90
|
-
"windows": {
|
|
91
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"type": "node",
|
|
96
|
-
"request": "launch",
|
|
97
|
-
"name": "Jest - Views",
|
|
98
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
99
|
-
"args": ["view.spec", "--runInBand"],
|
|
100
|
-
"console": "integratedTerminal",
|
|
101
|
-
"internalConsoleOptions": "neverOpen",
|
|
102
|
-
"disableOptimisticBPs": true,
|
|
103
|
-
"windows": {
|
|
104
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
"type": "node",
|
|
109
|
-
"request": "launch",
|
|
110
|
-
"name": "Jest - Applications",
|
|
111
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
112
|
-
"args": ["application.spec", "--runInBand"],
|
|
113
|
-
"console": "integratedTerminal",
|
|
114
|
-
"internalConsoleOptions": "neverOpen",
|
|
115
|
-
"disableOptimisticBPs": true,
|
|
116
|
-
"windows": {
|
|
117
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
"type": "node",
|
|
122
|
-
"request": "launch",
|
|
123
|
-
"name": "Jest Builder",
|
|
124
|
-
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
125
|
-
"args": ["builder", "--runInBand"],
|
|
126
|
-
"console": "integratedTerminal",
|
|
127
|
-
"internalConsoleOptions": "neverOpen",
|
|
128
|
-
"disableOptimisticBPs": true,
|
|
129
|
-
"windows": {
|
|
130
|
-
"program": "${workspaceFolder}/node_modules/jest-cli/bin/jest",
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
"type": "node",
|
|
135
|
-
"request": "launch",
|
|
136
|
-
"name": "Initialise Budibase",
|
|
137
|
-
"program": "yarn",
|
|
138
|
-
"args": ["run", "initialise"],
|
|
139
|
-
"console": "externalTerminal"
|
|
140
|
-
}
|
|
141
|
-
]
|
|
142
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
const { join } = require("path")
|
|
2
|
-
require("dotenv").config({
|
|
3
|
-
path: join(__dirname, "..", "..", "hosting", ".env"),
|
|
4
|
-
})
|
|
5
|
-
|
|
6
|
-
const jestTestcontainersConfigGenerator = require("../../jestTestcontainersConfigGenerator")
|
|
7
|
-
|
|
8
|
-
module.exports = jestTestcontainersConfigGenerator()
|