@directus/api 21.0.0-rc.0 → 21.0.1

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 (286) hide show
  1. package/dist/app.js +5 -5
  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.d.ts +2 -3
  7. package/dist/cache.js +9 -27
  8. package/dist/cli/commands/bootstrap/index.js +2 -8
  9. package/dist/cli/commands/init/index.js +10 -9
  10. package/dist/cli/utils/defaults.d.ts +11 -4
  11. package/dist/cli/utils/defaults.js +1 -7
  12. package/dist/constants.d.ts +1 -1
  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/tus.js +27 -13
  17. package/dist/controllers/users.js +55 -0
  18. package/dist/database/helpers/fn/types.d.ts +1 -2
  19. package/dist/database/helpers/fn/types.js +1 -1
  20. package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
  21. package/dist/database/helpers/geometry/dialects/mssql.js +2 -4
  22. package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
  23. package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
  24. package/dist/database/helpers/geometry/dialects/oracle.js +3 -5
  25. package/dist/database/helpers/geometry/types.d.ts +1 -1
  26. package/dist/database/helpers/geometry/types.js +2 -4
  27. package/dist/database/index.js +11 -8
  28. package/dist/database/migrations/20240305A-change-useragent-type.js +1 -1
  29. package/dist/database/migrations/20240716A-update-files-date-fields.js +33 -0
  30. package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
  31. package/dist/database/run-ast.js +458 -0
  32. package/dist/flows.js +4 -3
  33. package/dist/logger/index.js +1 -1
  34. package/dist/middleware/authenticate.js +7 -2
  35. package/dist/middleware/cache.js +1 -1
  36. package/dist/middleware/check-ip.d.ts +2 -0
  37. package/dist/middleware/check-ip.js +37 -0
  38. package/dist/middleware/error-handler.d.ts +2 -2
  39. package/dist/middleware/error-handler.js +54 -51
  40. package/dist/middleware/get-permissions.d.ts +3 -0
  41. package/dist/middleware/get-permissions.js +10 -0
  42. package/dist/middleware/respond.js +2 -1
  43. package/dist/request/is-denied-ip.js +7 -1
  44. package/dist/services/activity.js +10 -22
  45. package/dist/services/assets.d.ts +3 -2
  46. package/dist/services/assets.js +7 -15
  47. package/dist/services/authentication.js +18 -18
  48. package/dist/services/authorization.d.ts +17 -0
  49. package/dist/services/authorization.js +456 -0
  50. package/dist/services/collections.js +17 -18
  51. package/dist/services/fields.d.ts +4 -0
  52. package/dist/services/fields.js +53 -58
  53. package/dist/services/files/lib/get-sharp-instance.d.ts +2 -0
  54. package/dist/services/files/lib/get-sharp-instance.js +10 -0
  55. package/dist/services/files/utils/get-metadata.js +7 -6
  56. package/dist/services/files.js +8 -10
  57. package/dist/services/graphql/index.d.ts +3 -3
  58. package/dist/services/graphql/index.js +22 -126
  59. package/dist/services/graphql/subscription.js +4 -2
  60. package/dist/services/import-export.js +4 -18
  61. package/dist/services/index.d.ts +2 -3
  62. package/dist/services/index.js +2 -3
  63. package/dist/services/items.js +44 -115
  64. package/dist/services/mail/index.d.ts +1 -1
  65. package/dist/services/mail/index.js +9 -1
  66. package/dist/services/meta.js +23 -60
  67. package/dist/services/notifications.js +6 -14
  68. package/dist/services/payload.d.ts +10 -9
  69. package/dist/services/payload.js +3 -18
  70. package/dist/services/{permissions.d.ts → permissions/index.d.ts} +7 -5
  71. package/dist/services/{permissions.js → permissions/index.js} +54 -30
  72. package/dist/{permissions → services/permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
  73. package/dist/services/permissions/lib/with-app-minimal-permissions.js +13 -0
  74. package/dist/services/relations.d.ts +9 -1
  75. package/dist/services/relations.js +56 -31
  76. package/dist/services/roles.d.ts +12 -4
  77. package/dist/services/roles.js +424 -57
  78. package/dist/services/shares.d.ts +2 -0
  79. package/dist/services/shares.js +8 -12
  80. package/dist/services/specifications.d.ts +2 -2
  81. package/dist/services/specifications.js +27 -39
  82. package/dist/services/tus/data-store.js +4 -5
  83. package/dist/services/tus/server.d.ts +1 -1
  84. package/dist/services/tus/server.js +9 -2
  85. package/dist/services/users.d.ts +5 -1
  86. package/dist/services/users.js +161 -78
  87. package/dist/services/utils.js +7 -11
  88. package/dist/services/versions.d.ts +2 -0
  89. package/dist/services/versions.js +10 -34
  90. package/dist/telemetry/lib/get-report.js +2 -2
  91. package/dist/telemetry/utils/check-increased-user-limits.d.ts +7 -0
  92. package/dist/telemetry/utils/check-increased-user-limits.js +25 -0
  93. package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +6 -0
  94. package/dist/telemetry/utils/get-role-counts-by-roles.js +27 -0
  95. package/dist/telemetry/utils/get-role-counts-by-users.d.ts +11 -0
  96. package/dist/telemetry/utils/get-role-counts-by-users.js +34 -0
  97. package/dist/telemetry/utils/get-user-count.d.ts +8 -0
  98. package/dist/telemetry/utils/get-user-count.js +33 -0
  99. package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +7 -0
  100. package/dist/telemetry/utils/get-user-counts-by-roles.js +35 -0
  101. package/dist/types/ast.d.ts +1 -43
  102. package/dist/types/items.d.ts +0 -11
  103. package/dist/utils/apply-query.d.ts +3 -4
  104. package/dist/utils/apply-query.js +16 -39
  105. package/dist/utils/get-accountability-for-role.js +25 -16
  106. package/dist/utils/get-accountability-for-token.js +16 -17
  107. package/dist/utils/get-ast-from-query.d.ts +13 -0
  108. package/dist/utils/get-ast-from-query.js +297 -0
  109. package/dist/utils/get-cache-key.d.ts +1 -1
  110. package/dist/utils/get-cache-key.js +1 -12
  111. package/dist/utils/get-column.d.ts +1 -2
  112. package/dist/utils/get-column.js +0 -1
  113. package/dist/utils/get-permissions.d.ts +2 -0
  114. package/dist/utils/get-permissions.js +150 -0
  115. package/dist/utils/get-schema.js +22 -27
  116. package/dist/utils/get-service.js +1 -5
  117. package/dist/utils/merge-permissions-for-share.d.ts +4 -0
  118. package/dist/utils/merge-permissions-for-share.js +109 -0
  119. package/dist/utils/merge-permissions.d.ts +3 -0
  120. package/dist/utils/merge-permissions.js +95 -0
  121. package/dist/utils/reduce-schema.d.ts +6 -4
  122. package/dist/utils/reduce-schema.js +32 -16
  123. package/dist/websocket/authenticate.d.ts +2 -0
  124. package/dist/websocket/authenticate.js +12 -0
  125. package/dist/websocket/controllers/graphql.js +4 -1
  126. package/dist/websocket/controllers/hooks.js +0 -4
  127. package/dist/websocket/controllers/rest.js +2 -0
  128. package/dist/websocket/handlers/subscribe.js +2 -0
  129. package/dist/websocket/utils/items.d.ts +1 -1
  130. package/package.json +35 -36
  131. package/dist/controllers/access.d.ts +0 -2
  132. package/dist/controllers/access.js +0 -148
  133. package/dist/controllers/policies.d.ts +0 -2
  134. package/dist/controllers/policies.js +0 -169
  135. package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +0 -16
  136. package/dist/database/get-ast-from-query/get-ast-from-query.js +0 -82
  137. package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +0 -13
  138. package/dist/database/get-ast-from-query/lib/convert-wildcards.js +0 -69
  139. package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +0 -15
  140. package/dist/database/get-ast-from-query/lib/parse-fields.js +0 -190
  141. package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +0 -14
  142. package/dist/database/get-ast-from-query/utils/get-deep-query.js +0 -17
  143. package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +0 -2
  144. package/dist/database/get-ast-from-query/utils/get-related-collection.js +0 -13
  145. package/dist/database/get-ast-from-query/utils/get-relation.d.ts +0 -2
  146. package/dist/database/get-ast-from-query/utils/get-relation.js +0 -7
  147. package/dist/database/migrations/20240710A-permissions-policies.js +0 -169
  148. package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
  149. package/dist/database/run-ast/lib/get-db-query.js +0 -208
  150. package/dist/database/run-ast/lib/parse-current-level.d.ts +0 -7
  151. package/dist/database/run-ast/lib/parse-current-level.js +0 -41
  152. package/dist/database/run-ast/run-ast.d.ts +0 -7
  153. package/dist/database/run-ast/run-ast.js +0 -107
  154. package/dist/database/run-ast/types.js +0 -1
  155. package/dist/database/run-ast/utils/apply-case-when.d.ts +0 -16
  156. package/dist/database/run-ast/utils/apply-case-when.js +0 -26
  157. package/dist/database/run-ast/utils/apply-parent-filters.d.ts +0 -3
  158. package/dist/database/run-ast/utils/apply-parent-filters.js +0 -55
  159. package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +0 -10
  160. package/dist/database/run-ast/utils/get-column-pre-processor.js +0 -57
  161. package/dist/database/run-ast/utils/get-field-alias.d.ts +0 -2
  162. package/dist/database/run-ast/utils/get-field-alias.js +0 -4
  163. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +0 -5
  164. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +0 -23
  165. package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +0 -3
  166. package/dist/database/run-ast/utils/merge-with-parent-items.js +0 -87
  167. package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +0 -3
  168. package/dist/database/run-ast/utils/remove-temporary-fields.js +0 -73
  169. package/dist/permissions/cache.d.ts +0 -2
  170. package/dist/permissions/cache.js +0 -23
  171. package/dist/permissions/lib/fetch-permissions.d.ts +0 -10
  172. package/dist/permissions/lib/fetch-permissions.js +0 -55
  173. package/dist/permissions/lib/fetch-policies.d.ts +0 -7
  174. package/dist/permissions/lib/fetch-policies.js +0 -28
  175. package/dist/permissions/lib/fetch-roles-tree.d.ts +0 -3
  176. package/dist/permissions/lib/fetch-roles-tree.js +0 -28
  177. package/dist/permissions/lib/with-app-minimal-permissions.js +0 -10
  178. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +0 -7
  179. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +0 -56
  180. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +0 -3
  181. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +0 -16
  182. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +0 -8
  183. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +0 -24
  184. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +0 -9
  185. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +0 -31
  186. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +0 -16
  187. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +0 -27
  188. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +0 -10
  189. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +0 -23
  190. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
  191. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
  192. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
  193. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
  194. package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
  195. package/dist/permissions/modules/fetch-global-access/types.js +0 -1
  196. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
  197. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
  198. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +0 -12
  199. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +0 -32
  200. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +0 -4
  201. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +0 -29
  202. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +0 -4
  203. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +0 -49
  204. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +0 -3
  205. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +0 -56
  206. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +0 -4
  207. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +0 -8
  208. package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +0 -9
  209. package/dist/permissions/modules/process-ast/lib/inject-cases.js +0 -93
  210. package/dist/permissions/modules/process-ast/process-ast.d.ts +0 -9
  211. package/dist/permissions/modules/process-ast/process-ast.js +0 -39
  212. package/dist/permissions/modules/process-ast/types.d.ts +0 -24
  213. package/dist/permissions/modules/process-ast/types.js +0 -1
  214. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +0 -2
  215. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +0 -7
  216. package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +0 -12
  217. package/dist/permissions/modules/process-ast/utils/dedupe-access.js +0 -30
  218. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +0 -15
  219. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +0 -50
  220. package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +0 -3
  221. package/dist/permissions/modules/process-ast/utils/find-related-collection.js +0 -9
  222. package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +0 -3
  223. package/dist/permissions/modules/process-ast/utils/flatten-filter.js +0 -34
  224. package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +0 -1
  225. package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +0 -3
  226. package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +0 -5
  227. package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +0 -7
  228. package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +0 -2
  229. package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +0 -3
  230. package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +0 -2
  231. package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +0 -3
  232. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +0 -3
  233. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +0 -16
  234. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +0 -2
  235. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +0 -12
  236. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +0 -2
  237. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +0 -28
  238. package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +0 -5
  239. package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +0 -12
  240. package/dist/permissions/modules/process-payload/process-payload.d.ts +0 -13
  241. package/dist/permissions/modules/process-payload/process-payload.js +0 -77
  242. package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +0 -12
  243. package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +0 -11
  244. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +0 -9
  245. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +0 -33
  246. package/dist/permissions/modules/validate-access/validate-access.d.ts +0 -14
  247. package/dist/permissions/modules/validate-access/validate-access.js +0 -28
  248. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +0 -1
  249. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +0 -8
  250. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +0 -5
  251. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +0 -10
  252. package/dist/permissions/types.d.ts +0 -6
  253. package/dist/permissions/types.js +0 -1
  254. package/dist/permissions/utils/create-default-accountability.d.ts +0 -2
  255. package/dist/permissions/utils/create-default-accountability.js +0 -11
  256. package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +0 -8
  257. package/dist/permissions/utils/extract-required-dynamic-variable-context.js +0 -27
  258. package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +0 -9
  259. package/dist/permissions/utils/fetch-dynamic-variable-context.js +0 -43
  260. package/dist/permissions/utils/filter-policies-by-ip.d.ts +0 -2
  261. package/dist/permissions/utils/filter-policies-by-ip.js +0 -15
  262. package/dist/permissions/utils/get-unaliased-field-key.d.ts +0 -5
  263. package/dist/permissions/utils/get-unaliased-field-key.js +0 -17
  264. package/dist/permissions/utils/process-permissions.d.ts +0 -7
  265. package/dist/permissions/utils/process-permissions.js +0 -9
  266. package/dist/permissions/utils/with-cache.d.ts +0 -10
  267. package/dist/permissions/utils/with-cache.js +0 -25
  268. package/dist/services/access.d.ts +0 -10
  269. package/dist/services/access.js +0 -43
  270. package/dist/services/policies.d.ts +0 -12
  271. package/dist/services/policies.js +0 -87
  272. package/dist/telemetry/utils/check-user-limits.d.ts +0 -5
  273. package/dist/telemetry/utils/check-user-limits.js +0 -19
  274. package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +0 -17
  275. package/dist/utils/fetch-user-count/fetch-access-lookup.js +0 -22
  276. package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +0 -16
  277. package/dist/utils/fetch-user-count/fetch-access-roles.js +0 -37
  278. package/dist/utils/fetch-user-count/fetch-active-users.d.ts +0 -6
  279. package/dist/utils/fetch-user-count/fetch-active-users.js +0 -3
  280. package/dist/utils/fetch-user-count/fetch-user-count.d.ts +0 -12
  281. package/dist/utils/fetch-user-count/fetch-user-count.js +0 -57
  282. package/dist/utils/fetch-user-count/get-user-count-query.d.ts +0 -20
  283. package/dist/utils/fetch-user-count/get-user-count-query.js +0 -17
  284. package/dist/utils/validate-user-count-integrity.d.ts +0 -13
  285. package/dist/utils/validate-user-count-integrity.js +0 -29
  286. /package/dist/database/migrations/{20240710A-permissions-policies.d.ts → 20240716A-update-files-date-fields.d.ts} +0 -0
@@ -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
  }
