@budibase/backend-core 2.9.19-alpha.0 → 2.9.20

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 (257) hide show
  1. package/dist/index.js +324 -266
  2. package/dist/index.js.map +4 -4
  3. package/dist/index.js.meta.json +1 -1
  4. package/dist/package.json +19 -4
  5. package/dist/plugins.js +1 -1
  6. package/dist/plugins.js.map +1 -1
  7. package/dist/plugins.js.meta.json +1 -1
  8. package/dist/src/security/permissions.d.ts +1 -1
  9. package/dist/tests.js +260 -222
  10. package/dist/tests.js.map +4 -4
  11. package/dist/tests.js.meta.json +1 -1
  12. package/package.json +19 -4
  13. package/__mocks__/aws-sdk.ts +0 -18
  14. package/dist/tsconfig.build.tsbuildinfo +0 -1
  15. package/jest-testcontainers-config.js +0 -8
  16. package/jest.config.ts +0 -35
  17. package/scripts/build.js +0 -6
  18. package/scripts/test.sh +0 -13
  19. package/src/accounts/accounts.ts +0 -82
  20. package/src/accounts/api.ts +0 -59
  21. package/src/accounts/index.ts +0 -1
  22. package/src/auth/auth.ts +0 -208
  23. package/src/auth/index.ts +0 -1
  24. package/src/auth/tests/auth.spec.ts +0 -14
  25. package/src/blacklist/blacklist.ts +0 -54
  26. package/src/blacklist/index.ts +0 -1
  27. package/src/blacklist/tests/blacklist.spec.ts +0 -46
  28. package/src/cache/appMetadata.ts +0 -88
  29. package/src/cache/base/index.ts +0 -92
  30. package/src/cache/generic.ts +0 -30
  31. package/src/cache/index.ts +0 -5
  32. package/src/cache/tests/writethrough.spec.ts +0 -138
  33. package/src/cache/user.ts +0 -69
  34. package/src/cache/writethrough.ts +0 -133
  35. package/src/configs/configs.ts +0 -257
  36. package/src/configs/index.ts +0 -1
  37. package/src/configs/tests/configs.spec.ts +0 -184
  38. package/src/constants/db.ts +0 -63
  39. package/src/constants/index.ts +0 -2
  40. package/src/constants/misc.ts +0 -50
  41. package/src/context/Context.ts +0 -14
  42. package/src/context/identity.ts +0 -58
  43. package/src/context/index.ts +0 -3
  44. package/src/context/mainContext.ts +0 -310
  45. package/src/context/tests/index.spec.ts +0 -147
  46. package/src/context/types.ts +0 -11
  47. package/src/db/Replication.ts +0 -84
  48. package/src/db/constants.ts +0 -10
  49. package/src/db/couch/DatabaseImpl.ts +0 -238
  50. package/src/db/couch/connections.ts +0 -77
  51. package/src/db/couch/index.ts +0 -5
  52. package/src/db/couch/pouchDB.ts +0 -97
  53. package/src/db/couch/pouchDump.ts +0 -0
  54. package/src/db/couch/utils.ts +0 -50
  55. package/src/db/db.ts +0 -39
  56. package/src/db/errors.ts +0 -14
  57. package/src/db/index.ts +0 -12
  58. package/src/db/lucene.ts +0 -732
  59. package/src/db/searchIndexes/index.ts +0 -1
  60. package/src/db/searchIndexes/searchIndexes.ts +0 -62
  61. package/src/db/tests/index.spec.js +0 -25
  62. package/src/db/tests/lucene.spec.ts +0 -298
  63. package/src/db/tests/pouch.spec.js +0 -62
  64. package/src/db/tests/utils.spec.ts +0 -63
  65. package/src/db/utils.ts +0 -207
  66. package/src/db/views.ts +0 -241
  67. package/src/docIds/conversions.ts +0 -59
  68. package/src/docIds/ids.ts +0 -113
  69. package/src/docIds/index.ts +0 -2
  70. package/src/docIds/newid.ts +0 -5
  71. package/src/docIds/params.ts +0 -174
  72. package/src/docUpdates/index.ts +0 -29
  73. package/src/environment.ts +0 -201
  74. package/src/errors/errors.ts +0 -119
  75. package/src/errors/index.ts +0 -1
  76. package/src/events/analytics.ts +0 -6
  77. package/src/events/asyncEvents/index.ts +0 -2
  78. package/src/events/asyncEvents/publisher.ts +0 -12
  79. package/src/events/asyncEvents/queue.ts +0 -22
  80. package/src/events/backfill.ts +0 -183
  81. package/src/events/documentId.ts +0 -56
  82. package/src/events/events.ts +0 -40
  83. package/src/events/identification.ts +0 -310
  84. package/src/events/index.ts +0 -14
  85. package/src/events/processors/AnalyticsProcessor.ts +0 -64
  86. package/src/events/processors/AuditLogsProcessor.ts +0 -93
  87. package/src/events/processors/LoggingProcessor.ts +0 -37
  88. package/src/events/processors/Processors.ts +0 -52
  89. package/src/events/processors/async/DocumentUpdateProcessor.ts +0 -43
  90. package/src/events/processors/index.ts +0 -19
  91. package/src/events/processors/posthog/PosthogProcessor.ts +0 -118
  92. package/src/events/processors/posthog/index.ts +0 -2
  93. package/src/events/processors/posthog/rateLimiting.ts +0 -106
  94. package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +0 -168
  95. package/src/events/processors/types.ts +0 -1
  96. package/src/events/publishers/account.ts +0 -35
  97. package/src/events/publishers/app.ts +0 -155
  98. package/src/events/publishers/auditLog.ts +0 -26
  99. package/src/events/publishers/auth.ts +0 -73
  100. package/src/events/publishers/automation.ts +0 -110
  101. package/src/events/publishers/backfill.ts +0 -74
  102. package/src/events/publishers/backup.ts +0 -42
  103. package/src/events/publishers/datasource.ts +0 -48
  104. package/src/events/publishers/email.ts +0 -17
  105. package/src/events/publishers/environmentVariable.ts +0 -38
  106. package/src/events/publishers/group.ts +0 -99
  107. package/src/events/publishers/index.ts +0 -24
  108. package/src/events/publishers/installation.ts +0 -38
  109. package/src/events/publishers/layout.ts +0 -26
  110. package/src/events/publishers/license.ts +0 -84
  111. package/src/events/publishers/org.ts +0 -37
  112. package/src/events/publishers/plugin.ts +0 -47
  113. package/src/events/publishers/query.ts +0 -88
  114. package/src/events/publishers/role.ts +0 -62
  115. package/src/events/publishers/rows.ts +0 -29
  116. package/src/events/publishers/screen.ts +0 -36
  117. package/src/events/publishers/serve.ts +0 -43
  118. package/src/events/publishers/table.ts +0 -70
  119. package/src/events/publishers/user.ts +0 -202
  120. package/src/events/publishers/view.ts +0 -107
  121. package/src/featureFlags/index.ts +0 -77
  122. package/src/featureFlags/tests/featureFlags.spec.ts +0 -85
  123. package/src/helpers.ts +0 -9
  124. package/src/index.ts +0 -53
  125. package/src/installation.ts +0 -107
  126. package/src/logging/alerts.ts +0 -26
  127. package/src/logging/correlation/correlation.ts +0 -13
  128. package/src/logging/correlation/index.ts +0 -1
  129. package/src/logging/correlation/middleware.ts +0 -17
  130. package/src/logging/index.ts +0 -4
  131. package/src/logging/pino/logger.ts +0 -232
  132. package/src/logging/pino/middleware.ts +0 -45
  133. package/src/logging/system.ts +0 -81
  134. package/src/logging/tests/system.spec.ts +0 -61
  135. package/src/middleware/adminOnly.ts +0 -9
  136. package/src/middleware/auditLog.ts +0 -6
  137. package/src/middleware/authenticated.ts +0 -193
  138. package/src/middleware/builderOnly.ts +0 -20
  139. package/src/middleware/builderOrAdmin.ts +0 -20
  140. package/src/middleware/csrf.ts +0 -81
  141. package/src/middleware/errorHandling.ts +0 -29
  142. package/src/middleware/index.ts +0 -21
  143. package/src/middleware/internalApi.ts +0 -23
  144. package/src/middleware/joi-validator.ts +0 -45
  145. package/src/middleware/matchers.ts +0 -47
  146. package/src/middleware/passport/datasource/google.ts +0 -95
  147. package/src/middleware/passport/local.ts +0 -54
  148. package/src/middleware/passport/sso/google.ts +0 -77
  149. package/src/middleware/passport/sso/oidc.ts +0 -154
  150. package/src/middleware/passport/sso/sso.ts +0 -165
  151. package/src/middleware/passport/sso/tests/google.spec.ts +0 -67
  152. package/src/middleware/passport/sso/tests/oidc.spec.ts +0 -152
  153. package/src/middleware/passport/sso/tests/sso.spec.ts +0 -197
  154. package/src/middleware/passport/utils.ts +0 -38
  155. package/src/middleware/querystringToBody.ts +0 -28
  156. package/src/middleware/tenancy.ts +0 -36
  157. package/src/middleware/tests/builder.spec.ts +0 -180
  158. package/src/middleware/tests/matchers.spec.ts +0 -134
  159. package/src/migrations/definitions.ts +0 -40
  160. package/src/migrations/index.ts +0 -2
  161. package/src/migrations/migrations.ts +0 -191
  162. package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +0 -11
  163. package/src/migrations/tests/migrations.spec.ts +0 -64
  164. package/src/objectStore/buckets/app.ts +0 -40
  165. package/src/objectStore/buckets/global.ts +0 -29
  166. package/src/objectStore/buckets/index.ts +0 -3
  167. package/src/objectStore/buckets/plugins.ts +0 -71
  168. package/src/objectStore/buckets/tests/app.spec.ts +0 -171
  169. package/src/objectStore/buckets/tests/global.spec.ts +0 -74
  170. package/src/objectStore/buckets/tests/plugins.spec.ts +0 -111
  171. package/src/objectStore/cloudfront.ts +0 -41
  172. package/src/objectStore/index.ts +0 -3
  173. package/src/objectStore/objectStore.ts +0 -440
  174. package/src/objectStore/utils.ts +0 -27
  175. package/src/platform/index.ts +0 -3
  176. package/src/platform/platformDb.ts +0 -6
  177. package/src/platform/tenants.ts +0 -101
  178. package/src/platform/tests/tenants.spec.ts +0 -26
  179. package/src/platform/users.ts +0 -90
  180. package/src/plugin/index.ts +0 -1
  181. package/src/plugin/tests/validation.spec.ts +0 -83
  182. package/src/plugin/utils.ts +0 -156
  183. package/src/queue/constants.ts +0 -6
  184. package/src/queue/inMemoryQueue.ts +0 -141
  185. package/src/queue/index.ts +0 -2
  186. package/src/queue/listeners.ts +0 -195
  187. package/src/queue/queue.ts +0 -54
  188. package/src/redis/index.ts +0 -6
  189. package/src/redis/init.ts +0 -86
  190. package/src/redis/redis.ts +0 -308
  191. package/src/redis/redlockImpl.ts +0 -139
  192. package/src/redis/utils.ts +0 -117
  193. package/src/security/encryption.ts +0 -179
  194. package/src/security/permissions.ts +0 -159
  195. package/src/security/roles.ts +0 -420
  196. package/src/security/sessions.ts +0 -120
  197. package/src/security/tests/encryption.spec.ts +0 -31
  198. package/src/security/tests/permissions.spec.ts +0 -145
  199. package/src/security/tests/sessions.spec.ts +0 -12
  200. package/src/tenancy/db.ts +0 -6
  201. package/src/tenancy/index.ts +0 -2
  202. package/src/tenancy/tenancy.ts +0 -140
  203. package/src/tenancy/tests/tenancy.spec.ts +0 -184
  204. package/src/timers/index.ts +0 -1
  205. package/src/timers/timers.ts +0 -22
  206. package/src/users/db.ts +0 -460
  207. package/src/users/events.ts +0 -176
  208. package/src/users/index.ts +0 -4
  209. package/src/users/lookup.ts +0 -102
  210. package/src/users/users.ts +0 -276
  211. package/src/users/utils.ts +0 -55
  212. package/src/utils/hashing.ts +0 -14
  213. package/src/utils/index.ts +0 -3
  214. package/src/utils/stringUtils.ts +0 -8
  215. package/src/utils/tests/utils.spec.ts +0 -191
  216. package/src/utils/utils.ts +0 -239
  217. package/tests/core/logging.ts +0 -34
  218. package/tests/core/utilities/index.ts +0 -6
  219. package/tests/core/utilities/jestUtils.ts +0 -30
  220. package/tests/core/utilities/mocks/alerts.ts +0 -3
  221. package/tests/core/utilities/mocks/date.ts +0 -2
  222. package/tests/core/utilities/mocks/events.ts +0 -131
  223. package/tests/core/utilities/mocks/fetch.ts +0 -17
  224. package/tests/core/utilities/mocks/index.ts +0 -10
  225. package/tests/core/utilities/mocks/licenses.ts +0 -107
  226. package/tests/core/utilities/mocks/posthog.ts +0 -7
  227. package/tests/core/utilities/structures/Chance.ts +0 -20
  228. package/tests/core/utilities/structures/accounts.ts +0 -115
  229. package/tests/core/utilities/structures/apps.ts +0 -21
  230. package/tests/core/utilities/structures/common.ts +0 -7
  231. package/tests/core/utilities/structures/db.ts +0 -12
  232. package/tests/core/utilities/structures/documents/index.ts +0 -1
  233. package/tests/core/utilities/structures/documents/platform/index.ts +0 -1
  234. package/tests/core/utilities/structures/documents/platform/installation.ts +0 -12
  235. package/tests/core/utilities/structures/generator.ts +0 -2
  236. package/tests/core/utilities/structures/index.ts +0 -15
  237. package/tests/core/utilities/structures/koa.ts +0 -16
  238. package/tests/core/utilities/structures/licenses.ts +0 -167
  239. package/tests/core/utilities/structures/plugins.ts +0 -19
  240. package/tests/core/utilities/structures/quotas.ts +0 -67
  241. package/tests/core/utilities/structures/scim.ts +0 -80
  242. package/tests/core/utilities/structures/shared.ts +0 -19
  243. package/tests/core/utilities/structures/sso.ts +0 -119
  244. package/tests/core/utilities/structures/tenants.ts +0 -5
  245. package/tests/core/utilities/structures/userGroups.ts +0 -10
  246. package/tests/core/utilities/structures/users.ts +0 -73
  247. package/tests/core/utilities/testContainerUtils.ts +0 -98
  248. package/tests/core/utilities/utils/index.ts +0 -1
  249. package/tests/core/utilities/utils/time.ts +0 -3
  250. package/tests/extra/DBTestConfiguration.ts +0 -36
  251. package/tests/extra/index.ts +0 -2
  252. package/tests/extra/testEnv.ts +0 -95
  253. package/tests/index.ts +0 -1
  254. package/tests/jestEnv.ts +0 -6
  255. package/tests/jestSetup.ts +0 -28
  256. package/tsconfig.build.json +0 -29
  257. package/tsconfig.json +0 -4
