@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
package/dist/app.js CHANGED
@@ -10,7 +10,6 @@ import path from 'path';
10
10
  import qs from 'qs';
11
11
  import { registerAuthProviders } from './auth.js';
12
12
  import activityRouter from './controllers/activity.js';
13
- import accessRouter from './controllers/access.js';
14
13
  import assetsRouter from './controllers/assets.js';
15
14
  import authRouter from './controllers/auth.js';
16
15
  import collectionsRouter from './controllers/collections.js';
@@ -27,7 +26,6 @@ import notificationsRouter from './controllers/notifications.js';
27
26
  import operationsRouter from './controllers/operations.js';
28
27
  import panelsRouter from './controllers/panels.js';
29
28
  import permissionsRouter from './controllers/permissions.js';
30
- import policiesRouter from './controllers/policies.js';
31
29
  import presetsRouter from './controllers/presets.js';
32
30
  import relationsRouter from './controllers/relations.js';
33
31
  import revisionsRouter from './controllers/revisions.js';
@@ -37,6 +35,7 @@ import serverRouter from './controllers/server.js';
37
35
  import settingsRouter from './controllers/settings.js';
38
36
  import sharesRouter from './controllers/shares.js';
39
37
  import translationsRouter from './controllers/translations.js';
38
+ import { default as tusRouter, scheduleTusCleanup } from './controllers/tus.js';
40
39
  import usersRouter from './controllers/users.js';
41
40
  import utilsRouter from './controllers/utils.js';
42
41
  import versionsRouter from './controllers/versions.js';
@@ -48,9 +47,11 @@ import { getFlowManager } from './flows.js';
48
47
  import { createExpressLogger, useLogger } from './logger.js';
49
48
  import authenticate from './middleware/authenticate.js';
50
49
  import cache from './middleware/cache.js';
50
+ import { checkIP } from './middleware/check-ip.js';
51
51
  import cors from './middleware/cors.js';
52
52
  import errorHandler from './middleware/error-handler.js';
53
53
  import extractToken from './middleware/extract-token.js';
54
+ import getPermissions from './middleware/get-permissions.js';
54
55
  import rateLimiterGlobal from './middleware/rate-limiter-global.js';
55
56
  import rateLimiter from './middleware/rate-limiter-ip.js';
56
57
  import sanitizeQuery from './middleware/sanitize-query.js';
@@ -197,20 +198,24 @@ export default async function createApp() {
197
198
  }
198
199
  app.get('/server/ping', (_req, res) => res.send('pong'));
199
200
  app.use(authenticate);
201
+ app.use(checkIP);
200
202
  app.use(sanitizeQuery);
201
203
  app.use(cache);
202
204
  app.use(schema);
205
+ app.use(getPermissions);
203
206
  await emitter.emitInit('middlewares.after', { app });
204
207
  await emitter.emitInit('routes.before', { app });
205
208
  app.use('/auth', authRouter);
206
209
  app.use('/graphql', graphqlRouter);
207
210
  app.use('/activity', activityRouter);
208
- app.use('/access', accessRouter);
209
211
  app.use('/assets', assetsRouter);
210
212
  app.use('/collections', collectionsRouter);
211
213
  app.use('/dashboards', dashboardsRouter);
212
214
  app.use('/extensions', extensionsRouter);
213
215
  app.use('/fields', fieldsRouter);
216
+ if (env['TUS_ENABLED'] === true) {
217
+ app.use('/files/tus', tusRouter);
218
+ }
214
219
  app.use('/files', filesRouter);
215
220
  app.use('/flows', flowsRouter);
216
221
  app.use('/folders', foldersRouter);
