@budibase/worker 2.3.20 → 2.3.21-alpha.1

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 (180) hide show
  1. package/__mocks__/node-fetch.ts +23 -0
  2. package/jest-testcontainers-config.js +8 -0
  3. package/jest.config.ts +14 -18
  4. package/package.json +12 -8
  5. package/scripts/dev/manage.js +1 -0
  6. package/scripts/test.sh +12 -0
  7. package/src/api/controllers/global/auth.ts +109 -111
  8. package/src/api/controllers/global/configs.ts +150 -142
  9. package/src/api/controllers/global/self.ts +28 -44
  10. package/src/api/controllers/global/users.ts +211 -32
  11. package/src/api/controllers/system/accounts.ts +7 -5
  12. package/src/api/controllers/system/tenants.ts +4 -8
  13. package/src/api/index.ts +4 -20
  14. package/src/api/routes/global/auth.ts +10 -7
  15. package/src/api/routes/global/configs.ts +6 -12
  16. package/src/api/routes/global/tests/auditLogs.spec.ts +111 -0
  17. package/src/api/routes/global/tests/auth.spec.ts +217 -18
  18. package/src/api/routes/global/tests/configs.spec.ts +93 -65
  19. package/src/api/routes/global/tests/realEmail.spec.ts +1 -0
  20. package/src/api/routes/global/tests/roles.spec.ts +20 -14
  21. package/src/api/routes/global/tests/self.spec.ts +3 -4
  22. package/src/api/routes/global/tests/users.spec.ts +29 -28
  23. package/src/api/routes/global/users.ts +19 -14
  24. package/src/api/routes/index.ts +3 -0
  25. package/src/api/routes/system/tenants.ts +1 -1
  26. package/src/api/routes/system/tests/accounts.spec.ts +4 -4
  27. package/src/api/routes/system/tests/migrations.spec.ts +2 -2
  28. package/src/api/routes/system/tests/restore.spec.ts +2 -2
  29. package/src/api/routes/system/tests/status.spec.ts +5 -5
  30. package/src/db/index.ts +8 -2
  31. package/src/ddApm.ts +7 -0
  32. package/src/elasticApm.ts +10 -0
  33. package/src/environment.ts +4 -0
  34. package/src/index.ts +29 -8
  35. package/src/middleware/tests/tenancy.spec.ts +4 -4
  36. package/src/migrations/functions/globalInfoSyncUsers.ts +4 -3
  37. package/src/sdk/accounts/index.ts +2 -1
  38. package/src/sdk/accounts/{accounts.ts → metadata.ts} +0 -1
  39. package/src/sdk/auth/auth.ts +86 -0
  40. package/src/sdk/auth/index.ts +1 -0
  41. package/src/sdk/tenants/index.ts +1 -0
  42. package/src/sdk/tenants/tenants.ts +76 -0
  43. package/src/sdk/users/events.ts +4 -0
  44. package/src/sdk/users/index.ts +1 -0
  45. package/src/sdk/users/tests/users.spec.ts +76 -0
  46. package/src/sdk/users/users.ts +86 -53
  47. package/src/tests/TestConfiguration.ts +41 -62
  48. package/src/tests/api/auditLogs.ts +26 -0
  49. package/src/tests/api/auth.ts +44 -14
  50. package/src/tests/api/base.ts +2 -1
  51. package/src/tests/api/configs.ts +9 -1
  52. package/src/tests/api/email.ts +1 -0
  53. package/src/tests/api/index.ts +3 -0
  54. package/src/tests/api/restore.ts +1 -0
  55. package/src/tests/api/users.ts +2 -2
  56. package/src/tests/jestEnv.ts +2 -1
  57. package/src/tests/jestSetup.ts +10 -6
  58. package/src/tests/logging.ts +34 -0
  59. package/src/tests/structures/configs.ts +20 -13
  60. package/src/tests/structures/index.ts +0 -4
  61. package/src/utilities/email.ts +22 -68
  62. package/src/utilities/redis.ts +42 -2
  63. package/src/utilities/templates.ts +4 -9
  64. package/coverage/clover.xml +0 -2199
  65. package/coverage/coverage-final.json +0 -84
  66. package/coverage/lcov-report/base.css +0 -224
  67. package/coverage/lcov-report/block-navigation.js +0 -87
  68. package/coverage/lcov-report/favicon.png +0 -0
  69. package/coverage/lcov-report/index.html +0 -431
  70. package/coverage/lcov-report/prettify.css +0 -1
  71. package/coverage/lcov-report/prettify.js +0 -2
  72. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  73. package/coverage/lcov-report/sorter.js +0 -196
  74. package/coverage/lcov-report/src/api/controllers/global/auth.ts.html +0 -934
  75. package/coverage/lcov-report/src/api/controllers/global/configs.ts.html +0 -1348
  76. package/coverage/lcov-report/src/api/controllers/global/email.ts.html +0 -196
  77. package/coverage/lcov-report/src/api/controllers/global/events.ts.html +0 -136
  78. package/coverage/lcov-report/src/api/controllers/global/index.html +0 -251
  79. package/coverage/lcov-report/src/api/controllers/global/license.ts.html +0 -187
  80. package/coverage/lcov-report/src/api/controllers/global/roles.ts.html +0 -283
  81. package/coverage/lcov-report/src/api/controllers/global/self.ts.html +0 -577
  82. package/coverage/lcov-report/src/api/controllers/global/templates.ts.html +0 -316
  83. package/coverage/lcov-report/src/api/controllers/global/users.ts.html +0 -838
  84. package/coverage/lcov-report/src/api/controllers/global/workspaces.ts.html +0 -244
  85. package/coverage/lcov-report/src/api/controllers/system/accounts.ts.html +0 -148
  86. package/coverage/lcov-report/src/api/controllers/system/environment.ts.html +0 -124
  87. package/coverage/lcov-report/src/api/controllers/system/index.html +0 -191
  88. package/coverage/lcov-report/src/api/controllers/system/migrations.ts.html +0 -124
  89. package/coverage/lcov-report/src/api/controllers/system/restore.ts.html +0 -124
  90. package/coverage/lcov-report/src/api/controllers/system/status.ts.html +0 -133
  91. package/coverage/lcov-report/src/api/controllers/system/tenants.ts.html +0 -154
  92. package/coverage/lcov-report/src/api/index.html +0 -116
  93. package/coverage/lcov-report/src/api/index.ts.html +0 -595
  94. package/coverage/lcov-report/src/api/routes/global/auth.ts.html +0 -349
  95. package/coverage/lcov-report/src/api/routes/global/configs.ts.html +0 -457
  96. package/coverage/lcov-report/src/api/routes/global/email.ts.html +0 -193
  97. package/coverage/lcov-report/src/api/routes/global/events.ts.html +0 -109
  98. package/coverage/lcov-report/src/api/routes/global/index.html +0 -251
  99. package/coverage/lcov-report/src/api/routes/global/license.ts.html +0 -124
  100. package/coverage/lcov-report/src/api/routes/global/roles.ts.html +0 -133
  101. package/coverage/lcov-report/src/api/routes/global/self.ts.html +0 -139
  102. package/coverage/lcov-report/src/api/routes/global/templates.ts.html +0 -196
  103. package/coverage/lcov-report/src/api/routes/global/users.ts.html +0 -475
  104. package/coverage/lcov-report/src/api/routes/global/workspaces.ts.html +0 -196
  105. package/coverage/lcov-report/src/api/routes/index.html +0 -116
  106. package/coverage/lcov-report/src/api/routes/index.ts.html +0 -202
  107. package/coverage/lcov-report/src/api/routes/system/accounts.ts.html +0 -142
  108. package/coverage/lcov-report/src/api/routes/system/environment.ts.html +0 -109
  109. package/coverage/lcov-report/src/api/routes/system/index.html +0 -191
  110. package/coverage/lcov-report/src/api/routes/system/migrations.ts.html +0 -142
  111. package/coverage/lcov-report/src/api/routes/system/restore.ts.html +0 -109
  112. package/coverage/lcov-report/src/api/routes/system/status.ts.html +0 -109
  113. package/coverage/lcov-report/src/api/routes/system/tenants.ts.html +0 -124
  114. package/coverage/lcov-report/src/api/routes/validation/index.html +0 -131
  115. package/coverage/lcov-report/src/api/routes/validation/index.ts.html +0 -88
  116. package/coverage/lcov-report/src/api/routes/validation/users.ts.html +0 -235
  117. package/coverage/lcov-report/src/constants/index.html +0 -116
  118. package/coverage/lcov-report/src/constants/index.ts.html +0 -637
  119. package/coverage/lcov-report/src/constants/templates/index.html +0 -116
  120. package/coverage/lcov-report/src/constants/templates/index.ts.html +0 -316
  121. package/coverage/lcov-report/src/db/index.html +0 -116
  122. package/coverage/lcov-report/src/db/index.ts.html +0 -115
  123. package/coverage/lcov-report/src/environment.ts.html +0 -388
  124. package/coverage/lcov-report/src/index.html +0 -131
  125. package/coverage/lcov-report/src/index.ts.html +0 -394
  126. package/coverage/lcov-report/src/middleware/cloudRestricted.ts.html +0 -139
  127. package/coverage/lcov-report/src/middleware/index.html +0 -116
  128. package/coverage/lcov-report/src/migrations/functions/globalInfoSyncUsers.ts.html +0 -145
  129. package/coverage/lcov-report/src/migrations/functions/index.html +0 -116
  130. package/coverage/lcov-report/src/migrations/index.html +0 -116
  131. package/coverage/lcov-report/src/migrations/index.ts.html +0 -271
  132. package/coverage/lcov-report/src/sdk/accounts/accounts.ts.html +0 -262
  133. package/coverage/lcov-report/src/sdk/accounts/index.html +0 -131
  134. package/coverage/lcov-report/src/sdk/accounts/index.ts.html +0 -88
  135. package/coverage/lcov-report/src/sdk/index.html +0 -116
  136. package/coverage/lcov-report/src/sdk/index.ts.html +0 -106
  137. package/coverage/lcov-report/src/sdk/users/events.ts.html +0 -601
  138. package/coverage/lcov-report/src/sdk/users/index.html +0 -146
  139. package/coverage/lcov-report/src/sdk/users/index.ts.html +0 -88
  140. package/coverage/lcov-report/src/sdk/users/users.ts.html +0 -1999
  141. package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +0 -1075
  142. package/coverage/lcov-report/src/tests/api/accounts.ts.html +0 -160
  143. package/coverage/lcov-report/src/tests/api/auth.ts.html +0 -220
  144. package/coverage/lcov-report/src/tests/api/base.ts.html +0 -133
  145. package/coverage/lcov-report/src/tests/api/configs.ts.html +0 -226
  146. package/coverage/lcov-report/src/tests/api/email.ts.html +0 -148
  147. package/coverage/lcov-report/src/tests/api/environment.ts.html +0 -130
  148. package/coverage/lcov-report/src/tests/api/groups.ts.html +0 -163
  149. package/coverage/lcov-report/src/tests/api/index.html +0 -356
  150. package/coverage/lcov-report/src/tests/api/index.ts.html +0 -238
  151. package/coverage/lcov-report/src/tests/api/license.ts.html +0 -136
  152. package/coverage/lcov-report/src/tests/api/migrations.ts.html +0 -151
  153. package/coverage/lcov-report/src/tests/api/restore.ts.html +0 -127
  154. package/coverage/lcov-report/src/tests/api/roles.ts.html +0 -181
  155. package/coverage/lcov-report/src/tests/api/self.ts.html +0 -163
  156. package/coverage/lcov-report/src/tests/api/status.ts.html +0 -121
  157. package/coverage/lcov-report/src/tests/api/templates.ts.html +0 -175
  158. package/coverage/lcov-report/src/tests/api/tenants.ts.html +0 -130
  159. package/coverage/lcov-report/src/tests/api/users.ts.html +0 -514
  160. package/coverage/lcov-report/src/tests/controllers.ts.html +0 -100
  161. package/coverage/lcov-report/src/tests/index.html +0 -146
  162. package/coverage/lcov-report/src/tests/index.ts.html +0 -103
  163. package/coverage/lcov-report/src/tests/mocks/email.ts.html +0 -115
  164. package/coverage/lcov-report/src/tests/mocks/index.html +0 -131
  165. package/coverage/lcov-report/src/tests/mocks/index.ts.html +0 -106
  166. package/coverage/lcov-report/src/tests/structures/configs.ts.html +0 -313
  167. package/coverage/lcov-report/src/tests/structures/groups.ts.html +0 -118
  168. package/coverage/lcov-report/src/tests/structures/index.html +0 -161
  169. package/coverage/lcov-report/src/tests/structures/index.ts.html +0 -151
  170. package/coverage/lcov-report/src/tests/structures/users.ts.html +0 -196
  171. package/coverage/lcov-report/src/utilities/appService.ts.html +0 -208
  172. package/coverage/lcov-report/src/utilities/email.ts.html +0 -850
  173. package/coverage/lcov-report/src/utilities/fileSystem.ts.html +0 -100
  174. package/coverage/lcov-report/src/utilities/index.html +0 -206
  175. package/coverage/lcov-report/src/utilities/index.ts.html +0 -112
  176. package/coverage/lcov-report/src/utilities/redis.ts.html +0 -424
  177. package/coverage/lcov-report/src/utilities/templates.ts.html +0 -232
  178. package/coverage/lcov-report/src/utilities/users.ts.html +0 -133
  179. package/coverage/lcov.info +0 -4187
  180. package/src/tests/structures/users.ts +0 -37