@@ -6,7 +6,7 @@ export declare class GeometryHelperMSSQL extends GeometryHelper {
6
6
  isTrue(expression: Knex.Raw): Knex.Raw<any>;
7
7
  isFalse(expression: Knex.Raw): Knex.Raw<any>;
8
8
  createColumn(table: Knex.CreateTableBuilder, field: RawField | Field): Knex.ColumnBuilder;
9
- asText(table: string, column: string, alias: string | false): Knex.Raw;
9
+ asText(table: string, column: string): Knex.Raw;
10
10
  fromText(text: string): Knex.Raw;
11
11
  _intersects(key: string, geojson: GeoJSONGeometry): Knex.Raw;
12
12
  _intersects_bbox(key: string, geojson: GeoJSONGeometry): Knex.Raw;
@@ -12,10 +12,8 @@ export class GeometryHelperMSSQL extends GeometryHelper {
12
12
  }
13
13
  return table.specificType(field.field, 'geometry');
14
14
  }
15
- asText(table, column, alias) {
16
- if (alias)
17
- return this.knex.raw('??.??.STAsText() as ??', [table, column, alias]);
18
- return this.knex.raw('??.??.STAsText()', [table, column]);
15
+ asText(table, column) {
16
+ return this.knex.raw('??.??.STAsText() as ??', [table, column, column]);
19
17
  }
20
18
  fromText(text) {
21
19
  return this.knex.raw('geometry::STGeomFromText(?, 4326)', text);
@@ -1,7 +1,7 @@
1
1
  import { GeometryHelper } from '../types.js';
2
2
  export class GeometryHelperMySQL extends GeometryHelper {
3
3
  collect(table, column) {
4
- return this.knex.raw(`concat('geometrycollection(', group_concat(? separator ', '), ')'`, this.asText(table, column, column));
4
+ return this.knex.raw(`concat('geometrycollection(', group_concat(? separator ', '), ')'`, this.asText(table, column));
5
5
  }
6
6
  fromText(text) {
7
7
  return this.knex.raw('st_geomfromtext(?)', text);
@@ -6,7 +6,7 @@ export declare class GeometryHelperOracle extends GeometryHelper {
6
6
  isTrue(expression: Knex.Raw): Knex.Raw<any>;
7
7
  isFalse(expression: Knex.Raw): Knex.Raw<any>;
8
8
  createColumn(table: Knex.CreateTableBuilder, field: RawField | Field): Knex.ColumnBuilder;
9
- asText(table: string, column: string, alias: string | false): Knex.Raw;
9
+ asText(table: string, column: string): Knex.Raw;
10
10
  asGeoJSON(table: string, column: string): Knex.Raw;
11
11
  fromText(text: string): Knex.Raw;
12
12
  _intersects(key: string, geojson: GeoJSONGeometry): Knex.Raw;
@@ -12,10 +12,8 @@ export class GeometryHelperOracle extends GeometryHelper {
12
12
  }
13
13
  return table.specificType(field.field, 'sdo_geometry');
14
14
  }
15
- asText(table, column, alias) {
16
- if (alias)
17
- return this.knex.raw('sdo_util.to_wktgeometry(??.??) as ??', [table, column, alias]);
18
- return this.knex.raw('sdo_util.to_wktgeometry(??.??)', [table, column]);
15
+ asText(table, column) {
16
+ return this.knex.raw('sdo_util.to_wktgeometry(??.??) as ??', [table, column, column]);
19
17
  }
20
18
  asGeoJSON(table, column) {
21
19
  return this.knex.raw('sdo_util.to_geojson(??.??) as ??', [table, column, column]);
@@ -32,6 +30,6 @@ export class GeometryHelperOracle extends GeometryHelper {
32
30
  return this.knex.raw(`sdo_overlapbdyintersect(sdo_geom.sdo_mbr(??), sdo_geom.sdo_mbr(?))`, [key, geometry]);
33
31
  }
34
32
  collect(table, column) {
35
- return this.knex.raw(`concat('geometrycollection(', listagg(?, ', '), ')'`, this.asText(table, column, column));
33
+ return this.knex.raw(`concat('geometrycollection(', listagg(?, ', '), ')'`, this.asText(table, column));
36
34
  }
37
35
  }
@@ -7,7 +7,7 @@ export declare abstract class GeometryHelper extends DatabaseHelper {
7
7
  isTrue(expression: Knex.Raw): Knex.Raw<any>;
8
8
  isFalse(expression: Knex.Raw): Knex.Raw<any>;
9
9
  createColumn(table: Knex.CreateTableBuilder, field: RawField | Field): Knex.ColumnBuilder;
10
- asText(table: string, column: string, alias: string | false): Knex.Raw;
10
+ asText(table: string, column: string): Knex.Raw;
11
11
  fromText(text: string): Knex.Raw;
12
12
  fromGeoJSON(geojson: GeoJSONGeometry): Knex.Raw;
13
13
  _intersects(key: string, geojson: GeoJSONGeometry): Knex.Raw;
@@ -14,10 +14,8 @@ export class GeometryHelper extends DatabaseHelper {
14
14
  const type = field.type.split('.')[1] ?? 'geometry';
15
15
  return table.specificType(field.field, type);
16
16
  }
17
- asText(table, column, alias) {
18
- if (alias)
19
- return this.knex.raw('st_astext(??.??) as ??', [table, column, alias]);
20
- return this.knex.raw('st_astext(??.??)', [table, column]);
17
+ asText(table, column) {
18
+ return this.knex.raw('st_astext(??.??) as ??', [table, column, column]);
21
19
  }
22
20
  fromText(text) {
23
21
  return this.knex.raw('st_geomfromtext(?, 4326)', text);
@@ -106,7 +106,6 @@ export function getDatabase() {
106
106
  };
107
107
  }
108
108
  if (client === 'mysql') {
109
- Object.assign(knexConfig, { client: 'mysql2' });
110
109
  poolConfig.afterCreate = async (conn, callback) => {
111
110
  logger.trace('Retrieving database version');
112
111
  const run = promisify(conn.query.bind(conn));
@@ -123,15 +122,19 @@ export function getDatabase() {
123
122
  }
124
123
  database = knex.default(knexConfig);
125
124
  validateDatabaseCharset(database);
126
- const times = {};
125
+ const times = new Map();
127
126
  database
128
- .on('query', (queryInfo) => {
129
- times[queryInfo.__knexUid] = performance.now();
127
+ .on('query', ({ __knexUid }) => {
128
+ times.set(__knexUid, performance.now());
130
129
  })
131
130
  .on('query-response', (_response, queryInfo) => {
132
- const delta = performance.now() - times[queryInfo.__knexUid];
133
- logger.trace(`[${delta.toFixed(3)}ms] ${queryInfo.sql} [${queryInfo.bindings.join(', ')}]`);
134
- delete times[queryInfo.__knexUid];
131
+ const time = times.get(queryInfo.__knexUid);
132
+ let delta;
133
+ if (time) {
134
+ delta = performance.now() - time;
135
+ times.delete(queryInfo.__knexUid);
136
+ }
137
+ logger.trace(`[${delta ? delta.toFixed(3) : '?'}ms] ${queryInfo.sql} [${(queryInfo.bindings ?? []).join(', ')}]`);
135
138
  });
136
139
  return database;
137
140
  }
@@ -186,7 +189,7 @@ export async function validateDatabaseConnection(database) {
186
189
  export function getDatabaseClient(database) {
187
190
  database = database ?? getDatabase();
188
191
  switch (database.client.constructor.name) {
189
- case 'Client_MySQL2':
192
+ case 'Client_MySQL':
190
193
  return 'mysql';
191
194
  case 'Client_PG':
192
195
  return 'postgres';
@@ -7,7 +7,7 @@ export async function up(knex) {
7
7
  ]);
8
8
  }
9
9
  export async function down(knex) {
10
- const helper = await getHelpers(knex).schema;
10
+ const helper = getHelpers(knex).schema;
11
11
  const opts = {
12
12
  nullable: false,
13
13
  length: 255,
@@ -0,0 +1,33 @@
1
+ import { getHelpers } from '../helpers/index.js';
2
+ export async function up(knex) {
3
+ const helper = getHelpers(knex).schema;
4
+ const isMysql = helper.isOneOfClients(['mysql']);
5
+ if (isMysql) {
6
+ // Knex creates invalid statement on MySQL, see https://github.com/knex/knex/issues/1888
7
+ await knex.schema.raw('ALTER TABLE `directus_files` CHANGE `uploaded_on` `created_on` TIMESTAMP NOT NULL DEFAULT current_timestamp();');
8
+ }
9
+ else {
10
+ await knex.schema.alterTable('directus_files', (table) => {
11
+ table.renameColumn('uploaded_on', 'created_on');
12
+ });
13
+ }
14
+ await knex.schema.alterTable('directus_files', (table) => {
15
+ table.timestamp('uploaded_on');
16
+ });
17
+ await knex('directus_files').update('uploaded_on', knex.ref('created_on'));
18
+ }
19
+ export async function down(knex) {
20
+ await knex.schema.alterTable('directus_files', (table) => {
21
+ table.dropColumn('uploaded_on');
22
+ });
23
+ const helper = getHelpers(knex).schema;
24
+ const isMysql = helper.isOneOfClients(['mysql']);
25
+ if (isMysql) {
26
+ await knex.schema.raw('ALTER TABLE `directus_files` CHANGE `created_on` `uploaded_on` TIMESTAMP NOT NULL DEFAULT current_timestamp();');
27
+ }
28
+ else {
29
+ await knex.schema.alterTable('directus_files', (table) => {
30
+ table.renameColumn('created_on', 'uploaded_on');
31
+ });
32
+ }
33
+ }
@@ -1,6 +1,7 @@
1
+ import type { Item, SchemaOverview } from '@directus/types';
1
2
  import type { Knex } from 'knex';
2
- import type { AST } from '../../types/ast.js';
3
- export interface RunASTOptions {
3
+ import type { AST, NestedCollectionNode } from '../types/ast.js';
4
+ type RunASTOptions = {
4
5
  /**
5
6
  * Query override for the current level
6
7
  */
@@ -17,4 +18,9 @@ export interface RunASTOptions {
17
18
  * Whether or not to strip out non-requested required fields automatically (eg IDs / FKs)
18
19
  */
19
20
  stripNonRequested?: boolean;
20
- }
21
+ };
22
+ /**
23
+ * Execute a given AST using Knex. Returns array of items based on requested AST.
24
+ */
25
+ export default function runAST(originalAST: AST | NestedCollectionNode, schema: SchemaOverview, options?: RunASTOptions): Promise<null | Item | Item[]>;
26
+ export {};