@@ -1,420 +0,0 @@
1
- import { BuiltinPermissionID, PermissionLevel } from "./permissions"
2
- import { prefixRoleID, getRoleParams, DocumentType, SEPARATOR } from "../db"
3
- import { getAppDB } from "../context"
4
- import { doWithDB } from "../db"
5
- import { Screen, Role as RoleDoc } from "@budibase/types"
6
- import cloneDeep from "lodash/fp/cloneDeep"
7
-
8
- export const BUILTIN_ROLE_IDS = {
9
- ADMIN: "ADMIN",
10
- POWER: "POWER",
11
- BASIC: "BASIC",
12
- PUBLIC: "PUBLIC",
13
- }
14
-
15
- const BUILTIN_IDS = {
16
- ...BUILTIN_ROLE_IDS,
17
- BUILDER: "BUILDER",
18
- }
19
-
20
- // exclude internal roles like builder
21
- const EXTERNAL_BUILTIN_ROLE_IDS = [
22
- BUILTIN_IDS.ADMIN,
23
- BUILTIN_IDS.POWER,
24
- BUILTIN_IDS.BASIC,
25
- BUILTIN_IDS.PUBLIC,
26
- ]
27
-
28
- export const RoleIDVersion = {
29
- // original version, with a UUID based ID
30
- UUID: undefined,
31
- // new version - with name based ID
32
- NAME: "name",
33
- }
34
-
35
- export class Role implements RoleDoc {
36
- _id: string
37
- _rev?: string
38
- name: string
39
- permissionId: string
40
- inherits?: string
41
- version?: string
42
- permissions = {}
43
-
44
- constructor(id: string, name: string, permissionId: string) {
45
- this._id = id
46
- this.name = name
47
- this.permissionId = permissionId
48
- // version for managing the ID - removing the role_ when responding
49
- this.version = RoleIDVersion.NAME
50
- }
51
-
52
- addInheritance(inherits: string) {
53
- this.inherits = inherits
54
- return this
55
- }
56
- }
57
-
58
- const BUILTIN_ROLES = {
59
- ADMIN: new Role(
60
- BUILTIN_IDS.ADMIN,
61
- "Admin",
62
- BuiltinPermissionID.ADMIN
63
- ).addInheritance(BUILTIN_IDS.POWER),
64
- POWER: new Role(
65
- BUILTIN_IDS.POWER,
66
- "Power",
67
- BuiltinPermissionID.POWER
68
- ).addInheritance(BUILTIN_IDS.BASIC),
69
- BASIC: new Role(
70
- BUILTIN_IDS.BASIC,
71
- "Basic",
72
- BuiltinPermissionID.WRITE
73
- ).addInheritance(BUILTIN_IDS.PUBLIC),
74
- PUBLIC: new Role(BUILTIN_IDS.PUBLIC, "Public", BuiltinPermissionID.PUBLIC),
75
- BUILDER: new Role(BUILTIN_IDS.BUILDER, "Builder", BuiltinPermissionID.ADMIN),
76
- }
77
-
78
- export function getBuiltinRoles(): { [key: string]: RoleDoc } {
79
- return cloneDeep(BUILTIN_ROLES)
80
- }
81
-
82
- export const BUILTIN_ROLE_ID_ARRAY = Object.values(BUILTIN_ROLES).map(
83
- role => role._id
84
- )
85
-
86
- export const BUILTIN_ROLE_NAME_ARRAY = Object.values(BUILTIN_ROLES).map(
87
- role => role.name
88
- )
89
-
90
- export function isBuiltin(role?: string) {
91
- return BUILTIN_ROLE_ID_ARRAY.some(builtin => role?.includes(builtin))
92
- }
93
-
94
- /**
95
- * Works through the inheritance ranks to see how far up the builtin stack this ID is.
96
- */
97
- export function builtinRoleToNumber(id?: string) {
98
- if (!id) {
99
- return 0
100
- }
101
- const builtins = getBuiltinRoles()
102
- const MAX = Object.values(builtins).length + 1
103
- if (id === BUILTIN_IDS.ADMIN || id === BUILTIN_IDS.BUILDER) {
104
- return MAX
105
- }
106
- let role = builtins[id],
107
- count = 0
108
- do {
109
- if (!role) {
110
- break
111
- }
112
- role = builtins[role.inherits!]
113
- count++
114
- } while (role !== null)
115
- return count
116
- }
117
-
118
- /**
119
- * Converts any role to a number, but has to be async to get the roles from db.
120
- */
121
- export async function roleToNumber(id?: string) {
122
- if (isBuiltin(id)) {
123
- return builtinRoleToNumber(id)
124
- }
125
- const hierarchy = (await getUserRoleHierarchy(id)) as RoleDoc[]
126
- for (let role of hierarchy) {
127
- if (isBuiltin(role?.inherits)) {
128
- return builtinRoleToNumber(role.inherits) + 1
129
- }
130
- }
131
- return 0
132
- }
133
-
134
- /**
135
- * Returns whichever builtin roleID is lower.
136
- */
137
- export function lowerBuiltinRoleID(roleId1?: string, roleId2?: string): string {
138
- if (!roleId1) {
139
- return roleId2 as string
140
- }
141
- if (!roleId2) {
142
- return roleId1 as string
143
- }
144
- return builtinRoleToNumber(roleId1) > builtinRoleToNumber(roleId2)
145
- ? roleId2
146
- : roleId1
147
- }
148
-
149
- /**
150
- * Gets the role object, this is mainly useful for two purposes, to check if the level exists and
151
- * to check if the role inherits any others.
152
- * @param {string|null} roleId The level ID to lookup.
153
- * @param {object|null} opts options for the function, like whether to halt errors, instead return public.
154
- * @returns {Promise<Role|object|null>} The role object, which may contain an "inherits" property.
155
- */
156
- export async function getRole(
157
- roleId?: string,
158
- opts?: { defaultPublic?: boolean }
159
- ): Promise<RoleDoc | undefined> {
160
- if (!roleId) {
161
- return undefined
162
- }
163
- let role: any = {}
164
- // built in roles mostly come from the in-code implementation,
165
- // but can be extended by a doc stored about them (e.g. permissions)
166
- if (isBuiltin(roleId)) {
167
- role = cloneDeep(
168
- Object.values(BUILTIN_ROLES).find(role => role._id === roleId)
169
- )
170
- } else {
171
- // make sure has the prefix (if it has it then it won't be added)
172
- roleId = prefixRoleID(roleId)
173
- }
174
- try {
175
- const db = getAppDB()
176
- const dbRole = await db.get(getDBRoleID(roleId))
177
- role = Object.assign(role, dbRole)
178
- // finalise the ID
179
- role._id = getExternalRoleID(role._id, role.version)
180
- } catch (err) {
181
- if (!isBuiltin(roleId) && opts?.defaultPublic) {
182
- return cloneDeep(BUILTIN_ROLES.PUBLIC)
183
- }
184
- // only throw an error if there is no role at all
185
- if (Object.keys(role).length === 0) {
186
- throw err
187
- }
188
- }
189
- return role
190
- }
191
-
192
- /**
193
- * Simple function to get all the roles based on the top level user role ID.
194
- */
195
- async function getAllUserRoles(userRoleId?: string): Promise<RoleDoc[]> {
196
- // admins have access to all roles
197
- if (userRoleId === BUILTIN_IDS.ADMIN) {
198
- return getAllRoles()
199
- }
200
- let currentRole = await getRole(userRoleId)
201
- let roles = currentRole ? [currentRole] : []
202
- let roleIds = [userRoleId]
203
- // get all the inherited roles
204
- while (
205
- currentRole &&
206
- currentRole.inherits &&
207
- roleIds.indexOf(currentRole.inherits) === -1
208
- ) {
209
- roleIds.push(currentRole.inherits)
210
- currentRole = await getRole(currentRole.inherits)
211
- if (currentRole) {
212
- roles.push(currentRole)
213
- }
214
- }
215
- return roles
216
- }
217
-
218
- /**
219
- * Returns an ordered array of the user's inherited role IDs, this can be used
220
- * to determine if a user can access something that requires a specific role.
221
- * @param {string} userRoleId The user's role ID, this can be found in their access token.
222
- * @param {object} opts Various options, such as whether to only retrieve the IDs (default true).
223
- * @returns {Promise<string[]|object[]>} returns an ordered array of the roles, with the first being their
224
- * highest level of access and the last being the lowest level.
225
- */
226
- export async function getUserRoleHierarchy(
227
- userRoleId?: string,
228
- opts = { idOnly: true }
229
- ) {
230
- // special case, if they don't have a role then they are a public user
231
- const roles = await getAllUserRoles(userRoleId)
232
- return opts.idOnly ? roles.map(role => role._id) : roles
233
- }
234
-
235
- // this function checks that the provided permissions are in an array format
236
- // some templates/older apps will use a simple string instead of array for roles
237
- // convert the string to an array using the theory that write is higher than read
238
- export function checkForRoleResourceArray(
239
- rolePerms: { [key: string]: string[] },
240
- resourceId: string
241
- ) {
242
- if (rolePerms && !Array.isArray(rolePerms[resourceId])) {
243
- const permLevel = rolePerms[resourceId] as any
244
- rolePerms[resourceId] = [permLevel]
245
- if (permLevel === PermissionLevel.WRITE) {
246
- rolePerms[resourceId].push(PermissionLevel.READ)
247
- }
248
- }
249
- return rolePerms
250
- }
251
-
252
- /**
253
- * Given an app ID this will retrieve all of the roles that are currently within that app.
254
- * @return {Promise<object[]>} An array of the role objects that were found.
255
- */
256
- export async function getAllRoles(appId?: string) {
257
- if (appId) {
258
- return doWithDB(appId, internal)
259
- } else {
260
- let appDB
261
- try {
262
- appDB = getAppDB()
263
- } catch (error) {
264
- // We don't have any apps, so we'll just use the built-in roles
265
- }
266
- return internal(appDB)
267
- }
268
- async function internal(db: any) {
269
- let roles: RoleDoc[] = []
270
- if (db) {
271
- const body = await db.allDocs(
272
- getRoleParams(null, {
273
- include_docs: true,
274
- })
275
- )
276
- roles = body.rows.map((row: any) => row.doc)
277
- roles.forEach(
278
- role => (role._id = getExternalRoleID(role._id!, role.version))
279
- )
280
- }
281
- const builtinRoles = getBuiltinRoles()
282
-
283
- // need to combine builtin with any DB record of them (for sake of permissions)
284
- for (let builtinRoleId of EXTERNAL_BUILTIN_ROLE_IDS) {
285
- const builtinRole = builtinRoles[builtinRoleId]
286
- const dbBuiltin = roles.filter(
287
- dbRole =>
288
- getExternalRoleID(dbRole._id!, dbRole.version) === builtinRoleId
289
- )[0]
290
- if (dbBuiltin == null) {
291
- roles.push(builtinRole || builtinRoles.BASIC)
292
- } else {
293
- // remove role and all back after combining with the builtin
294
- roles = roles.filter(role => role._id !== dbBuiltin._id)
295
- dbBuiltin._id = getExternalRoleID(dbBuiltin._id!, dbBuiltin.version)
296
- roles.push(Object.assign(builtinRole, dbBuiltin))
297
- }
298
- }
299
- // check permissions
300
- for (let role of roles) {
301
- if (!role.permissions) {
302
- continue
303
- }
304
- for (let resourceId of Object.keys(role.permissions)) {
305
- role.permissions = checkForRoleResourceArray(
306
- role.permissions,
307
- resourceId
308
- )
309
- }
310
- }
311
- return roles
312
- }
313
- }
314
-
315
- /**
316
- * This retrieves the required role for a resource
317
- * @param permLevel The level of request
318
- * @param resourceId The resource being requested
319
- * @param subResourceId The sub resource being requested
320
- * @return {Promise<{permissions}|Object>} returns the permissions required to access.
321
- */
322
- export async function getRequiredResourceRole(
323
- permLevel: string,
324
- { resourceId, subResourceId }: { resourceId?: string; subResourceId?: string }
325
- ) {
326
- const roles = await getAllRoles()
327
- let main = [],
328
- sub = []
329
- for (let role of roles) {
330
- // no permissions, ignore it
331
- if (!role.permissions) {
332
- continue
333
- }
334
- const mainRes = resourceId ? role.permissions[resourceId] : undefined
335
- const subRes = subResourceId ? role.permissions[subResourceId] : undefined
336
- if (mainRes && mainRes.indexOf(permLevel) !== -1) {
337
- main.push(role._id)
338
- } else if (subRes && subRes.indexOf(permLevel) !== -1) {
339
- sub.push(role._id)
340
- }
341
- }
342
- // for now just return the IDs
343
- return main.concat(sub)
344
- }
345
-
346
- export class AccessController {
347
- userHierarchies: { [key: string]: string[] }
348
- constructor() {
349
- this.userHierarchies = {}
350
- }
351
-
352
- async hasAccess(tryingRoleId?: string, userRoleId?: string) {
353
- // special cases, the screen has no role, the roles are the same or the user
354
- // is currently in the builder
355
- if (
356
- tryingRoleId == null ||
357
- tryingRoleId === "" ||
358
- tryingRoleId === userRoleId ||
359
- tryingRoleId === BUILTIN_IDS.BUILDER ||
360
- userRoleId === BUILTIN_IDS.BUILDER
361
- ) {
362
- return true
363
- }
364
- let roleIds = userRoleId ? this.userHierarchies[userRoleId] : null
365
- if (!roleIds && userRoleId) {
366
- roleIds = (await getUserRoleHierarchy(userRoleId, {
367
- idOnly: true,
368
- })) as string[]
369
- this.userHierarchies[userRoleId] = roleIds
370
- }
371
-
372
- return roleIds?.indexOf(tryingRoleId) !== -1
373
- }
374
-
375
- async checkScreensAccess(screens: Screen[], userRoleId: string) {
376
- let accessibleScreens = []
377
- // don't want to handle this with Promise.all as this would mean all custom roles would be
378
- // retrieved at same time, it is likely a custom role will be re-used and therefore want
379
- // to work in sync for performance save
380
- for (let screen of screens) {
381
- const accessible = await this.checkScreenAccess(screen, userRoleId)
382
- if (accessible) {
383
- accessibleScreens.push(accessible)
384
- }
385
- }
386
- return accessibleScreens
387
- }
388
-
389
- async checkScreenAccess(screen: Screen, userRoleId: string) {
390
- const roleId = screen && screen.routing ? screen.routing.roleId : undefined
391
- if (await this.hasAccess(roleId, userRoleId)) {
392
- return screen
393
- }
394
- return null
395
- }
396
- }
397
-
398
- /**
399
- * Adds the "role_" for builtin role IDs which are to be written to the DB (for permissions).
400
- */
401
- export function getDBRoleID(roleName: string) {
402
- if (roleName?.startsWith(DocumentType.ROLE)) {
403
- return roleName
404
- }
405
- return prefixRoleID(roleName)
406
- }
407
-
408
- /**
409
- * Remove the "role_" from builtin role IDs that have been written to the DB (for permissions).
410
- */
411
- export function getExternalRoleID(roleId: string, version?: string) {
412
- // for built-in roles we want to remove the DB role ID element (role_)
413
- if (
414
- (roleId.startsWith(DocumentType.ROLE) && isBuiltin(roleId)) ||
415
- version === RoleIDVersion.NAME
416
- ) {
417
- return roleId.split(`${DocumentType.ROLE}${SEPARATOR}`)[1]
418
- }
419
- return roleId
420
- }
@@ -1,120 +0,0 @@
1
- const redis = require("../redis/init")
2
- const { v4: uuidv4 } = require("uuid")
3
- const { logWarn } = require("../logging")
4
- import env from "../environment"
5
- import {
6
- Session,
7
- ScannedSession,
8
- SessionKey,
9
- CreateSession,
10
- } from "@budibase/types"
11
-
12
- // a week in seconds
13
- const EXPIRY_SECONDS = 86400 * 7
14
-
15
- function makeSessionID(userId: string, sessionId: string) {
16
- return `${userId}/${sessionId}`
17
- }
18
-
19
- export async function getSessionsForUser(userId: string): Promise<Session[]> {
20
- if (!userId) {
21
- console.trace("Cannot get sessions for undefined userId")
22
- return []
23
- }
24
- const client = await redis.getSessionClient()
25
- const sessions: ScannedSession[] = await client.scan(userId)
26
- return sessions.map(session => session.value)
27
- }
28
-
29
- export async function invalidateSessions(
30
- userId: string,
31
- opts: { sessionIds?: string[]; reason?: string } = {}
32
- ) {
33
- try {
34
- const reason = opts?.reason || "unknown"
35
- let sessionIds: string[] = opts.sessionIds || []
36
- let sessionKeys: SessionKey[]
37
-
38
- // If no sessionIds, get all the sessions for the user
39
- if (sessionIds.length === 0) {
40
- const sessions = await getSessionsForUser(userId)
41
- sessionKeys = sessions.map(session => ({
42
- key: makeSessionID(session.userId, session.sessionId),
43
- }))
44
- } else {
45
- // use the passed array of sessionIds
46
- sessionIds = Array.isArray(sessionIds) ? sessionIds : [sessionIds]
47
- sessionKeys = sessionIds.map(sessionId => ({
48
- key: makeSessionID(userId, sessionId),
49
- }))
50
- }
51
-
52
- if (sessionKeys && sessionKeys.length > 0) {
53
- const client = await redis.getSessionClient()
54
- const promises = []
55
- for (let sessionKey of sessionKeys) {
56
- promises.push(client.delete(sessionKey.key))
57
- }
58
- if (!env.isTest()) {
59
- logWarn(
60
- `Invalidating sessions for ${userId} (reason: ${reason}) - ${sessionKeys
61
- .map(sessionKey => sessionKey.key)
62
- .join(", ")}`
63
- )
64
- }
65
- await Promise.all(promises)
66
- }
67
- } catch (err) {
68
- console.error(`Error invalidating sessions: ${err}`)
69
- }
70
- }
71
-
72
- export async function createASession(
73
- userId: string,
74
- createSession: CreateSession
75
- ) {
76
- // invalidate all other sessions
77
- await invalidateSessions(userId, { reason: "creation" })
78
-
79
- const client = await redis.getSessionClient()
80
- const sessionId = createSession.sessionId
81
- const csrfToken = createSession.csrfToken ? createSession.csrfToken : uuidv4()
82
- const key = makeSessionID(userId, sessionId)
83
-
84
- const session: Session = {
85
- ...createSession,
86
- csrfToken,
87
- createdAt: new Date().toISOString(),
88
- lastAccessedAt: new Date().toISOString(),
89
- userId,
90
- }
91
- await client.store(key, session, EXPIRY_SECONDS)
92
- return session
93
- }
94
-
95
- export async function updateSessionTTL(session: Session) {
96
- const client = await redis.getSessionClient()
97
- const key = makeSessionID(session.userId, session.sessionId)
98
- session.lastAccessedAt = new Date().toISOString()
99
- await client.store(key, session, EXPIRY_SECONDS)
100
- }
101
-
102
- export async function endSession(userId: string, sessionId: string) {
103
- const client = await redis.getSessionClient()
104
- await client.delete(makeSessionID(userId, sessionId))
105
- }
106
-
107
- export async function getSession(
108
- userId: string,
109
- sessionId: string
110
- ): Promise<Session> {
111
- if (!userId || !sessionId) {
112
- throw new Error(`Invalid session details - ${userId} - ${sessionId}`)
113
- }
114
- const client = await redis.getSessionClient()
115
- const session = await client.get(makeSessionID(userId, sessionId))
116
- if (!session) {
117
- throw new Error(`Session not found - ${userId} - ${sessionId}`)
118
- }
119
- return session
120
- }
@@ -1,31 +0,0 @@
1
- import { encrypt, decrypt, SecretOption, getSecret } from "../encryption"
2
- import env from "../../environment"
3
-
4
- describe("encryption", () => {
5
- it("should throw an error if API encryption key is not set", () => {
6
- const jwt = getSecret(SecretOption.API)
7
- expect(jwt).toBe(env.JWT_SECRET)
8
- })
9
-
10
- it("should throw an error if encryption key is not set", () => {
11
- expect(() => getSecret(SecretOption.ENCRYPTION)).toThrow(
12
- 'Secret "ENCRYPTION_KEY" has not been set in environment.'
13
- )
14
- })
15
-
16
- it("should encrypt and decrypt a string using API encryption key", () => {
17
- env._set("API_ENCRYPTION_KEY", "api_secret")
18
- const plaintext = "budibase"
19
- const apiEncrypted = encrypt(plaintext, SecretOption.API)
20
- const decrypted = decrypt(apiEncrypted, SecretOption.API)
21
- expect(decrypted).toEqual(plaintext)
22
- })
23
-
24
- it("should encrypt and decrypt a string using encryption key", () => {
25
- env._set("ENCRYPTION_KEY", "normal_secret")
26
- const plaintext = "budibase"
27
- const encryptionEncrypted = encrypt(plaintext, SecretOption.ENCRYPTION)
28
- const decrypted = decrypt(encryptionEncrypted, SecretOption.ENCRYPTION)
29
- expect(decrypted).toEqual(plaintext)
30
- })
31
- })
@@ -1,145 +0,0 @@
1
- import cloneDeep from "lodash/cloneDeep"
2
- import * as permissions from "../permissions"
3
- import { BUILTIN_ROLE_IDS } from "../roles"
4
-
5
- describe("levelToNumber", () => {
6
- it("should return 0 for EXECUTE", () => {
7
- expect(permissions.levelToNumber(permissions.PermissionLevel.EXECUTE)).toBe(
8
- 0
9
- )
10
- })
11
-
12
- it("should return 1 for READ", () => {
13
- expect(permissions.levelToNumber(permissions.PermissionLevel.READ)).toBe(1)
14
- })
15
-
16
- it("should return 2 for WRITE", () => {
17
- expect(permissions.levelToNumber(permissions.PermissionLevel.WRITE)).toBe(2)
18
- })
19
-
20
- it("should return 3 for ADMIN", () => {
21
- expect(permissions.levelToNumber(permissions.PermissionLevel.ADMIN)).toBe(3)
22
- })
23
-
24
- it("should return -1 for an unknown permission level", () => {
25
- expect(
26
- permissions.levelToNumber("unknown" as permissions.PermissionLevel)
27
- ).toBe(-1)
28
- })
29
- })
30
- describe("getAllowedLevels", () => {
31
- it('should return ["execute"] for EXECUTE', () => {
32
- expect(
33
- permissions.getAllowedLevels(permissions.PermissionLevel.EXECUTE)
34
- ).toEqual([permissions.PermissionLevel.EXECUTE])
35
- })
36
-
37
- it('should return ["execute", "read"] for READ', () => {
38
- expect(
39
- permissions.getAllowedLevels(permissions.PermissionLevel.READ)
40
- ).toEqual([
41
- permissions.PermissionLevel.EXECUTE,
42
- permissions.PermissionLevel.READ,
43
- ])
44
- })
45
-
46
- it('should return ["execute", "read", "write"] for WRITE', () => {
47
- expect(
48
- permissions.getAllowedLevels(permissions.PermissionLevel.WRITE)
49
- ).toEqual([
50
- permissions.PermissionLevel.EXECUTE,
51
- permissions.PermissionLevel.READ,
52
- permissions.PermissionLevel.WRITE,
53
- ])
54
- })
55
-
56
- it('should return ["execute", "read", "write"] for ADMIN', () => {
57
- expect(
58
- permissions.getAllowedLevels(permissions.PermissionLevel.ADMIN)
59
- ).toEqual([
60
- permissions.PermissionLevel.EXECUTE,
61
- permissions.PermissionLevel.READ,
62
- permissions.PermissionLevel.WRITE,
63
- ])
64
- })
65
-
66
- it("should return [] for an unknown permission level", () => {
67
- expect(
68
- permissions.getAllowedLevels("unknown" as permissions.PermissionLevel)
69
- ).toEqual([])
70
- })
71
- })
72
-
73
- describe("doesHaveBasePermission", () => {
74
- it("should return true if base permission has the required level", () => {
75
- const permType = permissions.PermissionType.USER
76
- const permLevel = permissions.PermissionLevel.READ
77
- const rolesHierarchy = [
78
- {
79
- roleId: BUILTIN_ROLE_IDS.ADMIN,
80
- permissionId: permissions.BuiltinPermissionID.ADMIN,
81
- },
82
- ]
83
- expect(
84
- permissions.doesHaveBasePermission(permType, permLevel, rolesHierarchy)
85
- ).toBe(true)
86
- })
87
-
88
- it("should return false if base permission does not have the required level", () => {
89
- const permType = permissions.PermissionType.APP
90
- const permLevel = permissions.PermissionLevel.READ
91
- const rolesHierarchy = [
92
- {
93
- roleId: BUILTIN_ROLE_IDS.PUBLIC,
94
- permissionId: permissions.BuiltinPermissionID.PUBLIC,
95
- },
96
- ]
97
- expect(
98
- permissions.doesHaveBasePermission(permType, permLevel, rolesHierarchy)
99
- ).toBe(false)
100
- })
101
- })
102
-
103
- describe("isPermissionLevelHigherThanRead", () => {
104
- it("should return true if level is higher than read", () => {
105
- expect(
106
- permissions.isPermissionLevelHigherThanRead(
107
- permissions.PermissionLevel.WRITE
108
- )
109
- ).toBe(true)
110
- })
111
-
112
- it("should return false if level is read or lower", () => {
113
- expect(
114
- permissions.isPermissionLevelHigherThanRead(
115
- permissions.PermissionLevel.READ
116
- )
117
- ).toBe(false)
118
- })
119
- })
120
-
121
- describe("getBuiltinPermissions", () => {
122
- it("returns a clone of the builtin permissions", () => {
123
- const builtins = permissions.getBuiltinPermissions()
124
- expect(builtins).toEqual(cloneDeep(permissions.BUILTIN_PERMISSIONS))
125
- expect(builtins).not.toBe(permissions.BUILTIN_PERMISSIONS)
126
- })
127
- })
128
-
129
- describe("getBuiltinPermissionByID", () => {
130
- it("returns correct permission object for valid ID", () => {
131
- const expectedPermission = {
132
- _id: permissions.BuiltinPermissionID.PUBLIC,
133
- name: "Public",
134
- permissions: [
135
- new permissions.Permission(
136
- permissions.PermissionType.WEBHOOK,
137
- permissions.PermissionLevel.EXECUTE
138
- ),
139
- ],
140
- }
141
- expect(permissions.getBuiltinPermissionByID("public")).toEqual(
142
- expectedPermission
143
- )
144
- })
145
- })