@directus/api 20.0.0-rc.0 → 20.0.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 (291) hide show
  1. package/dist/app.js +9 -4
  2. package/dist/auth/drivers/ldap.js +4 -4
  3. package/dist/auth/drivers/local.js +4 -4
  4. package/dist/auth/drivers/oauth2.js +4 -4
  5. package/dist/auth/drivers/openid.js +4 -2
  6. package/dist/cache.js +0 -3
  7. package/dist/cli/commands/bootstrap/index.js +2 -8
  8. package/dist/cli/commands/init/index.js +10 -9
  9. package/dist/cli/utils/defaults.d.ts +11 -4
  10. package/dist/cli/utils/defaults.js +1 -7
  11. package/dist/constants.d.ts +9 -1
  12. package/dist/constants.js +10 -0
  13. package/dist/controllers/auth.js +16 -5
  14. package/dist/controllers/permissions.js +2 -14
  15. package/dist/controllers/roles.js +1 -22
  16. package/dist/controllers/{access.d.ts → tus.d.ts} +1 -0
  17. package/dist/controllers/tus.js +72 -0
  18. package/dist/controllers/users.js +55 -0
  19. package/dist/database/helpers/fn/types.d.ts +1 -2
  20. package/dist/database/helpers/fn/types.js +1 -1
  21. package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
  22. package/dist/database/helpers/geometry/dialects/mssql.js +2 -4
  23. package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
  24. package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
  25. package/dist/database/helpers/geometry/dialects/oracle.js +3 -5
  26. package/dist/database/helpers/geometry/types.d.ts +1 -1
  27. package/dist/database/helpers/geometry/types.js +2 -4
  28. package/dist/database/index.js +1 -2
  29. package/dist/database/migrations/20240701A-add-tus-data.js +12 -0
  30. package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
  31. package/dist/database/run-ast.js +450 -0
  32. package/dist/flows.js +4 -3
  33. package/dist/middleware/authenticate.js +7 -2
  34. package/dist/middleware/cache.js +1 -1
  35. package/dist/middleware/check-ip.d.ts +2 -0
  36. package/dist/middleware/check-ip.js +37 -0
  37. package/dist/middleware/get-permissions.d.ts +3 -0
  38. package/dist/middleware/get-permissions.js +10 -0
  39. package/dist/middleware/respond.js +1 -1
  40. package/dist/services/activity.js +10 -22
  41. package/dist/services/assets.d.ts +3 -2
  42. package/dist/services/assets.js +5 -10
  43. package/dist/services/authentication.js +26 -32
  44. package/dist/services/authorization.d.ts +17 -0
  45. package/dist/services/authorization.js +456 -0
  46. package/dist/services/collections.js +17 -18
  47. package/dist/services/fields.d.ts +1 -0
  48. package/dist/services/fields.js +24 -53
  49. package/dist/services/files/lib/extract-metadata.d.ts +3 -0
  50. package/dist/services/files/lib/extract-metadata.js +32 -0
  51. package/dist/services/files/utils/get-metadata.d.ts +5 -0
  52. package/dist/services/files/utils/get-metadata.js +107 -0
  53. package/dist/services/files.d.ts +4 -6
  54. package/dist/services/files.js +24 -140
  55. package/dist/services/graphql/index.d.ts +3 -3
  56. package/dist/services/graphql/index.js +22 -126
  57. package/dist/services/graphql/subscription.js +4 -2
  58. package/dist/services/import-export.js +4 -18
  59. package/dist/services/index.d.ts +2 -3
  60. package/dist/services/index.js +2 -3
  61. package/dist/services/items.js +44 -115
  62. package/dist/services/meta.js +23 -60
  63. package/dist/services/payload.d.ts +10 -9
  64. package/dist/services/payload.js +3 -18
  65. package/dist/services/{permissions.d.ts → permissions/index.d.ts} +7 -5
  66. package/dist/services/{permissions.js → permissions/index.js} +54 -30
  67. package/dist/{permissions → services/permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
  68. package/dist/services/permissions/lib/with-app-minimal-permissions.js +13 -0
  69. package/dist/services/relations.d.ts +6 -0
  70. package/dist/services/relations.js +29 -26
  71. package/dist/services/roles.d.ts +12 -4
  72. package/dist/services/roles.js +424 -57
  73. package/dist/services/server.js +6 -0
  74. package/dist/services/shares.d.ts +2 -0
  75. package/dist/services/shares.js +8 -12
  76. package/dist/services/specifications.d.ts +2 -2
  77. package/dist/services/specifications.js +27 -39
  78. package/dist/services/tus/data-store.d.ts +36 -0
  79. package/dist/services/tus/data-store.js +214 -0
  80. package/dist/services/tus/index.d.ts +2 -0
  81. package/dist/services/tus/index.js +2 -0
  82. package/dist/services/tus/lockers.d.ts +36 -0
  83. package/dist/services/tus/lockers.js +83 -0
  84. package/dist/services/tus/server.d.ts +8 -0
  85. package/dist/services/tus/server.js +80 -0
  86. package/dist/services/tus/utils/wait-timeout.d.ts +1 -0
  87. package/dist/services/tus/utils/wait-timeout.js +13 -0
  88. package/dist/services/users.d.ts +5 -1
  89. package/dist/services/users.js +161 -78
  90. package/dist/services/utils.js +7 -11
  91. package/dist/services/versions.d.ts +2 -0
  92. package/dist/services/versions.js +10 -34
  93. package/dist/storage/register-locations.js +5 -1
  94. package/dist/telemetry/lib/get-report.js +2 -2
  95. package/dist/telemetry/utils/check-increased-user-limits.d.ts +7 -0
  96. package/dist/telemetry/utils/check-increased-user-limits.js +25 -0
  97. package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +6 -0
  98. package/dist/telemetry/utils/get-role-counts-by-roles.js +27 -0
  99. package/dist/telemetry/utils/get-role-counts-by-users.d.ts +11 -0
  100. package/dist/telemetry/utils/get-role-counts-by-users.js +34 -0
  101. package/dist/telemetry/utils/get-user-count.d.ts +8 -0
  102. package/dist/telemetry/utils/get-user-count.js +33 -0
  103. package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +7 -0
  104. package/dist/telemetry/utils/get-user-counts-by-roles.js +35 -0
  105. package/dist/types/ast.d.ts +1 -43
  106. package/dist/types/items.d.ts +0 -11
  107. package/dist/utils/apply-query.d.ts +3 -4
  108. package/dist/utils/apply-query.js +8 -37
  109. package/dist/utils/get-accountability-for-role.js +25 -16
  110. package/dist/utils/get-accountability-for-token.js +16 -17
  111. package/dist/utils/get-ast-from-query.d.ts +13 -0
  112. package/dist/utils/get-ast-from-query.js +297 -0
  113. package/dist/utils/get-cache-key.d.ts +1 -1
  114. package/dist/utils/get-cache-key.js +1 -12
  115. package/dist/utils/get-column.d.ts +1 -2
  116. package/dist/utils/get-column.js +0 -1
  117. package/dist/utils/get-permissions.d.ts +2 -0
  118. package/dist/utils/get-permissions.js +150 -0
  119. package/dist/utils/get-service.js +1 -5
  120. package/dist/utils/merge-permissions-for-share.d.ts +4 -0
  121. package/dist/utils/merge-permissions-for-share.js +109 -0
  122. package/dist/utils/merge-permissions.d.ts +3 -0
  123. package/dist/utils/merge-permissions.js +95 -0
  124. package/dist/utils/reduce-schema.d.ts +6 -4
  125. package/dist/utils/reduce-schema.js +34 -14
  126. package/dist/utils/verify-session-jwt.js +2 -1
  127. package/dist/websocket/authenticate.d.ts +2 -0
  128. package/dist/websocket/authenticate.js +12 -0
  129. package/dist/websocket/controllers/graphql.js +4 -1
  130. package/dist/websocket/controllers/hooks.js +0 -4
  131. package/dist/websocket/controllers/rest.js +2 -0
  132. package/dist/websocket/handlers/subscribe.js +2 -0
  133. package/dist/websocket/utils/items.d.ts +1 -1
  134. package/package.json +35 -33
  135. package/dist/controllers/access.js +0 -148
  136. package/dist/controllers/policies.d.ts +0 -2
  137. package/dist/controllers/policies.js +0 -169
  138. package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +0 -16
  139. package/dist/database/get-ast-from-query/get-ast-from-query.js +0 -82
  140. package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +0 -13
  141. package/dist/database/get-ast-from-query/lib/convert-wildcards.js +0 -69
  142. package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +0 -15
  143. package/dist/database/get-ast-from-query/lib/parse-fields.js +0 -190
  144. package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +0 -14
  145. package/dist/database/get-ast-from-query/utils/get-deep-query.js +0 -17
  146. package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +0 -2
  147. package/dist/database/get-ast-from-query/utils/get-related-collection.js +0 -13
  148. package/dist/database/get-ast-from-query/utils/get-relation.d.ts +0 -2
  149. package/dist/database/get-ast-from-query/utils/get-relation.js +0 -7
  150. package/dist/database/migrations/20240619A-permissions-policies.js +0 -163
  151. package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
  152. package/dist/database/run-ast/lib/get-db-query.js +0 -194
  153. package/dist/database/run-ast/lib/parse-current-level.d.ts +0 -7
  154. package/dist/database/run-ast/lib/parse-current-level.js +0 -41
  155. package/dist/database/run-ast/run-ast.d.ts +0 -7
  156. package/dist/database/run-ast/run-ast.js +0 -107
  157. package/dist/database/run-ast/types.js +0 -1
  158. package/dist/database/run-ast/utils/apply-case-when.d.ts +0 -16
  159. package/dist/database/run-ast/utils/apply-case-when.js +0 -26
  160. package/dist/database/run-ast/utils/apply-parent-filters.d.ts +0 -3
  161. package/dist/database/run-ast/utils/apply-parent-filters.js +0 -55
  162. package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +0 -10
  163. package/dist/database/run-ast/utils/get-column-pre-processor.js +0 -57
  164. package/dist/database/run-ast/utils/get-field-alias.d.ts +0 -2
  165. package/dist/database/run-ast/utils/get-field-alias.js +0 -4
  166. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +0 -5
  167. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +0 -23
  168. package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +0 -3
  169. package/dist/database/run-ast/utils/merge-with-parent-items.js +0 -87
  170. package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +0 -3
  171. package/dist/database/run-ast/utils/remove-temporary-fields.js +0 -73
  172. package/dist/permissions/cache.d.ts +0 -2
  173. package/dist/permissions/cache.js +0 -23
  174. package/dist/permissions/lib/fetch-permissions.d.ts +0 -10
  175. package/dist/permissions/lib/fetch-permissions.js +0 -55
  176. package/dist/permissions/lib/fetch-policies.d.ts +0 -7
  177. package/dist/permissions/lib/fetch-policies.js +0 -28
  178. package/dist/permissions/lib/fetch-roles-tree.d.ts +0 -3
  179. package/dist/permissions/lib/fetch-roles-tree.js +0 -28
  180. package/dist/permissions/lib/with-app-minimal-permissions.js +0 -10
  181. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +0 -7
  182. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +0 -56
  183. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +0 -3
  184. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +0 -16
  185. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +0 -8
  186. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +0 -24
  187. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +0 -9
  188. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +0 -31
  189. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +0 -16
  190. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +0 -27
  191. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +0 -10
  192. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +0 -23
  193. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
  194. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
  195. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
  196. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
  197. package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
  198. package/dist/permissions/modules/fetch-global-access/types.js +0 -1
  199. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
  200. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
  201. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +0 -12
  202. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +0 -32
  203. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +0 -4
  204. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +0 -29
  205. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +0 -4
  206. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +0 -49
  207. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +0 -3
  208. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +0 -56
  209. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +0 -4
  210. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +0 -8
  211. package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +0 -9
  212. package/dist/permissions/modules/process-ast/lib/inject-cases.js +0 -93
  213. package/dist/permissions/modules/process-ast/process-ast.d.ts +0 -9
  214. package/dist/permissions/modules/process-ast/process-ast.js +0 -39
  215. package/dist/permissions/modules/process-ast/types.d.ts +0 -24
  216. package/dist/permissions/modules/process-ast/types.js +0 -1
  217. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +0 -2
  218. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +0 -7
  219. package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +0 -12
  220. package/dist/permissions/modules/process-ast/utils/dedupe-access.js +0 -30
  221. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +0 -15
  222. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +0 -50
  223. package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +0 -3
  224. package/dist/permissions/modules/process-ast/utils/find-related-collection.js +0 -9
  225. package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +0 -3
  226. package/dist/permissions/modules/process-ast/utils/flatten-filter.js +0 -24
  227. package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +0 -1
  228. package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +0 -3
  229. package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +0 -5
  230. package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +0 -7
  231. package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +0 -2
  232. package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +0 -3
  233. package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +0 -2
  234. package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +0 -3
  235. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +0 -3
  236. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +0 -16
  237. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +0 -2
  238. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +0 -12
  239. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +0 -2
  240. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +0 -28
  241. package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +0 -5
  242. package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +0 -12
  243. package/dist/permissions/modules/process-payload/process-payload.d.ts +0 -13
  244. package/dist/permissions/modules/process-payload/process-payload.js +0 -77
  245. package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +0 -12
  246. package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +0 -11
  247. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +0 -9
  248. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +0 -33
  249. package/dist/permissions/modules/validate-access/validate-access.d.ts +0 -14
  250. package/dist/permissions/modules/validate-access/validate-access.js +0 -28
  251. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +0 -1
  252. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +0 -8
  253. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +0 -5
  254. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +0 -10
  255. package/dist/permissions/types.d.ts +0 -6
  256. package/dist/permissions/types.js +0 -1
  257. package/dist/permissions/utils/create-default-accountability.d.ts +0 -2
  258. package/dist/permissions/utils/create-default-accountability.js +0 -11
  259. package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +0 -8
  260. package/dist/permissions/utils/extract-required-dynamic-variable-context.js +0 -27
  261. package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +0 -9
  262. package/dist/permissions/utils/fetch-dynamic-variable-context.js +0 -43
  263. package/dist/permissions/utils/filter-policies-by-ip.d.ts +0 -2
  264. package/dist/permissions/utils/filter-policies-by-ip.js +0 -15
  265. package/dist/permissions/utils/get-unaliased-field-key.d.ts +0 -5
  266. package/dist/permissions/utils/get-unaliased-field-key.js +0 -17
  267. package/dist/permissions/utils/process-permissions.d.ts +0 -7
  268. package/dist/permissions/utils/process-permissions.js +0 -9
  269. package/dist/permissions/utils/with-cache.d.ts +0 -10
  270. package/dist/permissions/utils/with-cache.js +0 -25
  271. package/dist/services/access.d.ts +0 -10
  272. package/dist/services/access.js +0 -43
  273. package/dist/services/policies.d.ts +0 -12
  274. package/dist/services/policies.js +0 -87
  275. package/dist/telemetry/utils/check-user-limits.d.ts +0 -5
  276. package/dist/telemetry/utils/check-user-limits.js +0 -19
  277. package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +0 -17
  278. package/dist/utils/fetch-user-count/fetch-access-lookup.js +0 -22
  279. package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +0 -16
  280. package/dist/utils/fetch-user-count/fetch-access-roles.js +0 -37
  281. package/dist/utils/fetch-user-count/fetch-active-users.d.ts +0 -6
  282. package/dist/utils/fetch-user-count/fetch-active-users.js +0 -3
  283. package/dist/utils/fetch-user-count/fetch-user-count.d.ts +0 -12
  284. package/dist/utils/fetch-user-count/fetch-user-count.js +0 -57
  285. package/dist/utils/fetch-user-count/get-user-count-query.d.ts +0 -20
  286. package/dist/utils/fetch-user-count/get-user-count-query.js +0 -17
  287. package/dist/utils/validate-user-count-integrity.d.ts +0 -13
  288. package/dist/utils/validate-user-count-integrity.js +0 -29
  289. /package/dist/database/migrations/{20240619A-permissions-policies.d.ts → 20240701A-add-tus-data.d.ts} +0 -0
  290. /package/dist/{utils → services/files/utils}/parse-image-metadata.d.ts +0 -0
  291. /package/dist/{utils → services/files/utils}/parse-image-metadata.js +0 -0
@@ -1,17 +0,0 @@
1
- import { parseFilterKey } from '../../utils/parse-filter-key.js';
2
- /**
3
- * Derive the unaliased field key from the given AST node.
4
- */
5
- export function getUnaliasedFieldKey(node) {
6
- switch (node.type) {
7
- case 'o2m':
8
- return node.relation.meta.one_field;
9
- case 'a2o':
10
- case 'm2o':
11
- return node.relation.field;
12
- case 'field':
13
- case 'functionField':
14
- // The field name might still include a function, so process that here as well
15
- return parseFilterKey(node.name).fieldName;
16
- }
17
- }
@@ -1,7 +0,0 @@
1
- import type { Accountability, Permission } from '@directus/types';
2
- export interface ProcessPermissionsOptions {
3
- permissions: Permission[];
4
- accountability: Pick<Accountability, 'user' | 'role' | 'roles'>;
5
- permissionsContext: Record<string, any>;
6
- }
7
- export declare function processPermissions({ permissions, accountability, permissionsContext }: ProcessPermissionsOptions): Permission[];
@@ -1,9 +0,0 @@
1
- import { parseFilter, parsePreset } from '@directus/utils';
2
- export function processPermissions({ permissions, accountability, permissionsContext }) {
3
- return permissions.map((permission) => {
4
- permission.permissions = parseFilter(permission.permissions, accountability, permissionsContext);
5
- permission.validation = parseFilter(permission.validation, accountability, permissionsContext);
6
- permission.presets = parsePreset(permission.presets, accountability, permissionsContext);
7
- return permission;
8
- });
9
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * The `pick` parameter can be used to stabilize cache keys, by only using a subset of the available parameters and
3
- * ensuring key order.
4
- *
5
- * If the `pick` function is provided, we pass the picked result to the handler, in order for TypeScript to ensure that
6
- * the function only relies on the parameters that are used for generating the cache key.
7
- *
8
- * @NOTE only uses the first parameter for memoization
9
- */
10
- export declare function withCache<F extends (arg0: Arg0, ...args: any[]) => R, R, Arg0 = Parameters<F>[0]>(namespace: string, handler: F, prepareArg?: (arg0: Arg0) => Arg0): F;
@@ -1,25 +0,0 @@
1
- import { getSimpleHash } from '@directus/utils';
2
- import { useCache } from '../cache.js';
3
- /**
4
- * The `pick` parameter can be used to stabilize cache keys, by only using a subset of the available parameters and
5
- * ensuring key order.
6
- *
7
- * If the `pick` function is provided, we pass the picked result to the handler, in order for TypeScript to ensure that
8
- * the function only relies on the parameters that are used for generating the cache key.
9
- *
10
- * @NOTE only uses the first parameter for memoization
11
- */
12
- export function withCache(namespace, handler, prepareArg) {
13
- const cache = useCache();
14
- return (async (arg0, ...args) => {
15
- arg0 = prepareArg ? prepareArg(arg0) : arg0;
16
- const key = namespace + '-' + getSimpleHash(JSON.stringify(arg0));
17
- const cached = await cache.get(key);
18
- if (cached !== undefined) {
19
- return cached;
20
- }
21
- const res = await handler(arg0, ...args);
22
- cache.set(key, res);
23
- return res;
24
- });
25
- }
@@ -1,10 +0,0 @@
1
- import type { Item, PrimaryKey } from '@directus/types';
2
- import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
3
- import { ItemsService } from './items.js';
4
- export declare class AccessService extends ItemsService {
5
- constructor(options: AbstractServiceOptions);
6
- private clearCaches;
7
- createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
8
- updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
9
- deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
10
- }
@@ -1,43 +0,0 @@
1
- import { clearSystemCache } from '../cache.js';
2
- import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
3
- import { ItemsService } from './items.js';
4
- export class AccessService extends ItemsService {
5
- constructor(options) {
6
- super('directus_access', options);
7
- }
8
- async clearCaches(opts) {
9
- await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
10
- if (this.cache && opts?.autoPurgeCache !== false) {
11
- await this.cache.clear();
12
- }
13
- }
14
- async createOne(data, opts = {}) {
15
- // Creating a new policy attachments affects the number of admin/app/api users.
16
- // But it can only add app or admin users, so no need to check the remaining admin users.
17
- opts.userIntegrityCheckFlags =
18
- (opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None) | UserIntegrityCheckFlag.UserLimits;
19
- opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
20
- const result = await super.createOne(data, opts);
21
- // A new policy has been attached to a user or a role, clear the caches
22
- await this.clearCaches();
23
- return result;
24
- }
25
- async updateMany(keys, data, opts = {}) {
26
- // Updating policy attachments might affect the number of admin/app/api users
27
- opts.userIntegrityCheckFlags = UserIntegrityCheckFlag.All;
28
- opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
29
- const result = await super.updateMany(keys, data, { ...opts, userIntegrityCheckFlags: UserIntegrityCheckFlag.All });
30
- // Some policy attachments have been updated, clear the caches
31
- await this.clearCaches();
32
- return result;
33
- }
34
- async deleteMany(keys, opts = {}) {
35
- // Changes here can affect the number of admin/app/api users
36
- opts.userIntegrityCheckFlags = UserIntegrityCheckFlag.All;
37
- opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
38
- const result = await super.deleteMany(keys, opts);
39
- // Some policy attachments have been deleted, clear the caches
40
- await this.clearCaches();
41
- return result;
42
- }
43
- }
@@ -1,12 +0,0 @@
1
- import type { Policy, PrimaryKey } from '@directus/types';
2
- import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
3
- import { ItemsService } from './items.js';
4
- export declare class PoliciesService extends ItemsService<Policy> {
5
- constructor(options: AbstractServiceOptions);
6
- private clearCaches;
7
- private isIpAccessValid;
8
- private assertValidIpAccess;
9
- createOne(data: Partial<Policy>, opts?: MutationOptions): Promise<PrimaryKey>;
10
- updateMany(keys: PrimaryKey[], data: Partial<Policy>, opts?: MutationOptions): Promise<PrimaryKey[]>;
11
- deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
12
- }
@@ -1,87 +0,0 @@
1
- import { InvalidPayloadError } from '@directus/errors';
2
- import { getMatch } from 'ip-matching';
3
- import { clearSystemCache } from '../cache.js';
4
- import { clearCache as clearPermissionsCache } from '../permissions/cache.js';
5
- import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
6
- import { ItemsService } from './items.js';
7
- export class PoliciesService extends ItemsService {
8
- constructor(options) {
9
- super('directus_policies', options);
10
- }
11
- async clearCaches(opts) {
12
- await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
13
- if (this.cache && opts?.autoPurgeCache !== false) {
14
- await this.cache.clear();
15
- }
16
- }
17
- isIpAccessValid(value) {
18
- if (value === undefined)
19
- return false;
20
- if (value === null)
21
- return true;
22
- if (Array.isArray(value) && value.length === 0)
23
- return true;
24
- for (const ip of value) {
25
- if (typeof ip !== 'string' || ip.includes('*'))
26
- return false;
27
- try {
28
- const match = getMatch(ip);
29
- if (match.type == 'IPMask')
30
- return false;
31
- }
32
- catch {
33
- return false;
34
- }
35
- }
36
- return true;
37
- }
38
- assertValidIpAccess(partialItem) {
39
- if ('ip_access' in partialItem && !this.isIpAccessValid(partialItem['ip_access'])) {
40
- throw new InvalidPayloadError({
41
- reason: 'IP Access contains an incorrect value. Valid values are: IP addresses, IP ranges and CIDR blocks',
42
- });
43
- }
44
- }
45
- async createOne(data, opts = {}) {
46
- this.assertValidIpAccess(data);
47
- // A policy has been created, but the attachment to a user/role happens in the AccessService,
48
- // so no need to check user integrity
49
- const result = await super.createOne(data, opts);
50
- // TODO is this necessary? Since the attachment should be handled in the AccessService
51
- // A new policy has created, clear the permissions cache
52
- await clearPermissionsCache();
53
- return result;
54
- }
55
- async updateMany(keys, data, opts = {}) {
56
- this.assertValidIpAccess(data);
57
- if ('admin_access' in data) {
58
- let flags = UserIntegrityCheckFlag.RemainingAdmins;
59
- if (data['admin_access'] === true) {
60
- // Only need to perform a full user count if the policy allows admin access
61
- flags |= UserIntegrityCheckFlag.All;
62
- }
63
- opts.userIntegrityCheckFlags = (opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None) | flags;
64
- }
65
- if ('app_access' in data) {
66
- opts.userIntegrityCheckFlags =
67
- (opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None) | UserIntegrityCheckFlag.UserLimits;
68
- }
69
- if (opts.userIntegrityCheckFlags)
70
- opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
71
- const result = await super.updateMany(keys, data, opts);
72
- if ('admin_access' in data || 'app_access' in data || 'ip_access' in data || 'enforce_tfa' in data) {
73
- // Some relevant properties on policies have been updated, clear the caches
74
- await this.clearCaches(opts);
75
- }
76
- return result;
77
- }
78
- async deleteMany(keys, opts = {}) {
79
- opts.userIntegrityCheckFlags = UserIntegrityCheckFlag.All;
80
- opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
81
- const result = await super.deleteMany(keys, opts);
82
- // TODO is this necessary? Since the detachment should be handled in the AccessService
83
- // Some policies have been deleted, clear the permissions cache
84
- await this.clearCaches(opts);
85
- return result;
86
- }
87
- }
@@ -1,5 +0,0 @@
1
- import { type UserCount } from '../../utils/fetch-user-count/fetch-user-count.js';
2
- /**
3
- * Ensure that user limits are not reached
4
- */
5
- export declare function checkUserLimits(userCounts: UserCount): Promise<void>;
@@ -1,19 +0,0 @@
1
- import { useEnv } from '@directus/env';
2
- import { LimitExceededError } from '@directus/errors';
3
- import {} from '../../utils/fetch-user-count/fetch-user-count.js';
4
- const env = useEnv();
5
- /**
6
- * Ensure that user limits are not reached
7
- */
8
- export async function checkUserLimits(userCounts) {
9
- if (userCounts.admin > Number(env['USERS_ADMIN_ACCESS_LIMIT'])) {
10
- throw new LimitExceededError({ category: 'Active Admin users' });
11
- }
12
- // Both app and admin users count against the app access limit
13
- if (userCounts.app + userCounts.admin > Number(env['USERS_APP_ACCESS_LIMIT'])) {
14
- throw new LimitExceededError({ category: 'Active App users' });
15
- }
16
- if (userCounts.api > Number(env['USERS_API_ACCESS_LIMIT'])) {
17
- throw new LimitExceededError({ category: 'Active API users' });
18
- }
19
- }
@@ -1,17 +0,0 @@
1
- import type { PrimaryKey } from '@directus/types';
2
- import type { Knex } from 'knex';
3
- export interface AccessLookup {
4
- role: string | null;
5
- user: string | null;
6
- app_access: boolean | number;
7
- admin_access: boolean | number;
8
- }
9
- export interface FetchAccessLookupOptions {
10
- excludeAccessRows?: PrimaryKey[];
11
- excludePolicies?: PrimaryKey[];
12
- excludeUsers?: PrimaryKey[];
13
- excludeRoles?: PrimaryKey[];
14
- adminOnly?: boolean;
15
- knex: Knex;
16
- }
17
- export declare function fetchAccessLookup(options: FetchAccessLookupOptions): Promise<AccessLookup[]>;
@@ -1,22 +0,0 @@
1
- export async function fetchAccessLookup(options) {
2
- let query = options.knex
3
- .select('directus_access.role', 'directus_access.user', 'directus_policies.app_access', 'directus_policies.admin_access')
4
- .from('directus_access')
5
- .leftJoin('directus_policies', 'directus_access.policy', 'directus_policies.id');
6
- if (options.excludeAccessRows && options.excludeAccessRows.length > 0) {
7
- query = query.whereNotIn('directus_access.id', options.excludeAccessRows);
8
- }
9
- if (options.excludePolicies && options.excludePolicies.length > 0) {
10
- query = query.whereNotIn('directus_access.policy', options.excludePolicies);
11
- }
12
- if (options.excludeUsers && options.excludeUsers.length > 0) {
13
- query = query.where((q) => q.whereNotIn('directus_access.user', options.excludeUsers).orWhereNull('directus_access.user'));
14
- }
15
- if (options.excludeRoles && options.excludeRoles.length > 0) {
16
- query = query.where((q) => q.whereNotIn('directus_access.role', options.excludeRoles).orWhereNull('directus_access.role'));
17
- }
18
- if (options.adminOnly) {
19
- query = query.where('directus_policies.admin_access', 1);
20
- }
21
- return query;
22
- }
@@ -1,16 +0,0 @@
1
- import type { PrimaryKey } from '@directus/types';
2
- import type { Knex } from 'knex';
3
- export interface FetchAccessRolesOptions {
4
- adminRoles: Set<string>;
5
- appRoles: Set<string>;
6
- excludeRoles?: PrimaryKey[];
7
- }
8
- /**
9
- * Return a set of roles that allow app or admin access, if itself or any of its parents do
10
- */
11
- export declare function fetchAccessRoles(options: FetchAccessRolesOptions, context: {
12
- knex: Knex;
13
- }): Promise<{
14
- adminRoles: Set<string>;
15
- appRoles: Set<string>;
16
- }>;
@@ -1,37 +0,0 @@
1
- /**
2
- * Return a set of roles that allow app or admin access, if itself or any of its parents do
3
- */
4
- export async function fetchAccessRoles(options, context) {
5
- // Only fetch the roles that have a parent, as otherwise those roles should already be included in at least one of the input set
6
- const allChildRoles = await context.knex
7
- .select('id', 'parent')
8
- .from('directus_roles')
9
- .whereNotNull('parent')
10
- .whereNotIn('id', options.excludeRoles ?? []);
11
- const adminRoles = new Set(options.adminRoles);
12
- const appRoles = new Set(options.appRoles);
13
- const remainingRoles = new Set(allChildRoles);
14
- let hasChanged = remainingRoles.size > 0;
15
- // This loop accounts for the undefined order in which the roles are returned, as there is the possibility
16
- // of a role parent not being in the set of roles yet, so we need to iterate over the roles multiple times
17
- // until no further roles are added to the sets
18
- while (hasChanged) {
19
- hasChanged = false;
20
- for (const role of remainingRoles) {
21
- if (adminRoles.has(role.parent)) {
22
- adminRoles.add(role.id);
23
- remainingRoles.delete(role);
24
- hasChanged = true;
25
- }
26
- if (appRoles.has(role.parent)) {
27
- appRoles.add(role.id);
28
- remainingRoles.delete(role);
29
- hasChanged = true;
30
- }
31
- }
32
- }
33
- return {
34
- adminRoles,
35
- appRoles,
36
- };
37
- }
@@ -1,6 +0,0 @@
1
- import type { Knex } from 'knex';
2
- export interface ActiveUser {
3
- id: string;
4
- role: string | null;
5
- }
6
- export declare function fetchActiveUsers(knex: Knex): Promise<ActiveUser[]>;
@@ -1,3 +0,0 @@
1
- export async function fetchActiveUsers(knex) {
2
- return await knex.select('id', 'role').from('directus_users').where('status', 'active');
3
- }
@@ -1,12 +0,0 @@
1
- import { type FetchAccessLookupOptions } from './fetch-access-lookup.js';
2
- export interface FetchUserCountOptions extends FetchAccessLookupOptions {
3
- }
4
- export interface UserCount {
5
- admin: number;
6
- app: number;
7
- api: number;
8
- }
9
- /**
10
- * Returns counts of all active users in the system grouped by admin, app, and api access
11
- */
12
- export declare function fetchUserCount(options: FetchUserCountOptions): Promise<UserCount>;
@@ -1,57 +0,0 @@
1
- import { toBoolean } from '@directus/utils';
2
- import { fetchAccessLookup } from './fetch-access-lookup.js';
3
- import { fetchAccessRoles } from './fetch-access-roles.js';
4
- import { getUserCountQuery } from './get-user-count-query.js';
5
- /**
6
- * Returns counts of all active users in the system grouped by admin, app, and api access
7
- */
8
- export async function fetchUserCount(options) {
9
- const accessRows = await fetchAccessLookup(options);
10
- const adminRoles = new Set(accessRows.filter((row) => toBoolean(row.admin_access) && row.role !== null).map((row) => row.role));
11
- const appRoles = new Set(accessRows
12
- .filter((row) => !toBoolean(row.admin_access) && toBoolean(row.app_access) && row.role !== null)
13
- .map((row) => row.role));
14
- // All users that are directly granted rights through a connected policy
15
- const adminUsers = new Set(accessRows.filter((row) => toBoolean(row.admin_access) && row.user !== null).map((row) => row.user));
16
- // Some roles might be granted access rights through nesting, so determine all roles that grant admin or app access,
17
- // including nested roles
18
- const { adminRoles: allAdminRoles, appRoles: allAppRoles } = await fetchAccessRoles({
19
- adminRoles,
20
- appRoles,
21
- ...options,
22
- }, { knex: options.knex });
23
- // All users that are granted admin rights through a role, but not directly
24
- const adminCountQuery = getUserCountQuery(options.knex, {
25
- includeRoles: Array.from(allAdminRoles),
26
- excludeIds: [...adminUsers, ...(options.excludeUsers ?? [])],
27
- });
28
- if (options.adminOnly) {
29
- // Shortcut for only counting admin users
30
- const adminResult = await adminCountQuery;
31
- return {
32
- admin: Number(adminResult?.['count'] ?? 0) + adminUsers.size,
33
- app: 0,
34
- api: 0,
35
- };
36
- }
37
- const appUsers = new Set(accessRows
38
- .filter((row) => !toBoolean(row.admin_access) && toBoolean(row.app_access) && row.user !== null)
39
- .map((row) => row.user));
40
- // All users that are granted app rights through a role, but not directly, and that aren't admin users
41
- const appCountQuery = getUserCountQuery(options.knex, {
42
- includeRoles: Array.from(allAppRoles),
43
- excludeRoles: Array.from(allAdminRoles),
44
- excludeIds: [...appUsers, ...adminUsers, ...(options.excludeUsers ?? [])],
45
- });
46
- const allCountQuery = getUserCountQuery(options.knex, {
47
- excludeIds: options.excludeUsers ?? [],
48
- });
49
- const [adminResult, appResult, allResult] = await Promise.all([adminCountQuery, appCountQuery, allCountQuery]);
50
- const adminCount = Number(adminResult?.['count'] ?? 0) + adminUsers.size;
51
- const appCount = Number(appResult?.['count'] ?? 0) + appUsers.size;
52
- return {
53
- admin: adminCount,
54
- app: appCount,
55
- api: Number(allResult?.['count'] ?? 0) - adminCount - appCount,
56
- };
57
- }
@@ -1,20 +0,0 @@
1
- import type { PrimaryKey } from '@directus/types';
2
- import type { Knex } from 'knex';
3
- export interface GetUserCountOptions {
4
- excludeIds?: PrimaryKey[];
5
- excludeRoles?: PrimaryKey[];
6
- includeRoles?: PrimaryKey[];
7
- }
8
- export declare function getUserCountQuery(knex: Knex, options: GetUserCountOptions): Promise<{
9
- count: number;
10
- }> | Knex.QueryBuilder<any, {
11
- _base: {};
12
- _hasSelection: true;
13
- _keys: never;
14
- _aliases: {};
15
- _single: false;
16
- _intersectProps: {
17
- count?: string | number;
18
- };
19
- _unionProps: undefined;
20
- }>;
@@ -1,17 +0,0 @@
1
- export function getUserCountQuery(knex, options) {
2
- // Safety check for an empty list of includeRoles, which would otherwise return all users
3
- if (options.includeRoles && options.includeRoles.length === 0) {
4
- return Promise.resolve({ count: 0 });
5
- }
6
- let query = knex('directus_users').count({ count: '*' }).as('count').where('status', 'active');
7
- if (options.excludeIds && options.excludeIds.length > 0) {
8
- query = query.whereNotIn('id', options.excludeIds);
9
- }
10
- if (options.excludeRoles && options.excludeRoles.length > 0) {
11
- query = query.whereNotIn('role', options.excludeRoles);
12
- }
13
- if (options.includeRoles && options.includeRoles.length > 0) {
14
- query = query.whereIn('role', options.includeRoles);
15
- }
16
- return query.first();
17
- }
@@ -1,13 +0,0 @@
1
- import { type FetchUserCountOptions } from './fetch-user-count/fetch-user-count.js';
2
- export declare enum UserIntegrityCheckFlag {
3
- None = 0,
4
- /** Check if the number of remaining admin users is greater than 0 */
5
- RemainingAdmins = 1,
6
- /** Check if the number of users is within the limits */
7
- UserLimits = 2,
8
- All = 3
9
- }
10
- export interface ValidateUserCountIntegrityOptions extends Omit<FetchUserCountOptions, 'adminOnly'> {
11
- flags: UserIntegrityCheckFlag;
12
- }
13
- export declare function validateUserCountIntegrity(options: ValidateUserCountIntegrityOptions): Promise<void>;
@@ -1,29 +0,0 @@
1
- import { validateRemainingAdminCount } from '../permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js';
2
- import { checkUserLimits } from '../telemetry/utils/check-user-limits.js';
3
- import { shouldCheckUserLimits } from '../telemetry/utils/should-check-user-limits.js';
4
- import { fetchUserCount } from './fetch-user-count/fetch-user-count.js';
5
- export var UserIntegrityCheckFlag;
6
- (function (UserIntegrityCheckFlag) {
7
- UserIntegrityCheckFlag[UserIntegrityCheckFlag["None"] = 0] = "None";
8
- /** Check if the number of remaining admin users is greater than 0 */
9
- UserIntegrityCheckFlag[UserIntegrityCheckFlag["RemainingAdmins"] = 1] = "RemainingAdmins";
10
- /** Check if the number of users is within the limits */
11
- UserIntegrityCheckFlag[UserIntegrityCheckFlag["UserLimits"] = 2] = "UserLimits";
12
- UserIntegrityCheckFlag[UserIntegrityCheckFlag["All"] = 3] = "All";
13
- })(UserIntegrityCheckFlag || (UserIntegrityCheckFlag = {}));
14
- export async function validateUserCountIntegrity(options) {
15
- const validateUserLimits = (options.flags & UserIntegrityCheckFlag.UserLimits) !== 0;
16
- const validateRemainingAdminUsers = (options.flags & UserIntegrityCheckFlag.RemainingAdmins) !== 0;
17
- const limitCheck = validateUserLimits && shouldCheckUserLimits();
18
- if (!validateRemainingAdminUsers && !limitCheck) {
19
- return;
20
- }
21
- const adminOnly = validateRemainingAdminUsers && !limitCheck;
22
- const userCounts = await fetchUserCount({ ...options, adminOnly });
23
- if (limitCheck) {
24
- await checkUserLimits(userCounts);
25
- }
26
- if (validateRemainingAdminUsers) {
27
- validateRemainingAdminCount(userCounts.admin);
28
- }
29
- }