@directus/api 21.0.0 → 22.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 (285) hide show
  1. package/dist/app.js +4 -4
  2. package/dist/auth/drivers/ldap.js +4 -4
  3. package/dist/auth/drivers/local.js +4 -4
  4. package/dist/auth/drivers/oauth2.js +4 -4
  5. package/dist/auth/drivers/openid.js +2 -4
  6. package/dist/cache.js +3 -0
  7. package/dist/cli/commands/bootstrap/index.js +8 -2
  8. package/dist/cli/commands/init/index.js +9 -10
  9. package/dist/cli/utils/defaults.d.ts +4 -11
  10. package/dist/cli/utils/defaults.js +7 -1
  11. package/dist/constants.d.ts +1 -1
  12. package/dist/controllers/access.d.ts +2 -0
  13. package/dist/controllers/access.js +148 -0
  14. package/dist/controllers/auth.js +5 -16
  15. package/dist/controllers/permissions.js +14 -2
  16. package/dist/controllers/policies.d.ts +2 -0
  17. package/dist/controllers/policies.js +169 -0
  18. package/dist/controllers/roles.js +22 -1
  19. package/dist/controllers/tus.js +14 -26
  20. package/dist/controllers/users.js +0 -55
  21. package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +16 -0
  22. package/dist/database/get-ast-from-query/get-ast-from-query.js +82 -0
  23. package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +13 -0
  24. package/dist/database/get-ast-from-query/lib/convert-wildcards.js +69 -0
  25. package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +15 -0
  26. package/dist/database/get-ast-from-query/lib/parse-fields.js +200 -0
  27. package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +14 -0
  28. package/dist/database/get-ast-from-query/utils/get-deep-query.js +17 -0
  29. package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +2 -0
  30. package/dist/database/get-ast-from-query/utils/get-related-collection.js +13 -0
  31. package/dist/database/get-ast-from-query/utils/get-relation.d.ts +2 -0
  32. package/dist/database/get-ast-from-query/utils/get-relation.js +7 -0
  33. package/dist/database/helpers/fn/types.d.ts +2 -1
  34. package/dist/database/helpers/fn/types.js +1 -1
  35. package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
  36. package/dist/database/helpers/geometry/dialects/mssql.js +4 -2
  37. package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
  38. package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
  39. package/dist/database/helpers/geometry/dialects/oracle.js +5 -3
  40. package/dist/database/helpers/geometry/types.d.ts +1 -1
  41. package/dist/database/helpers/geometry/types.js +4 -2
  42. package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +2 -1
  43. package/dist/database/helpers/schema/dialects/cockroachdb.js +4 -0
  44. package/dist/database/helpers/schema/dialects/mssql.d.ts +2 -1
  45. package/dist/database/helpers/schema/dialects/mssql.js +4 -0
  46. package/dist/database/helpers/schema/dialects/oracle.d.ts +2 -1
  47. package/dist/database/helpers/schema/dialects/oracle.js +4 -0
  48. package/dist/database/helpers/schema/dialects/postgres.d.ts +2 -1
  49. package/dist/database/helpers/schema/dialects/postgres.js +4 -0
  50. package/dist/database/helpers/schema/types.d.ts +5 -0
  51. package/dist/database/helpers/schema/types.js +3 -0
  52. package/dist/database/helpers/schema/utils/preprocess-bindings.d.ts +8 -0
  53. package/dist/database/helpers/schema/utils/preprocess-bindings.js +30 -0
  54. package/dist/database/index.js +6 -1
  55. package/dist/{utils/merge-permissions.d.ts → database/migrations/20240806A-permissions-policies.d.ts} +4 -1
  56. package/dist/database/migrations/20240806A-permissions-policies.js +338 -0
  57. package/dist/database/run-ast/lib/get-db-query.d.ts +4 -0
  58. package/dist/database/run-ast/lib/get-db-query.js +218 -0
  59. package/dist/database/run-ast/lib/parse-current-level.d.ts +7 -0
  60. package/dist/database/run-ast/lib/parse-current-level.js +41 -0
  61. package/dist/database/run-ast/run-ast.d.ts +7 -0
  62. package/dist/database/run-ast/run-ast.js +107 -0
  63. package/dist/database/{run-ast.d.ts → run-ast/types.d.ts} +3 -9
  64. package/dist/database/run-ast/types.js +1 -0
  65. package/dist/database/run-ast/utils/apply-case-when.d.ts +16 -0
  66. package/dist/database/run-ast/utils/apply-case-when.js +27 -0
  67. package/dist/database/run-ast/utils/apply-parent-filters.d.ts +3 -0
  68. package/dist/database/run-ast/utils/apply-parent-filters.js +55 -0
  69. package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +10 -0
  70. package/dist/database/run-ast/utils/get-column-pre-processor.js +57 -0
  71. package/dist/database/run-ast/utils/get-field-alias.d.ts +2 -0
  72. package/dist/database/run-ast/utils/get-field-alias.js +4 -0
  73. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +5 -0
  74. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +23 -0
  75. package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +3 -0
  76. package/dist/database/run-ast/utils/merge-with-parent-items.js +87 -0
  77. package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +3 -0
  78. package/dist/database/run-ast/utils/remove-temporary-fields.js +73 -0
  79. package/dist/database/run-ast/utils/with-preprocess-bindings.d.ts +2 -0
  80. package/dist/database/run-ast/utils/with-preprocess-bindings.js +14 -0
  81. package/dist/flows.js +3 -4
  82. package/dist/middleware/authenticate.js +2 -7
  83. package/dist/middleware/cache.js +1 -1
  84. package/dist/middleware/respond.js +1 -1
  85. package/dist/permissions/cache.d.ts +2 -0
  86. package/dist/permissions/cache.js +23 -0
  87. package/dist/permissions/lib/fetch-permissions.d.ts +11 -0
  88. package/dist/permissions/lib/fetch-permissions.js +56 -0
  89. package/dist/permissions/lib/fetch-policies.d.ts +14 -0
  90. package/dist/permissions/lib/fetch-policies.js +43 -0
  91. package/dist/permissions/lib/fetch-roles-tree.d.ts +3 -0
  92. package/dist/permissions/lib/fetch-roles-tree.js +28 -0
  93. package/dist/{services/permissions → permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
  94. package/dist/permissions/lib/with-app-minimal-permissions.js +10 -0
  95. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +7 -0
  96. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +56 -0
  97. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +3 -0
  98. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +16 -0
  99. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +8 -0
  100. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +24 -0
  101. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +9 -0
  102. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +31 -0
  103. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +16 -0
  104. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +27 -0
  105. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +10 -0
  106. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +23 -0
  107. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +5 -0
  108. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +7 -0
  109. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +5 -0
  110. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +10 -0
  111. package/dist/permissions/modules/fetch-global-access/types.d.ts +4 -0
  112. package/dist/permissions/modules/fetch-global-access/types.js +1 -0
  113. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +4 -0
  114. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +27 -0
  115. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +12 -0
  116. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +32 -0
  117. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +4 -0
  118. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +29 -0
  119. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +4 -0
  120. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +49 -0
  121. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +3 -0
  122. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +56 -0
  123. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +4 -0
  124. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +8 -0
  125. package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +9 -0
  126. package/dist/permissions/modules/process-ast/lib/inject-cases.js +93 -0
  127. package/dist/permissions/modules/process-ast/process-ast.d.ts +9 -0
  128. package/dist/permissions/modules/process-ast/process-ast.js +39 -0
  129. package/dist/permissions/modules/process-ast/types.d.ts +18 -0
  130. package/dist/permissions/modules/process-ast/types.js +1 -0
  131. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +2 -0
  132. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +7 -0
  133. package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +12 -0
  134. package/dist/permissions/modules/process-ast/utils/dedupe-access.js +30 -0
  135. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +15 -0
  136. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +60 -0
  137. package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +3 -0
  138. package/dist/permissions/modules/process-ast/utils/find-related-collection.js +9 -0
  139. package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +3 -0
  140. package/dist/permissions/modules/process-ast/utils/flatten-filter.js +34 -0
  141. package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +1 -0
  142. package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +3 -0
  143. package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +5 -0
  144. package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +7 -0
  145. package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +2 -0
  146. package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +3 -0
  147. package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +2 -0
  148. package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +3 -0
  149. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +3 -0
  150. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +16 -0
  151. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +2 -0
  152. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +12 -0
  153. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +2 -0
  154. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +28 -0
  155. package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +5 -0
  156. package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +12 -0
  157. package/dist/permissions/modules/process-payload/process-payload.d.ts +13 -0
  158. package/dist/permissions/modules/process-payload/process-payload.js +77 -0
  159. package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +12 -0
  160. package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +11 -0
  161. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +9 -0
  162. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +33 -0
  163. package/dist/permissions/modules/validate-access/validate-access.d.ts +14 -0
  164. package/dist/permissions/modules/validate-access/validate-access.js +28 -0
  165. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +1 -0
  166. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +8 -0
  167. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +5 -0
  168. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +10 -0
  169. package/dist/permissions/types.d.ts +6 -0
  170. package/dist/permissions/types.js +1 -0
  171. package/dist/permissions/utils/create-default-accountability.d.ts +2 -0
  172. package/dist/permissions/utils/create-default-accountability.js +11 -0
  173. package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +8 -0
  174. package/dist/permissions/utils/extract-required-dynamic-variable-context.js +27 -0
  175. package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +9 -0
  176. package/dist/permissions/utils/fetch-dynamic-variable-context.js +43 -0
  177. package/dist/permissions/utils/filter-policies-by-ip.d.ts +2 -0
  178. package/dist/permissions/utils/filter-policies-by-ip.js +15 -0
  179. package/dist/permissions/utils/get-unaliased-field-key.d.ts +5 -0
  180. package/dist/permissions/utils/get-unaliased-field-key.js +17 -0
  181. package/dist/permissions/utils/process-permissions.d.ts +7 -0
  182. package/dist/permissions/utils/process-permissions.js +9 -0
  183. package/dist/permissions/utils/with-cache.d.ts +10 -0
  184. package/dist/permissions/utils/with-cache.js +25 -0
  185. package/dist/services/access.d.ts +10 -0
  186. package/dist/services/access.js +43 -0
  187. package/dist/services/activity.js +22 -10
  188. package/dist/services/assets.d.ts +2 -3
  189. package/dist/services/assets.js +10 -5
  190. package/dist/services/authentication.js +18 -18
  191. package/dist/services/collections.js +18 -17
  192. package/dist/services/fields.d.ts +0 -1
  193. package/dist/services/fields.js +54 -25
  194. package/dist/services/files.js +10 -3
  195. package/dist/services/graphql/index.d.ts +3 -3
  196. package/dist/services/graphql/index.js +126 -22
  197. package/dist/services/graphql/subscription.js +2 -4
  198. package/dist/services/import-export.d.ts +3 -1
  199. package/dist/services/import-export.js +67 -9
  200. package/dist/services/index.d.ts +3 -2
  201. package/dist/services/index.js +3 -2
  202. package/dist/services/items.js +115 -44
  203. package/dist/services/meta.js +60 -23
  204. package/dist/services/notifications.js +14 -6
  205. package/dist/services/payload.d.ts +9 -10
  206. package/dist/services/payload.js +18 -3
  207. package/dist/services/{permissions/index.d.ts → permissions.d.ts} +5 -7
  208. package/dist/services/{permissions/index.js → permissions.js} +30 -54
  209. package/dist/services/policies.d.ts +12 -0
  210. package/dist/services/policies.js +87 -0
  211. package/dist/services/relations.d.ts +0 -6
  212. package/dist/services/relations.js +27 -30
  213. package/dist/services/roles.d.ts +4 -12
  214. package/dist/services/roles.js +57 -424
  215. package/dist/services/shares.d.ts +0 -2
  216. package/dist/services/shares.js +12 -8
  217. package/dist/services/specifications.d.ts +2 -2
  218. package/dist/services/specifications.js +39 -27
  219. package/dist/services/users.d.ts +1 -5
  220. package/dist/services/users.js +78 -161
  221. package/dist/services/utils.js +11 -7
  222. package/dist/services/versions.d.ts +0 -2
  223. package/dist/services/versions.js +34 -10
  224. package/dist/telemetry/lib/get-report.js +2 -2
  225. package/dist/telemetry/utils/check-user-limits.d.ts +5 -0
  226. package/dist/telemetry/utils/check-user-limits.js +19 -0
  227. package/dist/types/ast.d.ts +43 -1
  228. package/dist/types/items.d.ts +11 -0
  229. package/dist/utils/apply-query.d.ts +11 -7
  230. package/dist/utils/apply-query.js +69 -11
  231. package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +19 -0
  232. package/dist/utils/fetch-user-count/fetch-access-lookup.js +23 -0
  233. package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +16 -0
  234. package/dist/utils/fetch-user-count/fetch-access-roles.js +37 -0
  235. package/dist/utils/fetch-user-count/fetch-active-users.d.ts +6 -0
  236. package/dist/utils/fetch-user-count/fetch-active-users.js +3 -0
  237. package/dist/utils/fetch-user-count/fetch-user-count.d.ts +12 -0
  238. package/dist/utils/fetch-user-count/fetch-user-count.js +64 -0
  239. package/dist/utils/fetch-user-count/get-user-count-query.d.ts +20 -0
  240. package/dist/utils/fetch-user-count/get-user-count-query.js +17 -0
  241. package/dist/utils/get-accountability-for-role.js +16 -25
  242. package/dist/utils/get-accountability-for-token.js +17 -16
  243. package/dist/utils/get-cache-key.d.ts +1 -1
  244. package/dist/utils/get-cache-key.js +12 -1
  245. package/dist/utils/get-column.d.ts +2 -1
  246. package/dist/utils/get-column.js +1 -0
  247. package/dist/utils/get-service.js +5 -1
  248. package/dist/utils/reduce-schema.d.ts +4 -6
  249. package/dist/utils/reduce-schema.js +16 -32
  250. package/dist/utils/sanitize-schema.d.ts +1 -1
  251. package/dist/utils/validate-user-count-integrity.d.ts +13 -0
  252. package/dist/utils/validate-user-count-integrity.js +29 -0
  253. package/dist/websocket/authenticate.d.ts +0 -2
  254. package/dist/websocket/authenticate.js +0 -12
  255. package/dist/websocket/controllers/graphql.js +1 -4
  256. package/dist/websocket/controllers/hooks.js +4 -0
  257. package/dist/websocket/controllers/rest.js +0 -2
  258. package/dist/websocket/handlers/subscribe.js +0 -2
  259. package/dist/websocket/utils/items.d.ts +1 -1
  260. package/package.json +30 -29
  261. package/dist/database/run-ast.js +0 -458
  262. package/dist/middleware/check-ip.d.ts +0 -2
  263. package/dist/middleware/check-ip.js +0 -37
  264. package/dist/middleware/get-permissions.d.ts +0 -3
  265. package/dist/middleware/get-permissions.js +0 -10
  266. package/dist/services/authorization.d.ts +0 -17
  267. package/dist/services/authorization.js +0 -456
  268. package/dist/services/permissions/lib/with-app-minimal-permissions.js +0 -13
  269. package/dist/telemetry/utils/check-increased-user-limits.d.ts +0 -7
  270. package/dist/telemetry/utils/check-increased-user-limits.js +0 -25
  271. package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +0 -6
  272. package/dist/telemetry/utils/get-role-counts-by-roles.js +0 -27
  273. package/dist/telemetry/utils/get-role-counts-by-users.d.ts +0 -11
  274. package/dist/telemetry/utils/get-role-counts-by-users.js +0 -34
  275. package/dist/telemetry/utils/get-user-count.d.ts +0 -8
  276. package/dist/telemetry/utils/get-user-count.js +0 -33
  277. package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +0 -7
  278. package/dist/telemetry/utils/get-user-counts-by-roles.js +0 -35
  279. package/dist/utils/get-ast-from-query.d.ts +0 -13
  280. package/dist/utils/get-ast-from-query.js +0 -297
  281. package/dist/utils/get-permissions.d.ts +0 -2
  282. package/dist/utils/get-permissions.js +0 -150
  283. package/dist/utils/merge-permissions-for-share.d.ts +0 -4
  284. package/dist/utils/merge-permissions-for-share.js +0 -109
  285. package/dist/utils/merge-permissions.js +0 -95
@@ -9,6 +9,7 @@ import { parse as wktToGeoJSON } from 'wellknown';
9
9
  import { getHelpers } from '../database/helpers/index.js';
10
10
  import getDatabase from '../database/index.js';
11
11
  import { generateHash } from '../utils/generate-hash.js';
12
+ import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
12
13
  /**
13
14
  * Process a given payload for a collection to ensure the special fields (hash, uuid, date etc) are
14
15
  * handled correctly.
@@ -317,6 +318,7 @@ export class PayloadService {
317
318
  return relation.collection === this.collection;
318
319
  });
319
320
  const revisions = [];
321
+ let userIntegrityCheckFlags = UserIntegrityCheckFlag.None;
320
322
  const nestedActionEvents = [];
321
323
  const payload = cloneDeep(data);
322
324
  // Only process related records that are actually in the payload
@@ -362,6 +364,7 @@ export class PayloadService {
362
364
  if (Object.keys(fieldsToUpdate).length > 0) {
363
365
  await service.updateOne(relatedPrimaryKey, relatedRecord, {
364
366
  onRevisionCreate: (pk) => revisions.push(pk),
367
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
365
368
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
366
369
  emitEvents: opts?.emitEvents,
367
370
  mutationTracker: opts?.mutationTracker,
@@ -371,6 +374,7 @@ export class PayloadService {
371
374
  else {
372
375
  relatedPrimaryKey = await service.createOne(relatedRecord, {
373
376
  onRevisionCreate: (pk) => revisions.push(pk),
377
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
374
378
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
375
379
  emitEvents: opts?.emitEvents,
376
380
  mutationTracker: opts?.mutationTracker,
@@ -379,7 +383,7 @@ export class PayloadService {
379
383
  // Overwrite the nested object with just the primary key, so the parent level can be saved correctly
380
384
  payload[relation.field] = relatedPrimaryKey;
381
385
  }
382
- return { payload, revisions, nestedActionEvents };
386
+ return { payload, revisions, nestedActionEvents, userIntegrityCheckFlags };
383
387
  }
384
388
  /**
385
389
  * Save/update all nested related m2o items inside the payload
@@ -388,6 +392,7 @@ export class PayloadService {
388
392
  const payload = cloneDeep(data);
389
393
  // All the revisions saved on this level
390
394
  const revisions = [];
395
+ let userIntegrityCheckFlags = UserIntegrityCheckFlag.None;
391
396
  const nestedActionEvents = [];
392
397
  // Many to one relations that exist on the current collection
393
398
  const relations = this.schema.relations.filter((relation) => {
@@ -424,6 +429,7 @@ export class PayloadService {
424
429
  if (Object.keys(fieldsToUpdate).length > 0) {
425
430
  await service.updateOne(relatedPrimaryKey, relatedRecord, {
426
431
  onRevisionCreate: (pk) => revisions.push(pk),
432
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
427
433
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
428
434
  emitEvents: opts?.emitEvents,
429
435
  mutationTracker: opts?.mutationTracker,
@@ -433,6 +439,7 @@ export class PayloadService {
433
439
  else {
434
440
  relatedPrimaryKey = await service.createOne(relatedRecord, {
435
441
  onRevisionCreate: (pk) => revisions.push(pk),
442
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
436
443
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
437
444
  emitEvents: opts?.emitEvents,
438
445
  mutationTracker: opts?.mutationTracker,
@@ -441,13 +448,14 @@ export class PayloadService {
441
448
  // Overwrite the nested object with just the primary key, so the parent level can be saved correctly
442
449
  payload[relation.field] = relatedPrimaryKey;
443
450
  }
444
- return { payload, revisions, nestedActionEvents };
451
+ return { payload, revisions, nestedActionEvents, userIntegrityCheckFlags };
445
452
  }
446
453
  /**
447
454
  * Recursively save/update all nested related o2m items
448
455
  */
449
456
  async processO2M(data, parent, opts) {
450
457
  const revisions = [];
458
+ let userIntegrityCheckFlags = UserIntegrityCheckFlag.None;
451
459
  const nestedActionEvents = [];
452
460
  const relations = this.schema.relations.filter((relation) => {
453
461
  return relation.related_collection === this.collection;
@@ -516,6 +524,7 @@ export class PayloadService {
516
524
  }
517
525
  savedPrimaryKeys.push(...(await service.upsertMany(recordsToUpsert, {
518
526
  onRevisionCreate: (pk) => revisions.push(pk),
527
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
519
528
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
520
529
  emitEvents: opts?.emitEvents,
521
530
  mutationTracker: opts?.mutationTracker,
@@ -540,6 +549,7 @@ export class PayloadService {
540
549
  if (relation.meta.one_deselect_action === 'delete') {
541
550
  // There's no revision for a deletion
542
551
  await service.deleteByQuery(query, {
552
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
543
553
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
544
554
  emitEvents: opts?.emitEvents,
545
555
  mutationTracker: opts?.mutationTracker,
@@ -548,6 +558,7 @@ export class PayloadService {
548
558
  else {
549
559
  await service.updateByQuery(query, { [relation.field]: null }, {
550
560
  onRevisionCreate: (pk) => revisions.push(pk),
561
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
551
562
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
552
563
  emitEvents: opts?.emitEvents,
553
564
  mutationTracker: opts?.mutationTracker,
@@ -590,6 +601,7 @@ export class PayloadService {
590
601
  }
591
602
  await service.createMany(createPayload, {
592
603
  onRevisionCreate: (pk) => revisions.push(pk),
604
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
593
605
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
594
606
  emitEvents: opts?.emitEvents,
595
607
  mutationTracker: opts?.mutationTracker,
@@ -603,6 +615,7 @@ export class PayloadService {
603
615
  [relation.field]: parent || payload[currentPrimaryKeyField],
604
616
  }, {
605
617
  onRevisionCreate: (pk) => revisions.push(pk),
618
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
606
619
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
607
620
  emitEvents: opts?.emitEvents,
608
621
  mutationTracker: opts?.mutationTracker,
@@ -628,6 +641,7 @@ export class PayloadService {
628
641
  };
629
642
  if (relation.meta.one_deselect_action === 'delete') {
630
643
  await service.deleteByQuery(query, {
644
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
631
645
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
632
646
  emitEvents: opts?.emitEvents,
633
647
  mutationTracker: opts?.mutationTracker,
@@ -636,6 +650,7 @@ export class PayloadService {
636
650
  else {
637
651
  await service.updateByQuery(query, { [relation.field]: null }, {
638
652
  onRevisionCreate: (pk) => revisions.push(pk),
653
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
639
654
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
640
655
  emitEvents: opts?.emitEvents,
641
656
  mutationTracker: opts?.mutationTracker,
@@ -644,7 +659,7 @@ export class PayloadService {
644
659
  }
645
660
  }
646
661
  }
647
- return { revisions, nestedActionEvents };
662
+ return { revisions, nestedActionEvents, userIntegrityCheckFlags };
648
663
  }
649
664
  /**
650
665
  * Transforms the input partial payload to match the output structure, to have consistency
@@ -1,12 +1,10 @@
1
- import type { Item, ItemPermissions, PermissionsAction, PrimaryKey, Query } from '@directus/types';
2
- import type Keyv from 'keyv';
3
- import type { AbstractServiceOptions, MutationOptions } from '../../types/index.js';
4
- import type { QueryOptions } from '../items.js';
5
- import { ItemsService } from '../items.js';
1
+ import type { Item, ItemPermissions, PrimaryKey, Query } from '@directus/types';
2
+ import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
3
+ import type { QueryOptions } from './items.js';
4
+ import { ItemsService } from './items.js';
6
5
  export declare class PermissionsService extends ItemsService {
7
- systemCache: Keyv<any>;
8
6
  constructor(options: AbstractServiceOptions);
9
- getAllowedFields(action: PermissionsAction, collection?: string): Record<string, string[]>;
7
+ private clearCaches;
10
8
  readByQuery(query: Query, opts?: QueryOptions): Promise<Partial<Item>[]>;
11
9
  createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
12
10
  createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
@@ -1,32 +1,17 @@
1
1
  import { ForbiddenError } from '@directus/errors';
2
- import { clearSystemCache, getCache } from '../../cache.js';
3
- import { AuthorizationService } from '../authorization.js';
4
- import { ItemsService } from '../items.js';
5
- import { withAppMinimalPermissions } from './lib/with-app-minimal-permissions.js';
2
+ import { clearSystemCache } from '../cache.js';
3
+ import { withAppMinimalPermissions } from '../permissions/lib/with-app-minimal-permissions.js';
4
+ import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
5
+ import { ItemsService } from './items.js';
6
6
  export class PermissionsService extends ItemsService {
7
- systemCache;
8
7
  constructor(options) {
9
8
  super('directus_permissions', options);
10
- const { systemCache } = getCache();
11
- this.systemCache = systemCache;
12
9
  }
13
- getAllowedFields(action, collection) {
14
- const results = this.accountability?.permissions?.filter((permission) => {
15
- let matchesCollection = true;
16
- if (collection) {
17
- matchesCollection = permission.collection === collection;
18
- }
19
- const matchesAction = permission.action === action;
20
- return collection ? matchesCollection && matchesAction : matchesAction;
21
- }) ?? [];
22
- const fieldsPerCollection = {};
23
- for (const result of results) {
24
- const { collection, fields } = result;
25
- if (!fieldsPerCollection[collection])
26
- fieldsPerCollection[collection] = [];
27
- fieldsPerCollection[collection].push(...(fields ?? []));
10
+ async clearCaches(opts) {
11
+ await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
12
+ if (this.cache && opts?.autoPurgeCache !== false) {
13
+ await this.cache.clear();
28
14
  }
29
- return fieldsPerCollection;
30
15
  }
31
16
  async readByQuery(query, opts) {
32
17
  const result = (await super.readByQuery(query, opts));
@@ -34,50 +19,32 @@ export class PermissionsService extends ItemsService {
34
19
  }
35
20
  async createOne(data, opts) {
36
21
  const res = await super.createOne(data, opts);
37
- await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
38
- if (this.cache && opts?.autoPurgeCache !== false) {
39
- await this.cache.clear();
40
- }
22
+ await this.clearCaches(opts);
41
23
  return res;
42
24
  }
43
25
  async createMany(data, opts) {
44
26
  const res = await super.createMany(data, opts);
45
- await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
46
- if (this.cache && opts?.autoPurgeCache !== false) {
47
- await this.cache.clear();
48
- }
27
+ await this.clearCaches(opts);
49
28
  return res;
50
29
  }
51
30
  async updateBatch(data, opts) {
52
31
  const res = await super.updateBatch(data, opts);
53
- await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
54
- if (this.cache && opts?.autoPurgeCache !== false) {
55
- await this.cache.clear();
56
- }
32
+ await this.clearCaches(opts);
57
33
  return res;
58
34
  }
59
35
  async updateMany(keys, data, opts) {
60
36
  const res = await super.updateMany(keys, data, opts);
61
- await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
62
- if (this.cache && opts?.autoPurgeCache !== false) {
63
- await this.cache.clear();
64
- }
37
+ await this.clearCaches(opts);
65
38
  return res;
66
39
  }
67
40
  async upsertMany(payloads, opts) {
68
41
  const res = await super.upsertMany(payloads, opts);
69
- await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
70
- if (this.cache && opts?.autoPurgeCache !== false) {
71
- await this.cache.clear();
72
- }
42
+ await this.clearCaches(opts);
73
43
  return res;
74
44
  }
75
45
  async deleteMany(keys, opts) {
76
46
  const res = await super.deleteMany(keys, opts);
77
- await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
78
- if (this.cache && opts?.autoPurgeCache !== false) {
79
- await this.cache.clear();
80
- }
47
+ await this.clearCaches(opts);
81
48
  return res;
82
49
  }
83
50
  async getItemPermissions(collection, primaryKey) {
@@ -115,16 +82,25 @@ export class PermissionsService extends ItemsService {
115
82
  updateAction = 'create';
116
83
  }
117
84
  }
118
- const authorizationService = new AuthorizationService({
119
- knex: this.knex,
120
- accountability: this.accountability,
121
- schema: this.schema,
122
- });
123
85
  await Promise.all(Object.keys(itemPermissions).map((key) => {
124
86
  const action = key;
125
87
  const checkAction = action === 'update' ? updateAction : action;
126
- return authorizationService
127
- .checkAccess(checkAction, collection, primaryKey)
88
+ if (!this.accountability) {
89
+ itemPermissions[action].access = true;
90
+ return Promise.resolve();
91
+ }
92
+ const opts = {
93
+ accountability: this.accountability,
94
+ action: checkAction,
95
+ collection,
96
+ };
97
+ if (primaryKey) {
98
+ opts.primaryKeys = [primaryKey];
99
+ }
100
+ return validateAccess(opts, {
101
+ schema: this.schema,
102
+ knex: this.knex,
103
+ })
128
104
  .then(() => (itemPermissions[action].access = true))
129
105
  .catch(() => { });
130
106
  }));
@@ -0,0 +1,12 @@
1
+ import type { Policy, PrimaryKey } from '@directus/types';
2
+ import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
3
+ import { ItemsService } from './items.js';
4
+ export declare class PoliciesService extends ItemsService<Policy> {
5
+ constructor(options: AbstractServiceOptions);
6
+ private clearCaches;
7
+ private isIpAccessValid;
8
+ private assertValidIpAccess;
9
+ createOne(data: Partial<Policy>, opts?: MutationOptions): Promise<PrimaryKey>;
10
+ updateMany(keys: PrimaryKey[], data: Partial<Policy>, opts?: MutationOptions): Promise<PrimaryKey[]>;
11
+ deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
12
+ }
@@ -0,0 +1,87 @@
1
+ import { InvalidPayloadError } from '@directus/errors';
2
+ import { getMatch } from 'ip-matching';
3
+ import { clearSystemCache } from '../cache.js';
4
+ import { clearCache as clearPermissionsCache } from '../permissions/cache.js';
5
+ import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
6
+ import { ItemsService } from './items.js';
7
+ export class PoliciesService extends ItemsService {
8
+ constructor(options) {
9
+ super('directus_policies', options);
10
+ }
11
+ async clearCaches(opts) {
12
+ await clearSystemCache({ autoPurgeCache: opts?.autoPurgeCache });
13
+ if (this.cache && opts?.autoPurgeCache !== false) {
14
+ await this.cache.clear();
15
+ }
16
+ }
17
+ isIpAccessValid(value) {
18
+ if (value === undefined)
19
+ return false;
20
+ if (value === null)
21
+ return true;
22
+ if (Array.isArray(value) && value.length === 0)
23
+ return true;
24
+ for (const ip of value) {
25
+ if (typeof ip !== 'string' || ip.includes('*'))
26
+ return false;
27
+ try {
28
+ const match = getMatch(ip);
29
+ if (match.type == 'IPMask')
30
+ return false;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ return true;
37
+ }
38
+ assertValidIpAccess(partialItem) {
39
+ if ('ip_access' in partialItem && !this.isIpAccessValid(partialItem['ip_access'])) {
40
+ throw new InvalidPayloadError({
41
+ reason: 'IP Access contains an incorrect value. Valid values are: IP addresses, IP ranges and CIDR blocks',
42
+ });
43
+ }
44
+ }
45
+ async createOne(data, opts = {}) {
46
+ this.assertValidIpAccess(data);
47
+ // A policy has been created, but the attachment to a user/role happens in the AccessService,
48
+ // so no need to check user integrity
49
+ const result = await super.createOne(data, opts);
50
+ // TODO is this necessary? Since the attachment should be handled in the AccessService
51
+ // A new policy has created, clear the permissions cache
52
+ await clearPermissionsCache();
53
+ return result;
54
+ }
55
+ async updateMany(keys, data, opts = {}) {
56
+ this.assertValidIpAccess(data);
57
+ if ('admin_access' in data) {
58
+ let flags = UserIntegrityCheckFlag.RemainingAdmins;
59
+ if (data['admin_access'] === true) {
60
+ // Only need to perform a full user count if the policy allows admin access
61
+ flags |= UserIntegrityCheckFlag.All;
62
+ }
63
+ opts.userIntegrityCheckFlags = (opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None) | flags;
64
+ }
65
+ if ('app_access' in data) {
66
+ opts.userIntegrityCheckFlags =
67
+ (opts.userIntegrityCheckFlags ?? UserIntegrityCheckFlag.None) | UserIntegrityCheckFlag.UserLimits;
68
+ }
69
+ if (opts.userIntegrityCheckFlags)
70
+ opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
71
+ const result = await super.updateMany(keys, data, opts);
72
+ if ('admin_access' in data || 'app_access' in data || 'ip_access' in data || 'enforce_tfa' in data) {
73
+ // Some relevant properties on policies have been updated, clear the caches
74
+ await this.clearCaches(opts);
75
+ }
76
+ return result;
77
+ }
78
+ async deleteMany(keys, opts = {}) {
79
+ opts.userIntegrityCheckFlags = UserIntegrityCheckFlag.All;
80
+ opts.onRequireUserIntegrityCheck?.(opts.userIntegrityCheckFlags);
81
+ const result = await super.deleteMany(keys, opts);
82
+ // TODO is this necessary? Since the detachment should be handled in the AccessService
83
+ // Some policies have been deleted, clear the permissions cache
84
+ await this.clearCaches(opts);
85
+ return result;
86
+ }
87
+ }
@@ -5,10 +5,8 @@ import type { Knex } from 'knex';
5
5
  import type { Helpers } from '../database/helpers/index.js';
6
6
  import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
7
7
  import { ItemsService, type QueryOptions } from './items.js';
8
- import { PermissionsService } from './permissions/index.js';
9
8
  export declare class RelationsService {
10
9
  knex: Knex;
11
- permissionsService: PermissionsService;
12
10
  schemaInspector: SchemaInspector;
13
11
  accountability: Accountability | null;
14
12
  schema: SchemaOverview;
@@ -34,10 +32,6 @@ export declare class RelationsService {
34
32
  * Delete an existing relationship
35
33
  */
36
34
  deleteOne(collection: string, field: string, opts?: MutationOptions): Promise<void>;
37
- /**
38
- * Whether or not the current user has read access to relations
39
- */
40
- private get hasReadAccess();
41
35
  /**
42
36
  * Combine raw schema foreign key information with Directus relations meta rows to form final
43
37
  * Relation objects
@@ -1,3 +1,4 @@
1
+ import { useEnv } from '@directus/env';
1
2
  import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
2
3
  import { createInspector } from '@directus/schema';
3
4
  import { systemRelationRows } from '@directus/system-data';
@@ -6,16 +7,16 @@ import { clearSystemCache, getCache, getCacheValue, setCacheValue } from '../cac
6
7
  import { getHelpers } from '../database/helpers/index.js';
7
8
  import getDatabase, { getSchemaInspector } from '../database/index.js';
8
9
  import emitter from '../emitter.js';
10
+ import { fetchAllowedFieldMap } from '../permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js';
11
+ import { fetchAllowedFields } from '../permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js';
12
+ import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
9
13
  import { getDefaultIndexName } from '../utils/get-default-index-name.js';
10
14
  import { getSchema } from '../utils/get-schema.js';
11
15
  import { transaction } from '../utils/transaction.js';
12
16
  import { ItemsService } from './items.js';
13
- import { PermissionsService } from './permissions/index.js';
14
- import { useEnv } from '@directus/env';
15
17
  const env = useEnv();
16
18
  export class RelationsService {
17
19
  knex;
18
- permissionsService;
19
20
  schemaInspector;
20
21
  accountability;
21
22
  schema;
@@ -25,7 +26,6 @@ export class RelationsService {
25
26
  helpers;
26
27
  constructor(options) {
27
28
  this.knex = options.knex || getDatabase();
28
- this.permissionsService = new PermissionsService(options);
29
29
  this.schemaInspector = options.knex ? createInspector(options.knex) : getSchemaInspector();
30
30
  this.schema = options.schema;
31
31
  this.accountability = options.accountability || null;
@@ -59,8 +59,15 @@ export class RelationsService {
59
59
  return foreignKeys;
60
60
  }
61
61
  async readAll(collection, opts) {
62
- if (this.accountability && this.accountability.admin !== true && this.hasReadAccess === false) {
63
- throw new ForbiddenError();
62
+ if (this.accountability) {
63
+ await validateAccess({
64
+ accountability: this.accountability,
65
+ action: 'read',
66
+ collection: 'directus_relations',
67
+ }, {
68
+ knex: this.knex,
69
+ schema: this.schema,
70
+ });
64
71
  }
65
72
  const metaReadQuery = {
66
73
  limit: -1,
@@ -86,18 +93,17 @@ export class RelationsService {
86
93
  }
87
94
  async readOne(collection, field) {
88
95
  if (this.accountability && this.accountability.admin !== true) {
89
- if (this.hasReadAccess === false) {
90
- throw new ForbiddenError();
91
- }
92
- const permissions = this.accountability.permissions?.find((permission) => {
93
- return permission.action === 'read' && permission.collection === collection;
96
+ await validateAccess({
97
+ accountability: this.accountability,
98
+ action: 'read',
99
+ collection: 'directus_relations',
100
+ }, {
101
+ schema: this.schema,
102
+ knex: this.knex,
94
103
  });
95
- if (!permissions || !permissions.fields)
104
+ const allowedFields = await fetchAllowedFields({ collection, action: 'read', accountability: this.accountability }, { schema: this.schema, knex: this.knex });
105
+ if (allowedFields.includes('*') === false && allowedFields.includes(field) === false) {
96
106
  throw new ForbiddenError();
97
- if (permissions.fields.includes('*') === false) {
98
- const allowedFields = permissions.fields;
99
- if (allowedFields.includes(field) === false)
100
- throw new ForbiddenError();
101
107
  }
102
108
  }
103
109
  const metaRow = await this.relationsItemService.readByQuery({
@@ -379,14 +385,6 @@ export class RelationsService {
379
385
  }
380
386
  }
381
387
  }
382
- /**
383
- * Whether or not the current user has read access to relations
384
- */
385
- get hasReadAccess() {
386
- return !!this.accountability?.permissions?.find((permission) => {
387
- return permission.collection === 'directus_relations' && permission.action === 'read';
388
- });
389
- }
390
388
  /**
391
389
  * Combine raw schema foreign key information with Directus relations meta rows to form final
392
390
  * Relation objects
@@ -435,12 +433,11 @@ export class RelationsService {
435
433
  async filterForbidden(relations) {
436
434
  if (this.accountability === null || this.accountability?.admin === true)
437
435
  return relations;
438
- const allowedCollections = this.accountability.permissions
439
- ?.filter((permission) => {
440
- return permission.action === 'read';
441
- })
442
- .map(({ collection }) => collection) ?? [];
443
- const allowedFields = this.permissionsService.getAllowedFields('read');
436
+ const allowedFields = await fetchAllowedFieldMap({
437
+ accountability: this.accountability,
438
+ action: 'read',
439
+ }, { schema: this.schema, knex: this.knex });
440
+ const allowedCollections = Object.keys(allowedFields);
444
441
  relations = toArray(relations);
445
442
  return relations.filter((relation) => {
446
443
  let collectionsAllowed = true;
@@ -1,18 +1,10 @@
1
- import type { Item, PrimaryKey, Query } from '@directus/types';
1
+ import type { Item, PrimaryKey } from '@directus/types';
2
2
  import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
3
3
  import { ItemsService } from './items.js';
4
4
  export declare class RolesService extends ItemsService {
5
5
  constructor(options: AbstractServiceOptions);
6
- private checkForOtherAdminRoles;
7
- private checkForOtherAdminUsers;
8
- private isIpAccessValid;
9
- private assertValidIpAccess;
10
- private getRoleAccessType;
11
- createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
12
- createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
13
- updateOne(key: PrimaryKey, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
14
- updateBatch(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
15
6
  updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
16
- updateByQuery(query: Query, data: Partial<Item>, opts?: MutationOptions | undefined): Promise<PrimaryKey[]>;
17
- deleteMany(keys: PrimaryKey[]): Promise<PrimaryKey[]>;
7
+ deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
8
+ private validateRoleNesting;
9
+ private clearCaches;
18
10
  }