@budibase/server 1.0.167 → 1.0.168

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 (172) hide show
  1. package/builder/assets/{index.9ee2182c.js → index.deb4ce04.js} +1 -1
  2. package/builder/index.html +1 -1
  3. package/coverage/clover.xml +24 -11
  4. package/coverage/coverage-final.json +1 -1
  5. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  7. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/index.html +1 -1
  15. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  40. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  44. package/coverage/lcov-report/api/index.html +1 -1
  45. package/coverage/lcov-report/api/index.js.html +1 -1
  46. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/index.html +1 -1
  57. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  71. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  74. package/coverage/lcov-report/automations/actions.js.html +1 -1
  75. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  76. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  77. package/coverage/lcov-report/automations/index.html +1 -1
  78. package/coverage/lcov-report/automations/index.js.html +1 -1
  79. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/index.html +1 -1
  86. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  96. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  105. package/coverage/lcov-report/constants/index.html +1 -1
  106. package/coverage/lcov-report/constants/index.js.html +1 -1
  107. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  108. package/coverage/lcov-report/constants/screens.js.html +1 -1
  109. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  110. package/coverage/lcov-report/db/index.html +1 -1
  111. package/coverage/lcov-report/db/index.js.html +1 -1
  112. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  113. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  116. package/coverage/lcov-report/db/newid.js.html +1 -1
  117. package/coverage/lcov-report/db/utils.js.html +1 -1
  118. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  119. package/coverage/lcov-report/events/index.html +1 -1
  120. package/coverage/lcov-report/events/index.js.html +1 -1
  121. package/coverage/lcov-report/events/utils.js.html +1 -1
  122. package/coverage/lcov-report/index.html +18 -18
  123. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  124. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  125. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  126. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  127. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  128. package/coverage/lcov-report/middleware/index.html +1 -1
  129. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  130. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  131. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  132. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  133. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  134. package/coverage/lcov-report/threads/automation.js.html +1 -1
  135. package/coverage/lcov-report/threads/index.html +1 -1
  136. package/coverage/lcov-report/threads/query.js.html +1 -1
  137. package/coverage/lcov-report/threads/utils.js.html +1 -1
  138. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  139. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  140. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  141. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  142. package/coverage/lcov-report/utilities/global.js.html +1 -1
  143. package/coverage/lcov-report/utilities/index.html +19 -19
  144. package/coverage/lcov-report/utilities/index.js.html +1 -1
  145. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  146. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  147. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  148. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  150. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  151. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  152. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  153. package/coverage/lcov-report/utilities/security.js.html +1 -1
  154. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  156. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  157. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  158. package/coverage/lcov-report/utilities/users.js.html +73 -10
  159. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  160. package/coverage/lcov.info +36 -13
  161. package/dist/api/controllers/application.js +7 -0
  162. package/dist/api/controllers/public/users.js +3 -23
  163. package/dist/environment.js +5 -1
  164. package/dist/package.json +5 -5
  165. package/dist/tsconfig.build.tsbuildinfo +1 -1
  166. package/dist/utilities/users.js +21 -0
  167. package/package.json +6 -6
  168. package/scripts/load/users.js +97 -0
  169. package/src/api/controllers/application.ts +9 -0
  170. package/src/api/controllers/public/users.ts +3 -24
  171. package/src/environment.js +6 -1
  172. package/src/utilities/users.js +21 -0
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  const { InternalTables } = require("../db/utils");
12
12
  const { getGlobalUser } = require("../utilities/global");
13
13
  const { getAppDB } = require("@budibase/backend-core/context");
14
+ const { getProdAppID } = require("@budibase/backend-core/db");
14
15
  exports.getFullUser = (ctx, userId) => __awaiter(void 0, void 0, void 0, function* () {
15
16
  const global = yield getGlobalUser(userId);
16
17
  let metadata;
@@ -28,3 +29,23 @@ exports.getFullUser = (ctx, userId) => __awaiter(void 0, void 0, void 0, functio
28
29
  // make sure the ID is always a local ID, not a global one
29
30
  _id: userId });
30
31
  });
