@directus/api 20.0.0 → 21.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/dist/app.js +5 -5
  2. package/dist/auth/drivers/ldap.js +5 -5
  3. package/dist/auth/drivers/local.js +4 -4
  4. package/dist/auth/drivers/oauth2.js +5 -5
  5. package/dist/auth/drivers/openid.js +3 -5
  6. package/dist/auth/drivers/saml.js +1 -1
  7. package/dist/auth.js +1 -1
  8. package/dist/cache.js +4 -1
  9. package/dist/cli/commands/bootstrap/index.js +10 -3
  10. package/dist/cli/commands/count/index.js +1 -1
  11. package/dist/cli/commands/database/install.js +1 -1
  12. package/dist/cli/commands/database/migrate.js +1 -1
  13. package/dist/cli/commands/init/index.js +9 -10
  14. package/dist/cli/commands/roles/create.js +1 -1
  15. package/dist/cli/commands/schema/apply.js +1 -1
  16. package/dist/cli/commands/schema/snapshot.js +1 -1
  17. package/dist/cli/commands/users/create.js +1 -1
  18. package/dist/cli/commands/users/passwd.js +1 -1
  19. package/dist/cli/load-extensions.js +1 -1
  20. package/dist/cli/utils/defaults.d.ts +4 -11
  21. package/dist/cli/utils/defaults.js +7 -1
  22. package/dist/constants.d.ts +1 -1
  23. package/dist/constants.js +2 -2
  24. package/dist/controllers/access.d.ts +2 -0
  25. package/dist/controllers/access.js +148 -0
  26. package/dist/controllers/assets.js +1 -1
  27. package/dist/controllers/auth.js +6 -17
  28. package/dist/controllers/files.js +1 -1
  29. package/dist/controllers/permissions.js +14 -2
  30. package/dist/controllers/policies.d.ts +2 -0
  31. package/dist/controllers/policies.js +169 -0
  32. package/dist/controllers/roles.js +22 -1
  33. package/dist/controllers/schema.js +1 -1
  34. package/dist/controllers/tus.js +11 -23
  35. package/dist/controllers/users.js +0 -55
  36. package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +16 -0
  37. package/dist/database/get-ast-from-query/get-ast-from-query.js +82 -0
  38. package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +13 -0
  39. package/dist/database/get-ast-from-query/lib/convert-wildcards.js +69 -0
  40. package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +15 -0
  41. package/dist/database/get-ast-from-query/lib/parse-fields.js +190 -0
  42. package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +14 -0
  43. package/dist/database/get-ast-from-query/utils/get-deep-query.js +17 -0
  44. package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +2 -0
  45. package/dist/database/get-ast-from-query/utils/get-related-collection.js +13 -0
  46. package/dist/database/get-ast-from-query/utils/get-relation.d.ts +2 -0
  47. package/dist/database/get-ast-from-query/utils/get-relation.js +7 -0
  48. package/dist/database/helpers/fn/types.d.ts +2 -1
  49. package/dist/database/helpers/fn/types.js +1 -1
  50. package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
  51. package/dist/database/helpers/geometry/dialects/mssql.js +4 -2
  52. package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
  53. package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
  54. package/dist/database/helpers/geometry/dialects/oracle.js +5 -3
  55. package/dist/database/helpers/geometry/types.d.ts +1 -1
  56. package/dist/database/helpers/geometry/types.js +4 -2
  57. package/dist/database/index.js +3 -2
  58. package/dist/database/migrations/20210518A-add-foreign-key-constraints.js +1 -1
  59. package/dist/database/migrations/20210519A-add-system-fk-triggers.js +1 -1
  60. package/dist/database/migrations/20210802A-replace-groups.js +1 -1
  61. package/dist/database/migrations/20230721A-require-shares-fields.js +1 -1
  62. package/dist/database/migrations/20240710A-permissions-policies.d.ts +3 -0
  63. package/dist/database/migrations/20240710A-permissions-policies.js +169 -0
  64. package/dist/database/migrations/run.js +1 -1
  65. package/dist/database/run-ast/lib/get-db-query.d.ts +4 -0
  66. package/dist/database/run-ast/lib/get-db-query.js +208 -0
  67. package/dist/database/run-ast/lib/parse-current-level.d.ts +7 -0
  68. package/dist/database/run-ast/lib/parse-current-level.js +41 -0
  69. package/dist/database/run-ast/run-ast.d.ts +7 -0
  70. package/dist/database/run-ast/run-ast.js +107 -0
  71. package/dist/database/{run-ast.d.ts → run-ast/types.d.ts} +3 -9
  72. package/dist/database/run-ast/types.js +1 -0
  73. package/dist/database/run-ast/utils/apply-case-when.d.ts +16 -0
  74. package/dist/database/run-ast/utils/apply-case-when.js +26 -0
  75. package/dist/database/run-ast/utils/apply-parent-filters.d.ts +3 -0
  76. package/dist/database/run-ast/utils/apply-parent-filters.js +55 -0
  77. package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +10 -0
  78. package/dist/database/run-ast/utils/get-column-pre-processor.js +57 -0
  79. package/dist/database/run-ast/utils/get-field-alias.d.ts +2 -0
  80. package/dist/database/run-ast/utils/get-field-alias.js +4 -0
  81. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +5 -0
  82. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +23 -0
  83. package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +3 -0
  84. package/dist/database/run-ast/utils/merge-with-parent-items.js +87 -0
  85. package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +3 -0
  86. package/dist/database/run-ast/utils/remove-temporary-fields.js +73 -0
  87. package/dist/emitter.js +1 -1
  88. package/dist/extensions/lib/get-shared-deps-mapping.js +1 -1
  89. package/dist/extensions/lib/installation/manager.js +1 -1
  90. package/dist/extensions/lib/sandbox/register/call-reference.js +1 -1
  91. package/dist/extensions/lib/sandbox/sdk/generators/log.js +1 -1
  92. package/dist/extensions/lib/sync-extensions.js +1 -1
  93. package/dist/extensions/manager.js +1 -1
  94. package/dist/flows.js +4 -5
  95. package/dist/{logger.js → logger/index.js} +2 -8
  96. package/dist/logger/redact-query.d.ts +1 -0
  97. package/dist/logger/redact-query.js +13 -0
  98. package/dist/mailer.js +1 -1
  99. package/dist/middleware/authenticate.js +2 -7
  100. package/dist/middleware/cache.js +2 -2
  101. package/dist/middleware/error-handler.js +1 -1
  102. package/dist/middleware/rate-limiter-global.js +1 -1
  103. package/dist/middleware/respond.js +2 -2
  104. package/dist/operations/log/index.js +1 -1
  105. package/dist/operations/mail/index.js +1 -1
  106. package/dist/permissions/cache.d.ts +2 -0
  107. package/dist/permissions/cache.js +23 -0
  108. package/dist/permissions/lib/fetch-permissions.d.ts +10 -0
  109. package/dist/permissions/lib/fetch-permissions.js +55 -0
  110. package/dist/permissions/lib/fetch-policies.d.ts +7 -0
  111. package/dist/permissions/lib/fetch-policies.js +28 -0
  112. package/dist/permissions/lib/fetch-roles-tree.d.ts +3 -0
  113. package/dist/permissions/lib/fetch-roles-tree.js +28 -0
  114. package/dist/{services/permissions → permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
  115. package/dist/permissions/lib/with-app-minimal-permissions.js +10 -0
  116. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +7 -0
  117. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +56 -0
  118. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +3 -0
  119. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +16 -0
  120. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +8 -0
  121. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +24 -0
  122. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +9 -0
  123. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +31 -0
  124. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +16 -0
  125. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +27 -0
  126. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +10 -0
  127. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +23 -0
  128. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +5 -0
  129. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +7 -0
  130. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +5 -0
  131. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +10 -0
  132. package/dist/permissions/modules/fetch-global-access/types.d.ts +4 -0
  133. package/dist/permissions/modules/fetch-global-access/types.js +1 -0
  134. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +4 -0
  135. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +27 -0
  136. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +12 -0
  137. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +32 -0
  138. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +4 -0
  139. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +29 -0
  140. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +4 -0
  141. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +49 -0
  142. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +3 -0
  143. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +56 -0
  144. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +4 -0
  145. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +8 -0
  146. package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +9 -0
  147. package/dist/permissions/modules/process-ast/lib/inject-cases.js +93 -0
  148. package/dist/permissions/modules/process-ast/process-ast.d.ts +9 -0
  149. package/dist/permissions/modules/process-ast/process-ast.js +39 -0
  150. package/dist/permissions/modules/process-ast/types.d.ts +24 -0
  151. package/dist/permissions/modules/process-ast/types.js +1 -0
  152. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +2 -0
  153. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +7 -0
  154. package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +12 -0
  155. package/dist/permissions/modules/process-ast/utils/dedupe-access.js +30 -0
  156. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +15 -0
  157. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +50 -0
  158. package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +3 -0
  159. package/dist/permissions/modules/process-ast/utils/find-related-collection.js +9 -0
  160. package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +3 -0
  161. package/dist/permissions/modules/process-ast/utils/flatten-filter.js +34 -0
  162. package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +1 -0
  163. package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +3 -0
  164. package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +5 -0
  165. package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +7 -0
  166. package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +2 -0
  167. package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +3 -0
  168. package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +2 -0
  169. package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +3 -0
  170. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +3 -0
  171. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +16 -0
  172. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +2 -0
  173. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +12 -0
  174. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +2 -0
  175. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +28 -0
  176. package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +5 -0
  177. package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +12 -0
  178. package/dist/permissions/modules/process-payload/process-payload.d.ts +13 -0
  179. package/dist/permissions/modules/process-payload/process-payload.js +77 -0
  180. package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +12 -0
  181. package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +11 -0
  182. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +9 -0
  183. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +33 -0
  184. package/dist/permissions/modules/validate-access/validate-access.d.ts +14 -0
  185. package/dist/permissions/modules/validate-access/validate-access.js +28 -0
  186. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +1 -0
  187. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +8 -0
  188. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +5 -0
  189. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +10 -0
  190. package/dist/permissions/types.d.ts +6 -0
  191. package/dist/permissions/types.js +1 -0
  192. package/dist/permissions/utils/create-default-accountability.d.ts +2 -0
  193. package/dist/permissions/utils/create-default-accountability.js +11 -0
  194. package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +8 -0
  195. package/dist/permissions/utils/extract-required-dynamic-variable-context.js +27 -0
  196. package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +9 -0
  197. package/dist/permissions/utils/fetch-dynamic-variable-context.js +43 -0
  198. package/dist/permissions/utils/filter-policies-by-ip.d.ts +2 -0
  199. package/dist/permissions/utils/filter-policies-by-ip.js +15 -0
  200. package/dist/permissions/utils/get-unaliased-field-key.d.ts +5 -0
  201. package/dist/permissions/utils/get-unaliased-field-key.js +17 -0
  202. package/dist/permissions/utils/process-permissions.d.ts +7 -0
  203. package/dist/permissions/utils/process-permissions.js +9 -0
  204. package/dist/permissions/utils/with-cache.d.ts +10 -0
  205. package/dist/permissions/utils/with-cache.js +25 -0
  206. package/dist/request/is-denied-ip.js +1 -1
  207. package/dist/server.js +1 -1
  208. package/dist/services/access.d.ts +10 -0
  209. package/dist/services/access.js +43 -0
  210. package/dist/services/activity.js +23 -11
  211. package/dist/services/assets.d.ts +2 -3
  212. package/dist/services/assets.js +11 -6
  213. package/dist/services/authentication.js +18 -18
  214. package/dist/services/collections.js +18 -17
  215. package/dist/services/fields.d.ts +0 -1
  216. package/dist/services/fields.js +53 -24
  217. package/dist/services/files/utils/get-metadata.js +1 -1
  218. package/dist/services/files.js +25 -15
  219. package/dist/services/graphql/index.d.ts +3 -3
  220. package/dist/services/graphql/index.js +126 -22
  221. package/dist/services/graphql/subscription.js +2 -4
  222. package/dist/services/graphql/utils/process-error.js +1 -1
  223. package/dist/services/graphql/utils/sanitize-gql-schema.js +1 -1
  224. package/dist/services/import-export.js +19 -5
  225. package/dist/services/index.d.ts +3 -2
  226. package/dist/services/index.js +3 -2
  227. package/dist/services/items.d.ts +3 -3
  228. package/dist/services/items.js +115 -44
  229. package/dist/services/mail/index.js +1 -1
  230. package/dist/services/meta.js +60 -23
  231. package/dist/services/notifications.js +15 -7
  232. package/dist/services/payload.d.ts +9 -10
  233. package/dist/services/payload.js +18 -3
  234. package/dist/services/{permissions/index.d.ts → permissions.d.ts} +5 -7
  235. package/dist/services/{permissions/index.js → permissions.js} +30 -54
  236. package/dist/services/policies.d.ts +12 -0
  237. package/dist/services/policies.js +87 -0
  238. package/dist/services/relations.d.ts +0 -6
  239. package/dist/services/relations.js +26 -29
  240. package/dist/services/roles.d.ts +4 -12
  241. package/dist/services/roles.js +57 -424
  242. package/dist/services/server.js +1 -1
  243. package/dist/services/shares.d.ts +0 -2
  244. package/dist/services/shares.js +13 -9
  245. package/dist/services/specifications.d.ts +2 -2
  246. package/dist/services/specifications.js +39 -27
  247. package/dist/services/tus/data-store.js +3 -1
  248. package/dist/services/users.d.ts +1 -5
  249. package/dist/services/users.js +79 -162
  250. package/dist/services/utils.js +11 -7
  251. package/dist/services/versions.d.ts +0 -2
  252. package/dist/services/versions.js +34 -10
  253. package/dist/services/webhooks.js +1 -1
  254. package/dist/telemetry/lib/get-report.js +2 -2
  255. package/dist/telemetry/lib/track.js +1 -1
  256. package/dist/telemetry/utils/check-user-limits.d.ts +5 -0
  257. package/dist/telemetry/utils/check-user-limits.js +19 -0
  258. package/dist/types/ast.d.ts +43 -1
  259. package/dist/types/items.d.ts +11 -0
  260. package/dist/utils/apply-diff.js +1 -1
  261. package/dist/utils/apply-query.d.ts +4 -3
  262. package/dist/utils/apply-query.js +37 -8
  263. package/dist/utils/delete-from-require-cache.js +1 -1
  264. package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +17 -0
  265. package/dist/utils/fetch-user-count/fetch-access-lookup.js +22 -0
  266. package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +16 -0
  267. package/dist/utils/fetch-user-count/fetch-access-roles.js +37 -0
  268. package/dist/utils/fetch-user-count/fetch-active-users.d.ts +6 -0
  269. package/dist/utils/fetch-user-count/fetch-active-users.js +3 -0
  270. package/dist/utils/fetch-user-count/fetch-user-count.d.ts +12 -0
  271. package/dist/utils/fetch-user-count/fetch-user-count.js +57 -0
  272. package/dist/utils/fetch-user-count/get-user-count-query.d.ts +20 -0
  273. package/dist/utils/fetch-user-count/get-user-count-query.js +17 -0
  274. package/dist/utils/get-accountability-for-role.js +16 -25
  275. package/dist/utils/get-accountability-for-token.js +17 -16
  276. package/dist/utils/get-cache-key.d.ts +1 -1
  277. package/dist/utils/get-cache-key.js +12 -1
  278. package/dist/utils/get-column.d.ts +2 -1
  279. package/dist/utils/get-column.js +1 -0
  280. package/dist/utils/get-default-value.js +1 -1
  281. package/dist/utils/get-ip-from-req.js +1 -1
  282. package/dist/utils/get-schema.js +1 -1
  283. package/dist/utils/get-service.js +5 -1
  284. package/dist/utils/is-url-allowed.js +1 -1
  285. package/dist/utils/reduce-schema.d.ts +4 -6
  286. package/dist/utils/reduce-schema.js +16 -32
  287. package/dist/utils/sanitize-query.js +1 -1
  288. package/dist/utils/transaction.js +1 -1
  289. package/dist/utils/validate-env.js +1 -1
  290. package/dist/utils/validate-storage.js +1 -1
  291. package/dist/utils/validate-user-count-integrity.d.ts +13 -0
  292. package/dist/utils/validate-user-count-integrity.js +29 -0
  293. package/dist/websocket/authenticate.d.ts +0 -2
  294. package/dist/websocket/authenticate.js +0 -12
  295. package/dist/websocket/controllers/base.d.ts +1 -1
  296. package/dist/websocket/controllers/base.js +21 -17
  297. package/dist/websocket/controllers/graphql.js +2 -5
  298. package/dist/websocket/controllers/hooks.js +4 -0
  299. package/dist/websocket/controllers/rest.js +1 -3
  300. package/dist/websocket/errors.js +1 -1
  301. package/dist/websocket/handlers/subscribe.js +0 -2
  302. package/dist/websocket/utils/items.d.ts +1 -1
  303. package/package.json +28 -27
  304. package/dist/database/run-ast.js +0 -450
  305. package/dist/middleware/check-ip.d.ts +0 -2
  306. package/dist/middleware/check-ip.js +0 -37
  307. package/dist/middleware/get-permissions.d.ts +0 -3
  308. package/dist/middleware/get-permissions.js +0 -10
  309. package/dist/services/authorization.d.ts +0 -17
  310. package/dist/services/authorization.js +0 -456
  311. package/dist/services/permissions/lib/with-app-minimal-permissions.js +0 -13
  312. package/dist/telemetry/utils/check-increased-user-limits.d.ts +0 -7
  313. package/dist/telemetry/utils/check-increased-user-limits.js +0 -25
  314. package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +0 -6
  315. package/dist/telemetry/utils/get-role-counts-by-roles.js +0 -27
  316. package/dist/telemetry/utils/get-role-counts-by-users.d.ts +0 -11
  317. package/dist/telemetry/utils/get-role-counts-by-users.js +0 -34
  318. package/dist/telemetry/utils/get-user-count.d.ts +0 -8
  319. package/dist/telemetry/utils/get-user-count.js +0 -33
  320. package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +0 -7
  321. package/dist/telemetry/utils/get-user-counts-by-roles.js +0 -35
  322. package/dist/utils/get-ast-from-query.d.ts +0 -13
  323. package/dist/utils/get-ast-from-query.js +0 -297
  324. package/dist/utils/get-permissions.d.ts +0 -2
  325. package/dist/utils/get-permissions.js +0 -150
  326. package/dist/utils/merge-permissions-for-share.d.ts +0 -4
  327. package/dist/utils/merge-permissions-for-share.js +0 -109
  328. package/dist/utils/merge-permissions.d.ts +0 -3
  329. package/dist/utils/merge-permissions.js +0 -95
  330. /package/dist/{logger.d.ts → logger/index.d.ts} +0 -0
@@ -1,456 +0,0 @@
1
- import { ForbiddenError } from '@directus/errors';
2
- import { validatePayload } from '@directus/utils';
3
- import { FailedValidationError, joiValidationErrorItemToErrorExtensions } from '@directus/validation';
4
- import { cloneDeep, flatten, isArray, isNil, merge, reduce, uniq, uniqWith } from 'lodash-es';
5
- import { GENERATE_SPECIAL } from '../constants.js';
6
- import getDatabase from '../database/index.js';
7
- import { getRelationInfo } from '../utils/get-relation-info.js';
8
- import { parseFilterKey } from '../utils/parse-filter-key.js';
9
- import { ItemsService } from './items.js';
10
- import { PayloadService } from './payload.js';
11
- export class AuthorizationService {
12
- knex;
13
- accountability;
14
- payloadService;
15
- schema;
16
- constructor(options) {
17
- this.knex = options.knex || getDatabase();
18
- this.accountability = options.accountability || null;
19
- this.schema = options.schema;
20
- this.payloadService = new PayloadService('directus_permissions', {
21
- knex: this.knex,
22
- schema: this.schema,
23
- });
24
- }
25
- async processAST(ast, action = 'read') {
26
- const collectionsRequested = getCollectionsFromAST(ast);
27
- const permissionsForCollections = uniqWith(this.accountability?.permissions?.filter((permission) => {
28
- return (permission.action === action &&
29
- collectionsRequested.map(({ collection }) => collection).includes(permission.collection));
30
- }), (curr, prev) => curr.collection === prev.collection && curr.action === prev.action && curr.role === prev.role) ?? [];
31
- // If the permissions don't match the collections, you don't have permission to read all of them
32
- const uniqueCollectionsRequestedCount = uniq(collectionsRequested.map(({ collection }) => collection)).length;
33
- if (uniqueCollectionsRequestedCount !== permissionsForCollections.length) {
34
- throw new ForbiddenError();
35
- }
36
- validateFields(ast);
37
- validateFilterPermissions(ast, this.schema, action, this.accountability);
38
- applyFilters(ast, this.accountability);
39
- return ast;
40
- /**
41
- * Traverses the AST and returns an array of all collections that are being fetched
42
- */
43
- function getCollectionsFromAST(ast) {
44
- const collections = [];
45
- if (ast.type === 'a2o') {
46
- collections.push(...ast.names.map((name) => ({ collection: name, field: ast.fieldKey })));
47
- for (const children of Object.values(ast.children)) {
48
- for (const nestedNode of children) {
49
- if (nestedNode.type !== 'field' && nestedNode.type !== 'functionField') {
50
- collections.push(...getCollectionsFromAST(nestedNode));
51
- }
52
- }
53
- }
54
- }
55
- else {
56
- collections.push({
57
- collection: ast.name,
58
- field: ast.type === 'root' ? null : ast.fieldKey,
59
- });
60
- for (const nestedNode of ast.children) {
61
- if (nestedNode.type === 'functionField') {
62
- collections.push({
63
- collection: nestedNode.relatedCollection,
64
- field: null,
65
- });
66
- }
67
- else if (nestedNode.type !== 'field') {
68
- collections.push(...getCollectionsFromAST(nestedNode));
69
- }
70
- }
71
- }
72
- return collections;
73
- }
74
- function validateFields(ast) {
75
- if (ast.type !== 'field' && ast.type !== 'functionField') {
76
- if (ast.type === 'a2o') {
77
- for (const [collection, children] of Object.entries(ast.children)) {
78
- checkFields(collection, children, ast.query?.[collection]?.aggregate);
79
- }
80
- }
81
- else {
82
- checkFields(ast.name, ast.children, ast.query?.aggregate);
83
- }
84
- }
85
- function checkFields(collection, children, aggregate) {
86
- // We check the availability of the permissions in the step before this is run
87
- const permissions = permissionsForCollections.find((permission) => permission.collection === collection);
88
- const allowedFields = permissions.fields || [];
89
- if (aggregate && allowedFields.includes('*') === false) {
90
- for (const aliasMap of Object.values(aggregate)) {
91
- if (!aliasMap)
92
- continue;
93
- for (const column of Object.values(aliasMap)) {
94
- if (column === '*')
95
- continue;
96
- if (allowedFields.includes(column) === false)
97
- throw new ForbiddenError();
98
- }
99
- }
100
- }
101
- for (const childNode of children) {
102
- if (childNode.type !== 'field') {
103
- validateFields(childNode);
104
- continue;
105
- }
106
- if (allowedFields.includes('*'))
107
- continue;
108
- const { fieldName } = parseFilterKey(childNode.name);
109
- if (allowedFields.includes(fieldName) === false) {
110
- throw new ForbiddenError();
111
- }
112
- }
113
- }
114
- }
115
- function validateFilterPermissions(ast, schema, action, accountability) {
116
- let requiredFieldPermissions = {};
117
- if (ast.type !== 'field' && ast.type !== 'functionField') {
118
- if (ast.type === 'a2o') {
119
- for (const collection of Object.keys(ast.children)) {
120
- requiredFieldPermissions = mergeRequiredFieldPermissions(requiredFieldPermissions, extractRequiredFieldPermissions(collection, ast.query?.[collection]?.filter ?? {}));
121
- for (const child of ast.children[collection]) {
122
- const childPermissions = validateFilterPermissions(child, schema, action, accountability);
123
- if (Object.keys(childPermissions).length > 0) {
124
- //Only add relational field if deep child has a filter
125
- if (child.type !== 'field') {
126
- (requiredFieldPermissions[collection] || (requiredFieldPermissions[collection] = new Set())).add(child.fieldKey);
127
- }
128
- requiredFieldPermissions = mergeRequiredFieldPermissions(requiredFieldPermissions, childPermissions);
129
- }
130
- }
131
- }
132
- }
133
- else {
134
- requiredFieldPermissions = mergeRequiredFieldPermissions(requiredFieldPermissions, extractRequiredFieldPermissions(ast.name, ast.query?.filter ?? {}));
135
- for (const child of ast.children) {
136
- const childPermissions = validateFilterPermissions(child, schema, action, accountability);
137
- if (Object.keys(childPermissions).length > 0) {
138
- // Only add relational field if deep child has a filter
139
- if (child.type !== 'field') {
140
- (requiredFieldPermissions[ast.name] || (requiredFieldPermissions[ast.name] = new Set())).add(child.fieldKey);
141
- }
142
- requiredFieldPermissions = mergeRequiredFieldPermissions(requiredFieldPermissions, childPermissions);
143
- }
144
- }
145
- }
146
- }
147
- if (ast.type === 'root') {
148
- // Validate all required permissions once at the root level
149
- checkFieldPermissions(ast.name, schema, action, requiredFieldPermissions, ast.query.alias);
150
- }
151
- return requiredFieldPermissions;
152
- function extractRequiredFieldPermissions(collection, filter, parentCollection, parentField) {
153
- return reduce(filter, function (result, filterValue, filterKey) {
154
- if (filterKey.startsWith('_')) {
155
- if (filterKey === '_and' || filterKey === '_or') {
156
- if (isArray(filterValue)) {
157
- for (const filter of filterValue) {
158
- const requiredPermissions = extractRequiredFieldPermissions(collection, filter, parentCollection, parentField);
159
- result = mergeRequiredFieldPermissions(result, requiredPermissions);
160
- }
161
- }
162
- return result;
163
- }
164
- // Filter value is not a filter, so we should skip it
165
- return result;
166
- }
167
- // virtual o2m/o2a filter in the form of `$FOLLOW(...)`
168
- else if (collection && filterKey.startsWith('$FOLLOW')) {
169
- (result[collection] || (result[collection] = new Set())).add(filterKey);
170
- // add virtual relation to the required permissions
171
- const { relation } = getRelationInfo([], collection, filterKey);
172
- if (relation?.collection && relation?.field) {
173
- (result[relation.collection] || (result[relation.collection] = new Set())).add(relation.field);
174
- }
175
- }
176
- // a2o filter in the form of `item:collection`
177
- else if (filterKey.includes(':')) {
178
- const [field, collectionScope] = filterKey.split(':');
179
- if (collection) {
180
- // Add the `item` field to the required permissions
181
- (result[collection] || (result[collection] = new Set())).add(field);
182
- // Add the `collection` field to the required permissions
183
- result[collection].add('collection');
184
- }
185
- else {
186
- const relation = schema.relations.find((relation) => {
187
- return ((relation.collection === parentCollection && relation.field === parentField) ||
188
- (relation.related_collection === parentCollection && relation.meta?.one_field === parentField));
189
- });
190
- // Filter key not found in parent collection
191
- if (!relation)
192
- throw new ForbiddenError();
193
- const relatedCollectionName = relation.related_collection === parentCollection ? relation.collection : relation.related_collection;
194
- // Add the `item` field to the required permissions
195
- (result[relatedCollectionName] || (result[relatedCollectionName] = new Set())).add(field);
196
- // Add the `collection` field to the required permissions
197
- result[relatedCollectionName].add('collection');
198
- }
199
- // Continue to parse the filter for nested `collection` afresh
200
- const requiredPermissions = extractRequiredFieldPermissions(collectionScope, filterValue);
201
- result = mergeRequiredFieldPermissions(result, requiredPermissions);
202
- }
203
- else {
204
- if (collection) {
205
- (result[collection] || (result[collection] = new Set())).add(filterKey);
206
- }
207
- else {
208
- const relation = schema.relations.find((relation) => {
209
- return ((relation.collection === parentCollection && relation.field === parentField) ||
210
- (relation.related_collection === parentCollection && relation.meta?.one_field === parentField));
211
- });
212
- // Filter key not found in parent collection
213
- if (!relation)
214
- throw new ForbiddenError();
215
- parentCollection =
216
- relation.related_collection === parentCollection ? relation.collection : relation.related_collection;
217
- (result[parentCollection] || (result[parentCollection] = new Set())).add(filterKey);
218
- }
219
- if (typeof filterValue === 'object') {
220
- // Parent collection is undefined when we process the top level filter
221
- if (!parentCollection)
222
- parentCollection = collection;
223
- for (const [childFilterKey, childFilterValue] of Object.entries(filterValue)) {
224
- if (childFilterKey.startsWith('_')) {
225
- if (childFilterKey === '_and' || childFilterKey === '_or') {
226
- if (isArray(childFilterValue)) {
227
- for (const filter of childFilterValue) {
228
- const requiredPermissions = extractRequiredFieldPermissions('', filter, parentCollection, filterKey);
229
- result = mergeRequiredFieldPermissions(result, requiredPermissions);
230
- }
231
- }
232
- }
233
- }
234
- else {
235
- const requiredPermissions = extractRequiredFieldPermissions('', filterValue, parentCollection, filterKey);
236
- result = mergeRequiredFieldPermissions(result, requiredPermissions);
237
- }
238
- }
239
- }
240
- }
241
- return result;
242
- }, {});
243
- }
244
- function mergeRequiredFieldPermissions(current, child) {
245
- for (const collection of Object.keys(child)) {
246
- if (!current[collection]) {
247
- current[collection] = child[collection];
248
- }
249
- else {
250
- current[collection] = new Set([...current[collection], ...child[collection]]);
251
- }
252
- }
253
- return current;
254
- }
255
- function checkFieldPermissions(rootCollection, schema, action, requiredPermissions, aliasMap) {
256
- if (accountability?.admin === true)
257
- return;
258
- for (const collection of Object.keys(requiredPermissions)) {
259
- const permission = accountability?.permissions?.find((permission) => permission.collection === collection && permission.action === 'read');
260
- let allowedFields;
261
- // Allow the filtering of top level ID for actions such as update and delete
262
- if (action !== 'read' && collection === rootCollection) {
263
- const actionPermission = accountability?.permissions?.find((permission) => permission.collection === collection && permission.action === action);
264
- if (!actionPermission || !actionPermission.fields) {
265
- throw new ForbiddenError();
266
- }
267
- allowedFields = permission?.fields
268
- ? [...permission.fields, schema.collections[collection].primary]
269
- : [schema.collections[collection].primary];
270
- }
271
- else if (!permission || !permission.fields) {
272
- throw new ForbiddenError();
273
- }
274
- else {
275
- allowedFields = permission.fields;
276
- }
277
- if (allowedFields.includes('*'))
278
- continue;
279
- // Allow legacy permissions with an empty fields array, where id can be accessed
280
- if (allowedFields.length === 0)
281
- allowedFields.push(schema.collections[collection].primary);
282
- for (const field of requiredPermissions[collection]) {
283
- if (field.startsWith('$FOLLOW'))
284
- continue;
285
- const { fieldName } = parseFilterKey(field);
286
- let originalFieldName = fieldName;
287
- if (collection === rootCollection && aliasMap?.[fieldName]) {
288
- originalFieldName = aliasMap[fieldName];
289
- }
290
- if (!allowedFields.includes(originalFieldName)) {
291
- throw new ForbiddenError();
292
- }
293
- }
294
- }
295
- }
296
- }
297
- function applyFilters(ast, accountability) {
298
- if (ast.type === 'functionField') {
299
- const collection = ast.relatedCollection;
300
- updateFilterQuery(collection, ast.query);
301
- }
302
- else if (ast.type !== 'field') {
303
- if (ast.type === 'a2o') {
304
- const collections = Object.keys(ast.children);
305
- for (const collection of collections) {
306
- updateFilterQuery(collection, ast.query[collection]);
307
- }
308
- for (const [collection, children] of Object.entries(ast.children)) {
309
- ast.children[collection] = children.map((child) => applyFilters(child, accountability));
310
- }
311
- }
312
- else {
313
- const collection = ast.name;
314
- updateFilterQuery(collection, ast.query);
315
- ast.children = ast.children.map((child) => applyFilters(child, accountability));
316
- }
317
- }
318
- return ast;
319
- function updateFilterQuery(collection, query) {
320
- // We check the availability of the permissions in the step before this is run
321
- const permissions = permissionsForCollections.find((permission) => permission.collection === collection);
322
- if (!query.filter || Object.keys(query.filter).length === 0) {
323
- query.filter = { _and: [] };
324
- }
325
- else {
326
- query.filter = { _and: [query.filter] };
327
- }
328
- if (permissions.permissions && Object.keys(permissions.permissions).length > 0) {
329
- query.filter._and.push(permissions.permissions);
330
- }
331
- if (query.filter._and.length === 0)
332
- delete query.filter;
333
- }
334
- }
335
- }
336
- /**
337
- * Checks if the provided payload matches the configured permissions, and adds the presets to the payload.
338
- */
339
- validatePayload(action, collection, data) {
340
- const payload = cloneDeep(data);
341
- let permission;
342
- if (this.accountability?.admin === true) {
343
- permission = {
344
- id: 0,
345
- role: this.accountability?.role,
346
- collection,
347
- action,
348
- permissions: {},
349
- validation: {},
350
- fields: ['*'],
351
- presets: {},
352
- };
353
- }
354
- else {
355
- permission = this.accountability?.permissions?.find((permission) => {
356
- return permission.collection === collection && permission.action === action;
357
- });
358
- if (!permission)
359
- throw new ForbiddenError();
360
- // Check if you have permission to access the fields you're trying to access
361
- const allowedFields = permission.fields || [];
362
- if (allowedFields.includes('*') === false) {
363
- const keysInData = Object.keys(payload);
364
- const invalidKeys = keysInData.filter((fieldKey) => allowedFields.includes(fieldKey) === false);
365
- if (invalidKeys.length > 0) {
366
- throw new ForbiddenError();
367
- }
368
- }
369
- }
370
- const preset = permission.presets ?? {};
371
- const payloadWithPresets = merge({}, preset, payload);
372
- const fieldValidationRules = Object.values(this.schema.collections[collection].fields)
373
- .map((field) => field.validation)
374
- .filter((v) => v);
375
- const hasValidationRules = isNil(permission.validation) === false && Object.keys(permission.validation ?? {}).length > 0;
376
- const hasFieldValidationRules = fieldValidationRules && fieldValidationRules.length > 0;
377
- const requiredColumns = [];
378
- for (const field of Object.values(this.schema.collections[collection].fields)) {
379
- const specials = field?.special ?? [];
380
- const hasGenerateSpecial = GENERATE_SPECIAL.some((name) => specials.includes(name));
381
- const nullable = field.nullable || hasGenerateSpecial || field.generated;
382
- if (!nullable) {
383
- requiredColumns.push(field);
384
- }
385
- }
386
- if (hasValidationRules === false && hasFieldValidationRules === false && requiredColumns.length === 0) {
387
- return payloadWithPresets;
388
- }
389
- if (requiredColumns.length > 0) {
390
- permission.validation = hasValidationRules ? { _and: [permission.validation] } : { _and: [] };
391
- for (const field of requiredColumns) {
392
- if (action === 'create' && field.defaultValue === null) {
393
- permission.validation._and.push({
394
- [field.field]: {
395
- _submitted: true,
396
- },
397
- });
398
- }
399
- permission.validation._and.push({
400
- [field.field]: {
401
- _nnull: true,
402
- },
403
- });
404
- }
405
- }
406
- if (hasFieldValidationRules) {
407
- if (permission.validation && Object.keys(permission.validation).length > 0) {
408
- permission.validation = { _and: [permission.validation, ...fieldValidationRules] };
409
- }
410
- else {
411
- permission.validation = { _and: fieldValidationRules };
412
- }
413
- }
414
- const validationErrors = [];
415
- validationErrors.push(...flatten(validatePayload(permission.validation, payloadWithPresets).map((error) => error.details.map((details) => new FailedValidationError(joiValidationErrorItemToErrorExtensions(details))))));
416
- if (validationErrors.length > 0)
417
- throw validationErrors;
418
- return payloadWithPresets;
419
- }
420
- async checkAccess(action, collection, pk) {
421
- if (this.accountability?.admin === true)
422
- return;
423
- const itemsService = new ItemsService(collection, {
424
- accountability: this.accountability,
425
- knex: this.knex,
426
- schema: this.schema,
427
- });
428
- const query = {
429
- fields: ['*'],
430
- };
431
- if (Array.isArray(pk)) {
432
- const result = await itemsService.readMany(pk, { ...query, limit: pk.length }, { permissionsAction: action });
433
- // for the unexpected case that the result is not an array (for example due to filter hook)
434
- if (!isArray(result))
435
- throw new ForbiddenError();
436
- if (result.length !== pk.length)
437
- throw new ForbiddenError();
438
- }
439
- else if (pk) {
440
- const result = await itemsService.readOne(pk, query, { permissionsAction: action });
441
- if (!result)
442
- throw new ForbiddenError();
443
- }
444
- else {
445
- query.limit = 1;
446
- const result = await itemsService.readByQuery(query, { permissionsAction: action });
447
- // for the unexpected case that the result is not an array (for example due to filter hook)
448
- if (!isArray(result))
449
- throw new ForbiddenError();
450
- // for create action, an empty array is expected - for other actions, the first item is expected to be available
451
- const access = action === 'create' ? result.length === 0 : !!result[0];
452
- if (!access)
453
- throw new ForbiddenError();
454
- }
455
- }
456
- }
@@ -1,13 +0,0 @@
1
- import { appAccessMinimalPermissions } from '@directus/system-data';
2
- import { filterItems } from '../../../utils/filter-items.js';
3
- import { mergePermissions } from '../../../utils/merge-permissions.js';
4
- export function withAppMinimalPermissions(accountability, permissions, filter) {
5
- if (accountability?.app === true) {
6
- const filteredAppMinimalPermissions = filterItems(appAccessMinimalPermissions.map((permission) => ({
7
- ...permission,
8
- role: accountability.role,
9
- })), filter);
10
- return mergePermissions('or', permissions, filteredAppMinimalPermissions);
11
- }
12
- return permissions;
13
- }
@@ -1,7 +0,0 @@
1
- import type { PrimaryKey } from '@directus/types';
2
- import type { Knex } from 'knex';
3
- import { type AccessTypeCount } from './get-user-count.js';
4
- /**
5
- * Ensure that user limits are not reached
6
- */
7
- export declare function checkIncreasedUserLimits(db: Knex, increasedUserCounts: AccessTypeCount, ignoreIds?: PrimaryKey[]): Promise<void>;
@@ -1,25 +0,0 @@
1
- import { useEnv } from '@directus/env';
2
- import { LimitExceededError } from '@directus/errors';
3
- import { getUserCount } from './get-user-count.js';
4
- const env = useEnv();
5
- /**
6
- * Ensure that user limits are not reached
7
- */
8
- export async function checkIncreasedUserLimits(db, increasedUserCounts, ignoreIds = []) {
9
- if (!increasedUserCounts.admin && !increasedUserCounts.app && !increasedUserCounts.api)
10
- return;
11
- const userCounts = await getUserCount(db, ignoreIds);
12
- // Admins have full permissions, therefore should count under app access limit
13
- const existingAppUsersCount = userCounts.admin + userCounts.app;
14
- const newAppUsersCount = increasedUserCounts.admin + increasedUserCounts.app;
15
- if (increasedUserCounts.admin > 0 &&
16
- increasedUserCounts.admin + userCounts.admin > Number(env['USERS_ADMIN_ACCESS_LIMIT'])) {
17
- throw new LimitExceededError({ category: 'Active Admin users' });
18
- }
19
- if (newAppUsersCount > 0 && newAppUsersCount + existingAppUsersCount > Number(env['USERS_APP_ACCESS_LIMIT'])) {
20
- throw new LimitExceededError({ category: 'Active App users' });
21
- }
22
- if (increasedUserCounts.api > 0 && increasedUserCounts.api + userCounts.api > Number(env['USERS_API_ACCESS_LIMIT'])) {
23
- throw new LimitExceededError({ category: 'Active API users' });
24
- }
25
- }
@@ -1,6 +0,0 @@
1
- import type { Knex } from 'knex';
2
- import { type AccessTypeCount } from './get-user-count.js';
3
- /**
4
- * Get the role type counts by role IDs
5
- */
6
- export declare function getRoleCountsByRoles(db: Knex, roles: string[]): Promise<AccessTypeCount>;
@@ -1,27 +0,0 @@
1
- import { toBoolean } from '@directus/utils';
2
- import {} from './get-user-count.js';
3
- /**
4
- * Get the role type counts by role IDs
5
- */
6
- export async function getRoleCountsByRoles(db, roles) {
7
- const counts = {
8
- admin: 0,
9
- app: 0,
10
- api: 0,
11
- };
12
- const result = (await db.select('id', 'admin_access', 'app_access').from('directus_roles').whereIn('id', roles));
13
- for (const role of result) {
14
- const adminAccess = toBoolean(role.admin_access);
15
- const appAccess = toBoolean(role.app_access);
16
- if (adminAccess) {
17
- counts.admin++;
18
- }
19
- else if (appAccess) {
20
- counts.app++;
21
- }
22
- else {
23
- counts.api++;
24
- }
25
- }
26
- return counts;
27
- }
@@ -1,11 +0,0 @@
1
- import type { PrimaryKey } from '@directus/types';
2
- import type { Knex } from 'knex';
3
- import type { AccessTypeCount } from './get-user-count.js';
4
- type CountOptions = {
5
- inactiveUsers?: boolean;
6
- };
7
- /**
8
- * Get the role type counts by user IDs
9
- */
10
- export declare function getRoleCountsByUsers(db: Knex, userIds: PrimaryKey[], options?: CountOptions): Promise<AccessTypeCount>;
11
- export {};
@@ -1,34 +0,0 @@
1
- import { toBoolean } from '@directus/utils';
2
- /**
3
- * Get the role type counts by user IDs
4
- */
5
- export async function getRoleCountsByUsers(db, userIds, options = {}) {
6
- const counts = {
7
- admin: 0,
8
- app: 0,
9
- api: 0,
10
- };
11
- const result = await db
12
- .count('directus_users.id', { as: 'count' })
13
- .select('directus_roles.admin_access', 'directus_roles.app_access')
14
- .from('directus_users')
15
- .whereIn('directus_users.id', userIds)
16
- .andWhere('directus_users.status', options.inactiveUsers ? '!=' : '=', 'active')
17
- .leftJoin('directus_roles', 'directus_users.role', '=', 'directus_roles.id')
18
- .groupBy('directus_roles.admin_access', 'directus_roles.app_access');
19
- for (const record of result) {
20
- const adminAccess = toBoolean(record.admin_access);
21
- const appAccess = toBoolean(record.app_access);
22
- const count = Number(record.count);
23
- if (adminAccess) {
24
- counts.admin += count;
25
- }
26
- else if (appAccess) {
27
- counts.app += count;
28
- }
29
- else {
30
- counts.api += count;
31
- }
32
- }
33
- return counts;
34
- }
@@ -1,8 +0,0 @@
1
- import type { PrimaryKey } from '@directus/types';
2
- import { type Knex } from 'knex';
3
- export interface AccessTypeCount {
4
- admin: number;
5
- app: number;
6
- api: number;
7
- }
8
- export declare const getUserCount: (db: Knex, ignoreIds?: PrimaryKey[]) => Promise<AccessTypeCount>;
@@ -1,33 +0,0 @@
1
- import { toBoolean } from '@directus/utils';
2
- import {} from 'knex';
3
- export const getUserCount = async (db, ignoreIds = []) => {
4
- const counts = {
5
- admin: 0,
6
- app: 0,
7
- api: 0,
8
- };
9
- const result = (await db
10
- .count('directus_users.id', { as: 'count' })
11
- .select('directus_roles.admin_access', 'directus_roles.app_access')
12
- .from('directus_users')
13
- .whereNotIn('directus_users.id', ignoreIds)
14
- .andWhere('directus_users.status', 'active')
15
- .leftJoin('directus_roles', 'directus_users.role', '=', 'directus_roles.id')
16
- .where('directus_users.status', '=', 'active')
17
- .groupBy('directus_roles.admin_access', 'directus_roles.app_access'));
18
- for (const record of result) {
19
- const adminAccess = toBoolean(record.admin_access);
20
- const appAccess = toBoolean(record.app_access);
21
- const count = Number(record.count);
22
- if (adminAccess) {
23
- counts.admin += count;
24
- }
25
- else if (appAccess) {
26
- counts.app += count;
27
- }
28
- else {
29
- counts.api += count;
30
- }
31
- }
32
- return counts;
33
- };
@@ -1,7 +0,0 @@
1
- import type { PrimaryKey } from '@directus/types';
2
- import type { Knex } from 'knex';
3
- import { type AccessTypeCount } from './get-user-count.js';
4
- /**
5
- * Get the user type counts by role IDs
6
- */
7
- export declare function getUserCountsByRoles(db: Knex, roleIds: PrimaryKey[]): Promise<AccessTypeCount>;