@budibase/worker 2.3.17 → 2.3.18-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/__mocks__/node-fetch.ts +23 -0
- package/jest-testcontainers-config.js +8 -0
- package/jest.config.ts +3 -2
- package/package.json +10 -7
- package/scripts/dev/manage.js +1 -0
- package/src/api/controllers/global/auth.ts +77 -70
- package/src/api/controllers/global/self.ts +28 -44
- package/src/api/controllers/global/users.ts +65 -25
- package/src/api/controllers/system/accounts.ts +7 -5
- package/src/api/controllers/system/tenants.ts +4 -8
- package/src/api/index.ts +4 -20
- package/src/api/routes/global/auth.ts +10 -7
- package/src/api/routes/global/tests/auth.spec.ts +226 -17
- package/src/api/routes/global/tests/configs.spec.ts +5 -5
- package/src/api/routes/global/tests/roles.spec.ts +20 -14
- package/src/api/routes/global/tests/self.spec.ts +3 -4
- package/src/api/routes/global/tests/users.spec.ts +24 -27
- package/src/api/routes/system/tenants.ts +1 -1
- package/src/api/routes/system/tests/accounts.spec.ts +4 -4
- package/src/api/routes/system/tests/migrations.spec.ts +2 -2
- package/src/api/routes/system/tests/restore.spec.ts +2 -2
- package/src/api/routes/system/tests/status.spec.ts +5 -5
- package/src/ddApm.ts +7 -0
- package/src/elasticApm.ts +10 -0
- package/src/environment.ts +15 -1
- package/src/index.ts +12 -7
- package/src/middleware/tests/tenancy.spec.ts +4 -4
- package/src/migrations/functions/globalInfoSyncUsers.ts +4 -3
- package/src/sdk/accounts/index.ts +2 -1
- package/src/sdk/accounts/{accounts.ts → metadata.ts} +0 -1
- package/src/sdk/auth/auth.ts +86 -0
- package/src/sdk/auth/index.ts +1 -0
- package/src/sdk/tenants/index.ts +1 -0
- package/src/sdk/tenants/tenants.ts +76 -0
- package/src/sdk/users/events.ts +4 -0
- package/src/sdk/users/index.ts +1 -0
- package/src/sdk/users/tests/users.spec.ts +52 -0
- package/src/sdk/users/users.ts +53 -46
- package/src/tests/TestConfiguration.ts +41 -62
- package/src/tests/api/auth.ts +42 -14
- package/src/tests/api/base.ts +2 -1
- package/src/tests/api/configs.ts +2 -2
- package/src/tests/api/restore.ts +1 -0
- package/src/tests/api/users.ts +2 -2
- package/src/tests/jestEnv.ts +2 -1
- package/src/tests/jestSetup.ts +10 -6
- package/src/tests/logging.ts +34 -0
- package/src/tests/structures/index.ts +0 -4
- package/src/utilities/email.ts +3 -3
- package/coverage/clover.xml +0 -2199
- package/coverage/coverage-final.json +0 -84
- 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 -934
- package/coverage/lcov-report/src/api/controllers/global/configs.ts.html +0 -1348
- package/coverage/lcov-report/src/api/controllers/global/email.ts.html +0 -196
- package/coverage/lcov-report/src/api/controllers/global/events.ts.html +0 -136
- package/coverage/lcov-report/src/api/controllers/global/index.html +0 -251
- 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 -838
- 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 -595
- 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/events.ts.html +0 -109
- package/coverage/lcov-report/src/api/routes/global/index.html +0 -251
- 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 -475
- 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 -202
- 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 -637
- 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 -388
- 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 -601
- 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 -1999
- package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +0 -1075
- 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/groups.ts.html +0 -163
- package/coverage/lcov-report/src/tests/api/index.html +0 -356
- package/coverage/lcov-report/src/tests/api/index.ts.html +0 -238
- package/coverage/lcov-report/src/tests/api/license.ts.html +0 -136
- 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/roles.ts.html +0 -181
- 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/templates.ts.html +0 -175
- package/coverage/lcov-report/src/tests/api/tenants.ts.html +0 -130
- package/coverage/lcov-report/src/tests/api/users.ts.html +0 -514
- 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 -103
- package/coverage/lcov-report/src/tests/mocks/email.ts.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 -208
- 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 -4187
- package/src/tests/structures/users.ts +0 -37
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import fs from "fs"
|
|
2
|
+
module FetchMock {
|
|
3
|
+
const fetch = jest.requireActual("node-fetch")
|
|
4
|
+
|
|
5
|
+
const func = async (url: any, opts: any) => {
|
|
6
|
+
if (url.includes("http://someconfigurl")) {
|
|
7
|
+
return {
|
|
8
|
+
ok: true,
|
|
9
|
+
json: () => ({
|
|
10
|
+
issuer: "test",
|
|
11
|
+
authorization_endpoint: "http://localhost/auth",
|
|
12
|
+
token_endpoint: "http://localhost/token",
|
|
13
|
+
userinfo_endpoint: "http://localhost/userinfo",
|
|
14
|
+
}),
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return fetch(url, opts)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func.Headers = fetch.Headers
|
|
21
|
+
|
|
22
|
+
module.exports = func
|
|
23
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
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()
|
package/jest.config.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Config } from "@jest/types"
|
|
2
2
|
import * as fs from "fs"
|
|
3
|
+
const preset = require("ts-jest/jest-preset")
|
|
3
4
|
|
|
4
5
|
const config: Config.InitialOptions = {
|
|
5
|
-
|
|
6
|
+
...preset,
|
|
7
|
+
preset: "@trendyol/jest-testcontainers",
|
|
6
8
|
setupFiles: ["./src/tests/jestEnv.ts"],
|
|
7
9
|
setupFilesAfterEnv: ["./src/tests/jestSetup.ts"],
|
|
8
10
|
collectCoverageFrom: ["src/**/*.{js,ts}"],
|
|
@@ -18,7 +20,6 @@ if (!process.env.CI) {
|
|
|
18
20
|
"@budibase/backend-core/(.*)": "<rootDir>/../backend-core/$1",
|
|
19
21
|
"@budibase/backend-core": "<rootDir>/../backend-core/src",
|
|
20
22
|
"@budibase/types": "<rootDir>/../types/src",
|
|
21
|
-
"^axios.*$": "<rootDir>/node_modules/axios/lib/axios.js",
|
|
22
23
|
}
|
|
23
24
|
// add pro sources if they exist
|
|
24
25
|
if (fs.existsSync("../../../budibase-pro")) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/worker",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "2.3.
|
|
4
|
+
"version": "2.3.18-alpha.0",
|
|
5
5
|
"description": "Budibase background service",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -36,16 +36,17 @@
|
|
|
36
36
|
"author": "Budibase",
|
|
37
37
|
"license": "GPL-3.0",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@budibase/backend-core": "
|
|
40
|
-
"@budibase/pro": "2.3.
|
|
41
|
-
"@budibase/string-templates": "
|
|
42
|
-
"@budibase/types": "
|
|
39
|
+
"@budibase/backend-core": "2.3.18-alpha.0",
|
|
40
|
+
"@budibase/pro": "2.3.17",
|
|
41
|
+
"@budibase/string-templates": "2.3.18-alpha.0",
|
|
42
|
+
"@budibase/types": "2.3.18-alpha.0",
|
|
43
43
|
"@koa/router": "8.0.8",
|
|
44
44
|
"@sentry/node": "6.17.7",
|
|
45
45
|
"@techpass/passport-openidconnect": "0.3.2",
|
|
46
46
|
"@types/global-agent": "2.1.1",
|
|
47
47
|
"aws-sdk": "2.1030.0",
|
|
48
48
|
"bcryptjs": "2.4.3",
|
|
49
|
+
"dd-trace": "3.13.2",
|
|
49
50
|
"dotenv": "8.6.0",
|
|
50
51
|
"elastic-apm-node": "3.38.0",
|
|
51
52
|
"global-agent": "3.0.0",
|
|
@@ -72,7 +73,8 @@
|
|
|
72
73
|
"devDependencies": {
|
|
73
74
|
"@swc/core": "^1.3.25",
|
|
74
75
|
"@swc/jest": "^0.2.24",
|
|
75
|
-
"@
|
|
76
|
+
"@trendyol/jest-testcontainers": "^2.1.1",
|
|
77
|
+
"@types/jest": "28.1.1",
|
|
76
78
|
"@types/jsonwebtoken": "8.5.1",
|
|
77
79
|
"@types/koa": "2.13.4",
|
|
78
80
|
"@types/koa__router": "8.0.8",
|
|
@@ -80,6 +82,7 @@
|
|
|
80
82
|
"@types/node-fetch": "2.6.1",
|
|
81
83
|
"@types/pouchdb": "6.4.0",
|
|
82
84
|
"@types/server-destroy": "1.0.1",
|
|
85
|
+
"@types/supertest": "2.0.12",
|
|
83
86
|
"@types/uuid": "8.3.4",
|
|
84
87
|
"@typescript-eslint/parser": "5.45.0",
|
|
85
88
|
"copyfiles": "2.4.1",
|
|
@@ -97,5 +100,5 @@
|
|
|
97
100
|
"typescript": "4.7.3",
|
|
98
101
|
"update-dotenv": "1.1.1"
|
|
99
102
|
},
|
|
100
|
-
"gitHead": "
|
|
103
|
+
"gitHead": "f4dd710b75eb0a7a65e6f9d8b8f709d3b76c435b"
|
|
101
104
|
}
|
package/scripts/dev/manage.js
CHANGED
|
@@ -29,6 +29,7 @@ async function init() {
|
|
|
29
29
|
SERVICE: "worker-service",
|
|
30
30
|
DEPLOYMENT_ENVIRONMENT: "development",
|
|
31
31
|
TENANT_FEATURE_FLAGS: "*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR",
|
|
32
|
+
ENABLE_EMAIL_TEST_MODE: 1,
|
|
32
33
|
}
|
|
33
34
|
let envFile = ""
|
|
34
35
|
Object.keys(envFileJson).forEach(key => {
|
|
@@ -1,49 +1,55 @@
|
|
|
1
1
|
import {
|
|
2
|
-
auth,
|
|
2
|
+
auth as authCore,
|
|
3
3
|
constants,
|
|
4
4
|
context,
|
|
5
5
|
db as dbCore,
|
|
6
6
|
events,
|
|
7
7
|
tenancy,
|
|
8
|
-
|
|
9
|
-
utils,
|
|
8
|
+
utils as utilsCore,
|
|
10
9
|
} from "@budibase/backend-core"
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import {
|
|
11
|
+
ConfigType,
|
|
12
|
+
User,
|
|
13
|
+
Ctx,
|
|
14
|
+
LoginRequest,
|
|
15
|
+
SSOUser,
|
|
16
|
+
PasswordResetRequest,
|
|
17
|
+
PasswordResetUpdateRequest,
|
|
18
|
+
} from "@budibase/types"
|
|
14
19
|
import env from "../../../environment"
|
|
15
|
-
import sdk from "../../../sdk"
|
|
16
|
-
import { ConfigType, User } from "@budibase/types"
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const { passport, ssoCallbackUrl, google, oidc } = auth
|
|
21
|
+
import * as authSdk from "../../../sdk/auth"
|
|
22
|
+
import * as userSdk from "../../../sdk/users"
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
24
|
+
const { Cookie, Header } = constants
|
|
25
|
+
const { passport, ssoCallbackUrl, google, oidc } = authCore
|
|
26
|
+
const { setCookie, getCookie, clearCookie } = utilsCore
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
return ssoCallbackUrl(tenancy.getGlobalDB(), config, ConfigType.OIDC)
|
|
28
|
-
}
|
|
28
|
+
// LOGIN / LOGOUT
|
|
29
29
|
|
|
30
|
-
async function
|
|
30
|
+
async function passportCallback(
|
|
31
|
+
ctx: Ctx,
|
|
32
|
+
user: User,
|
|
33
|
+
err: any = null,
|
|
34
|
+
info: { message: string } | null = null
|
|
35
|
+
) {
|
|
31
36
|
if (err) {
|
|
32
37
|
console.error("Authentication error")
|
|
33
38
|
console.error(err)
|
|
34
39
|
console.trace(err)
|
|
35
40
|
return ctx.throw(403, info ? info : "Unauthorized")
|
|
36
41
|
}
|
|
37
|
-
|
|
38
42
|
if (!user) {
|
|
39
43
|
console.error("Authentication error - no user provided")
|
|
40
44
|
return ctx.throw(403, info ? info : "Unauthorized")
|
|
41
45
|
}
|
|
42
46
|
|
|
47
|
+
const token = await authSdk.loginUser(user)
|
|
48
|
+
|
|
43
49
|
// set a cookie for browser access
|
|
44
|
-
setCookie(ctx,
|
|
50
|
+
setCookie(ctx, token, Cookie.Auth, { sign: false })
|
|
45
51
|
// set the token in a header as well for APIs
|
|
46
|
-
ctx.set(Header.TOKEN,
|
|
52
|
+
ctx.set(Header.TOKEN, token)
|
|
47
53
|
// get rid of any app cookies on login
|
|
48
54
|
// have to check test because this breaks cypress
|
|
49
55
|
if (!env.isTest()) {
|
|
@@ -51,11 +57,18 @@ async function authInternal(ctx: any, user: any, err: any = null, info = null) {
|
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
export const
|
|
60
|
+
export const login = async (ctx: Ctx<LoginRequest>, next: any) => {
|
|
61
|
+
const email = ctx.request.body.username
|
|
62
|
+
|
|
63
|
+
const user = await userSdk.getUserByEmail(email)
|
|
64
|
+
if (user && (await userSdk.isPreventSSOPasswords(user))) {
|
|
65
|
+
ctx.throw(400, "SSO user cannot login using password")
|
|
66
|
+
}
|
|
67
|
+
|
|
55
68
|
return passport.authenticate(
|
|
56
69
|
"local",
|
|
57
70
|
async (err: any, user: User, info: any) => {
|
|
58
|
-
await
|
|
71
|
+
await passportCallback(ctx, user, err, info)
|
|
59
72
|
await context.identity.doInUserContext(user, async () => {
|
|
60
73
|
await events.auth.login("local")
|
|
61
74
|
})
|
|
@@ -64,6 +77,15 @@ export const authenticate = async (ctx: any, next: any) => {
|
|
|
64
77
|
)(ctx, next)
|
|
65
78
|
}
|
|
66
79
|
|
|
80
|
+
export const logout = async (ctx: any) => {
|
|
81
|
+
if (ctx.user && ctx.user._id) {
|
|
82
|
+
await authSdk.logout({ ctx, userId: ctx.user._id })
|
|
83
|
+
}
|
|
84
|
+
ctx.body = { message: "User logged out." }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// INIT
|
|
88
|
+
|
|
67
89
|
export const setInitInfo = (ctx: any) => {
|
|
68
90
|
const initInfo = ctx.request.body
|
|
69
91
|
setCookie(ctx, initInfo, Cookie.Init)
|
|
@@ -79,32 +101,16 @@ export const getInitInfo = (ctx: any) => {
|
|
|
79
101
|
}
|
|
80
102
|
}
|
|
81
103
|
|
|
104
|
+
// PASSWORD MANAGEMENT
|
|
105
|
+
|
|
82
106
|
/**
|
|
83
107
|
* Reset the user password, used as part of a forgotten password flow.
|
|
84
108
|
*/
|
|
85
|
-
export const reset = async (ctx:
|
|
109
|
+
export const reset = async (ctx: Ctx<PasswordResetRequest>) => {
|
|
86
110
|
const { email } = ctx.request.body
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
400,
|
|
91
|
-
"Please contact your platform administrator, SMTP is not configured."
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
try {
|
|
95
|
-
const user = (await usersCore.getGlobalUserByEmail(email)) as User
|
|
96
|
-
// only if user exists, don't error though if they don't
|
|
97
|
-
if (user) {
|
|
98
|
-
await sendEmail(email, EmailTemplatePurpose.PASSWORD_RECOVERY, {
|
|
99
|
-
user,
|
|
100
|
-
subject: "{{ company }} platform password reset",
|
|
101
|
-
})
|
|
102
|
-
await events.user.passwordResetRequested(user)
|
|
103
|
-
}
|
|
104
|
-
} catch (err) {
|
|
105
|
-
console.log(err)
|
|
106
|
-
// don't throw any kind of error to the user, this might give away something
|
|
107
|
-
}
|
|
111
|
+
|
|
112
|
+
await authSdk.reset(email)
|
|
113
|
+
|
|
108
114
|
ctx.body = {
|
|
109
115
|
message: "Please check your email for a reset link.",
|
|
110
116
|
}
|
|
@@ -113,32 +119,21 @@ export const reset = async (ctx: any) => {
|
|
|
113
119
|
/**
|
|
114
120
|
* Perform the user password update if the provided reset code is valid.
|
|
115
121
|
*/
|
|
116
|
-
export const resetUpdate = async (ctx:
|
|
122
|
+
export const resetUpdate = async (ctx: Ctx<PasswordResetUpdateRequest>) => {
|
|
117
123
|
const { resetCode, password } = ctx.request.body
|
|
118
124
|
try {
|
|
119
|
-
|
|
120
|
-
const db = tenancy.getGlobalDB()
|
|
121
|
-
const user = await db.get(userId)
|
|
122
|
-
user.password = await hash(password)
|
|
123
|
-
await db.put(user)
|
|
125
|
+
await authSdk.resetUpdate(resetCode, password)
|
|
124
126
|
ctx.body = {
|
|
125
127
|
message: "password reset successfully.",
|
|
126
128
|
}
|
|
127
|
-
// remove password from the user before sending events
|
|
128
|
-
delete user.password
|
|
129
|
-
await events.user.passwordReset(user)
|
|
130
129
|
} catch (err) {
|
|
131
|
-
console.
|
|
130
|
+
console.warn(err)
|
|
131
|
+
// hide any details of the error for security
|
|
132
132
|
ctx.throw(400, "Cannot reset password.")
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
if (ctx.user && ctx.user._id) {
|
|
138
|
-
await platformLogout({ ctx, userId: ctx.user._id })
|
|
139
|
-
}
|
|
140
|
-
ctx.body = { message: "User logged out." }
|
|
141
|
-
}
|
|
136
|
+
// DATASOURCE
|
|
142
137
|
|
|
143
138
|
export const datasourcePreAuth = async (ctx: any, next: any) => {
|
|
144
139
|
const provider = ctx.params.provider
|
|
@@ -166,6 +161,12 @@ export const datasourceAuth = async (ctx: any, next: any) => {
|
|
|
166
161
|
return handler.postAuth(passport, ctx, next)
|
|
167
162
|
}
|
|
168
163
|
|
|
164
|
+
// GOOGLE SSO
|
|
165
|
+
|
|
166
|
+
export async function googleCallbackUrl(config?: { callbackURL?: string }) {
|
|
167
|
+
return ssoCallbackUrl(tenancy.getGlobalDB(), config, ConfigType.GOOGLE)
|
|
168
|
+
}
|
|
169
|
+
|
|
169
170
|
/**
|
|
170
171
|
* The initial call that google authentication makes to take you to the google login screen.
|
|
171
172
|
* On a successful login, you will be redirected to the googleAuth callback route.
|
|
@@ -181,7 +182,7 @@ export const googlePreAuth = async (ctx: any, next: any) => {
|
|
|
181
182
|
const strategy = await google.strategyFactory(
|
|
182
183
|
config,
|
|
183
184
|
callbackUrl,
|
|
184
|
-
|
|
185
|
+
userSdk.save
|
|
185
186
|
)
|
|
186
187
|
|
|
187
188
|
return passport.authenticate(strategy, {
|
|
@@ -191,7 +192,7 @@ export const googlePreAuth = async (ctx: any, next: any) => {
|
|
|
191
192
|
})(ctx, next)
|
|
192
193
|
}
|
|
193
194
|
|
|
194
|
-
export const
|
|
195
|
+
export const googleCallback = async (ctx: any, next: any) => {
|
|
195
196
|
const db = tenancy.getGlobalDB()
|
|
196
197
|
|
|
197
198
|
const config = await dbCore.getScopedConfig(db, {
|
|
@@ -202,14 +203,14 @@ export const googleAuth = async (ctx: any, next: any) => {
|
|
|
202
203
|
const strategy = await google.strategyFactory(
|
|
203
204
|
config,
|
|
204
205
|
callbackUrl,
|
|
205
|
-
|
|
206
|
+
userSdk.save
|
|
206
207
|
)
|
|
207
208
|
|
|
208
209
|
return passport.authenticate(
|
|
209
210
|
strategy,
|
|
210
211
|
{ successRedirect: "/", failureRedirect: "/error" },
|
|
211
|
-
async (err: any, user:
|
|
212
|
-
await
|
|
212
|
+
async (err: any, user: SSOUser, info: any) => {
|
|
213
|
+
await passportCallback(ctx, user, err, info)
|
|
213
214
|
await context.identity.doInUserContext(user, async () => {
|
|
214
215
|
await events.auth.login("google-internal")
|
|
215
216
|
})
|
|
@@ -218,6 +219,12 @@ export const googleAuth = async (ctx: any, next: any) => {
|
|
|
218
219
|
)(ctx, next)
|
|
219
220
|
}
|
|
220
221
|
|
|
222
|
+
// OIDC SSO
|
|
223
|
+
|
|
224
|
+
export async function oidcCallbackUrl(config?: { callbackURL?: string }) {
|
|
225
|
+
return ssoCallbackUrl(tenancy.getGlobalDB(), config, ConfigType.OIDC)
|
|
226
|
+
}
|
|
227
|
+
|
|
221
228
|
export const oidcStrategyFactory = async (ctx: any, configId: any) => {
|
|
222
229
|
const db = tenancy.getGlobalDB()
|
|
223
230
|
const config = await dbCore.getScopedConfig(db, {
|
|
@@ -233,7 +240,7 @@ export const oidcStrategyFactory = async (ctx: any, configId: any) => {
|
|
|
233
240
|
chosenConfig,
|
|
234
241
|
callbackUrl
|
|
235
242
|
)
|
|
236
|
-
return oidc.strategyFactory(enrichedConfig,
|
|
243
|
+
return oidc.strategyFactory(enrichedConfig, userSdk.save)
|
|
237
244
|
}
|
|
238
245
|
|
|
239
246
|
/**
|
|
@@ -265,15 +272,15 @@ export const oidcPreAuth = async (ctx: any, next: any) => {
|
|
|
265
272
|
})(ctx, next)
|
|
266
273
|
}
|
|
267
274
|
|
|
268
|
-
export const
|
|
275
|
+
export const oidcCallback = async (ctx: any, next: any) => {
|
|
269
276
|
const configId = getCookie(ctx, Cookie.OIDC_CONFIG)
|
|
270
277
|
const strategy = await oidcStrategyFactory(ctx, configId)
|
|
271
278
|
|
|
272
279
|
return passport.authenticate(
|
|
273
280
|
strategy,
|
|
274
281
|
{ successRedirect: "/", failureRedirect: "/error" },
|
|
275
|
-
async (err: any, user:
|
|
276
|
-
await
|
|
282
|
+
async (err: any, user: SSOUser, info: any) => {
|
|
283
|
+
await passportCallback(ctx, user, err, info)
|
|
277
284
|
await context.identity.doInUserContext(user, async () => {
|
|
278
285
|
await events.auth.login("oidc")
|
|
279
286
|
})
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as userSdk from "../../../sdk/users"
|
|
2
2
|
import {
|
|
3
|
-
events,
|
|
4
3
|
featureFlags,
|
|
5
4
|
tenancy,
|
|
6
5
|
constants,
|
|
7
6
|
db as dbCore,
|
|
8
7
|
utils,
|
|
9
|
-
cache,
|
|
10
8
|
encryption,
|
|
9
|
+
auth as authCore,
|
|
11
10
|
} from "@budibase/backend-core"
|
|
12
11
|
import env from "../../../environment"
|
|
13
12
|
import { groups } from "@budibase/pro"
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
import {
|
|
14
|
+
UpdateSelfRequest,
|
|
15
|
+
UpdateSelfResponse,
|
|
16
|
+
UpdateSelf,
|
|
17
|
+
UserCtx,
|
|
18
|
+
} from "@budibase/types"
|
|
19
|
+
const { getCookie, clearCookie, newid } = utils
|
|
16
20
|
|
|
17
21
|
function newTestApiKey() {
|
|
18
22
|
return env.ENCRYPTED_TEST_PUBLIC_API_KEY
|
|
@@ -93,17 +97,6 @@ const addSessionAttributesToUser = (ctx: any) => {
|
|
|
93
97
|
ctx.body.csrfToken = ctx.user.csrfToken
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
const sanitiseUserUpdate = (ctx: any) => {
|
|
97
|
-
const allowed = ["firstName", "lastName", "password", "forceResetPassword"]
|
|
98
|
-
const resp: { [key: string]: any } = {}
|
|
99
|
-
for (let [key, value] of Object.entries(ctx.request.body)) {
|
|
100
|
-
if (allowed.includes(key)) {
|
|
101
|
-
resp[key] = value
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return resp
|
|
105
|
-
}
|
|
106
|
-
|
|
107
100
|
export async function getSelf(ctx: any) {
|
|
108
101
|
if (!ctx.user) {
|
|
109
102
|
ctx.throw(403, "User not logged in")
|
|
@@ -116,7 +109,7 @@ export async function getSelf(ctx: any) {
|
|
|
116
109
|
checkCurrentApp(ctx)
|
|
117
110
|
|
|
118
111
|
// get the main body of the user
|
|
119
|
-
const user = await
|
|
112
|
+
const user = await userSdk.getUser(userId)
|
|
120
113
|
ctx.body = await groups.enrichUserRolesFromGroups(user)
|
|
121
114
|
|
|
122
115
|
// add the feature flags for this tenant
|
|
@@ -126,39 +119,30 @@ export async function getSelf(ctx: any) {
|
|
|
126
119
|
addSessionAttributesToUser(ctx)
|
|
127
120
|
}
|
|
128
121
|
|
|
129
|
-
export async function updateSelf(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
122
|
+
export async function updateSelf(
|
|
123
|
+
ctx: UserCtx<UpdateSelfRequest, UpdateSelfResponse>
|
|
124
|
+
) {
|
|
125
|
+
const body = ctx.request.body
|
|
126
|
+
const update: UpdateSelf = {
|
|
127
|
+
firstName: body.firstName,
|
|
128
|
+
lastName: body.lastName,
|
|
129
|
+
password: body.password,
|
|
130
|
+
forceResetPassword: body.forceResetPassword,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const user = await userSdk.updateSelf(ctx.user._id!, update)
|
|
134
|
+
|
|
135
|
+
if (update.password) {
|
|
139
136
|
// Log all other sessions out apart from the current one
|
|
140
|
-
await platformLogout({
|
|
137
|
+
await authCore.platformLogout({
|
|
141
138
|
ctx,
|
|
142
|
-
userId: ctx.user._id
|
|
139
|
+
userId: ctx.user._id!,
|
|
143
140
|
keepActiveSession: true,
|
|
144
141
|
})
|
|
145
142
|
}
|
|
146
143
|
|
|
147
|
-
const response = await db.put({
|
|
148
|
-
...user,
|
|
149
|
-
...userUpdateObj,
|
|
150
|
-
})
|
|
151
|
-
await userCache.invalidateUser(user._id)
|
|
152
144
|
ctx.body = {
|
|
153
|
-
_id:
|
|
154
|
-
_rev:
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// remove the old password from the user before sending events
|
|
158
|
-
user._rev = response.rev
|
|
159
|
-
delete user.password
|
|
160
|
-
await events.user.updated(user)
|
|
161
|
-
if (passwordChange) {
|
|
162
|
-
await events.user.passwordUpdated(user)
|
|
145
|
+
_id: user._id!,
|
|
146
|
+
_rev: user._rev!,
|
|
163
147
|
}
|
|
164
148
|
}
|