@budibase/worker 2.3.18-alpha.9 → 2.3.18

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