@directus/api 19.3.1 → 20.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 (285) hide show
  1. package/dist/app.js +4 -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 +2 -4
  6. package/dist/cache.js +3 -0
  7. package/dist/cli/commands/bootstrap/index.js +8 -2
  8. package/dist/cli/commands/init/index.js +9 -10
  9. package/dist/cli/utils/defaults.d.ts +4 -11
  10. package/dist/cli/utils/defaults.js +7 -1
  11. package/dist/constants.d.ts +1 -1
  12. package/dist/controllers/access.d.ts +2 -0
  13. package/dist/controllers/access.js +148 -0
  14. package/dist/controllers/auth.js +5 -16
  15. package/dist/controllers/permissions.js +14 -2
  16. package/dist/controllers/policies.d.ts +2 -0
  17. package/dist/controllers/policies.js +169 -0
  18. package/dist/controllers/roles.js +22 -1
  19. package/dist/controllers/users.js +0 -55
  20. package/dist/database/errors/dialects/mysql.js +23 -23
  21. package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +16 -0
  22. package/dist/database/get-ast-from-query/get-ast-from-query.js +82 -0
  23. package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +13 -0
  24. package/dist/database/get-ast-from-query/lib/convert-wildcards.js +69 -0
  25. package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +15 -0
  26. package/dist/database/get-ast-from-query/lib/parse-fields.js +190 -0
  27. package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +14 -0
  28. package/dist/database/get-ast-from-query/utils/get-deep-query.js +17 -0
  29. package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +2 -0
  30. package/dist/database/get-ast-from-query/utils/get-related-collection.js +13 -0
  31. package/dist/database/get-ast-from-query/utils/get-relation.d.ts +2 -0
  32. package/dist/database/get-ast-from-query/utils/get-relation.js +7 -0
  33. package/dist/database/helpers/fn/types.d.ts +2 -1
  34. package/dist/database/helpers/fn/types.js +1 -1
  35. package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
  36. package/dist/database/helpers/geometry/dialects/mssql.js +4 -2
  37. package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
  38. package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
  39. package/dist/database/helpers/geometry/dialects/oracle.js +5 -3
  40. package/dist/database/helpers/geometry/types.d.ts +1 -1
  41. package/dist/database/helpers/geometry/types.js +4 -2
  42. package/dist/database/index.js +2 -1
  43. package/dist/database/migrations/20240619A-permissions-policies.d.ts +3 -0
  44. package/dist/database/migrations/20240619A-permissions-policies.js +163 -0
  45. package/dist/database/run-ast/lib/get-db-query.d.ts +4 -0
  46. package/dist/database/run-ast/lib/get-db-query.js +194 -0
  47. package/dist/database/run-ast/lib/parse-current-level.d.ts +7 -0
  48. package/dist/database/run-ast/lib/parse-current-level.js +41 -0
  49. package/dist/database/run-ast/run-ast.d.ts +7 -0
  50. package/dist/database/run-ast/run-ast.js +107 -0
  51. package/dist/database/{run-ast.d.ts → run-ast/types.d.ts} +3 -9
  52. package/dist/database/run-ast/types.js +1 -0
  53. package/dist/database/run-ast/utils/apply-case-when.d.ts +16 -0
  54. package/dist/database/run-ast/utils/apply-case-when.js +26 -0
  55. package/dist/database/run-ast/utils/apply-parent-filters.d.ts +3 -0
  56. package/dist/database/run-ast/utils/apply-parent-filters.js +55 -0
  57. package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +10 -0
  58. package/dist/database/run-ast/utils/get-column-pre-processor.js +57 -0
  59. package/dist/database/run-ast/utils/get-field-alias.d.ts +2 -0
  60. package/dist/database/run-ast/utils/get-field-alias.js +4 -0
  61. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +5 -0
  62. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +23 -0
  63. package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +3 -0
  64. package/dist/database/run-ast/utils/merge-with-parent-items.js +87 -0
  65. package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +3 -0
  66. package/dist/database/run-ast/utils/remove-temporary-fields.js +73 -0
  67. package/dist/extensions/lib/sandbox/generate-api-extensions-sandbox-entrypoint.d.ts +1 -1
  68. package/dist/flows.js +3 -4
  69. package/dist/middleware/authenticate.js +2 -7
  70. package/dist/middleware/cache.js +1 -1
  71. package/dist/middleware/cors.js +4 -4
  72. package/dist/middleware/respond.js +1 -1
  73. package/dist/permissions/cache.d.ts +2 -0
  74. package/dist/permissions/cache.js +23 -0
  75. package/dist/permissions/lib/fetch-permissions.d.ts +10 -0
  76. package/dist/permissions/lib/fetch-permissions.js +55 -0
  77. package/dist/permissions/lib/fetch-policies.d.ts +7 -0
  78. package/dist/permissions/lib/fetch-policies.js +28 -0
  79. package/dist/permissions/lib/fetch-roles-tree.d.ts +3 -0
  80. package/dist/permissions/lib/fetch-roles-tree.js +28 -0
  81. package/dist/{services/permissions → permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
  82. package/dist/permissions/lib/with-app-minimal-permissions.js +10 -0
  83. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +7 -0
  84. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +56 -0
  85. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +3 -0
  86. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +16 -0
  87. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +8 -0
  88. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +24 -0
  89. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +9 -0
  90. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +31 -0
  91. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +16 -0
  92. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +27 -0
  93. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +10 -0
  94. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +23 -0
  95. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +5 -0
  96. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +7 -0
  97. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +5 -0
  98. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +10 -0
  99. package/dist/permissions/modules/fetch-global-access/types.d.ts +4 -0
  100. package/dist/permissions/modules/fetch-global-access/types.js +1 -0
  101. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +4 -0
  102. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +27 -0
  103. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +12 -0
  104. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +32 -0
  105. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +4 -0
  106. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +29 -0
  107. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +4 -0
  108. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +49 -0
  109. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +3 -0
  110. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +56 -0
  111. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +4 -0
  112. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +8 -0
  113. package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +9 -0
  114. package/dist/permissions/modules/process-ast/lib/inject-cases.js +93 -0
  115. package/dist/permissions/modules/process-ast/process-ast.d.ts +9 -0
  116. package/dist/permissions/modules/process-ast/process-ast.js +39 -0
  117. package/dist/permissions/modules/process-ast/types.d.ts +24 -0
  118. package/dist/permissions/modules/process-ast/types.js +1 -0
  119. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +2 -0
  120. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +7 -0
  121. package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +12 -0
  122. package/dist/permissions/modules/process-ast/utils/dedupe-access.js +30 -0
  123. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +15 -0
  124. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +50 -0
  125. package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +3 -0
  126. package/dist/permissions/modules/process-ast/utils/find-related-collection.js +9 -0
  127. package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +3 -0
  128. package/dist/permissions/modules/process-ast/utils/flatten-filter.js +24 -0
  129. package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +1 -0
  130. package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +3 -0
  131. package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +5 -0
  132. package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +7 -0
  133. package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +2 -0
  134. package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +3 -0
  135. package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +2 -0
  136. package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +3 -0
  137. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +3 -0
  138. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +16 -0
  139. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +2 -0
  140. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +12 -0
  141. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +2 -0
  142. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +28 -0
  143. package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +5 -0
  144. package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +12 -0
  145. package/dist/permissions/modules/process-payload/process-payload.d.ts +13 -0
  146. package/dist/permissions/modules/process-payload/process-payload.js +77 -0
  147. package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +12 -0
  148. package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +11 -0
  149. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +9 -0
  150. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +33 -0
  151. package/dist/permissions/modules/validate-access/validate-access.d.ts +14 -0
  152. package/dist/permissions/modules/validate-access/validate-access.js +28 -0
  153. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +1 -0
  154. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +8 -0
  155. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +5 -0
  156. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +10 -0
  157. package/dist/permissions/types.d.ts +6 -0
  158. package/dist/permissions/types.js +1 -0
  159. package/dist/permissions/utils/create-default-accountability.d.ts +2 -0
  160. package/dist/permissions/utils/create-default-accountability.js +11 -0
  161. package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +8 -0
  162. package/dist/permissions/utils/extract-required-dynamic-variable-context.js +27 -0
  163. package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +9 -0
  164. package/dist/permissions/utils/fetch-dynamic-variable-context.js +43 -0
  165. package/dist/permissions/utils/filter-policies-by-ip.d.ts +2 -0
  166. package/dist/permissions/utils/filter-policies-by-ip.js +15 -0
  167. package/dist/permissions/utils/get-unaliased-field-key.d.ts +5 -0
  168. package/dist/permissions/utils/get-unaliased-field-key.js +17 -0
  169. package/dist/permissions/utils/process-permissions.d.ts +7 -0
  170. package/dist/permissions/utils/process-permissions.js +9 -0
  171. package/dist/permissions/utils/with-cache.d.ts +10 -0
  172. package/dist/permissions/utils/with-cache.js +25 -0
  173. package/dist/services/access.d.ts +10 -0
  174. package/dist/services/access.js +43 -0
  175. package/dist/services/activity.js +22 -10
  176. package/dist/services/assets.d.ts +2 -3
  177. package/dist/services/assets.js +10 -5
  178. package/dist/services/authentication.js +18 -18
  179. package/dist/services/collections.js +18 -17
  180. package/dist/services/fields.d.ts +0 -1
  181. package/dist/services/fields.js +53 -24
  182. package/dist/services/files.d.ts +0 -4
  183. package/dist/services/files.js +10 -10
  184. package/dist/services/flows.d.ts +0 -2
  185. package/dist/services/flows.js +2 -14
  186. package/dist/services/graphql/index.d.ts +3 -3
  187. package/dist/services/graphql/index.js +126 -22
  188. package/dist/services/graphql/subscription.js +2 -4
  189. package/dist/services/import-export.js +23 -9
  190. package/dist/services/index.d.ts +3 -2
  191. package/dist/services/index.js +3 -2
  192. package/dist/services/items.d.ts +40 -14
  193. package/dist/services/items.js +182 -79
  194. package/dist/services/meta.js +60 -23
  195. package/dist/services/notifications.d.ts +0 -1
  196. package/dist/services/notifications.js +0 -7
  197. package/dist/services/operations.d.ts +0 -2
  198. package/dist/services/operations.js +2 -14
  199. package/dist/services/payload.d.ts +9 -10
  200. package/dist/services/payload.js +35 -19
  201. package/dist/services/{permissions/index.d.ts → permissions.d.ts} +5 -7
  202. package/dist/services/{permissions/index.js → permissions.js} +30 -54
  203. package/dist/services/policies.d.ts +12 -0
  204. package/dist/services/policies.js +87 -0
  205. package/dist/services/relations.d.ts +0 -6
  206. package/dist/services/relations.js +26 -29
  207. package/dist/services/roles.d.ts +4 -14
  208. package/dist/services/roles.js +56 -430
  209. package/dist/services/shares.d.ts +0 -2
  210. package/dist/services/shares.js +12 -8
  211. package/dist/services/specifications.d.ts +2 -2
  212. package/dist/services/specifications.js +39 -27
  213. package/dist/services/users.d.ts +2 -20
  214. package/dist/services/users.js +87 -192
  215. package/dist/services/utils.js +11 -7
  216. package/dist/services/versions.d.ts +0 -2
  217. package/dist/services/versions.js +34 -10
  218. package/dist/telemetry/lib/get-report.js +6 -3
  219. package/dist/telemetry/types/report.d.ts +4 -0
  220. package/dist/telemetry/utils/check-user-limits.d.ts +5 -0
  221. package/dist/telemetry/utils/check-user-limits.js +19 -0
  222. package/dist/telemetry/utils/get-filesize-sum.d.ts +5 -0
  223. package/dist/telemetry/utils/get-filesize-sum.js +7 -0
  224. package/dist/types/ast.d.ts +43 -1
  225. package/dist/types/items.d.ts +11 -0
  226. package/dist/utils/apply-query.d.ts +4 -3
  227. package/dist/utils/apply-query.js +37 -8
  228. package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +17 -0
  229. package/dist/utils/fetch-user-count/fetch-access-lookup.js +22 -0
  230. package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +16 -0
  231. package/dist/utils/fetch-user-count/fetch-access-roles.js +37 -0
  232. package/dist/utils/fetch-user-count/fetch-active-users.d.ts +6 -0
  233. package/dist/utils/fetch-user-count/fetch-active-users.js +3 -0
  234. package/dist/utils/fetch-user-count/fetch-user-count.d.ts +12 -0
  235. package/dist/utils/fetch-user-count/fetch-user-count.js +57 -0
  236. package/dist/utils/fetch-user-count/get-user-count-query.d.ts +20 -0
  237. package/dist/utils/fetch-user-count/get-user-count-query.js +17 -0
  238. package/dist/utils/get-accountability-for-role.js +16 -25
  239. package/dist/utils/get-accountability-for-token.js +17 -16
  240. package/dist/utils/get-cache-key.d.ts +1 -1
  241. package/dist/utils/get-cache-key.js +12 -1
  242. package/dist/utils/get-column.d.ts +2 -1
  243. package/dist/utils/get-column.js +1 -0
  244. package/dist/utils/get-graphql-type.js +1 -0
  245. package/dist/utils/get-service.d.ts +1 -1
  246. package/dist/utils/get-service.js +14 -10
  247. package/dist/utils/reduce-schema.d.ts +4 -6
  248. package/dist/utils/reduce-schema.js +14 -34
  249. package/dist/utils/validate-user-count-integrity.d.ts +13 -0
  250. package/dist/utils/validate-user-count-integrity.js +29 -0
  251. package/dist/websocket/authenticate.d.ts +0 -2
  252. package/dist/websocket/authenticate.js +0 -12
  253. package/dist/websocket/controllers/graphql.js +1 -4
  254. package/dist/websocket/controllers/hooks.js +4 -0
  255. package/dist/websocket/controllers/rest.js +0 -2
  256. package/dist/websocket/handlers/subscribe.js +0 -2
  257. package/dist/websocket/utils/items.d.ts +1 -1
  258. package/dist/websocket/utils/items.js +4 -1
  259. package/package.json +31 -30
  260. package/dist/database/run-ast.js +0 -450
  261. package/dist/middleware/check-ip.d.ts +0 -2
  262. package/dist/middleware/check-ip.js +0 -37
  263. package/dist/middleware/get-permissions.d.ts +0 -3
  264. package/dist/middleware/get-permissions.js +0 -10
  265. package/dist/services/authorization.d.ts +0 -17
  266. package/dist/services/authorization.js +0 -456
  267. package/dist/services/permissions/lib/with-app-minimal-permissions.js +0 -13
  268. package/dist/telemetry/utils/check-increased-user-limits.d.ts +0 -7
  269. package/dist/telemetry/utils/check-increased-user-limits.js +0 -22
  270. package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +0 -6
  271. package/dist/telemetry/utils/get-role-counts-by-roles.js +0 -27
  272. package/dist/telemetry/utils/get-role-counts-by-users.d.ts +0 -11
  273. package/dist/telemetry/utils/get-role-counts-by-users.js +0 -34
  274. package/dist/telemetry/utils/get-user-count.d.ts +0 -8
  275. package/dist/telemetry/utils/get-user-count.js +0 -33
  276. package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +0 -7
  277. package/dist/telemetry/utils/get-user-counts-by-roles.js +0 -35
  278. package/dist/utils/get-ast-from-query.d.ts +0 -13
  279. package/dist/utils/get-ast-from-query.js +0 -297
  280. package/dist/utils/get-permissions.d.ts +0 -2
  281. package/dist/utils/get-permissions.js +0 -150
  282. package/dist/utils/merge-permissions-for-share.d.ts +0 -4
  283. package/dist/utils/merge-permissions-for-share.js +0 -109
  284. package/dist/utils/merge-permissions.d.ts +0 -3
  285. package/dist/utils/merge-permissions.js +0 -95
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@directus/api",
3
- "version": "19.3.1",
3
+ "version": "20.0.0-rc.0",
4
4
  "description": "Directus is a real-time API and App dashboard for managing SQL database content",
5
5
  "keywords": [
6
6
  "directus",
@@ -91,7 +91,7 @@
91
91
  "flat": "6.0.1",
92
92
  "fs-extra": "11.2.0",
93
93
  "glob-to-regexp": "0.4.1",
94
- "graphql": "16.8.1",
94
+ "graphql": "16.8.2",
95
95
  "graphql-compose": "9.0.11",
96
96
  "graphql-ws": "5.16.0",
97
97
  "helmet": "7.1.0",
@@ -119,7 +119,7 @@
119
119
  "nanoid": "5.0.7",
120
120
  "node-machine-id": "1.1.12",
121
121
  "node-schedule": "2.1.1",
122
- "nodemailer": "6.9.13",
122
+ "nodemailer": "6.9.14",
123
123
  "object-hash": "3.0.0",
124
124
  "openapi3-ts": "4.3.2",
125
125
  "openid-client": "5.6.5",
@@ -128,16 +128,16 @@
128
128
  "p-limit": "5.0.0",
129
129
  "p-queue": "8.0.1",
130
130
  "papaparse": "5.4.1",
131
- "pino": "9.1.0",
131
+ "pino": "9.2.0",
132
132
  "pino-http": "9.0.0",
133
133
  "pino-http-print": "3.1.0",
134
- "pino-pretty": "11.0.0",
134
+ "pino-pretty": "11.2.1",
135
135
  "qs": "6.12.1",
136
136
  "rate-limiter-flexible": "5.0.3",
137
137
  "rollup": "4.17.2",
138
138
  "samlify": "2.8.10",
139
139
  "sanitize-html": "2.13.0",
140
- "sharp": "0.33.3",
140
+ "sharp": "0.33.4",
141
141
  "snappy": "7.2.2",
142
142
  "stream-json": "1.8.0",
143
143
  "tar": "7.2.0",
@@ -145,30 +145,30 @@
145
145
  "wellknown": "0.5.0",
146
146
  "ws": "8.17.0",
147
147
  "zod": "3.23.8",
148
- "zod-validation-error": "3.2.0",
149
- "@directus/constants": "11.0.4",
150
- "@directus/app": "12.1.4",
151
- "@directus/env": "1.1.6",
152
- "@directus/extensions": "1.0.8",
153
- "@directus/errors": "0.3.2",
154
- "@directus/extensions-registry": "1.0.8",
155
- "@directus/extensions-sdk": "11.0.8",
148
+ "zod-validation-error": "3.3.0",
149
+ "@directus/app": "13.0.0-rc.0",
150
+ "@directus/constants": "11.1.0-rc.0",
151
+ "@directus/env": "1.1.7-rc.0",
152
+ "@directus/errors": "0.4.0-rc.0",
153
+ "@directus/extensions-registry": "1.0.9-rc.0",
154
+ "@directus/extensions-sdk": "11.0.9-rc.0",
156
155
  "@directus/format-title": "10.1.2",
157
- "@directus/pressure": "1.0.20",
158
- "@directus/memory": "1.0.9",
159
- "@directus/schema": "11.0.3",
156
+ "@directus/extensions": "2.0.0-rc.0",
157
+ "@directus/memory": "1.1.0-rc.0",
158
+ "@directus/pressure": "1.0.21-rc.0",
160
159
  "@directus/specs": "10.2.10",
160
+ "@directus/schema": "11.0.3",
161
161
  "@directus/storage": "10.0.13",
162
- "@directus/storage-driver-azure": "10.0.22",
163
- "@directus/storage-driver-gcs": "10.0.23",
162
+ "@directus/storage-driver-azure": "10.0.23-rc.0",
163
+ "@directus/storage-driver-cloudinary": "10.0.23-rc.0",
164
+ "@directus/storage-driver-gcs": "10.0.24-rc.0",
164
165
  "@directus/storage-driver-local": "10.0.20",
165
- "@directus/storage-driver-cloudinary": "10.0.22",
166
- "@directus/storage-driver-s3": "10.0.23",
167
- "@directus/storage-driver-supabase": "1.0.14",
168
- "@directus/system-data": "1.0.4",
169
- "@directus/utils": "11.0.9",
170
- "@directus/validation": "0.0.17",
171
- "directus": "10.12.1"
166
+ "@directus/storage-driver-supabase": "1.0.15-rc.0",
167
+ "@directus/storage-driver-s3": "10.0.24-rc.0",
168
+ "@directus/utils": "12.0.0-rc.0",
169
+ "@directus/system-data": "2.0.0-rc.0",
170
+ "@directus/validation": "0.0.18-rc.0",
171
+ "directus": "11.0.0-rc.1"
172
172
  },
173
173
  "devDependencies": {
174
174
  "@ngneat/falso": "7.2.0",
@@ -211,14 +211,14 @@
211
211
  "vitest": "1.5.3",
212
212
  "@directus/random": "0.2.8",
213
213
  "@directus/tsconfig": "1.0.1",
214
- "@directus/types": "11.1.3"
214
+ "@directus/types": "12.0.0-rc.0"
215
215
  },
216
216
  "optionalDependencies": {
217
217
  "@keyv/redis": "2.8.4",
218
- "mysql": "2.18.1",
218
+ "mysql2": "3.10.0",
219
219
  "nodemailer-mailgun-transport": "2.1.5",
220
220
  "nodemailer-sendgrid": "1.0.3",
221
- "oracledb": "6.5.0",
221
+ "oracledb": "6.5.1",
222
222
  "pg": "8.11.5",
223
223
  "sqlite3": "5.1.7",
224
224
  "tedious": "18.2.0"
@@ -230,6 +230,7 @@
230
230
  "build": "tsc --project tsconfig.prod.json && copyfiles \"src/**/*.{yaml,liquid}\" -u 1 dist",
231
231
  "cli": "NODE_ENV=development SERVE_APP=false tsx src/cli/run.ts",
232
232
  "dev": "NODE_ENV=development SERVE_APP=true tsx watch --ignore extensions --clear-screen=false src/start.ts",
233
- "test": "vitest --watch=false"
233
+ "test": "vitest run",
234
+ "test:watch": "vitest"
234
235
  }
235
236
  }