@@ -219,7 +224,6 @@ export default async function createApp() {
219
224
  app.use('/operations', operationsRouter);
220
225
  app.use('/panels', panelsRouter);
221
226
  app.use('/permissions', permissionsRouter);
222
- app.use('/policies', policiesRouter);
223
227
  app.use('/presets', presetsRouter);
224
228
  app.use('/translations', translationsRouter);
225
229
  app.use('/relations', relationsRouter);
@@ -241,6 +245,7 @@ export default async function createApp() {
241
245
  app.use(errorHandler);
242
246
  await emitter.emitInit('routes.after', { app });
243
247
  initTelemetry();
248
+ scheduleTusCleanup();
244
249
  await emitter.emitInit('app.after', { app });
245
250
  return app;
246
251
  }
@@ -3,17 +3,16 @@ import { ErrorCode, InvalidCredentialsError, InvalidPayloadError, InvalidProvide
3
3
  import { Router } from 'express';
4
4
  import Joi from 'joi';
5
5
  import ldap from 'ldapjs';
6
- import { REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS } from '../../constants.js';
7
6
  import getDatabase from '../../database/index.js';
8
7
  import emitter from '../../emitter.js';
9
8
  import { useLogger } from '../../logger.js';
10
9
  import { respond } from '../../middleware/respond.js';
11
- import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
12
10
  import { AuthenticationService } from '../../services/authentication.js';
13
11
  import { UsersService } from '../../services/users.js';
14
12
  import asyncHandler from '../../utils/async-handler.js';
15
13
  import { getIPFromReq } from '../../utils/get-ip-from-req.js';
16
14
  import { AuthDriver } from '../auth.js';
15
+ import { REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS } from '../../constants.js';
17
16
  // 0x2: ACCOUNTDISABLE
18
17
  // 0x10: LOCKOUT
19
18
  // 0x800000: PASSWORD_EXPIRED
@@ -296,9 +295,10 @@ export function createLDAPAuthRouter(provider) {
296
295
  }).unknown();
297
296
  router.post('/', asyncHandler(async (req, res, next) => {
298
297
  const env = useEnv();
299
- const accountability = createDefaultAccountability({
298
+ const accountability = {
300
299
  ip: getIPFromReq(req),
301
- });
300
+ role: null,
301
+ };
302
302
  const userAgent = req.get('user-agent')?.substring(0, 1024);
303
303
  if (userAgent)
304
304
  accountability.userAgent = userAgent;
@@ -1,12 +1,11 @@
1
- import { useEnv } from '@directus/env';
2
1
  import { InvalidCredentialsError, InvalidPayloadError } from '@directus/errors';
3
2
  import argon2 from 'argon2';
4
3
  import { Router } from 'express';
5
4
  import Joi from 'joi';
6
5
  import { performance } from 'perf_hooks';
7
6
  import { REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS } from '../../constants.js';
7
+ import { useEnv } from '@directus/env';
8
8
  import { respond } from '../../middleware/respond.js';
9
- import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
10
9
  import { AuthenticationService } from '../../services/authentication.js';
11
10
  import asyncHandler from '../../utils/async-handler.js';
12
11
  import { getIPFromReq } from '../../utils/get-ip-from-req.js';
@@ -48,9 +47,10 @@ export function createLocalAuthRouter(provider) {
48
47
  router.post('/', asyncHandler(async (req, res, next) => {
49
48
  const STALL_TIME = env['LOGIN_STALL_TIME'];
50
49
  const timeStart = performance.now();
51
- const accountability = createDefaultAccountability({
50
+ const accountability = {
52
51
  ip: getIPFromReq(req),
53
- });
52
+ role: null,
53
+ };
54
54
  const userAgent = req.get('user-agent')?.substring(0, 1024);
55
55
  if (userAgent)
56
56
  accountability.userAgent = userAgent;
@@ -11,16 +11,15 @@ import getDatabase from '../../database/index.js';
11
11
  import emitter from '../../emitter.js';
12
12
  import { useLogger } from '../../logger.js';
13
13
  import { respond } from '../../middleware/respond.js';
14
- import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
15
14
  import { AuthenticationService } from '../../services/authentication.js';
16
15
  import { UsersService } from '../../services/users.js';
17
16
  import asyncHandler from '../../utils/async-handler.js';
18
17
  import { getConfigFromEnv } from '../../utils/get-config-from-env.js';
19
18
  import { getIPFromReq } from '../../utils/get-ip-from-req.js';
20
- import { getSecret } from '../../utils/get-secret.js';
21
19
  import { isLoginRedirectAllowed } from '../../utils/is-login-redirect-allowed.js';
22
20
  import { Url } from '../../utils/url.js';
23
21
  import { LocalAuthDriver } from './local.js';
22
+ import { getSecret } from '../../utils/get-secret.js';
24
23
  export class OAuth2AuthDriver extends LocalAuthDriver {
25
24
  client;
26
25
  redirectUrl;
@@ -252,9 +251,10 @@ export function createOAuth2AuthRouter(providerName) {
252
251
  throw new InvalidCredentialsError();
253
252
  }
254
253
  const { verifier, redirect, prompt } = tokenData;
255
- const accountability = createDefaultAccountability({
254
+ const accountability = {
256
255
  ip: getIPFromReq(req),
257
- });
256
+ role: null,
257
+ };
258
258
  const userAgent = req.get('user-agent')?.substring(0, 1024);
259
259
  if (userAgent)
260
260
  accountability.userAgent = userAgent;
@@ -11,7 +11,6 @@ import getDatabase from '../../database/index.js';
11
11
  import emitter from '../../emitter.js';
12
12
  import { useLogger } from '../../logger.js';
13
13
  import { respond } from '../../middleware/respond.js';
14
- import { createDefaultAccountability } from '../../permissions/utils/create-default-accountability.js';
15
14
  import { AuthenticationService } from '../../services/authentication.js';
16
15
  import { UsersService } from '../../services/users.js';
17
16
  import asyncHandler from '../../utils/async-handler.js';
@@ -273,7 +272,10 @@ export function createOpenIDAuthRouter(providerName) {
273
272
  throw new InvalidCredentialsError();
274
273
  }
275
274
  const { verifier, redirect, prompt } = tokenData;
276
- const accountability = createDefaultAccountability({ ip: getIPFromReq(req) });
275
+ const accountability = {
276
+ ip: getIPFromReq(req),
277
+ role: null,
278
+ };
277
279
  const userAgent = req.get('user-agent')?.substring(0, 1024);
278
280
  if (userAgent)
279
281
  accountability.userAgent = userAgent;
package/dist/cache.js CHANGED
@@ -8,7 +8,6 @@ import { compress, decompress } from './utils/compress.js';
8
8
  import { getConfigFromEnv } from './utils/get-config-from-env.js';
9
9
  import { getMilliseconds } from './utils/get-milliseconds.js';
10
10
  import { validateEnv } from './utils/validate-env.js';
11
- import { clearCache as clearPermissionCache } from './permissions/cache.js';
12
11
  import { createRequire } from 'node:module';
13
12
  const logger = useLogger();
14
13
  const env = useEnv();
@@ -67,8 +66,6 @@ export async function clearSystemCache(opts) {
67
66
  }
68
67
  await sharedSchemaCache.clear();
69
68
  await localSchemaCache.clear();
70
- // Since a lot of cached permission function rely on the schema it needs to be cleared as well
71
- await clearPermissionCache();
72
69
  messenger.publish('schemaChanged', { autoPurgeCache: opts?.autoPurgeCache });
73
70
  }
74
71
  export async function setSystemCache(key, value, ttl) {
@@ -3,13 +3,11 @@ import getDatabase, { hasDatabaseConnection, isInstalled, validateDatabaseConnec
3
3
  import runMigrations from '../../../database/migrations/run.js';
4
4
  import installDatabase from '../../../database/seeds/run.js';
5
5
  import { useLogger } from '../../../logger.js';
6
- import { AccessService } from '../../../services/access.js';
7
- import { PoliciesService } from '../../../services/policies.js';
8
6
  import { RolesService } from '../../../services/roles.js';
9
7
  import { SettingsService } from '../../../services/settings.js';
10
8
  import { UsersService } from '../../../services/users.js';
11
9
  import { getSchema } from '../../../utils/get-schema.js';
12
- import { defaultAdminPolicy, defaultAdminRole, defaultAdminUser } from '../../utils/defaults.js';
10
+ import { defaultAdminRole, defaultAdminUser } from '../../utils/defaults.js';
13
11
  export default async function bootstrap({ skipAdminInit }) {
14
12
  const logger = useLogger();
15
13
  logger.info('Initializing bootstrap...');
@@ -60,12 +58,8 @@ async function createDefaultAdmin(schema) {
60
58
  const env = useEnv();
61
59
  const { nanoid } = await import('nanoid');
62
60
  logger.info('Setting up first admin role...');
63
- const accessService = new AccessService({ schema });
64
- const policiesService = new PoliciesService({ schema });
65
61
  const rolesService = new RolesService({ schema });
66
62
  const role = await rolesService.createOne(defaultAdminRole);
67
- const policy = await policiesService.createOne(defaultAdminPolicy);
68
- await accessService.createOne({ policy, role });
69
63
  logger.info('Adding first admin user...');
70
64
  const usersService = new UsersService({ schema });
71
65
  let adminEmail = env['ADMIN_EMAIL'];
@@ -78,5 +72,5 @@ async function createDefaultAdmin(schema) {
78
72
  adminPassword = nanoid(12);
79
73
  logger.info(`No admin password provided. Defaulting to "${adminPassword}"`);
80
74
  }
81
- await usersService.createOne({ ...defaultAdminUser, email: adminEmail, password: adminPassword, role });
75
+ await usersService.createOne({ email: adminEmail, password: adminPassword, role, ...defaultAdminUser });
82
76
  }
@@ -9,7 +9,7 @@ import runSeed from '../../../database/seeds/run.js';
9
9
  import { generateHash } from '../../../utils/generate-hash.js';
10
10
  import createDBConnection from '../../utils/create-db-connection.js';
11
11
  import createEnv from '../../utils/create-env/index.js';
12
- import { defaultAdminPolicy, defaultAdminRole, defaultAdminUser } from '../../utils/defaults.js';
12
+ import { defaultAdminRole, defaultAdminUser } from '../../utils/defaults.js';
13
13
  import { drivers, getDriverForClient } from '../../utils/drivers.js';
14
14
  import { databaseQuestions } from './questions.js';
15
15
  export default async function init() {
@@ -79,17 +79,18 @@ export default async function init() {
79
79
  },
80
80
  ]);
81
81
  firstUser.password = await generateHash(firstUser.password);
82
- const role = randomUUID();
83
- const policy = randomUUID();
84
- await db('directus_roles').insert({ ...defaultAdminRole, id: role });
85
- await db('directus_policies').insert({ ...defaultAdminPolicy, id: policy });
86
- await db('directus_access').insert({ id: randomUUID(), role, policy });
82
+ const userID = randomUUID();
83
+ const roleID = randomUUID();
84
+ await db('directus_roles').insert({
85
+ id: roleID,
86
+ ...defaultAdminRole,
87
+ });
87
88
  await db('directus_users').insert({
88
- ...defaultAdminUser,
89
- id: randomUUID(),
89
+ id: userID,
90
90
  email: firstUser.email,
91
91
  password: firstUser.password,
92
- role,
92
+ role: roleID,
93
+ ...defaultAdminUser,
93
94
  });
94
95
  await db.destroy();
95
96
  process.stdout.write(`\nYour project has been created at ${chalk.green(rootPath)}.\n`);
@@ -1,4 +1,11 @@
1
- import type { Policy, Role, User } from '@directus/types';
2
- export declare const defaultAdminRole: Partial<Role>;
3
- export declare const defaultAdminUser: Partial<User>;
4
- export declare const defaultAdminPolicy: Partial<Policy>;
1
+ export declare const defaultAdminRole: {
2
+ name: string;
3
+ icon: string;
4
+ admin_access: boolean;
5
+ description: string;
6
+ };
7
+ export declare const defaultAdminUser: {
8
+ status: string;
9
+ first_name: string;
10
+ last_name: string;
11
+ };
@@ -1,6 +1,7 @@
1
1
  export const defaultAdminRole = {
2
2
  name: 'Administrator',
3
3
  icon: 'verified',
4
+ admin_access: true,
4
5
  description: '$t:admin_description',
5
6
  };
6
7
  export const defaultAdminUser = {
@@ -8,10 +9,3 @@ export const defaultAdminUser = {
8
9
  first_name: 'Admin',
9
10
  last_name: 'User',
10
11
  };
11
- export const defaultAdminPolicy = {
12
- name: 'Administrator',
13
- icon: 'verified',
14
- admin_access: true,
15
- app_access: true,
16
- description: '$t:admin_description',
17
- };
@@ -6,7 +6,7 @@ export declare const FILTER_VARIABLES: string[];
6
6
  export declare const ALIAS_TYPES: string[];
7
7
  export declare const DEFAULT_AUTH_PROVIDER = "default";
8
8
  export declare const COLUMN_TRANSFORMS: string[];
9
- export declare const GENERATE_SPECIAL: readonly ["uuid", "date-created", "role-created", "user-created"];
9
+ export declare const GENERATE_SPECIAL: string[];
10
10
  export declare const UUID_REGEX = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
11
11
  export declare const REFRESH_COOKIE_OPTIONS: CookieOptions;
12
12
  export declare const SESSION_COOKIE_OPTIONS: CookieOptions;
@@ -15,3 +15,11 @@ export declare const OAS_REQUIRED_SCHEMAS: string[];
15
15
  export declare const SUPPORTED_IMAGE_TRANSFORM_FORMATS: string[];
16
16
  /** Formats where metadata extraction is supported */
17
17
  export declare const SUPPORTED_IMAGE_METADATA_FORMATS: string[];
18
+ /** Resumable uploads */
19
+ export declare const RESUMABLE_UPLOADS: {
20
+ ENABLED: boolean;
21
+ CHUNK_SIZE: number;
22
+ MAX_SIZE: number;
23
+ EXPIRATION_TIME: number;
24
+ SCHEDULE: string;
25
+ };
package/dist/constants.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { getMilliseconds } from './utils/get-milliseconds.js';
2
2
  import { useEnv } from '@directus/env';
3
+ import { toBoolean } from '@directus/utils';
4
+ import bytes from 'bytes';
3
5
  const env = useEnv();
4
6
  export const SYSTEM_ASSET_ALLOW_LIST = [
5
7
  {
@@ -77,3 +79,11 @@ export const SUPPORTED_IMAGE_METADATA_FORMATS = [
77
79
  'image/tiff',
78
80
  'image/avif',
79
81
  ];
82
+ /** Resumable uploads */
83
+ export const RESUMABLE_UPLOADS = {
84
+ ENABLED: toBoolean(env['TUS_ENABLED']),
85
+ CHUNK_SIZE: bytes(env['TUS_CHUNK_SIZE']),
86
+ MAX_SIZE: bytes(env['FILES_MAX_UPLOAD_SIZE']),
87
+ EXPIRATION_TIME: getMilliseconds(env['TUS_UPLOAD_EXPIRATION'], 600_000 /* 10min */),
88
+ SCHEDULE: String(env['TUS_CLEANUP_SCHEDULE']),
89
+ };
@@ -5,7 +5,6 @@ import { createLDAPAuthRouter, createLocalAuthRouter, createOAuth2AuthRouter, cr
5
5
  import { DEFAULT_AUTH_PROVIDER, REFRESH_COOKIE_OPTIONS, SESSION_COOKIE_OPTIONS } from '../constants.js';
6
6
  import { useLogger } from '../logger.js';
7
7
  import { respond } from '../middleware/respond.js';
8
- import { createDefaultAccountability } from '../permissions/utils/create-default-accountability.js';
9
8
  import { AuthenticationService } from '../services/authentication.js';
10
9
  import { UsersService } from '../services/users.js';
11
10
  import asyncHandler from '../utils/async-handler.js';
@@ -72,7 +71,10 @@ function getCurrentRefreshToken(req, mode) {
72
71
  return undefined;
73
72
  }
74
73
  router.post('/refresh', asyncHandler(async (req, res, next) => {
75
- const accountability = createDefaultAccountability({ ip: getIPFromReq(req) });
74
+ const accountability = {
75
+ ip: getIPFromReq(req),
76
+ role: null,
77
+ };
76
78
  const userAgent = req.get('user-agent')?.substring(0, 1024);
77
79
  if (userAgent)
78
80
  accountability.userAgent = userAgent;
@@ -109,7 +111,10 @@ router.post('/refresh', asyncHandler(async (req, res, next) => {
109
111
  return next();
110
112
  }), respond);
111
113
  router.post('/logout', asyncHandler(async (req, res, next) => {
112
- const accountability = createDefaultAccountability({ ip: getIPFromReq(req) });
114
+ const accountability = {
115
+ ip: getIPFromReq(req),
116
+ role: null,
117
+ };
113
118
  const userAgent = req.get('user-agent')?.substring(0, 1024);
114
119
  if (userAgent)
115
120
  accountability.userAgent = userAgent;
@@ -140,7 +145,10 @@ router.post('/password/request', asyncHandler(async (req, _res, next) => {
140
145
  if (typeof req.body.email !== 'string') {
141
146
  throw new InvalidPayloadError({ reason: `"email" field is required` });
142
147
  }
143
- const accountability = createDefaultAccountability({ ip: getIPFromReq(req) });
148
+ const accountability = {
149
+ ip: getIPFromReq(req),
150
+ role: null,
151
+ };
144
152
  const userAgent = req.get('user-agent')?.substring(0, 1024);
145
153
  if (userAgent)
146
154
  accountability.userAgent = userAgent;
@@ -169,7 +177,10 @@ router.post('/password/reset', asyncHandler(async (req, _res, next) => {
169
177
  if (typeof req.body.password !== 'string') {
170
178
  throw new InvalidPayloadError({ reason: `"password" field is required` });
171
179
  }
172
- const accountability = createDefaultAccountability({ ip: getIPFromReq(req) });
180
+ const accountability = {
181
+ ip: getIPFromReq(req),
182
+ role: null,
183
+ };
173
184
  const userAgent = req.get('user-agent')?.substring(0, 1024);
174
185
  if (userAgent)
175
186
  accountability.userAgent = userAgent;
@@ -1,12 +1,10 @@
1
- import { ErrorCode, ForbiddenError, isDirectusError } from '@directus/errors';
1
+ import { ErrorCode, isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import getDatabase from '../database/index.js';
4
3
  import { respond } from '../middleware/respond.js';
5
4
  import useCollection from '../middleware/use-collection.js';
6
5
  import { validateBatch } from '../middleware/validate-batch.js';
7
- import { fetchAccountabilityCollectionAccess } from '../permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js';
8
6
  import { MetaService } from '../services/meta.js';
9
- import { PermissionsService } from '../services/permissions.js';
7
+ import { PermissionsService } from '../services/permissions/index.js';
10
8
  import asyncHandler from '../utils/async-handler.js';
11
9
  import { sanitizeQuery } from '../utils/sanitize-query.js';
12
10
  const router = express.Router();
@@ -71,16 +69,6 @@ const readHandler = asyncHandler(async (req, res, next) => {
71
69
  });
72
70
  router.get('/', validateBatch('read'), readHandler, respond);
73
71
  router.search('/', validateBatch('read'), readHandler, respond);
74
- router.get('/me', asyncHandler(async (req, res, next) => {
75
- if (!req.accountability?.user && !req.accountability?.role)
76
- throw new ForbiddenError();
77
- const result = await fetchAccountabilityCollectionAccess(req.accountability, {
78
- schema: req.schema,
79
- knex: getDatabase(),
80
- });
81
- res.locals['payload'] = { data: result };
82
- return next();
83
- }), respond);
84
72
  router.get('/:pk', asyncHandler(async (req, res, next) => {
85
73
  if (req.path.endsWith('me'))
86
74
  return next();
@@ -1,4 +1,4 @@
1
- import { ErrorCode, ForbiddenError, isDirectusError } from '@directus/errors';
1
+ import { ErrorCode, isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
3
  import { respond } from '../middleware/respond.js';
4
4
  import useCollection from '../middleware/use-collection.js';
@@ -57,27 +57,6 @@ const readHandler = asyncHandler(async (req, res, next) => {
57
57
  });
58
58
  router.get('/', validateBatch('read'), readHandler, respond);
59
59
  router.search('/', validateBatch('read'), readHandler, respond);
60
- router.get('/me', asyncHandler(async (req, res, next) => {
61
- if (!req.accountability?.user && !req.accountability?.role)
62
- throw new ForbiddenError();
63
- const service = new RolesService({
64
- accountability: req.accountability,
65
- schema: req.schema,
66
- });
67
- const query = { ...req.sanitizedQuery, limit: -1 };
68
- try {
69
- const roles = await service.readMany(req.accountability.roles, query);
70
- res.locals['payload'] = { data: roles || null };
71
- }
72
- catch (error) {
73
- if (isDirectusError(error, ErrorCode.Forbidden)) {
74
- res.locals['payload'] = { data: req.accountability.roles.map((id) => ({ id })) };
75
- return next();
76
- }
77
- throw error;
78
- }
79
- return next();
80
- }), respond);
81
60
  router.get('/:pk', asyncHandler(async (req, res, next) => {
82
61
  const service = new RolesService({
83
62
  accountability: req.accountability,
@@ -1,2 +1,3 @@
1
+ export declare function scheduleTusCleanup(): void;
1
2
  declare const router: import("express-serve-static-core").Router;
2
3
  export default router;
@@ -0,0 +1,72 @@
1
+ import { Router } from 'express';
2
+ import { getSchema } from '../utils/get-schema.js';
3
+ import { scheduleSynchronizedJob, validateCron } from '../utils/schedule.js';
4
+ import { createTusServer } from '../services/tus/index.js';
5
+ import { AuthorizationService } from '../services/authorization.js';
6
+ import asyncHandler from '../utils/async-handler.js';
7
+ import { ForbiddenError } from '@directus/errors';
8
+ import { RESUMABLE_UPLOADS } from '../constants.js';
9
+ const mapAction = (method) => {
10
+ switch (method) {
11
+ case 'POST':
12
+ return 'create';
13
+ case 'PATCH':
14
+ return 'update';
15
+ case 'DELETE':
16
+ return 'delete';
17
+ default:
18
+ return 'read';
19
+ }
20
+ };
21
+ const checkFileAccess = asyncHandler(async (req, _res, next) => {
22
+ const auth = new AuthorizationService({
23
+ accountability: req.accountability,
24
+ schema: req.schema,
25
+ });
26
+ if (!req.accountability?.admin) {
27
+ const action = mapAction(req.method);
28
+ if (action === 'create') {
29
+ // checkAccess doesnt seem to work as expected for "create" actions
30
+ const hasPermission = Boolean(req.accountability?.permissions?.find((permission) => {
31
+ return permission.collection === 'directus_files' && permission.action === action;
32
+ }));
33
+ if (!hasPermission)
34
+ throw new ForbiddenError();
35
+ }
36
+ else {
37
+ try {
38
+ await auth.checkAccess(action, 'directus_files');
39
+ }
40
+ catch (e) {
41
+ throw new ForbiddenError();
42
+ }
43
+ }
44
+ }
45
+ return next();
46
+ });
47
+ const handler = asyncHandler(async (req, res) => {
48
+ const tusServer = await createTusServer({
49
+ schema: req.schema,
50
+ accountability: req.accountability,
51
+ });
52
+ await tusServer.handle(req, res);
53
+ });
54
+ export function scheduleTusCleanup() {
55
+ if (!RESUMABLE_UPLOADS.ENABLED)
56
+ return;
57
+ if (validateCron(RESUMABLE_UPLOADS.SCHEDULE)) {
58
+ scheduleSynchronizedJob('tus-cleanup', RESUMABLE_UPLOADS.SCHEDULE, async () => {
59
+ const tusServer = await createTusServer({
60
+ schema: await getSchema(),
61
+ });
62
+ await tusServer.cleanUpExpiredUploads();
63
+ });
64
+ }
65
+ }
66
+ const router = Router();
67
+ router.post('/', checkFileAccess, handler);
68
+ router.patch('/:id', checkFileAccess, handler);
69
+ router.delete('/:id', checkFileAccess, handler);
70
+ router.options('/:id', checkFileAccess, handler);
71
+ router.head('/:id', checkFileAccess, handler);
72
+ export default router;
@@ -7,6 +7,7 @@ import useCollection from '../middleware/use-collection.js';
7
7
  import { validateBatch } from '../middleware/validate-batch.js';
8
8
  import { AuthenticationService } from '../services/authentication.js';
9
9
  import { MetaService } from '../services/meta.js';
10
+ import { RolesService } from '../services/roles.js';
10
11
  import { TFAService } from '../services/tfa.js';
11
12
  import { UsersService } from '../services/users.js';
12
13
  import asyncHandler from '../utils/async-handler.js';
@@ -261,6 +262,33 @@ router.post('/me/tfa/enable/', asyncHandler(async (req, _res, next) => {
261
262
  if (!req.body.otp) {
262
263
  throw new InvalidPayloadError({ reason: `"otp" is required` });
263
264
  }
265
+ // Override permissions only when enforce TFA is enabled in role
266
+ if (req.accountability.role) {
267
+ const rolesService = new RolesService({
268
+ schema: req.schema,
269
+ });
270
+ const role = (await rolesService.readOne(req.accountability.role));
271
+ if (role && role.enforce_tfa) {
272
+ const existingPermission = await req.accountability.permissions?.find((p) => p.collection === 'directus_users' && p.action === 'update');
273
+ if (existingPermission) {
274
+ existingPermission.fields = ['tfa_secret'];
275
+ existingPermission.permissions = { id: { _eq: req.accountability.user } };
276
+ existingPermission.presets = null;
277
+ existingPermission.validation = null;
278
+ }
279
+ else {
280
+ (req.accountability.permissions || (req.accountability.permissions = [])).push({
281
+ action: 'update',
282
+ collection: 'directus_users',
283
+ fields: ['tfa_secret'],
284
+ permissions: { id: { _eq: req.accountability.user } },
285
+ presets: null,
286
+ role: req.accountability.role,
287
+ validation: null,
288
+ });
289
+ }
290
+ }
291
+ }
264
292
  const service = new TFAService({
265
293
  accountability: req.accountability,
266
294
  schema: req.schema,
@@ -275,6 +303,33 @@ router.post('/me/tfa/disable', asyncHandler(async (req, _res, next) => {
275
303
  if (!req.body.otp) {
276
304
  throw new InvalidPayloadError({ reason: `"otp" is required` });
277
305
  }
306
+ // Override permissions only when enforce TFA is enabled in role
307
+ if (req.accountability.role) {
308
+ const rolesService = new RolesService({
309
+ schema: req.schema,
310
+ });
311
+ const role = (await rolesService.readOne(req.accountability.role));
312
+ if (role && role.enforce_tfa) {
313
+ const existingPermission = await req.accountability.permissions?.find((p) => p.collection === 'directus_users' && p.action === 'update');
314
+ if (existingPermission) {
315
+ existingPermission.fields = ['tfa_secret'];
316
+ existingPermission.permissions = { id: { _eq: req.accountability.user } };
317
+ existingPermission.presets = null;
318
+ existingPermission.validation = null;
319
+ }
320
+ else {
321
+ (req.accountability.permissions || (req.accountability.permissions = [])).push({
322
+ action: 'update',
323
+ collection: 'directus_users',
324
+ fields: ['tfa_secret'],
325
+ permissions: { id: { _eq: req.accountability.user } },
326
+ presets: null,
327
+ role: req.accountability.role,
328
+ validation: null,
329
+ });
330
+ }
331
+ }
332
+ }
278
333
  const service = new TFAService({
279
334
  accountability: req.accountability,
280
335
  schema: req.schema,
@@ -1,10 +1,9 @@
1
- import type { Filter, Query, SchemaOverview } from '@directus/types';
1
+ import type { Query, SchemaOverview } from '@directus/types';
2
2
  import type { Knex } from 'knex';
3
3
  import { DatabaseHelper } from '../types.js';
4
4
  export type FnHelperOptions = {
5
5
  type: string | undefined;
6
6
  query: Query | undefined;
7
- cases: Filter[] | undefined;
8
7
  originalCollectionName: string | undefined;
9
8
  };
10
9
  export declare abstract class FnHelper extends DatabaseHelper {
@@ -28,7 +28,7 @@ export class FnHelper extends DatabaseHelper {
28
28
  collection: relation.collection,
29
29
  },
30
30
  };
31
- countQuery = applyFilter(this.knex, this.schema, countQuery, options.query.filter, relation.collection, aliasMap, options.cases ?? []).query;
31
+ countQuery = applyFilter(this.knex, this.schema, countQuery, options.query.filter, relation.collection, aliasMap).query;
32
32
  }
33
33
  return this.knex.raw('(' + countQuery.toQuery() + ')');
34
34
  }