@@ -2,38 +2,37 @@ import * as email from "../../../utilities/email"
2
2
  import env from "../../../environment"
3
3
  import { googleCallbackUrl, oidcCallbackUrl } from "./auth"
4
4
  import {
5
- events,
6
5
  cache,
7
- objectStore,
8
- tenancy,
6
+ configs,
9
7
  db as dbCore,
10
8
  env as coreEnv,
9
+ events,
10
+ objectStore,
11
+ tenancy,
11
12
  } from "@budibase/backend-core"
12
13
  import { checkAnyUserExists } from "../../../utilities/users"
13
14
  import {
14
- Database,
15
- Config as ConfigDoc,
15
+ Config,
16
16
  ConfigType,
17
- SSOType,
18
- GoogleConfig,
19
- OIDCConfig,
20
- SettingsConfig,
17
+ Ctx,
18
+ GetPublicOIDCConfigResponse,
19
+ GetPublicSettingsResponse,
20
+ GoogleInnerConfig,
21
21
  isGoogleConfig,
22
22
  isOIDCConfig,
23
23
  isSettingsConfig,
24
24
  isSMTPConfig,
25
- Ctx,
25
+ OIDCConfigs,
26
+ SettingsInnerConfig,
27
+ SSOConfig,
28
+ SSOConfigType,
26
29
  UserCtx,
27
30
  } from "@budibase/types"