32
+ exports.publicApiUserFix = ctx => {
33
+ if (!ctx.request.body) {
34
+ return ctx;
35
+ }
36
+ if (!ctx.request.body._id && ctx.params.userId) {
37
+ ctx.request.body._id = ctx.params.userId;
38
+ }
39
+ if (!ctx.request.body.roles) {
40
+ ctx.request.body.roles = {};
41
+ }
42
+ else {
43
+ const newRoles = {};
44
+ for (let [appId, role] of Object.entries(ctx.request.body.roles)) {
45
+ // @ts-ignore
46
+ newRoles[getProdAppID(appId)] = role;
47
+ }
48
+ ctx.request.body.roles = newRoles;
49
+ }
50
+ return ctx;
51
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "1.0.167",
4
+ "version": "1.0.168",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -69,10 +69,10 @@
69
69
  "license": "GPL-3.0",
70
70
  "dependencies": {
71
71
  "@apidevtools/swagger-parser": "^10.0.3",
72
- "@budibase/backend-core": "^1.0.167",
73
- "@budibase/client": "^1.0.167",
74
- "@budibase/pro": "1.0.166",
75
- "@budibase/string-templates": "^1.0.167",
72
+ "@budibase/backend-core": "^1.0.168",
73
+ "@budibase/client": "^1.0.168",
74
+ "@budibase/pro": "1.0.167",
75
+ "@budibase/string-templates": "^1.0.168",
76
76
  "@bull-board/api": "^3.7.0",
77
77
  "@bull-board/koa": "^3.7.0",
78
78
  "@elastic/elasticsearch": "7.10.0",
@@ -183,5 +183,5 @@
183
183
  "optionalDependencies": {
184
184
  "oracledb": "^5.3.0"
185
185
  },
186
- "gitHead": "de26757649b77235b1ce62d31b9d0d34e10112b1"
186
+ "gitHead": "7e71bec61d8581f453d2259a2189911c2ea42d41"
187
187
  }
@@ -0,0 +1,97 @@
1
+ // get the JWT secret etc
2
+ require("../../src/environment")
3
+ require("@budibase/backend-core").init()
4
+ const {
5
+ getProdAppID,
6
+ generateGlobalUserID,
7
+ } = require("@budibase/backend-core/db")
8
+ const { doInTenant, getGlobalDB } = require("@budibase/backend-core/tenancy")
9
+ const { internalSaveUser } = require("@budibase/backend-core/utils")
10
+ const { publicApiUserFix } = require("../../src/utilities/users")
11
+ const { hash } = require("@budibase/backend-core/utils")
12
+
13
+ const USER_LOAD_NUMBER = 10000
14
+ const BATCH_SIZE = 200
15
+ const PASSWORD = "test"
16
+ const TENANT_ID = "default"
17
+
18
+ const APP_ID = process.argv[2]
19
+
20
+ const words = [
21
+ "test",
22
+ "testing",
23
+ "budi",
24
+ "mail",
25
+ "age",
26
+ "risk",
27
+ "load",
28
+ "uno",
29
+ "arm",
30
+ "leg",
31
+ "pen",
32
+ "glass",
33
+ "box",
34
+ "chicken",
35
+ "bottle",
36
+ ]
37
+
38
+ if (!APP_ID) {
39
+ console.error("Must supply app ID as first CLI option!")
40
+ process.exit(-1)
41
+ }
42
+
43
+ const WORD_1 = words[Math.floor(Math.random() * words.length)]
44
+ const WORD_2 = words[Math.floor(Math.random() * words.length)]
45
+ let HASHED_PASSWORD
46
+
47
+ function generateUser(count) {
48
+ return {
49
+ _id: generateGlobalUserID(),
50
+ password: HASHED_PASSWORD,
51
+ email: `${WORD_1}${count}@${WORD_2}.com`,
52
+ roles: {
53
+ [getProdAppID(APP_ID)]: "BASIC",
54
+ },
55
+ status: "active",
56
+ forceResetPassword: false,
57
+ firstName: "John",
58
+ lastName: "Smith",
59
+ }
60
+ }
61
+
62
+ async function run() {
63
+ HASHED_PASSWORD = await hash(PASSWORD)
64
+ return doInTenant(TENANT_ID, async () => {
65
+ const db = getGlobalDB()
66
+ for (let i = 0; i < USER_LOAD_NUMBER; i += BATCH_SIZE) {
67
+ let userSavePromises = []
68
+ for (let j = 0; j < BATCH_SIZE; j++) {
69
+ // like the public API
70
+ const ctx = publicApiUserFix({
71
+ request: {
72
+ body: generateUser(i + j),
73
+ },
74
+ })
75
+ userSavePromises.push(
76
+ internalSaveUser(ctx.request.body, TENANT_ID, {
77
+ hashPassword: false,
78
+ requirePassword: true,
79
+ bulkCreate: true,
80
+ })
81
+ )
82
+ }
83
+ const users = await Promise.all(userSavePromises)
84
+ await db.bulkDocs(users)
85
+ console.log(`${i + BATCH_SIZE} users have been created.`)
86
+ }
87
+ })
88
+ }
89
+
90
+ run()
91
+ .then(() => {
92
+ console.log(`Generated ${USER_LOAD_NUMBER} users!`)
93
+ })
94
+ .catch(err => {
95
+ console.error("Failed for reason: ", err)
96
+ process.exit(-1)
97
+ })
@@ -439,6 +439,15 @@ export const destroy = async (ctx: any) => {
439
439
  }
440
440
 
441
441
  export const sync = async (ctx: any, next: any) => {
442
+ if (env.DISABLE_AUTO_PROD_APP_SYNC) {
443
+ ctx.status = 200
444
+ ctx.body = {
445
+ message:
446
+ "App sync disabled. You can reenable with the DISABLE_AUTO_PROD_APP_SYNC environment variable.",
447
+ }
448
+ return next()
449
+ }
450
+
442
451
  const appId = ctx.params.appId
443
452
  if (!isDevAppID(appId)) {
444
453
  ctx.throw(400, "This action cannot be performed for production apps")
@@ -4,30 +4,9 @@ import {
4
4
  readGlobalUser,
5
5
  saveGlobalUser,
6
6
  } from "../../../utilities/workerRequests"
7
+ import { publicApiUserFix } from "../../../utilities/users"
7
8
  import { search as stringSearch } from "./utils"
8
9
 
9
- const { getProdAppID } = require("@budibase/backend-core/db")
10
-
11
- function fixUser(ctx: any) {
12
- if (!ctx.request.body) {
13
- return ctx
14
- }
15
- if (!ctx.request.body._id && ctx.params.userId) {
16
- ctx.request.body._id = ctx.params.userId
17
- }
18
- if (!ctx.request.body.roles) {
19
- ctx.request.body.roles = {}
20
- } else {
21
- const newRoles: { [key: string]: string } = {}
22
- for (let [appId, role] of Object.entries(ctx.request.body.roles)) {
23
- // @ts-ignore
24
- newRoles[getProdAppID(appId)] = role
25
- }
26
- ctx.request.body.roles = newRoles
27
- }
28
- return ctx
29
- }
30
-
31
10
  function getUser(ctx: any, userId?: string) {
32
11
  if (userId) {
33
12
  ctx.params = { userId }
@@ -45,7 +24,7 @@ export async function search(ctx: any, next: any) {
45
24
  }
46
25
 
47
26
  export async function create(ctx: any, next: any) {
48
- const response = await saveGlobalUser(fixUser(ctx))
27
+ const response = await saveGlobalUser(publicApiUserFix(ctx))
49
28
  ctx.body = await getUser(ctx, response._id)
50
29
  await next()
51
30
  }
@@ -61,7 +40,7 @@ export async function update(ctx: any, next: any) {
61
40
  ...ctx.request.body,
62
41
  _rev: user._rev,
63
42
  }
64
- const response = await saveGlobalUser(fixUser(ctx))
43
+ const response = await saveGlobalUser(publicApiUserFix(ctx))
65
44
  ctx.body = await getUser(ctx, response._id)
66
45
  await next()
67
46
  }
@@ -1,3 +1,5 @@
1
+ const { join } = require("path")
2
+
1
3
  function isTest() {
2
4
  return (
3
5
  process.env.NODE_ENV === "jest" ||
@@ -20,7 +22,9 @@ function isCypress() {
20
22
 
21
23
  let LOADED = false
22
24
  if (!LOADED && isDev() && !isTest()) {
23
- require("dotenv").config()
25
+ require("dotenv").config({
26
+ path: join(__dirname, "..", ".env"),
27
+ })
24
28
  LOADED = true
25
29
  }
26
30
 
@@ -57,6 +61,7 @@ module.exports = {
57
61
  JEST_WORKER_ID: process.env.JEST_WORKER_ID,
58
62
  BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT,
59
63
  DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
64
+ DISABLE_AUTO_PROD_APP_SYNC: process.env.DISABLE_AUTO_PROD_APP_SYNC,
60
65
  // minor
61
66
  SALT_ROUNDS: process.env.SALT_ROUNDS,
62
67
  LOGGER: process.env.LOGGER,
@@ -1,6 +1,7 @@
1
1
  const { InternalTables } = require("../db/utils")
2
2
  const { getGlobalUser } = require("../utilities/global")
3
3
  const { getAppDB } = require("@budibase/backend-core/context")
4
+ const { getProdAppID } = require("@budibase/backend-core/db")
4
5
 
5
6
  exports.getFullUser = async (ctx, userId) => {
6
7
  const global = await getGlobalUser(userId)
@@ -22,3 +23,23 @@ exports.getFullUser = async (ctx, userId) => {
22
23
  _id: userId,
23
24
  }
24
25
  }
26
+
27
+ exports.publicApiUserFix = ctx => {
28
+ if (!ctx.request.body) {
29
+ return ctx
30
+ }
31
+ if (!ctx.request.body._id && ctx.params.userId) {
32
+ ctx.request.body._id = ctx.params.userId
33
+ }
34
+ if (!ctx.request.body.roles) {
35
+ ctx.request.body.roles = {}
36
+ } else {
37
+ const newRoles = {}
38
+ for (let [appId, role] of Object.entries(ctx.request.body.roles)) {
39
+ // @ts-ignore
40
+ newRoles[getProdAppID(appId)] = role
41
+ }
42
+ ctx.request.body.roles = newRoles
43
+ }
44
+ return ctx
45
+ }