@@ -1,450 +0,0 @@
1
- import { useEnv } from '@directus/env';
2
- import { toArray } from '@directus/utils';
3
- import { clone, cloneDeep, isNil, merge, pick, uniq } from 'lodash-es';
4
- import { PayloadService } from '../services/payload.js';
5
- import { applyFunctionToColumnName } from '../utils/apply-function-to-column-name.js';
6
- import applyQuery, { applyLimit, applySort, generateAlias } from '../utils/apply-query.js';
7
- import { getCollectionFromAlias } from '../utils/get-collection-from-alias.js';
8
- import { getColumn } from '../utils/get-column.js';
9
- import { parseFilterKey } from '../utils/parse-filter-key.js';
10
- import { getHelpers } from './helpers/index.js';
11
- import getDatabase from './index.js';
12
- /**
13
- * Execute a given AST using Knex. Returns array of items based on requested AST.
14
- */
15
- export default async function runAST(originalAST, schema, options) {
16
- const ast = cloneDeep(originalAST);
17
- const knex = options?.knex || getDatabase();
18
- if (ast.type === 'a2o') {
19
- const results = {};
20
- for (const collection of ast.names) {
21
- results[collection] = await run(collection, ast.children[collection], ast.query[collection]);
22
- }
23
- return results;
24
- }
25
- else {
26
- return await run(ast.name, ast.children, options?.query || ast.query);
27
- }
28
- async function run(collection, children, query) {
29
- const env = useEnv();
30
- // Retrieve the database columns to select in the current AST
31
- const { fieldNodes, primaryKeyField, nestedCollectionNodes } = await parseCurrentLevel(schema, collection, children, query);
32
- // The actual knex query builder instance. This is a promise that resolves with the raw items from the db
33
- const dbQuery = await getDBQuery(schema, knex, collection, fieldNodes, query);
34
- const rawItems = await dbQuery;
35
- if (!rawItems)
36
- return null;
37
- // Run the items through the special transforms
38
- const payloadService = new PayloadService(collection, { knex, schema });
39
- let items = await payloadService.processValues('read', rawItems, query.alias ?? {});
40
- if (!items || (Array.isArray(items) && items.length === 0))
41
- return items;
42
- // Apply the `_in` filters to the nested collection batches
43
- const nestedNodes = applyParentFilters(schema, nestedCollectionNodes, items);
44
- for (const nestedNode of nestedNodes) {
45
- let nestedItems = [];
46
- if (nestedNode.type === 'o2m') {
47
- let hasMore = true;
48
- let batchCount = 0;
49
- while (hasMore) {
50
- const node = merge({}, nestedNode, {
51
- query: {
52
- limit: env['RELATIONAL_BATCH_SIZE'],
53
- offset: batchCount * env['RELATIONAL_BATCH_SIZE'],
54
- page: null,
55
- },
56
- });
57
- nestedItems = (await runAST(node, schema, { knex, nested: true }));
58
- if (nestedItems) {
59
- items = mergeWithParentItems(schema, nestedItems, items, nestedNode);
60
- }
61
- if (!nestedItems || nestedItems.length < env['RELATIONAL_BATCH_SIZE']) {
62
- hasMore = false;
63
- }
64
- batchCount++;
65
- }
66
- }
67
- else {
68
- const node = merge({}, nestedNode, {
69
- query: { limit: -1 },
70
- });
71
- nestedItems = (await runAST(node, schema, { knex, nested: true }));
72
- if (nestedItems) {
73
- // Merge all fetched nested records with the parent items
74
- items = mergeWithParentItems(schema, nestedItems, items, nestedNode);
75
- }
76
- }
77
- }
78
- // During the fetching of data, we have to inject a couple of required fields for the child nesting
79
- // to work (primary / foreign keys) even if they're not explicitly requested. After all fetching
80
- // and nesting is done, we parse through the output structure, and filter out all non-requested
81
- // fields
82
- if (options?.nested !== true && options?.stripNonRequested !== false) {
83
- items = removeTemporaryFields(schema, items, originalAST, primaryKeyField);
84
- }
85
- return items;
86
- }
87
- }
88
- async function parseCurrentLevel(schema, collection, children, query) {
89
- const primaryKeyField = schema.collections[collection].primary;
90
- const columnsInCollection = Object.keys(schema.collections[collection].fields);
91
- const columnsToSelectInternal = [];
92
- const nestedCollectionNodes = [];
93
- for (const child of children) {
94
- if (child.type === 'field' || child.type === 'functionField') {
95
- const { fieldName } = parseFilterKey(child.name);
96
- if (columnsInCollection.includes(fieldName)) {
97
- columnsToSelectInternal.push(child.fieldKey);
98
- }
99
- continue;
100
- }
101
- if (!child.relation)
102
- continue;
103
- if (child.type === 'm2o') {
104
- columnsToSelectInternal.push(child.relation.field);
105
- }
106
- if (child.type === 'a2o') {
107
- columnsToSelectInternal.push(child.relation.field);
108
- columnsToSelectInternal.push(child.relation.meta.one_collection_field);
109
- }
110
- nestedCollectionNodes.push(child);
111
- }
112
- const isAggregate = (query.group || (query.aggregate && Object.keys(query.aggregate).length > 0)) ?? false;
113
- /** Always fetch primary key in case there's a nested relation that needs it. Aggregate payloads
114
- * can't have nested relational fields
115
- */
116
- if (isAggregate === false && columnsToSelectInternal.includes(primaryKeyField) === false) {
117
- columnsToSelectInternal.push(primaryKeyField);
118
- }
119
- /** Make sure select list has unique values */
120
- const columnsToSelect = [...new Set(columnsToSelectInternal)];
121
- const fieldNodes = columnsToSelect.map((column) => children.find((childNode) => (childNode.type === 'field' || childNode.type === 'functionField') && childNode.fieldKey === column) ?? {
122
- type: 'field',
123
- name: column,
124
- fieldKey: column,
125
- });
126
- return { fieldNodes, nestedCollectionNodes, primaryKeyField };
127
- }
128
- function getColumnPreprocessor(knex, schema, table) {
129
- const helpers = getHelpers(knex);
130
- return function (fieldNode) {
131
- let alias = undefined;
132
- if (fieldNode.name !== fieldNode.fieldKey) {
133
- alias = fieldNode.fieldKey;
134
- }
135
- let field;
136
- if (fieldNode.type === 'field' || fieldNode.type === 'functionField') {
137
- const { fieldName } = parseFilterKey(fieldNode.name);
138
- field = schema.collections[table].fields[fieldName];
139
- }
140
- else {
141
- field = schema.collections[fieldNode.relation.collection].fields[fieldNode.relation.field];
142
- }
143
- if (field?.type?.startsWith('geometry')) {
144
- return helpers.st.asText(table, field.field);
145
- }
146
- if (fieldNode.type === 'functionField') {
147
- return getColumn(knex, table, fieldNode.name, alias, schema, { query: fieldNode.query });
148
- }
149
- return getColumn(knex, table, fieldNode.name, alias, schema);
150
- };
151
- }
152
- async function getDBQuery(schema, knex, table, fieldNodes, query) {
153
- const env = useEnv();
154
- const preProcess = getColumnPreprocessor(knex, schema, table);
155
- const queryCopy = clone(query);
156
- const helpers = getHelpers(knex);
157
- queryCopy.limit = typeof queryCopy.limit === 'number' ? queryCopy.limit : Number(env['QUERY_LIMIT_DEFAULT']);
158
- // Queries with aggregates and groupBy will not have duplicate result
159
- if (queryCopy.aggregate || queryCopy.group) {
160
- const flatQuery = knex.select(fieldNodes.map(preProcess)).from(table);
161
- return await applyQuery(knex, table, flatQuery, queryCopy, schema).query;
162
- }
163
- const primaryKey = schema.collections[table].primary;
164
- const aliasMap = Object.create(null);
165
- let dbQuery = knex.from(table);
166
- let sortRecords;
167
- const innerQuerySortRecords = [];
168
- let hasMultiRelationalSort;
169
- if (queryCopy.sort) {
170
- const sortResult = applySort(knex, schema, dbQuery, queryCopy, table, aliasMap, true);
171
- if (sortResult) {
172
- sortRecords = sortResult.sortRecords;
173
- hasMultiRelationalSort = sortResult.hasMultiRelationalSort;
174
- }
175
- }
176
- const { hasMultiRelationalFilter } = applyQuery(knex, table, dbQuery, queryCopy, schema, {
177
- aliasMap,
178
- isInnerQuery: true,
179
- hasMultiRelationalSort,
180
- });
181
- const needsInnerQuery = hasMultiRelationalSort || hasMultiRelationalFilter;
182
- if (needsInnerQuery) {
183
- dbQuery.select(`${table}.${primaryKey}`).distinct();
184
- }
185
- else {
186
- dbQuery.select(fieldNodes.map(preProcess));
187
- }
188
- if (sortRecords) {
189
- // Clears the order if any, eg: from MSSQL offset
190
- dbQuery.clear('order');
191
- if (needsInnerQuery) {
192
- let orderByString = '';
193
- const orderByFields = [];
194
- sortRecords.map((sortRecord) => {
195
- if (orderByString.length !== 0) {
196
- orderByString += ', ';
197
- }
198
- const sortAlias = `sort_${generateAlias()}`;
199
- if (sortRecord.column.includes('.')) {
200
- const [alias, field] = sortRecord.column.split('.');
201
- const originalCollectionName = getCollectionFromAlias(alias, aliasMap);
202
- dbQuery.select(getColumn(knex, alias, field, sortAlias, schema, { originalCollectionName }));
203
- orderByString += `?? ${sortRecord.order}`;
204
- orderByFields.push(getColumn(knex, alias, field, false, schema, { originalCollectionName }));
205
- }
206
- else {
207
- dbQuery.select(getColumn(knex, table, sortRecord.column, sortAlias, schema));
208
- orderByString += `?? ${sortRecord.order}`;
209
- orderByFields.push(getColumn(knex, table, sortRecord.column, false, schema));
210
- }
211
- innerQuerySortRecords.push({ alias: sortAlias, order: sortRecord.order });
212
- });
213
- dbQuery.orderByRaw(orderByString, orderByFields);
214
- if (hasMultiRelationalSort) {
215
- dbQuery = helpers.schema.applyMultiRelationalSort(knex, dbQuery, table, primaryKey, orderByString, orderByFields);
216
- }
217
- }
218
- else {
219
- sortRecords.map((sortRecord) => {
220
- if (sortRecord.column.includes('.')) {
221
- const [alias, field] = sortRecord.column.split('.');
222
- sortRecord.column = getColumn(knex, alias, field, false, schema, {
223
- originalCollectionName: getCollectionFromAlias(alias, aliasMap),
224
- });
225
- }
226
- else {
227
- sortRecord.column = getColumn(knex, table, sortRecord.column, false, schema);
228
- }
229
- });
230
- dbQuery.orderBy(sortRecords);
231
- }
232
- }
233
- if (!needsInnerQuery)
234
- return dbQuery;
235
- const wrapperQuery = knex
236
- .select(fieldNodes.map(preProcess))
237
- .from(table)
238
- .innerJoin(knex.raw('??', dbQuery.as('inner')), `${table}.${primaryKey}`, `inner.${primaryKey}`);
239
- if (sortRecords && needsInnerQuery) {
240
- innerQuerySortRecords.map((innerQuerySortRecord) => {
241
- wrapperQuery.orderBy(`inner.${innerQuerySortRecord.alias}`, innerQuerySortRecord.order);
242
- });
243
- if (hasMultiRelationalSort) {
244
- wrapperQuery.where('inner.directus_row_number', '=', 1);
245
- applyLimit(knex, wrapperQuery, queryCopy.limit);
246
- }
247
- }
248
- return wrapperQuery;
249
- }
250
- function applyParentFilters(schema, nestedCollectionNodes, parentItem) {
251
- const parentItems = toArray(parentItem);
252
- for (const nestedNode of nestedCollectionNodes) {
253
- if (!nestedNode.relation)
254
- continue;
255
- if (nestedNode.type === 'm2o') {
256
- const foreignField = schema.collections[nestedNode.relation.related_collection].primary;
257
- const foreignIds = uniq(parentItems.map((res) => res[nestedNode.relation.field])).filter((id) => !isNil(id));
258
- merge(nestedNode, { query: { filter: { [foreignField]: { _in: foreignIds } } } });
259
- }
260
- else if (nestedNode.type === 'o2m') {
261
- const relatedM2OisFetched = !!nestedNode.children.find((child) => {
262
- return child.type === 'field' && child.name === nestedNode.relation.field;
263
- });
264
- if (relatedM2OisFetched === false) {
265
- nestedNode.children.push({
266
- type: 'field',
267
- name: nestedNode.relation.field,
268
- fieldKey: nestedNode.relation.field,
269
- });
270
- }
271
- if (nestedNode.relation.meta?.sort_field) {
272
- nestedNode.children.push({
273
- type: 'field',
274
- name: nestedNode.relation.meta.sort_field,
275
- fieldKey: nestedNode.relation.meta.sort_field,
276
- });
277
- }
278
- const foreignField = nestedNode.relation.field;
279
- const foreignIds = uniq(parentItems.map((res) => res[nestedNode.parentKey])).filter((id) => !isNil(id));
280
- merge(nestedNode, { query: { filter: { [foreignField]: { _in: foreignIds } } } });
281
- }
282
- else if (nestedNode.type === 'a2o') {
283
- const keysPerCollection = {};
284
- for (const parentItem of parentItems) {
285
- const collection = parentItem[nestedNode.relation.meta.one_collection_field];
286
- if (!keysPerCollection[collection])
287
- keysPerCollection[collection] = [];
288
- keysPerCollection[collection].push(parentItem[nestedNode.relation.field]);
289
- }
290
- for (const relatedCollection of nestedNode.names) {
291
- const foreignField = nestedNode.relatedKey[relatedCollection];
292
- const foreignIds = uniq(keysPerCollection[relatedCollection]);
293
- merge(nestedNode, {
294
- query: { [relatedCollection]: { filter: { [foreignField]: { _in: foreignIds } }, limit: foreignIds.length } },
295
- });
296
- }
297
- }
298
- }
299
- return nestedCollectionNodes;
300
- }
301
- function mergeWithParentItems(schema, nestedItem, parentItem, nestedNode) {
302
- const env = useEnv();
303
- const nestedItems = toArray(nestedItem);
304
- const parentItems = clone(toArray(parentItem));
305
- if (nestedNode.type === 'm2o') {
306
- for (const parentItem of parentItems) {
307
- const itemChild = nestedItems.find((nestedItem) => {
308
- return (nestedItem[schema.collections[nestedNode.relation.related_collection].primary] ==
309
- parentItem[nestedNode.relation.field]);
310
- });
311
- parentItem[nestedNode.fieldKey] = itemChild || null;
312
- }
313
- }
314
- else if (nestedNode.type === 'o2m') {
315
- for (const parentItem of parentItems) {
316
- if (!parentItem[nestedNode.fieldKey])
317
- parentItem[nestedNode.fieldKey] = [];
318
- const itemChildren = nestedItems.filter((nestedItem) => {
319
- if (nestedItem === null)
320
- return false;
321
- if (Array.isArray(nestedItem[nestedNode.relation.field]))
322
- return true;
323
- return (nestedItem[nestedNode.relation.field] ==
324
- parentItem[schema.collections[nestedNode.relation.related_collection].primary] ||
325
- nestedItem[nestedNode.relation.field]?.[schema.collections[nestedNode.relation.related_collection].primary] == parentItem[schema.collections[nestedNode.relation.related_collection].primary]);
326
- });
327
- parentItem[nestedNode.fieldKey].push(...itemChildren);
328
- const limit = nestedNode.query.limit ?? Number(env['QUERY_LIMIT_DEFAULT']);
329
- if (nestedNode.query.page && nestedNode.query.page > 1) {
330
- parentItem[nestedNode.fieldKey] = parentItem[nestedNode.fieldKey].slice(limit * (nestedNode.query.page - 1));
331
- }
332
- if (nestedNode.query.offset && nestedNode.query.offset >= 0) {
333
- parentItem[nestedNode.fieldKey] = parentItem[nestedNode.fieldKey].slice(nestedNode.query.offset);
334
- }
335
- if (limit !== -1) {
336
- parentItem[nestedNode.fieldKey] = parentItem[nestedNode.fieldKey].slice(0, limit);
337
- }
338
- parentItem[nestedNode.fieldKey] = parentItem[nestedNode.fieldKey].sort((a, b) => {
339
- // This is pre-filled in get-ast-from-query
340
- const sortField = nestedNode.query.sort[0];
341
- let column = sortField;
342
- let order = 'asc';
343
- if (sortField.startsWith('-')) {
344
- column = sortField.substring(1);
345
- order = 'desc';
346
- }
347
- if (a[column] === b[column])
348
- return 0;
349
- if (a[column] === null)
350
- return 1;
351
- if (b[column] === null)
352
- return -1;
353
- if (order === 'asc') {
354
- return a[column] < b[column] ? -1 : 1;
355
- }
356
- else {
357
- return a[column] < b[column] ? 1 : -1;
358
- }
359
- });
360
- }
361
- }
362
- else if (nestedNode.type === 'a2o') {
363
- for (const parentItem of parentItems) {
364
- if (!nestedNode.relation.meta?.one_collection_field) {
365
- parentItem[nestedNode.fieldKey] = null;
366
- continue;
367
- }
368
- const relatedCollection = parentItem[nestedNode.relation.meta.one_collection_field];
369
- if (!nestedItem[relatedCollection]) {
370
- parentItem[nestedNode.fieldKey] = null;
371
- continue;
372
- }
373
- const itemChild = nestedItem[relatedCollection].find((nestedItem) => {
374
- return nestedItem[nestedNode.relatedKey[relatedCollection]] == parentItem[nestedNode.fieldKey];
375
- });
376
- parentItem[nestedNode.fieldKey] = itemChild || null;
377
- }
378
- }
379
- return Array.isArray(parentItem) ? parentItems : parentItems[0];
380
- }
381
- function removeTemporaryFields(schema, rawItem, ast, primaryKeyField, parentItem) {
382
- const rawItems = cloneDeep(toArray(rawItem));
383
- const items = [];
384
- if (ast.type === 'a2o') {
385
- const fields = {};
386
- const nestedCollectionNodes = {};
387
- for (const relatedCollection of ast.names) {
388
- if (!fields[relatedCollection])
389
- fields[relatedCollection] = [];
390
- if (!nestedCollectionNodes[relatedCollection])
391
- nestedCollectionNodes[relatedCollection] = [];
392
- for (const child of ast.children[relatedCollection]) {
393
- if (child.type === 'field' || child.type === 'functionField') {
394
- fields[relatedCollection].push(child.name);
395
- }
396
- else {
397
- fields[relatedCollection].push(child.fieldKey);
398
- nestedCollectionNodes[relatedCollection].push(child);
399
- }
400
- }
401
- }
402
- for (const rawItem of rawItems) {
403
- const relatedCollection = parentItem?.[ast.relation.meta.one_collection_field];
404
- if (rawItem === null || rawItem === undefined)
405
- return rawItem;
406
- let item = rawItem;
407
- for (const nestedNode of nestedCollectionNodes[relatedCollection]) {
408
- item[nestedNode.fieldKey] = removeTemporaryFields(schema, item[nestedNode.fieldKey], nestedNode, schema.collections[nestedNode.relation.collection].primary, item);
409
- }
410
- const fieldsWithFunctionsApplied = fields[relatedCollection].map((field) => applyFunctionToColumnName(field));
411
- item =
412
- fields[relatedCollection].length > 0 ? pick(rawItem, fieldsWithFunctionsApplied) : rawItem[primaryKeyField];
413
- items.push(item);
414
- }
415
- }
416
- else {
417
- const fields = [];
418
- const nestedCollectionNodes = [];
419
- for (const child of ast.children) {
420
- fields.push(child.fieldKey);
421
- if (child.type !== 'field' && child.type !== 'functionField') {
422
- nestedCollectionNodes.push(child);
423
- }
424
- }
425
- // Make sure any requested aggregate fields are included
426
- if (ast.query?.aggregate) {
427
- for (const [operation, aggregateFields] of Object.entries(ast.query.aggregate)) {
428
- if (!fields)
429
- continue;
430
- if (operation === 'count' && aggregateFields.includes('*'))
431
- fields.push('count');
432
- fields.push(...aggregateFields.map((field) => `${operation}.${field}`));
433
- }
434
- }
435
- for (const rawItem of rawItems) {
436
- if (rawItem === null || rawItem === undefined)
437
- return rawItem;
438
- let item = rawItem;
439
- for (const nestedNode of nestedCollectionNodes) {
440
- item[nestedNode.fieldKey] = removeTemporaryFields(schema, item[nestedNode.fieldKey], nestedNode, nestedNode.type === 'm2o'
441
- ? schema.collections[nestedNode.relation.related_collection].primary
442
- : schema.collections[nestedNode.relation.collection].primary, item);
443
- }
444
- const fieldsWithFunctionsApplied = fields.map((field) => applyFunctionToColumnName(field));
445
- item = fields.length > 0 ? pick(rawItem, fieldsWithFunctionsApplied) : rawItem[primaryKeyField];
446
- items.push(item);
447
- }
448
- }
449
- return Array.isArray(rawItem) ? items : items[0];
450
- }
@@ -1,2 +0,0 @@
1
- import type { RequestHandler } from 'express';
2
- export declare const checkIP: RequestHandler;
@@ -1,37 +0,0 @@
1
- import { InvalidIpError } from '@directus/errors';
2
- import getDatabase from '../database/index.js';
3
- import { useLogger } from '../logger.js';
4
- import asyncHandler from '../utils/async-handler.js';
5
- import { ipInNetworks } from '../utils/ip-in-networks.js';
6
- export const checkIP = asyncHandler(async (req, _res, next) => {
7
- const database = getDatabase();
8
- const logger = useLogger();
9
- const { role: roleId, ip } = req.accountability;
10
- const query = database.select('ip_access').from('directus_roles');
11
- if (roleId) {
12
- query.where({ id: roleId });
13
- }
14
- else {
15
- query.whereNull('id');
16
- }
17
- const role = await query.first();
18
- if (!role?.ip_access)
19
- return next();
20
- const ipAllowList = role.ip_access.split(',').filter((ip) => ip);
21
- if (ipAllowList.length > 0) {
22
- if (!ip)
23
- throw new InvalidIpError();
24
- let allowed;
25
- try {
26
- allowed = ipInNetworks(ip, ipAllowList);
27
- }
28
- catch (error) {
29
- logger.warn(`Invalid IP access configuration for role "${roleId}"`);
30
- logger.warn(error);
31
- throw new InvalidIpError();
32
- }
33
- if (!allowed)
34
- throw new InvalidIpError();
35
- }
36
- return next();
37
- });
@@ -1,3 +0,0 @@
1
- import type { RequestHandler } from 'express';
2
- declare const getPermissions: RequestHandler;
3
- export default getPermissions;
@@ -1,10 +0,0 @@
1
- import asyncHandler from '../utils/async-handler.js';
2
- import { getPermissions as getPermissionsUtil } from '../utils/get-permissions.js';
3
- const getPermissions = asyncHandler(async (req, _res, next) => {
4
- if (!req.accountability) {
5
- throw new Error('getPermissions middleware needs to be called after authenticate');
6
- }
7
- req.accountability.permissions = await getPermissionsUtil(req.accountability, req.schema);
8
- return next();
9
- });
10
- export default getPermissions;
@@ -1,17 +0,0 @@
1
- import type { Accountability, Item, PermissionsAction, PrimaryKey, SchemaOverview } from '@directus/types';
2
- import type { Knex } from 'knex';
3
- import type { AST, AbstractServiceOptions } from '../types/index.js';
4
- import { PayloadService } from './payload.js';
5
- export declare class AuthorizationService {
6
- knex: Knex;
7
- accountability: Accountability | null;
8
- payloadService: PayloadService;
9
- schema: SchemaOverview;
10
- constructor(options: AbstractServiceOptions);
11
- processAST(ast: AST, action?: PermissionsAction): Promise<AST>;
12
- /**
13
- * Checks if the provided payload matches the configured permissions, and adds the presets to the payload.
14
- */
15
- validatePayload(action: PermissionsAction, collection: string, data: Partial<Item>): Partial<Item>;
16
- checkAccess(action: PermissionsAction, collection: string, pk?: PrimaryKey | PrimaryKey[]): Promise<void>;
17
- }