31
+ import * as pro from "@budibase/pro"
28
32
 
29
- const getEventFns = async (db: Database, config: ConfigDoc) => {
33
+ const getEventFns = async (config: Config, existing?: Config) => {
30
34
  const fns = []
31
35
 
32
- let existing
33
- if (config._id) {
34
- existing = await db.get(config._id)
35
- }
36
-
37
36
  if (!existing) {
38
37
  if (isSMTPConfig(config)) {
39
38
  fns.push(events.email.SMTPCreated)
@@ -125,31 +124,96 @@ const getEventFns = async (db: Database, config: ConfigDoc) => {
125
124
  return fns
126
125
  }
127
126
 
128
- export async function save(ctx: UserCtx) {
129
- const db = tenancy.getGlobalDB()
130
- const { type, workspace, user, config } = ctx.request.body
131
- let eventFns = await getEventFns(db, ctx.request.body)
132
- // Config does not exist yet
133
- if (!ctx.request.body._id) {
134
- ctx.request.body._id = dbCore.generateConfigID({
135
- type,
136
- workspace,
137
- user,
138
- })
127
+ type SSOConfigs = { [key in SSOConfigType]: SSOConfig | undefined }
128
+
129
+ async function getSSOConfigs(): Promise<SSOConfigs> {
130
+ const google = await configs.getGoogleConfig()
131
+ const oidc = await configs.getOIDCConfig()
132
+ return {
133
+ [ConfigType.GOOGLE]: google,
134
+ [ConfigType.OIDC]: oidc,
135
+ }
136
+ }
137
+
138
+ async function hasActivatedConfig(ssoConfigs?: SSOConfigs) {
139
+ if (!ssoConfigs) {
140
+ ssoConfigs = await getSSOConfigs()
141
+ }
142
+ return !!Object.values(ssoConfigs).find(c => c?.activated)
143
+ }
144
+
145
+ async function verifySettingsConfig(config: SettingsInnerConfig) {
146
+ if (config.isSSOEnforced) {
147
+ const valid = await hasActivatedConfig()
148
+ if (!valid) {
149
+ throw new Error("Cannot enforce SSO without an activated configuration")
150
+ }
151
+ }
152
+ }
153
+
154
+ async function verifySSOConfig(type: SSOConfigType, config: SSOConfig) {
155
+ const settings = await configs.getSettingsConfig()
156
+ if (settings.isSSOEnforced && !config.activated) {
157
+ // config is being saved as deactivated
158
+ // ensure there is at least one other activated sso config
159
+ const ssoConfigs = await getSSOConfigs()
160
+
161
+ // overwrite the config being updated
162
+ // to reflect the desired state
163
+ ssoConfigs[type] = config
164
+
165
+ const activated = await hasActivatedConfig(ssoConfigs)
166
+ if (!activated) {
167
+ throw new Error(
168
+ "Configuration cannot be deactivated while SSO is enforced"
169
+ )
170
+ }
171
+ }
172
+ }
173
+
174
+ async function verifyGoogleConfig(config: GoogleInnerConfig) {
175
+ await verifySSOConfig(ConfigType.GOOGLE, config)
176
+ }
177
+
178
+ async function verifyOIDCConfig(config: OIDCConfigs) {
179
+ await verifySSOConfig(ConfigType.OIDC, config.configs[0])
180
+ }
181
+
182
+ export async function save(ctx: UserCtx<Config>) {
183
+ const body = ctx.request.body
184
+ const type = body.type
185
+ const config = body.config
186
+
187
+ const existingConfig = await configs.getConfig(type)
188
+ let eventFns = await getEventFns(ctx.request.body, existingConfig)
189
+
190
+ if (existingConfig) {
191
+ body._rev = existingConfig._rev
139
192
  }
193
+
140
194
  try {
141
195
  // verify the configuration
142
196
  switch (type) {
143
197
  case ConfigType.SMTP:
144
198
  await email.verifyConfig(config)
145
199
  break
200
+ case ConfigType.SETTINGS:
201
+ await verifySettingsConfig(config)
202
+ break
203
+ case ConfigType.GOOGLE:
204
+ await verifyGoogleConfig(config)
205
+ break
206
+ case ConfigType.OIDC:
207
+ await verifyOIDCConfig(config)
208
+ break
146
209
  }
147
210
  } catch (err: any) {
148
211
  ctx.throw(400, err)
149
212
  }
150
213
 
151
214
  try {
152
- const response = await db.put(ctx.request.body)
215
+ body._id = configs.generateConfigID(type)
216
+ const response = await configs.save(body)
153
217
  await cache.bustCache(cache.CacheKey.CHECKLIST)
154
218
  await cache.bustCache(cache.CacheKey.ANALYTICS_ENABLED)
155
219
 
@@ -167,44 +231,11 @@ export async function save(ctx: UserCtx) {
167
231
  }
168
232
  }
169
233
 
170
- export async function fetch(ctx: UserCtx) {
171
- const db = tenancy.getGlobalDB()
172
- const response = await db.allDocs(
173
- dbCore.getConfigParams(
174
- { type: ctx.params.type },
175
- {
176
- include_docs: true,
177
- }
178
- )
179
- )
180
- ctx.body = response.rows.map(row => row.doc)
181
- }
182
-
183
- /**
184
- * Gets the most granular config for a particular configuration type.
185
- * The hierarchy is type -> workspace -> user.
186
- */
187
234
  export async function find(ctx: UserCtx) {
188
- const db = tenancy.getGlobalDB()
189
-
190
- const { userId, workspaceId } = ctx.query
191
- if (workspaceId && userId) {
192
- const workspace = await db.get(workspaceId as string)
193
- const userInWorkspace = workspace.users.some(
194
- (workspaceUser: any) => workspaceUser === userId
195
- )
196
- if (!ctx.user!.admin && !userInWorkspace) {
197
- ctx.throw(400, `User is not in specified workspace: ${workspace}.`)
198
- }
199
- }
200
-
201
235
  try {
202
236
  // Find the config with the most granular scope based on context
203
- const scopedConfig = await dbCore.getScopedFullConfig(db, {
204
- type: ctx.params.type,
205
- user: userId,
206
- workspace: workspaceId,
207
- })
237
+ const type = ctx.params.type
238
+ const scopedConfig = await configs.getConfig(type)
208
239
 
209
240
  if (scopedConfig) {
210
241
  ctx.body = scopedConfig
@@ -217,85 +248,70 @@ export async function find(ctx: UserCtx) {
217
248
  }
218
249
  }
219
250
 
220
- export async function publicOidc(ctx: Ctx) {
221
- const db = tenancy.getGlobalDB()
251
+ export async function publicOidc(ctx: Ctx<void, GetPublicOIDCConfigResponse>) {
222
252
  try {
223
253
  // Find the config with the most granular scope based on context
224
- const oidcConfig: OIDCConfig = await dbCore.getScopedFullConfig(db, {
225
- type: ConfigType.OIDC,
226
- })
254
+ const config = await configs.getOIDCConfig()
227
255
 
228
- if (!oidcConfig) {
229
- ctx.body = {}
256
+ if (!config) {
257
+ ctx.body = []
230
258
  } else {
231
- ctx.body = oidcConfig.config.configs.map(config => ({
232
- logo: config.logo,
233
- name: config.name,
234
- uuid: config.uuid,
235
- }))
259
+ ctx.body = [
260
+ {
261
+ logo: config.logo,
262
+ name: config.name,
263
+ uuid: config.uuid,
264
+ },
265
+ ]
236
266
  }
237
267
  } catch (err: any) {
238
268
  ctx.throw(err.status, err)
239
269
  }
240
270
  }
241
271
 
242
- export async function publicSettings(ctx: Ctx) {
243
- const db = tenancy.getGlobalDB()
244
-
272
+ export async function publicSettings(
273
+ ctx: Ctx<void, GetPublicSettingsResponse>
274
+ ) {
245
275
  try {
246
- // Find the config with the most granular scope based on context
247
- const publicConfig = await dbCore.getScopedFullConfig(db, {
248
- type: ConfigType.SETTINGS,
249
- })
250
-
251
- const googleConfig = await dbCore.getScopedFullConfig(db, {
252
- type: ConfigType.GOOGLE,
253
- })
254
-
255
- const oidcConfig = await dbCore.getScopedFullConfig(db, {
256
- type: ConfigType.OIDC,
257
- })
258
-
259
- let config
260
- if (!publicConfig) {
261
- config = {
262
- config: {},
263
- }
264
- } else {
265
- config = publicConfig
266
- }
267
-
268
- // enrich the logo url
269
- // empty url means deleted
270
- if (config.config.logoUrl && config.config.logoUrl !== "") {
271
- config.config.logoUrl = objectStore.getGlobalFileUrl(
276
+ // settings
277
+ const configDoc = await configs.getSettingsConfigDoc()
278
+ const config = configDoc.config
279
+ // enrich the logo url - empty url means deleted
280
+ if (config.logoUrl && config.logoUrl !== "") {
281
+ config.logoUrl = objectStore.getGlobalFileUrl(
272
282
  "settings",
273
283
  "logoUrl",
274
- config.config.logoUrlEtag
284
+ config.logoUrlEtag
275
285
  )
276
286
  }
277
287
 
278
- // google button flag
279
- if (googleConfig && googleConfig.config) {
280
- // activated by default for configs pre-activated flag
281
- config.config.google =
282
- googleConfig.config.activated == null || googleConfig.config.activated
283
- } else {
284
- config.config.google = false
285
- }
288
+ // google
289
+ const googleConfig = await configs.getGoogleConfig()
290
+ const preActivated = googleConfig?.activated == null
291
+ const google = preActivated || !!googleConfig?.activated
292
+ const _googleCallbackUrl = await googleCallbackUrl(googleConfig)
286
293
 
287
- // callback urls
288
- config.config.oidcCallbackUrl = await oidcCallbackUrl()
289
- config.config.googleCallbackUrl = await googleCallbackUrl()
294
+ // oidc
295
+ const oidcConfig = await configs.getOIDCConfig()
296
+ const oidc = oidcConfig?.activated || false
297
+ const _oidcCallbackUrl = await oidcCallbackUrl()
290
298
 
291
- // oidc button flag
292
- if (oidcConfig && oidcConfig.config) {
293
- config.config.oidc = oidcConfig.config.configs[0].activated
294
- } else {
295
- config.config.oidc = false
296
- }
299
+ // sso enforced
300
+ const isSSOEnforced = await pro.features.isSSOEnforced({ config })
297
301
 
298
- ctx.body = config
302
+ ctx.body = {
303
+ type: ConfigType.SETTINGS,
304
+ _id: configDoc._id,
305
+ _rev: configDoc._rev,
306
+ config: {
307
+ ...config,
308
+ google,
309
+ oidc,
310
+ isSSOEnforced,
311
+ oidcCallbackUrl: _oidcCallbackUrl,
312
+ googleCallbackUrl: _googleCallbackUrl,
313
+ },
314
+ }
299
315
  } catch (err: any) {
300
316
  ctx.throw(err.status, err)
301
317
  }
@@ -319,12 +335,11 @@ export async function upload(ctx: UserCtx) {
319
335
  })
320
336
 
321
337
  // add to configuration structure
322
- // TODO: right now this only does a global level
323
- const db = tenancy.getGlobalDB()
324
- let cfgStructure = await dbCore.getScopedFullConfig(db, { type })
325
- if (!cfgStructure) {
326
- cfgStructure = {
327
- _id: dbCore.generateConfigID({ type }),
338
+ let config = await configs.getConfig(type)
339
+ if (!config) {
340
+ config = {
341
+ _id: configs.generateConfigID(type),
342
+ type,
328
343
  config: {},
329
344
  }
330
345
  }
@@ -332,14 +347,14 @@ export async function upload(ctx: UserCtx) {
332
347
  // save the Etag for cache bursting
333
348
  const etag = result.ETag
334
349
  if (etag) {
335
- cfgStructure.config[`${name}Etag`] = etag.replace(/"/g, "")
350
+ config.config[`${name}Etag`] = etag.replace(/"/g, "")
336
351
  }
337
352
 
338
353
  // save the file key
339
- cfgStructure.config[`${name}`] = key
354
+ config.config[`${name}`] = key
340
355
 
341
356
  // write back to db
342
- await db.put(cfgStructure)
357
+ await configs.save(config)
343
358
 
344
359
  ctx.body = {
345
360
  message: "File has been uploaded and url stored to config.",
@@ -360,7 +375,6 @@ export async function destroy(ctx: UserCtx) {
360
375
  }
361
376
 
362
377
  export async function configChecklist(ctx: Ctx) {
363
- const db = tenancy.getGlobalDB()
364
378
  const tenantId = tenancy.getTenantId()
365
379
 
366
380
  try {
@@ -375,19 +389,13 @@ export async function configChecklist(ctx: Ctx) {
375
389
  }
376
390
 
377
391
  // They have set up SMTP
378
- const smtpConfig = await dbCore.getScopedFullConfig(db, {
379
- type: ConfigType.SMTP,
380
- })
392
+ const smtpConfig = await configs.getSMTPConfig()
381
393
 
382
394
  // They have set up Google Auth
383
- const googleConfig = await dbCore.getScopedFullConfig(db, {
384
- type: ConfigType.GOOGLE,
385
- })
395
+ const googleConfig = await configs.getGoogleConfig()
386
396
 
387
397
  // They have set up OIDC
388
- const oidcConfig = await dbCore.getScopedFullConfig(db, {
389
- type: ConfigType.OIDC,
390
- })
398
+ const oidcConfig = await configs.getOIDCConfig()
391
399
 
392
400
  // They have set up a global user
393
401
  const userExists = await checkAnyUserExists()
@@ -1,18 +1,22 @@
1
- import sdk from "../../../sdk"
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
- const { hash, platformLogout, getCookie, clearCookie, newid } = utils
15
- const { user: userCache } = cache
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 sdk.users.getUser(userId)
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(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)
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: 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)
145
+ _id: user._id!,
146
+ _rev: user._rev!,
163
147
  }
164
148
  }