@directus/api 20.0.0-rc.1 → 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 -164
  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
@@ -0,0 +1,35 @@
1
+ import { toBoolean } from '@directus/utils';
2
+ import {} from './get-user-count.js';
3
+ /**
4
+ * Get the user type counts by role IDs
5
+ */
6
+ export async function getUserCountsByRoles(db, roleIds) {
7
+ const counts = {
8
+ admin: 0,
9
+ app: 0,
10
+ api: 0,
11
+ };
12
+ const result = (await db
13
+ .count('directus_users.id', { as: 'count' })
14
+ .select('directus_roles.admin_access', 'directus_roles.app_access')
15
+ .from('directus_users')
16
+ .whereIn('directus_roles.id', roleIds)
17
+ .andWhere('directus_users.status', '=', 'active')
18
+ .leftJoin('directus_roles', 'directus_users.role', '=', 'directus_roles.id')
19
+ .groupBy('directus_roles.admin_access', 'directus_roles.app_access'));
20
+ for (const record of result) {
21
+ const adminAccess = toBoolean(record.admin_access);
22
+ const appAccess = toBoolean(record.app_access);
23
+ const count = Number(record.count);
24
+ if (adminAccess) {
25
+ counts.admin += count;
26
+ }
27
+ else if (appAccess) {
28
+ counts.app += count;
29
+ }
30
+ else {
31
+ counts.api += count;
32
+ }
33
+ }
34
+ return counts;
35
+ }
@@ -1,4 +1,4 @@
1
- import type { Filter, Query, Relation } from '@directus/types';
1
+ import type { Query, Relation } from '@directus/types';
2
2
  export type M2ONode = {
3
3
  type: 'm2o';
4
4
  name: string;
@@ -8,14 +8,6 @@ export type M2ONode = {
8
8
  relation: Relation;
9
9
  parentKey: string;
10
10
  relatedKey: string;
11
- /**
12
- * Which permission cases have to be met on the current item for this field to return a value
13
- */
14
- whenCase: number[];
15
- /**
16
- * Permissions rules for the item access of the children of this item.
17
- */
18
- cases: Filter[];
19
11
  };
20
12
  export type A2MNode = {
21
13
  type: 'a2o';
@@ -32,16 +24,6 @@ export type A2MNode = {
32
24
  fieldKey: string;
33
25
  relation: Relation;
34
26
  parentKey: string;
35
- /**
36
- * Which permission cases have to be met on the current item for this field to return a value
37
- */
38
- whenCase: number[];
39
- /**
40
- * Permissions rules for the item access of the children of this item.
41
- */
42
- cases: {
43
- [collection: string]: Filter[];
44
- };
45
27
  };
46
28
  export type O2MNode = {
47
29
  type: 'o2m';
@@ -52,24 +34,12 @@ export type O2MNode = {
52
34
  relation: Relation;
53
35
  parentKey: string;
54
36
  relatedKey: string;
55
- /**
56
- * Which permission cases have to be met on the current item for this field to return a value
57
- */
58
- whenCase: number[];
59
- /**
60
- * Permissions rules for the item access of the children of this item.
61
- */
62
- cases: Filter[];
63
37
  };
64
38
  export type NestedCollectionNode = M2ONode | O2MNode | A2MNode;
65
39
  export type FieldNode = {
66
40
  type: 'field';
67
41
  name: string;
68
42
  fieldKey: string;
69
- /**
70
- * Which permission cases have to be met on the current item for this field to return a value
71
- */
72
- whenCase: number[];
73
43
  };
74
44
  export type FunctionFieldNode = {
75
45
  type: 'functionField';
@@ -77,22 +47,10 @@ export type FunctionFieldNode = {
77
47
  fieldKey: string;
78
48
  query: Query;
79
49
  relatedCollection: string;
80
- /**
81
- * Which permission cases have to be met on the current item for this field to return a value
82
- */
83
- whenCase: number[];
84
- /**
85
- * Permissions rules for the item access of the related collection of this item.
86
- */
87
- cases: Filter[];
88
50
  };
89
51
  export type AST = {
90
52
  type: 'root';
91
53
  name: string;
92
54
  children: (NestedCollectionNode | FieldNode | FunctionFieldNode)[];
93
55
  query: Query;
94
- /**
95
- * Permissions rules for the item access of the children of this item.
96
- */
97
- cases: Filter[];
98
56
  };
@@ -1,7 +1,6 @@
1
1
  import type { DirectusError } from '@directus/errors';
2
2
  import type { EventContext, PrimaryKey } from '@directus/types';
3
3
  import type { MutationTracker } from '../services/items.js';
4
- import type { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
5
4
  export type MutationOptions = {
6
5
  /**
7
6
  * Callback function that's fired whenever a revision is made in the mutation
@@ -34,16 +33,6 @@ export type MutationOptions = {
34
33
  mutationTracker?: MutationTracker | undefined;
35
34
  preMutationError?: DirectusError | undefined;
36
35
  bypassAutoIncrementSequenceReset?: boolean;
37
- /**
38
- * Indicate that the top level mutation needs to perform a user integrity check before commiting the transaction
39
- * This is a combination of flags
40
- * @see UserIntegrityCheckFlag
41
- */
42
- userIntegrityCheckFlags?: UserIntegrityCheckFlag;
43
- /**
44
- * Callback function that is called whenever a mutation requires a user integrity check to be made
45
- */
46
- onRequireUserIntegrityCheck?: ((flags: UserIntegrityCheckFlag) => void) | undefined;
47
36
  };
48
37
  export type ActionEventParams = {
49
38
  event: string | string[];
@@ -5,7 +5,7 @@ export declare const generateAlias: (size?: number | undefined) => string;
5
5
  /**
6
6
  * Apply the Query to a given Knex query builder instance
7
7
  */
8
- export default function applyQuery(knex: Knex, collection: string, dbQuery: Knex.QueryBuilder, query: Query, schema: SchemaOverview, cases: Filter[], options?: {
8
+ export default function applyQuery(knex: Knex, collection: string, dbQuery: Knex.QueryBuilder, query: Query, schema: SchemaOverview, options?: {
9
9
  aliasMap?: AliasMap;
10
10
  isInnerQuery?: boolean;
11
11
  hasMultiRelationalSort?: boolean | undefined;
@@ -32,11 +32,10 @@ export declare function applySort(knex: Knex, schema: SchemaOverview, rootQuery:
32
32
  };
33
33
  export declare function applyLimit(knex: Knex, rootQuery: Knex.QueryBuilder, limit: any): void;
34
34
  export declare function applyOffset(knex: Knex, rootQuery: Knex.QueryBuilder, offset: any): void;
35
- export declare function applyFilter(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootFilter: Filter, collection: string, aliasMap: AliasMap, cases: Filter[]): {
35
+ export declare function applyFilter(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootFilter: Filter, collection: string, aliasMap: AliasMap): {
36
36
  query: Knex.QueryBuilder<any, any>;
37
37
  hasJoins: boolean;
38
38
  hasMultiRelationalFilter: boolean;
39
39
  };
40
- export declare function applySearch(knex: Knex, schema: SchemaOverview, dbQuery: Knex.QueryBuilder, searchQuery: string, collection: string): void;
40
+ export declare function applySearch(knex: Knex, schema: SchemaOverview, dbQuery: Knex.QueryBuilder, searchQuery: string, collection: string): Promise<void>;
41
41
  export declare function applyAggregate(schema: SchemaOverview, dbQuery: Knex.QueryBuilder, aggregate: Aggregate, collection: string, hasJoins: boolean): void;
42
- export declare function joinFilterWithCases(filter: Filter | null | undefined, cases: Filter[]): Filter | null;
@@ -14,7 +14,7 @@ export const generateAlias = customAlphabet('abcdefghijklmnopqrstuvwxyz', 5);
14
14
  /**
15
15
  * Apply the Query to a given Knex query builder instance
16
16
  */
17
- export default function applyQuery(knex, collection, dbQuery, query, schema, cases, options) {
17
+ export default function applyQuery(knex, collection, dbQuery, query, schema, options) {
18
18
  const aliasMap = options?.aliasMap ?? Object.create(null);
19
19
  let hasJoins = false;
20
20
  let hasMultiRelationalFilter = false;
@@ -37,14 +37,8 @@ export default function applyQuery(knex, collection, dbQuery, query, schema, cas
37
37
  if (query.group) {
38
38
  dbQuery.groupBy(query.group.map((column) => getColumn(knex, collection, column, false, schema)));
39
39
  }
40
- // `cases` are the permissions cases that are required for the current data set. We're
41
- // dynamically adding those into the filters that the user provided to enforce the permission
42
- // rules. You should be able to read an item if one or more of the cases matches. The actual case
43
- // is reused in the column selection case/when to dynamically return or nullify the field values
44
- // you're actually allowed to read
45
- const filter = joinFilterWithCases(query.filter, cases);
46
- if (filter) {
47
- const filterResult = applyFilter(knex, schema, dbQuery, filter, collection, aliasMap, cases);
40
+ if (query.filter) {
41
+ const filterResult = applyFilter(knex, schema, dbQuery, query.filter, collection, aliasMap);
48
42
  if (!hasJoins) {
49
43
  hasJoins = filterResult.hasJoins;
50
44
  }
@@ -232,7 +226,7 @@ export function applyOffset(knex, rootQuery, offset) {
232
226
  getHelpers(knex).schema.applyOffset(rootQuery, offset);
233
227
  }
234
228
  }
235
- export function applyFilter(knex, schema, rootQuery, rootFilter, collection, aliasMap, cases) {
229
+ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, aliasMap) {
236
230
  const helpers = getHelpers(knex);
237
231
  const relations = schema.relations;
238
232
  let hasJoins = false;
@@ -241,23 +235,12 @@ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, ali
241
235
  addWhereClauses(knex, rootQuery, rootFilter, collection);
242
236
  return { query: rootQuery, hasJoins, hasMultiRelationalFilter };
243
237
  function addJoins(dbQuery, filter, collection) {
244
- // eslint-disable-next-line prefer-const
245
- for (let [key, value] of Object.entries(filter)) {
238
+ for (const [key, value] of Object.entries(filter)) {
246
239
  if (key === '_or' || key === '_and') {
247
240
  // If the _or array contains an empty object (full permissions), we should short-circuit and ignore all other
248
241
  // permission checks, as {} already matches full permissions.
249
242
  if (key === '_or' && value.some((subFilter) => Object.keys(subFilter).length === 0)) {
250
- // But only do so, if the value is not equal to `cases` (since then this is not permission related at all)
251
- // or the length of value is 1, ie. only the empty filter.
252
- // If the length is more than one it means that some items (and fields) might now be available, so
253
- // the joins are required for the case/when construction.
254
- if (value !== cases || value.length === 1) {
255
- continue;
256
- }
257
- else {
258
- // Otherwise we can at least filter out all empty filters that would not add joins anyway
259
- value = value.filter((subFilter) => Object.keys(subFilter).length > 0);
260
- }
243
+ continue;
261
244
  }
262
245
  value.forEach((subFilter) => {
263
246
  addJoins(dbQuery, subFilter, collection);
@@ -328,7 +311,7 @@ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, ali
328
311
  .select({ [field]: column })
329
312
  .from(collection)
330
313
  .whereNotNull(column);
331
- applyQuery(knex, relation.collection, subQueryKnex, { filter }, schema, cases);
314
+ applyQuery(knex, relation.collection, subQueryKnex, { filter }, schema);
332
315
  };
333
316
  const childKey = Object.keys(value)?.[0];
334
317
  if (childKey === '_none') {
@@ -568,7 +551,7 @@ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, ali
568
551
  }
569
552
  }
570
553
  }
571
- export function applySearch(knex, schema, dbQuery, searchQuery, collection) {
554
+ export async function applySearch(knex, schema, dbQuery, searchQuery, collection) {
572
555
  const { number: numberHelper } = getHelpers(knex);
573
556
  const fields = Object.entries(schema.collections[collection].fields);
574
557
  dbQuery.andWhere(function () {
@@ -644,18 +627,6 @@ export function applyAggregate(schema, dbQuery, aggregate, collection, hasJoins)
644
627
  }
645
628
  }
646
629
  }
647
- export function joinFilterWithCases(filter, cases) {
648
- if (cases.length > 0 && !filter) {
649
- return { _or: cases };
650
- }
651
- else if (filter && cases.length === 0) {
652
- return filter ?? null;
653
- }
654
- else if (filter && cases.length > 0) {
655
- return { _and: [filter, { _or: cases }] };
656
- }
657
- return null;
658
- }
659
630
  function getFilterPath(key, value) {
660
631
  const path = [key];
661
632
  const childKey = Object.keys(value)[0];
@@ -1,31 +1,40 @@
1
- import { fetchRolesTree } from '../permissions/lib/fetch-roles-tree.js';
2
- import { fetchGlobalAccess } from '../permissions/modules/fetch-global-access/fetch-global-access.js';
3
- import { createDefaultAccountability } from '../permissions/utils/create-default-accountability.js';
1
+ import { getPermissions } from './get-permissions.js';
4
2
  export async function getAccountabilityForRole(role, context) {
5
- let generatedAccountability;
3
+ let generatedAccountability = context.accountability;
6
4
  if (role === null) {
7
- generatedAccountability = createDefaultAccountability();
5
+ generatedAccountability = {
6
+ role: null,
7
+ user: null,
8
+ admin: false,
9
+ app: false,
10
+ };
11
+ generatedAccountability.permissions = await getPermissions(generatedAccountability, context.schema);
8
12
  }
9
13
  else if (role === 'system') {
10
- generatedAccountability = createDefaultAccountability({
14
+ generatedAccountability = {
15
+ user: null,
16
+ role: null,
11
17
  admin: true,
12
18
  app: true,
13
- });
19
+ permissions: [],
20
+ };
14
21
  }
15
22
  else {
16
- const roles = await fetchRolesTree(role, context.database);
17
- // The roles tree should always include the passed role. If it doesn't, it's because it
18
- // couldn't be read from the database and therefore doesn't exist
19
- if (roles.length === 0) {
23
+ const roleInfo = await context.database
24
+ .select(['app_access', 'admin_access'])
25
+ .from('directus_roles')
26
+ .where({ id: role })
27
+ .first();
28
+ if (!roleInfo) {
20
29
  throw new Error(`Configured role "${role}" isn't a valid role ID or doesn't exist.`);
21
30
  }
22
- const globalAccess = await fetchGlobalAccess({ user: null, roles, ip: context.accountability?.ip ?? null }, context.database);
23
- generatedAccountability = createDefaultAccountability({
31
+ generatedAccountability = {
24
32
  role,
25
- roles,
26
33
  user: null,
27
- ...globalAccess,
28
- });
34
+ admin: roleInfo.admin_access === 1 || roleInfo.admin_access === '1' || roleInfo.admin_access === true,
35
+ app: roleInfo.app_access === 1 || roleInfo.app_access === '1' || roleInfo.app_access === true,
36
+ };
37
+ generatedAccountability.permissions = await getPermissions(generatedAccountability, context.schema);
29
38
  }
30
39
  return generatedAccountability;
31
40
  }
@@ -1,40 +1,41 @@
1
1
  import { InvalidCredentialsError } from '@directus/errors';
2
2
  import getDatabase from '../database/index.js';
3
- import { fetchRolesTree } from '../permissions/lib/fetch-roles-tree.js';
4
- import { fetchGlobalAccess } from '../permissions/modules/fetch-global-access/fetch-global-access.js';
5
- import { createDefaultAccountability } from '../permissions/utils/create-default-accountability.js';
6
3
  import { getSecret } from './get-secret.js';
7
4
  import isDirectusJWT from './is-directus-jwt.js';
8
- import { verifyAccessJWT } from './jwt.js';
9
5
  import { verifySessionJWT } from './verify-session-jwt.js';
6
+ import { verifyAccessJWT } from './jwt.js';
10
7
  export async function getAccountabilityForToken(token, accountability) {
11
8
  if (!accountability) {
12
- accountability = createDefaultAccountability();
9
+ accountability = {
10
+ user: null,
11
+ role: null,
12
+ admin: false,
13
+ app: false,
14
+ };
13
15
  }
14
- // Try finding the user with the provided token
15
- const database = getDatabase();
16
16
  if (token) {
17
17
  if (isDirectusJWT(token)) {
18
18
  const payload = verifyAccessJWT(token, getSecret());
19
19
  if ('session' in payload) {
20
20
  await verifySessionJWT(payload);
21
21
  }
22
+ accountability.role = payload.role;
23
+ accountability.admin = payload.admin_access === true || payload.admin_access == 1;
24
+ accountability.app = payload.app_access === true || payload.app_access == 1;
22
25
  if (payload.share)
23
26
  accountability.share = payload.share;
24
27
  if (payload.share_scope)
25
28
  accountability.share_scope = payload.share_scope;
26
29
  if (payload.id)
27
30
  accountability.user = payload.id;
28
- accountability.role = payload.role;
29
- accountability.roles = await fetchRolesTree(payload.role, database);
30
- const { admin, app } = await fetchGlobalAccess(accountability, database);
31
- accountability.admin = admin;
32
- accountability.app = app;
33
31
  }
34
32
  else {
33
+ // Try finding the user with the provided token
34
+ const database = getDatabase();
35
35
  const user = await database
36
- .select('directus_users.id', 'directus_users.role')
36
+ .select('directus_users.id', 'directus_users.role', 'directus_roles.admin_access', 'directus_roles.app_access')
37
37
  .from('directus_users')
38
+ .leftJoin('directus_roles', 'directus_users.role', 'directus_roles.id')
38
39
  .where({
39
40
  'directus_users.token': token,
40
41
  status: 'active',
@@ -45,10 +46,8 @@ export async function getAccountabilityForToken(token, accountability) {
45
46
  }
46
47
  accountability.user = user.id;
47
48
  accountability.role = user.role;
48
- accountability.roles = await fetchRolesTree(user.role, database);
49
- const { admin, app } = await fetchGlobalAccess(accountability, database);
50
- accountability.admin = admin;
51
- accountability.app = app;
49
+ accountability.admin = user.admin_access === true || user.admin_access == 1;
50
+ accountability.app = user.app_access === true || user.app_access == 1;
52
51
  }
53
52
  }
54
53
  return accountability;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Generate an AST based on a given collection and query
3
+ */
4
+ import type { Accountability, PermissionsAction, Query, SchemaOverview } from '@directus/types';
5
+ import type { Knex } from 'knex';
6
+ import type { AST } from '../types/index.js';
7
+ type GetASTOptions = {
8
+ accountability?: Accountability | null;
9
+ action?: PermissionsAction;
10
+ knex?: Knex;
11
+ };
12
+ export default function getASTFromQuery(collection: string, query: Query, schema: SchemaOverview, options?: GetASTOptions): Promise<AST>;
13
+ export {};